Explicación detallada de 5 juegos sencillos y fáciles de entender en lenguaje C

prefacio

Usamos 5 minijuegos fáciles de entender para fortalecer nuestra comprensión del lenguaje C. Estos cinco minijuegos no solo incluyen juegos para un solo jugador, sino también juegos de hombre a máquina y de todos a jugadores. ¡Juguemos un juego emocionante después de estudiar!

1. Preparación

Vamos a hacer 5 juegos pequeños y necesitamos crear un archivo de encabezado y un archivo fuente para cada uno de los 5 juegos pequeños . Son juego1.h/juego1.c, juego2.h/juego2.c, juego3.h/juego3.c, juego4.h/juego4.c, juego5.h/juego5.c. El propósito de esto es construir cada juego por separado para facilitar operaciones como la reconstrucción de nuestro minijuego en el futuro. También necesitamos un main.c para incluir los archivos de encabezado de estos 5 pequeños juegos. La función principal solo es responsable de llamar. Implementamos todas las funciones del código del minijuego en otros archivos y los decoramos con estática, para que los usuarios puedan usar la función del juego para llamar indirectamente al código de nuestro minijuego.

2. Menú del juego

Construyamos main.c primero:
1. Debe incluir los archivos de encabezado de cinco juegos pequeños
2. Construya nuestra función principal

#include"game1.h"//包含小游戏1的头文件
#include"game2.h"//包含小游戏2的头文件
#include"game3.h"//包含小游戏3的头文件
#include"game4.h"//包含小游戏4的头文件
#include"game5.h"//包含小游戏5的头文件
#include<time.h>
int main()
{
    
    
	srand((unsigned int)time(NULL));//用来生成随机数
	do
	{
    
    
		int optional = 0;//创建一个接收选择的变量
		menu();
		printf("请输入你的选项:\n");
		scanf("%d", &optional);
		switch (optional)
		{
    
    
		case 1:
			game1();
			break;
		case 2:
			game2();
			break;
		case 3:
			game3();
			break;
		case 4:
			game4();
			break;
		case 5:
			game5();
			break;
		case 0:
			printf("感谢你的游玩,欢迎下次使用。\n");
			exit(0);
		default:
			printf("你的选项输入有误,请重新输入:\n");
			break;
		}
	} while (1);
}

Usamos un bucle do-while en la función principal, el propósito es permitir que el usuario haga una elección, y el usuario no saldrá hasta que elija salir o se equivoque.
La función scanf es arriesgada, cuando el usuario confunde las letras de entrada, causará excepciones en el búfer. Así que ponemos la variable de selección que queremos recibir en el ciclo y le damos un valor inicial de 0 para hacer que el programa salga cuando el usuario ingrese una letra.
La función srand se usa para generar números aleatorios.Cuando solo usamos la función rand, los números aleatorios generados permanecerán sin cambios, lo que empeorará nuestra experiencia de juego repetido.
Estamos creando un menú para la colección de estos juegos, que permite a los usuarios elegir qué juego jugar.

void menu()
{
    
    
	printf("*****************************\n");
	printf("*****1.猜数字   2.三子棋*****\n");
	printf("*****3.扫  雷   4.五子棋*****\n");
	printf("*****5.飞行棋   0.退  出*****\n");
	printf("*****************************\n");
}

El menú básico está listo, entramos en el menú de cada minijuego.
Primero vamos a crear el archivo de encabezado del mini juego:

#pragma once
#include<stdio.h>
#include<stdlib.h>
void game1();

Los minijuegos nos corresponden con el juego en los archivos de cabecera de los minijuegos, tomo el minijuego 1 como ejemplo, y los otros cuatro minijuegos son similares a este.
Luego creamos archivos fuente para cada uno:

#include"game1.h"
static void menu1()
{
    
    
	printf("*****************************\n");
	printf("*****      猜数字       *****\n");
	printf("***** 1.Start the game ******\n");
	printf("***** 0.Exit the game  ******\n");
	printf("*****************************\n");
}
void game1()
{
    
    
	int optional = 0;//创建一个接收选择的变量
	do
	{
    
    
		optional = 0;
		menu1();
		printf("请输入你的选项:\n");
		scanf("%d", &optional);
		switch (optional)
		{
    
    
		case 1:
			//game();
			break;
		case 0:
			printf("猜数字小游戏以退出。\n");
			break;
		default:
			printf("你的选项输入有误,请重新输入:\n");
			break;
		}
	} while (optional);
}

Aún tome el juego 1 como ejemplo, las opciones en otros minijuegos son las mismas que en el juego 1, solo cambie el nombre del minijuego en la función de menú. La función de juego en el bucle se usa para llamar a la función de composición en este pequeño juego.
Vamos a ejecutarlo ahora para probar si el código es lo que esperábamos. La
inserte la descripción de la imagen aquí
prueba se puede llevar a cabo normalmente de acuerdo con nuestras ideas. Ahora escribamos formalmente cada pequeño juego.

3. Contenido del juego

1. Adivina el número

Idea: El sistema genera aleatoriamente un número aleatorio.Al comparar el número que ingresamos con el número generado, nos dará un aviso para adivinar si es demasiado grande o demasiado pequeño.

static void game()
{
    
    
	int num = rand() % 100 + 1;//创建一个变量,用来存放随机数。
	int guess = 0;//创建一个变量,用来存放所猜的数字。	
	//rand函数是用来生成随机数的,我们用rand函数生成的随机数对100取模并加1,可以产生1~100的随机数
	while(1)
	{
    
    
		printf("请输入你猜测的数字:");
		scanf("%d", &guess);
		if (guess == num)
		{
    
    
			printf("恭喜你,猜对了!\n");
			break;
		}
		else if (guess > num)
		{
    
    
			printf("你猜的数字过大,请重新猜测吧!\n");
		}
		else if (guess < num)
		{
    
    
			printf("你猜的数字过小,请重新猜测吧!\n");
		}
	}
	return;
}

¡Simplemente vamos a ejecutarlo!
inserte la descripción de la imagen aquí
Funciona bien, y podemos reproducirlo repetidamente.

2. Chaquete

Idea: Usar una matriz para almacenar nuestras piezas de ajedrez y juzgar si ganamos.
1. Imprimir el tablero de ajedrez
2. El jugador juega al ajedrez
3. Determinar si el jugador gana
4. La computadora juega al ajedrez
5. Determinar si la computadora gana
Primero definimos dos macros: se utilizan para determinar el tamaño del tablero de ajedrez que podemos establecer.

#define ROW 3  //行
#define COL 3  //列

Comenzamos a construir la función del juego para ver qué módulos se necesitan para respaldar la idea del juego:

static void game()
{
    
    
	char win;//创建一个变量,存放判段获胜条件的字符。
	//我们把C代表继续,D代表平局,*代表玩家获胜,#代表电脑获胜
	char checkerboard[ROW][COL] = {
    
     0 };//创建一个数组,用来存放棋盘信息
	initialization(checkerboard,ROW,COL);//初始化数组,把数组中的每个元素初始化为空格
	ptintinitialization(checkerboard, ROW, COL);//打印棋盘
	while(1)
	{
    
    
		Player(checkerboard, ROW, COL, '*');//玩家下棋,玩家的标志为 *
		win = Iswin(checkerboard, ROW, COL);//判断是否获胜
		if (win != 'C')
		{
    
    
			break;
		}
		ptintinitialization(checkerboard, ROW, COL);//打印棋盘
		Computer(checkerboard, ROW, COL, '#');//电脑下棋,电脑的标志为 #
		win = Iswin(checkerboard, ROW, COL);
		if (win != 'C')
		{
    
    
			break;
		}
		ptintinitialization(checkerboard, ROW, COL);//打印棋盘
	}
	if (win == 'D')
	{
    
    
		printf("平局\n");
		ptintinitialization(checkerboard, ROW, COL);
	}
	else if (win == '*')
	{
    
    
		printf("恭喜你获得胜利\n");
		ptintinitialization(checkerboard, ROW, COL);
	}
	else
	{
    
    
		printf("很遗憾,你输掉了比赛\n");
		ptintinitialization(checkerboard, ROW, COL);
	}
}

Primero creamos la matriz que usamos y una variable que puede juzgar si ganamos o perdemos. Inicializamos la matriz y la imprimimos para que el jugador sepa la posición en la que puede jugar al ajedrez. La batalla hombre-máquina se realiza a través del ajedrez del jugador. función y la función de ajedrez de la computadora.
Inicializar función de matriz:

static void initialization(char arr[ROW][COL],int row,int col)//初始化数组
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
    
    
		for (j = 0; j < col; j++)
		{
    
    
			arr[i][j] = ' ';//把数组中的每个元素赋值为空格
		}
	}
}

Imprimir función de tablero de ajedrez:

static void ptintinitialization(char arr[ROW][COL], int row, int col)//打印棋盘
{
    
    
	int i = 0;
	for (i = 0; i < row; i++)
	{
    
    
		int j = 0;
		for (j = 0; j < col; j++)
		{
    
    
			if (j < col - 1)
			{
    
    
				printf(" %c |", arr[i][j]);//打印棋盘,如果为列中的最后一个元素,则不打印|
			}
			else
			{
    
    
				printf(" %c ", arr[i][j]);
			}
		}
		printf("\n");
		if(i < row-1)//打印棋盘,如果为行中的最后一个元素,则不打印---
		{
    
    
			for (j = 0; j < col; j++)
			{
    
    
				if (j < col)
				{
    
    
					printf("--- ");
				}
			}
		}
		printf("\n");
	}
}

inserte la descripción de la imagen aquí
El efecto de impresión se muestra en la figura.
Cuando cambiamos la macro a:

#define ROW 9  //行
#define COL 9  //列

inserte la descripción de la imagen aquí
Podemos ver que el tablero de ajedrez impreso se expande. Este es el beneficio de las macros que no requieren que modifiquemos el valor en cada función. Simplemente cambie el valor definido por la macro para cambiar el tamaño de nuestro tablero de ajedrez.

Función de ajedrez del jugador:

static void Player(char arr[ROW][COL], int row, int col, char ch)//玩家下棋函数
{
    
    
	int x = 0;
	int y = 0;
	while(1)
	{
    
    
		printf("请输入你要下棋的坐标:");
		scanf("%d %d", &x, &y);
		if (x<1 || x>row || y<1 || y>col)//判断坐标是否合法
		{
    
    
			printf("你输入的坐标不合法,请重新输入。\n");
		}
		else if (arr[x - 1][y - 1] != ' ')//判断输入坐标是否被占用
		{
    
    
			printf("你输入的坐标已被占用,请重新输入。\n");
		}
		else
		{
    
    
			arr[x - 1][y - 1] = ch;//数组下标从0开始,所以玩家的真实坐标要进行减1
			break;
		}
	}
}

Función de ajedrez de computadora:

static void Computer(char arr[ROW][COL], int row, int col, char ch)
{
    
    
	while (1)
	{
    
    
		int x = rand() % 3;//产生0~2的数字
		int y = rand() % 3;
		if (arr[x][y] == ' ')//如果坐标未被占用,则电脑下棋,否则产生新的坐标进行判断
		{
    
    
			arr[x][y] = ch;//电脑的坐标的下标和数组下标对应,不需要进行减1操作
			break;
		}
	}
}

Juzgando si ganar la función:

static char Iswin(char arr[ROW][COL], int row, int col)//判断是否获胜
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)//判断每一排中是否有人获胜
	{
    
    
		if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][1] != ' ')
		{
    
    
			return arr[i][1];
		}
	}
	for (i = 0; i < col; i++)//判断每一列中是否有人获胜
	{
    
    
		if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[1][i] != ' ')
		{
    
    
			return arr[1][i];
		}
	}
	if ((arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ') || 
		(arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1] != ' '))//判断对角线上是否有人获胜
	{
    
    
		return arr[1][1];
	}
	for (i = 0; i < row; i++)
	{
    
    
		for (j = 0; i < col; i++)
		{
    
    
			if (arr[i][j] == ' ');//判断是否还有空位
			{
    
    
				return 'C';
			}
		}
	}
	return 'D';
}

¡Ejecutémoslo y veamos el resultado!
inserte la descripción de la imagen aquí
Nota:
1. El scanf que usamos no es seguro. Puede encontrar la solución correspondiente para entender por qué no es seguro.
2. Al inicializar la matriz utilizada, preste atención al intervalo. Al pasar un parámetro de matriz, preste atención a si los tipos del parámetro formal y el parámetro real son consistentes. Usamos una matriz de tipo char. ¿Qué sucederá si el parámetro formal es aceptado por int? Todos pueden bajar y probar.
3. Puede refactorizar este código y todos pueden jugar unos contra otros. Aquí solo se muestra la batalla hombre-máquina, refactoricémosla y unámonos a la batalla hombre-máquina.
Si el parámetro formal es aceptado por int, hará que la matriz se salga de los límites y cause un error de pila.

3. Buscaminas

Idea: use una matriz para almacenar la información de las minas y descubra dónde no hay minas a través de la investigación.
1. Imprima el mapa
2. El jugador realiza el barrido de minas
3. Determine si el jugador pisa las minas
4. Actualice el
análisis del mapa:
Inserte la descripción de la imagen aquí La inserte la descripción de la imagen aquí
imagen de arriba es un mapa de barrido de minas de 9 x 9. Cuando queremos juzgar el rojo lugar, necesitamos juzgar el área circundante Está obligado a causar acceso fuera de los límites. ¿Cómo resolver este problema?
Expandimos la matriz en una línea hacia arriba, hacia abajo, a la izquierda y a la derecha, de modo que el juicio no haga que la matriz se salga de los límites. Analicemos el problema de imprimir matrices a través del código.
Configuramos dos matrices, una se usa para almacenar información del mapa y la otra se usa para mostrar al jugador. La matriz que se muestra al jugador necesita juzgar el lugar seguro en el mapa almacenando la matriz de información del mapa.
Primero definimos cinco macros: determinamos respectivamente el tamaño del mapa que podemos configurar y el tamaño de nuestro mapa impreso, y la última macro se usa para almacenar el número de nuestras minas, lo que también es conveniente para que lo probemos más adelante.

#define ROW 9  //显示的行
#define COL 9  //显示的列
#define ROWS ROW+2  //真实数组的行
#define COLS COL+2  //真实数组的列
#define MINENUM 10  //地雷的个数

Luego agregue nuestra función de juego para ver las ideas específicas:

static void game()
{
    
    
	int winnum = ROW * COL - MINENUM;//设置一个变量,用来存放还有多少个安全的地方
	char minemap[ROWS][COLS] = {
    
     0 };//雷分布的地图
	char showmap[ROWS][COLS] = {
    
     0 };//向玩家展示的地图
	Initialization(minemap, showmap, ROWS, COLS);//初始化数组,把雷分布随机分布在地图中,并且把向玩家展示的地图全部替换为 * 
	//Ptintinitialization(minemap, ROW, COL);//测试代码,用来打印地图
	while (winnum)
	{
    
    
		int x = 0;
		int y = 0;
		Ptintinitialization(showmap, ROW, COL);//打印展示地图
		printf("请输入排雷坐标:");
		scanf("%d %d", &x, &y);
		if (x<1 || x>ROW || y<1 || y>COL)//判断坐标是否合法
		{
    
    
			printf("你输入的坐标不合法,请重新输入。\n");
		}
		else if (showmap[x][y] != '*')//判断坐标是否已被排查过
		{
    
    
			printf("你输入的坐标已被排过雷了,请重新输入。\n");
		}
		else 
		{
    
    
			if (!Determine(minemap, x, y))//!Determine(minemap, x, y)用来判断是否踩到雷
			{
    
    
				Ptintinitialization(minemap, ROW, COL);//打印地雷地图,让玩家知道地雷在哪里。
				break;
			}
			Renewmap(minemap, showmap, x, y);//用来更新向玩家展示的地图
			winnum--;//对安全的地方进行减1
		}
	}
	if(winnum == 0)//当安全地方为0时,证明排雷成功
	{
    
    
		printf("恭喜你排雷成功!\n");
		Ptintinitialization(showmap, ROW, COL);//打印展示地图,让玩家知道自己获胜地图
	}
}

Inicializar función de matriz:

static void Initialization(char minemap[ROWS][COLS], char showmap[ROWS][COLS], int rows, int cols)
{
    
    
	int count = MINENUM;//创建一个变量,用来计算放置的雷的数量
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)//把地雷地图全部赋值为字符0
	{
    
    
		for (j = 0; j < cols; j++)
		{
    
    
			minemap[i][j] = '0';
		}
	}
	while (count)//把雷分布随机分布在地雷地图中
	//我们把0代表安全,1代表雷区
	{
    
    
		int x = rand() % ROW + 1;//创建随机变量范围在1~9
		int y = rand() % COL + 1;//创建随机变量范围在1~9
		if (minemap[x][y] == '0')//判断该位置是否已有雷
		{
    
    
			minemap[x][y] = '1';//放置地雷
			count--;
		}
	}
	for (i = 0; i < rows; i++)//把展示地图全部赋值为字符*
	{
    
    
		for (j = 0; j < cols; j++)
		{
    
    
			showmap[i][j] = '*';
		}
	}
}

inserte la descripción de la imagen aquí
La fila del mapa que mostramos es 1 ~ ROW, y la columna es 1 ~ COL, por lo que las coordenadas de las minas generadas se controlan dentro de este rango.
Función de impresión de mapa:

static void Ptintinitialization(char showmap[ROWS][COLS], int row, int col)//打印地图
{
    
    
	int i = 1;
	int j = 1;
	for (i = 1; i <= row; i++)
	{
    
    
		if (i == 1)//当i为1时,需要多一个空格,目的为了和地图对齐
		{
    
    
			printf(" ");
		}
		printf(" %d", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)//打印我们所需要的地图
	{
    
    
		printf("%d", i);
		for (j = 1; j <= col; j++)
		{
    
    
			printf(" %c", showmap[i][j]);
		}
		printf("\n");
	}
}

Comenzamos a imprimir desde 1, imprimimos a ROW, y solo imprimimos donde necesitamos.
Para juzgar si pisar el mío:

static bool Determine(char minemap[ROWS][COLS],int x,int y)
{
    
    
	if (minemap[x][y] == '1')
	{
    
    
		printf("排雷失败,你已死亡!\n");
		return false;
	}
	else
	{
    
    
		return true;
	}
}

Actualice el mapa mostrado:

static void Renewmap(char minemap[ROWS][COLS], char showmap[ROWS][COLS], int x, int y)
{
    
    
	showmap[x][y] = (minemap[x - 1][y - 1] + minemap[x - 1][y] + minemap[x - 1][y + 1]
				  + minemap[x][y - 1] + minemap[x][y + 1]
				  + minemap[x + 1][y - 1] + minemap[x + 1][y] + minemap[x + 1][y + 1]) - 8*'0' + '0';
}

inserte la descripción de la imagen aquí
Actualiza el mapa que se muestra al jugador para sumar el número de minas circundantes y reemplázalas con el número correspondiente. Estamos utilizando una matriz de caracteres, que almacena el carácter 1 y el carácter 0, por lo que debemos restar el valor del código ASCLL de 0 para obtener un número entero, sumarlos para representar el número de minas en 8 lugares alrededor de este cuadrado y finalmente sumar El valor de código ASCLL de 0 obtiene el número de carácter correspondiente.
Vamos a probarlo: descomentamos el código de prueba y configuramos el número de minas definidas por nuestra macro para que sea mayor. Primero lo configuré en 79. Puedes cambiarlo según la dificultad que quieras jugar cuando realmente juegues. Tomemos una mirada a
inserte la descripción de la imagen aquí
la remoción de minas Si la falla se mostrará normalmente:
inserte la descripción de la imagen aquí
la falla de remoción de minas también se mostrará normalmente.
Nota:
1. scanf no es seguro
2. Preste atención al intervalo al inicializar la matriz utilizada, y preste atención a si está fuera de los límites al acceder a la matriz.
3. Ideas de refactorización: puede agregar un mapa expandido (se puede expandir cuando no hay minas en los 8 lugares circundantes, hasta que sepa que hay una mina alrededor de una cuadrícula) y agregar una pequeña bandera (reemplace el lugar que se considera una mina con una bandera pequeña, solo cancele la bandera pequeña para cambiarla) Buscaminas solo se puede realizar en la posición), agregando tiempo (cuando el tiempo expira, si no se eliminan todas las minas, el juego termina) , etc.

4. Chaquete

Ideas: Determinar qué jugador ha jugado cinco piezas consecutivas (una fila o una columna o una línea diagonal con 5 piezas consecutivas de la misma pieza) 1. Imprimir el tablero 2. El jugador 1
juega
al ajedrez
3. Determinar si el jugador 1 gana
4. El jugador 2 juega Jugar al ajedrez
5. Determinar si el jugador 2 gana
o no Todavía usamos macros para definir primero el tamaño del tablero:

#define ROW 9  //棋盘的行
#define COL 9  //棋盘的列

Mira la idea del juego de nuevo:

static void game()
{
    
    
	char win;//创建一个变量,存放判段获胜条件的字符。
	//我们把C代表继续,D代表平局,白棋(@)代表玩家1获胜,黑棋(O)代表玩家2获胜
	char checkerboard[ROW][COL] = {
    
     0 };//棋盘数组
	Initialization(checkerboard, ROW, COL);//初始化数组,把棋盘的所有位置都赋值为 *
	Ptintinitialization(checkerboard, ROW, COL);//打印棋盘
	while (1)
	{
    
    
		Player(checkerboard, ROW, COL, '@');//玩家1下棋,玩家1的标志为 @
		win = Iswin(checkerboard, ROW, COL);//判断是否获胜
		if (win != 'C')
		{
    
    
			break;
		}
		Ptintinitialization(checkerboard, ROW, COL);//打印棋盘
		Player(checkerboard, ROW, COL, 'O');//玩家2下棋,玩家2的标志为 O
		win = Iswin(checkerboard, ROW, COL);//判断是否获胜
		if (win != 'C')
		{
    
    
			break;
		}
		Ptintinitialization(checkerboard, ROW, COL);//打印棋盘
	}
	if (win == 'D')
	{
    
    
		printf("平局\n");
		Ptintinitialization(checkerboard, ROW, COL);
	}
	else if (win == '@')
	{
    
    
		printf("玩家1获胜\n");
		Ptintinitialization(checkerboard, ROW, COL);
	}
	else
	{
    
    
		printf("玩家2获胜\n");
		Ptintinitialization(checkerboard, ROW, COL);
	}
}

La idea del backgammon es exactamente la misma que la del backgammon, excepto que la computadora es reemplazada por otro jugador. Entonces, el código de la función del juego básicamente no ha cambiado mucho. Los jugadores tienen el mismo pensamiento al jugar al ajedrez, por lo que solo necesitamos una función para resolver el pensamiento de dos jugadores que juegan al ajedrez.
Inicializar función de matriz:

static void Initialization(char arr[ROW][COL], int row, int col)//初始化数组,把棋盘的所有位置都赋值为 *
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)//把展示地图全部赋值为字符*
	{
    
    
		for (j = 0; j < col; j++)
		{
    
    
			arr[i][j] = '*';
		}
	}
}

La idea de inicializar la matriz es exactamente la misma que el mapa que se muestra al jugador en el buscaminas.
Función de impresión de mapa:

static void Ptintinitialization(char arr[ROW][COL], int row, int col)//打印棋盘
{
    
    
	int i = 0;
	int j = 0;
	for (i = 1; i <= row; i++)
	{
    
    
		if (i == 1)//当i为1时,需要多两个空格,目的为了和地图对齐
		{
    
    
			printf("  ");
		}
		if (i < 9)//当i小于9时,需要多一个个空格,目的为了和地图对齐
		{
    
    
			printf(" %d ", i);
		}
		else//当i大于于9时,不需要多一个个空格
		{
    
    
			printf(" %d", i);
		}
	}
	printf("\n");
	for (i = 0; i < row; i++)//打印我们所需要的地图
	{
    
    
		printf("%2d", i + 1);
		for (j = 0; j < col; j++)
		{
    
    
			printf(" %c ", arr[i][j]);//需要多一个个空格,目的为了和地图对齐
		}
		printf("\n");
	}
}

El mapa de backgammon se puede acercar y alejar a voluntad, y debe prestar atención a si el mapa está alineado con las filas y columnas de arriba.
Función de ajedrez del jugador:

int x = 0;//用来接收玩家下棋的坐标
int y = 0;//用来接收玩家下棋的坐标
static void  Player(char arr[ROW][COL], int row, int col, char ch)//玩家下棋函数,通过ch来判断是玩家1还是玩家2
{
    
    
	int player = 0;//创建一个变量来确定是玩家几
	if (ch == '@')//如果ch为白棋(@),则代表玩家1
	{
    
    
		player = 1;
	}
	else//反之则为玩家2
	{
    
    
		player = 2;
	}
	while (1)
	{
    
    
		printf("请玩家 %d 输入要下棋的坐标:",player);
		scanf("%d %d", &x, &y);
		if (x<1 || x>row || y<1 || y>col)//判断坐标是否合法
		{
    
    
			printf("你输入的坐标不合法,请重新输入。\n");
		}
		else if (arr[x - 1][y - 1] != '*')//判断输入坐标是否被占用
		{
    
    
			printf("你输入的坐标已被占用,请重新输入。\n");
		}
		else
		{
    
    
			arr[x - 1][y - 1] = ch;//数组下标从0开始,所以玩家的真实坐标要进行减1
			break;
		}
	}
}

Establecemos las coordenadas del ajedrez del jugador como una variable global, para que podamos juzgar si es el caso de cinco hijos seguidos.
Juzgando si ganar la función:
inserte la descripción de la imagen aquí

enum Direction
{
    
    
	LEFT,
	RIGHT,
	UP,
	DOWN,
	LEFTUP,
	RIGHTDOWN,
	RIGHTUP,
	LEFTDOWN
};
static char Iswin(char arr[ROW][COL], int row, int col)//判断是否获胜
{
    
    
	static chessnum = 0;//创建一个静态变量,用来存放棋盘中使用的格数
	chessnum++;//每进行一次判断调用就对棋盘使用格数进行+1
	int winnum1 = 1 + Wincount(arr, ROW, COL, LEFT) + Wincount(arr, ROW, COL, RIGHT);
	//确定左和右共计多少相同个棋子,需要加上自身的棋子
	int winnum2 = 1 + Wincount(arr, ROW, COL, UP) + Wincount(arr, ROW, COL, DOWN);
	//确定上和下共计多少相同个棋子,需要加上自身的棋子
	int winnum3 = 1 + Wincount(arr, ROW, COL, LEFTUP) + Wincount(arr, ROW, COL, RIGHTDOWN);
	//确定左上和右下共计多少相同个棋子,需要加上自身的棋子
	int winnum4 = 1 + Wincount(arr, ROW, COL, RIGHTUP) + Wincount(arr, ROW, COL, LEFTDOWN);
	//确定右上和左下共计多少相同个棋子,需要加上自身的棋子
	if (winnum1 >= 5 || winnum2 >= 5 || winnum3 >= 5 || winnum4 >= 5)//判断是否获胜
	{
    
    
		return arr[x - 1][y - 1];//返回获胜棋子的字符
	}
	else
	{
    
    
		if (chessnum == ROW * COL)//如果棋盘使用格数等于棋盘的格数,证明平局
		{
    
    
			return 'D';
		}
		else//如果棋盘使用格数不等于棋盘的格数,证明还有空位,继续进行比赛
		{
    
    
			return 'C';
		}
	}
}

Necesitamos contar la misma cantidad de piezas de ajedrez en estas 8 direcciones. No habrá 5 situaciones * consecutivas, y la dirección que guardemos será siempre la dirección del último jugador. Representamos las 8 direcciones con el tipo de menú.

static int Wincount(char arr[ROW][COL], int row, int col, enum Direction dir)
{
    
    
	int count = 0;//记录相同棋子个数
	int _x = x - 1;//要对坐标进行减1,因为我们的棋盘从1开始,数组下标从0开始
	int _y = y - 1;//要对坐标进行减1,因为我们的棋盘从1开始,数组下标从0开始
	//用局部变量保存,避免在这里修改全局变量的值
	while (1)
	{
    
    
		switch (dir)
		{
    
    
		case LEFT:
			_y--;//对中心坐标的列坐标进行减1
			break;
		case RIGHT:
			_y++;//对中心坐标的列坐标进行加1
			break;
		case UP:
			_x++;
			break;
		case DOWN:
			_x--;
			break;
		case LEFTUP:
			_y--;
			_x++;
			break;
		case RIGHTDOWN:
			_y++;
			_x--;
			break;
		case RIGHTUP:
			_y++;
			_x++;
			break;
		case LEFTDOWN:
			_y--;
			_x--;
			break;
		default:
			break;
		}
		if (_x < 0 || _x > ROW || _y < 0 || _y>COL)//判断位置是否合法
		{
    
    
			return count;
		}
		else if(arr[_x][_y] != arr[x-1][y-1])//判断是否和上一个玩家的棋子相同
		{
    
    
			return count;
		}
		else
		{
    
    
			count++;
		}
	}
}

Lo configuramos como un ciclo infinito para juzgar el número específico de piezas de ajedrez en la misma dirección. El tipo de menú es diferente de los parámetros que pasamos, por lo que tomamos diferentes rutas en la rama del interruptor.
Nota:
matriz fuera de los límites. Reconstruyendo ideas
para juzgar a Wuzilianzhu : puedes unirte a la red, realizar batallas en línea, puedes agregar la función de ajedrez arrepentido, etc.

5. ludo

Cómo jugar: 1. Excepto que la posición inicial es la misma, el resto del tiempo cuando la posición de un jugador es la misma que la posición de otro jugador, se produce una estampida.
2. Cuando el jugador pise los accesorios, realice la operación de accesorios correspondiente
3. El jugador que llegue primero al final es la
idea ganadora:
1. Use una matriz para almacenar información del mapa
2. Use una estructura para construir información del jugador
3. Use una estructura Matrices para almacenar información del jugador
4. Usar funciones aleatorias para simular operaciones de tamiz
Primero construyamos la idea del juego:

int map[100];//创建一个地图大小为100的地图。并且把地图元素全部初始化为0
//为了对数组进行方便的操作,我们把数组设置为全局变量,使每个函数可以直接访问数组
static void game()
{
    
    
	struct Player play[2];//创建一个玩家数组,里面存放玩家信息
	Initializationmap();//初始化地图数组,把地图相应位置填上道具元素,
	//我们把地图数组设置为了全局函数,所以不要需要传参
	Initializationplay(play);//初始化玩家数组,加入玩家信息,并把玩家位置置于地图开始位置
	Ptintinitialization(play);//打印棋盘,地图数组为全局函数,所以不要对地图传参。
	//需要玩家信息来判断地图要填的字符,所以要对玩家进行传参
	while (1)//使玩家交替进行游玩,直到产生胜利者
	{
    
    
		if (play[0].flags == false)//判断玩家1是否处于暂停回合。
		{
    
    
			Play(&play[0], &play[1],play);//玩家1进行游戏
			Ptintinitialization(play);//打印棋盘
		}
		else//处于暂停回合,把暂停回合改为继续
		{
    
    
			play[0].flags = false;
		}
		if (play[0].position >= 99)//判断玩家1是否获胜
		{
    
    
			printf("%s侥幸赢了%s\n", play[0].name, play[1].name);
			break;
		}
		if (play[1].flags == false)//判断玩家2是否处于暂停回合。
		{
    
    
			Play(&play[1], &play[0],play);//玩家2进行游戏
			Ptintinitialization(play);//打印棋盘
		}
		else
		{
    
    
			play[1].flags = false;//更改暂停选项
		}
		if (play[1].position >= 99)//判断玩家2是否获胜
		{
    
    
			printf("%s侥幸赢了%s\n", play[1].name, play[0].name);
			break;
		}
	}
}

Por conveniencia, configuramos la matriz del mapa como una matriz global, lo que reduce el paso de parámetros. Y no es necesario cambiar la matriz después de la inicialización. También configuramos una matriz de estructura para almacenar información del jugador (posición, si está en una posición de pausa).
Inicialice la función de mapa:

static void Initializationmap()//初始化地图数组
//地图数组中
//0代表什么都没有
//1代表道具1(幸运轮盘),2代表道具2(地雷),3代表道具3(暂停),4代表道具4(时空隧道)
{
    
    
	int luckyturn[] = {
    
    1, 20, 45, 60, 75, 90};//在相应的位置放入 幸运轮盘
	for (int i = 0; i < sizeof(luckyturn) / sizeof(luckyturn[0]); i++)
	//sizeof(luckyturn) / sizeof(luckyturn[0])用来求出数组元素的个数
	{
    
    
		map[luckyturn[i]] = 1;
	}
	int Landmine[] = {
    
     3, 6, 19, 25, 36, 49, 69, 70, 80 };//在相应的位置放入 地雷
	for (int i = 0; i < sizeof(Landmine) / sizeof(Landmine[0]); i++)
	{
    
    
		map[Landmine[i]] = 2;
	}
	int puse[] = {
    
     2, 11, 26, 35, 44, 59, 71, 88 };//在相应的位置放入 暂停
	for (int i = 0; i < sizeof(puse) / sizeof(puse[0]); i++)
	{
    
    
		map[puse[i]] = 3;
	}
	int timetunnel[] = {
    
     5, 15, 30, 50, 77 };//在相应的位置放入 时空隧道
	for (int i = 0; i < sizeof(timetunnel) / sizeof(timetunnel[0]); i++)
	{
    
    
		map[timetunnel[i]] = 4;
	}
}

La operación inicial del mapa nos permite colocar los accesorios apropiados en la posición deseada, y la posición de los accesorios se puede cambiar según nuestras preferencias.
Inicializa la función del reproductor:

static void Initializationplay(struct Player *play)
{
    
    
	printf("请输入玩家A的姓名\n");
	scanf("%s", &(play[0].name));
	while (!strcmp(play[0].name,""))//判断玩家A的姓名是否为空
	{
    
    
		printf("玩家姓名不能为空,请重新输入玩家A的姓名\n");
		scanf("%s", &(play[0].name));
	}
	printf("请输入玩家B的姓名\n");
	scanf("%s", &(play[1].name));
	while (1)
	{
    
    
		if (!strcmp(play[1].name, ""))//判断玩家B的姓名是否为空
		{
    
    
			printf("玩家姓名不能为空,请重新输入玩家B的姓名\n");
			scanf("%s", &(play[1].name));
		}
		else if(!strcmp(play[1].name, play[0].name))//判断玩家B的姓名和玩家A是否相同
		{
    
    
			printf("玩家姓名不能一致,请重新输入玩家B的姓名\n");
			scanf("%s", &(play[1].name));
		}
		else
		{
    
    
			break;
		}
	}
	play[0].position = 0;//把玩家A的位置置于0位置(地图开始位置)
	play[0].flags = false;//把玩家A的暂停条件置为假。
	play[1].position = 0;//把玩家B的位置置于0位置(地图开始位置)
	play[1].flags = false;//把玩家B的暂停条件置为假。
}

En esta función, hemos realizado una comparación de cadenas. No puede usar directamente == para la comparación de cadenas. Debe usar la función strcmp
para mostrar la función de mapa:

extern char Drawstrmap(const struct Player* play, int i);//对Drawstrmap函数进行声明
static void Ptintinitialization(const struct Player* play) //打印棋盘
//由于不会对玩家信息进行更改,我们把参数设置为const,防止在函数中误改
{
    
    
		printf("图例:幸运轮盘:#    地雷:@    暂停:I     时空隧道:>     \n");//向玩家展示道具信息
		//第一段
		for (int i = 0; i < 30; i++)
		{
    
    
			printf("%c ", Drawstrmap(play, i));
		}
		printf("\n");
		//第一竖列
		for (int i = 30; i < 35; i++)
		{
    
    
			for (int j = 0; j <= 28; j++)
			{
    
    
				printf("  ");
			}
			printf("%c ", Drawstrmap(play, i));
			printf("\n");
		}
		//第二段
		for (int i = 64; i >= 35; i--)//地图为从前向后打打印
		{
    
    
			printf("%c ", Drawstrmap(play, i));
		}
		printf("\n");
		//第二数列
		for (int i = 65; i <= 69; i++)
		{
    
    
			printf("%c ", Drawstrmap(play, i));
			printf("\n");
		}
	    //第三行竖列
		for (int i = 70; i <= 99; i++)
		{
    
    
			printf("%c ", Drawstrmap(play, i));
		}
		printf("\n");//画完地图换行
}

static char Drawstrmap(const struct Player* play, int i)//打印地图元素
{
    
    
	char ch;
	if (play[0].position == play[1].position && play[0].position == i)
	//当玩家1和玩家2的位置处于起始位置时
	{
    
    
		ch = 'M';
	}
	else if (play[0].position == i)//当玩家1位于当前位置时
	{
    
    
		ch = 'A';
	}
	else if (play[1].position == i)//当玩家2位于当前位置时
	{
    
    
		ch = 'B';
	}
	else
	{
    
    
		switch (map[i])
		{
    
    
		case 0://地图数组元素为0时
			ch = 'O';
			break;
		case 1:
			ch = '#';
			break;
		case 2:
			ch = '@';
			break;
		case 3:
			ch = 'I';
			break;
		case 4:
			ch = '>';
			break;
		}
	}
	return ch;
}

inserte la descripción de la imagen aquí
Aquí construimos una función Drawstrmap, el propósito es construir los elementos enteros en la matriz del mapa en los elementos de caracteres que necesitamos, pasamos la ubicación del mapa para determinar qué caracteres imprimir y no cambiamos nuestra matriz del mapa.
Función de reproducción:

static void Play(struct Player *play1, struct Player* play2, struct Player* play)
//play1为当前玩家,play2为另一名玩家,play为玩家数组,传玩家数组方便进行位置判断
{
    
    
	int points = rand() % 6 + 1;//设置随机变量,范围为1~6
	printf("%s请按任意键开始致筛子\n", play1->name);
	system("pause");//暂停屏幕
	printf("%s筛到了%d,前进%d格,", play1->name, points, points);
	system("pause");
	play1->position += points;//对玩家位置进行更新
	Weizhi(play);//判断玩家位置是否在合法的范围内
	if (play1->position == play2->position)//现在玩家的位置和另一名玩家位置相同时
	{
    
    
		printf("%s踩到了%s,%s退6格,", play1->name, play2->name, play2->name);
		system("pause");
		play2->position -= 6;//对另一名玩家位置进行更新
		Weizhi(play);//判断玩家位置是否在合法的范围内
		printf("%s已退6格,", play2->name);
		system("pause");
	}
	else
	{
    
    
		switch (map[play1->position])//检查本位玩家是否进行到道具位置
		{
    
    
		case 0:
			printf("%s踩到了方块,安全,", play1->name);
			system("pause");
			break;
		case 1:
		{
    
    
			printf("%s踩到了幸运转盘,1————交换位置,2————轰炸对方,请选择按键\n", play1->name);
			int a = 0;//用来接收用户的选择
			scanf("%d", &a);
			while (1)
			{
    
    
				if (a == 1)
				{
    
    
					printf("%s选择了交换位置,", play1->name);
					system("pause");
					int b = play1->position;
					play1->position = play2->position;
					play2->position = b;
					Weizhi(play);//判断玩家位置是否在合法的范围内
					printf("交换完成,");
					system("pause");
					break;
				}
				else if (a == 2)
				{
    
    
					printf("%s选择了轰炸对方,%s向后退6格,", play1->name, play2->name);
					system("pause");
					play2->position -= 6;
					Weizhi(play);
					printf("执行成功,\n");
					system("pause");
					break;
				}
				else
				{
    
    
					printf("输入不正确,请重新输入");
					int ch;
					while ((ch = fgetc(stdin)) != EOF && ch != '\n');
					//清除缓冲区,防止缓冲区问题使程序不能正常进行
					scanf("%d", &a);
				}
			}
		}
			break;
		case 2:
			printf("%s踩到了地雷,退6格,", play1->name);
			system("pause");
			play1->position -= 6;
			Weizhi(play);
			break;
		case 3:
			printf("%s踩到了暂停,下一回合禁止行动", play1->name);
			system("pause");
			play1->flags = true;
			break;
		case 4:
			printf("%s踩到了时空隧道,前进十格", play1->name);
			system("pause");
			play1->position += 10;
			Weizhi(play);
			break;
		}
	}
	Weizhi(play);
	system("cls");//清除屏幕
}

Simulamos el tamiz y usamos accesorios en la función de juego. Configuramos el búfer claro para resolver el problema del búfer de la función scanf y evitar un bucle infinito.
Nota:
matriz fuera de los límites. Queremos asegurarnos de que la posición de cada jugador esté dentro del mapa.
Ideas para
la reconstrucción de la comparación de cadenas: 1. Puede unirse a la red para realizar batallas en línea 2. Encapsular por separado la ruleta de la suerte en una función. 3. Agregue más accesorios. 4. Únete a otros jugadores. Se pueden agregar 5 puntos y los puntos se pueden cambiar por accesorios.

Resumir

Nuestros cinco minijuegos están listos. Los siguientes son puntos a tener en cuenta al hacer juegos pequeños:
La función scanf no es segura. Podemos encontrar una función segura para reemplazarla, o resolver el problema de seguridad de scanf.
Escriba arreglos, así como arreglos enteros, tenga cuidado con los arreglos. fuera de los límites y preste atención a los parámetros de la matriz.
Construya códigos de uso frecuente como funciones para reducir la redundancia de código.

Supongo que te gusta

Origin blog.csdn.net/2301_76986069/article/details/130986103
Recomendado
Clasificación