【C/C++】Los ejercicios de tres golpes son simples y fáciles de entender


prefacio

La práctica del ajedrez de las tres lunas es usar y probar el conocimiento aprendido anteriormente. El ajedrez de las tres lunas aquí necesita encapsular la función en una función funcional, porque el código del ajedrez de las tres lunas es largo y ciertamente no se puede colocar en la función principal. Si todo está colocado en la función principal El código de la función principal es difícil de reutilizar y la legibilidad no es buena.
Siempre que la función se encapsule en una función de función, la legibilidad del código también mejorará, porque siempre que agregue un comentario antes de la función, puede encontrar fácilmente la función que necesita y también se puede reutilizar.


1. Idea general

需要完成的效果图
inserte la descripción de la imagen aquí

接下来介绍一下需要完成的功能

这里打错字了为了节省时间暂时先不改,
Ejemplo: pandas es una herramienta basada en NumPy creada para resolver tareas de análisis de datos.

Pensemos primero en el proceso de producción general.
El primer paso es imprimir el inicio y el final del juego. Es concebible que este paso sea imprimir directamente con printf.

En el segundo paso, debe completar el efecto de seleccionar el inicio, y aquí puede usar el interruptor para completar el efecto de la selección.

El tercer paso es imprimir el tablero de ajedrez. Observe primero el tablero de ajedrez. Hay tres caracteres en el tablero de ajedrez: espacios, delimitadores y barras. Solo necesita usar un bucle de varias capas para lograrlo. Tiene que probarlo usted mismo.
El cuarto paso requiere interacción humano-computadora Aquí, la función de interacción humano-computadora se puede dividir en dos funciones funcionales.
El quinto paso se implementa con la función de biblioteca de entrada de uso común scanf.

这里在补充一点,人机交互肯定是需要重复执行,所以这里直接用死循环


Dos, el archivo de encabezado

头文件比较重要还是单独拿出来讲解

¿Qué es un archivo de encabezado? Según tengo entendido, hay varios archivos de origen en un proyecto. Por ejemplo, el archivo A y el archivo B existen de forma independiente. Si el archivo A quiere llamar a la función del archivo B, debe estar en el archivo de encabezado. Es suficiente declarar en el archivo la función del archivo B. Después de todo, el archivo de encabezado es para hacer que los dos archivos fuente independientes estén directamente relacionados.

三子棋头文件完整代码

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

//符合定义
#define ROW 3
#define COL 3

//函数声明  
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void playerMove(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);


//判断输赢
//玩家 - 'x'
//电脑赢 - '#'
//平局 - 'Q'
//继续 - 'C'
char IsWin(char board[ROW][COL], int row, int col);


3. Proceso de implementación

说了这么还是得动手实操,来跟我一起深入浅出的学习吧!

1. El primer paso

文件目录

El archivo de encabezado game.h se usa para declarar la
implementación de la función game.c. La función del juego
prueba el cuerpo principal del juego y llama a game.c desde este.

以上后面会细讲

inserte la descripción de la imagen aquí


这里是函数主体布局完整代码,我会分几步讲解

El código es el siguiente (ejemplo):

int main()
{
    
    
	int input = 0;
	do					
	{
    
    
		menu();			//开始界面打印
		printf("请选择>");
		scanf("%d", &input);	//输入坐标
		switch (input)			//开始与结束选项
		{
    
    
			case 1:
				printf("三子棋游戏\n");
				game();		//三子棋内部的实现
				break;
			case 0:
				printf("退出游戏\n");
				
			default:
				printf("选择错误,请重新输入\n");
				break;
		}
	} while (input);

		return 0;
}

打印开始界面其实很简单用printf就能实现。


1.0, instrucciones complementarias do-while

Aquí hay una explicación complementaria para aquellos que no están familiarizados con el bucle do-while: Para esta persona, soy yo . do-while se ejecuta primero en el juicio, y el resultado del juicio es falso y termina directamente, por lo que es muy adecuado ejecutar do-while aquí.

do
{
    
    

}
while();

1.1, menú ()

开始界面打印
El código es el siguiente (ejemplo):

void menu()
{
    
    
	printf("*********************************\n");
	printf("*********   1.play   ************\n");
	printf("*********   0.exit   ************\n");
	printf("*********************************\n");
}

**打印开始界面其实很简单用printf就能实现。**


2. La función central de la función de juego Sanbang

1.0 Explicación interna de la función del juego

game()函数是三子棋核心函数

		switch (input)
		{
    
    
			case 1:
				printf("三子棋游戏\n");
				game();		//game()函数是三子棋核心函数
				break;
			case 0:
				printf("退出游戏\n");
				
			default:
				printf("选择错误,请重新输入\n");
				break;
		}

完整game功能函数

void game()
{
    
    
	//存储数据 - 二维数组
	char board[ROW][COL];
	//初始化棋盘 - 初始化
	InitBoard(board, ROW, COL);
	//打印一下棋盘 - 本质是打印数组的内容
	DisplayBoard(board, ROW, COL);
	char ret = 0;
	while (1)
	{
    
    
		//电脑下棋
		ComputerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);

		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;

		//玩家下棋
		playerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);

		//判断输赢
		ret=IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
	}
	if (ret == '*')
		printf("玩家赢!\n");
	else if (ret == '#')
		printf("电脑赢!\n");
	else
		printf("平局!\n");
}

1.1, InitBoard (inicializar la placa)

InitBoard完整代码

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col)
{
    
    
	int i = 0;
	for (i = 0; i< row; i++)
	{
    
    																
		int j = 0;
		for (j = 0; j < col; j++)
		{
    
    
			board[i][j] = ' ';
		}
	}
}

补充#define知识

Las instrucciones de preprocesamiento #define también se denominan definiciones de macro, que pueden definir constantes y las funciones también se pueden definir en profundidad. #define se usa para definir constantes en tres ajedrez

	#define ROW 3
	#define COL 3
	//二维数组用来存储棋盘数据
	char board[ROW][COL];		//这种定义的好处是可以让三子棋变成五子棋
	//初始化棋盘 - 初始化
	InitBoard(board, ROW, COL);			//1.把数组传入,2.初始化棋盘时用循环时肯定需要一个限定值,那就得把行跟列传过去
void InitBoard(char board[ROW][COL], int row, int col)	//函数传参,char board[ROW][COL]这里传了个二维数组,后面的传的就是行跟列
{
    
    
	
	int i = 0;
	for (i = 0; i< row; i++)	//初始化行
	{
    
    																
		int j = 0;
		for (j = 0; j < col; j++)	//初始化列
		{
    
    
			board[i][j] = ' ';		//把初始化的空格传给二维数组
		}
	}
}

1.2, DisplayBoard (imprime el código completo del tablero de ajedrez)

DisplayBoard完整代码

//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
    
    
	int i = 0;
	for (i = 0; i < row; i++)		//遍历行
	{
    
    
		int j = 0;
		for (j = 0; j < col; j++)		//遍历列
		{
    
    
			printf(" %c ", board[i][j]);	//数据的打印,%c两边还有两空格让打印的数据更加美观
			if (j < col - 1)		//
			 	printf("|");
		}
		printf("\n");
		if (i < row - 1)
		{
    
    
			int j = 0;
			for (j = 0; j < col; j++)
			{
    
    
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}

1.2.1 Impresión de datos y delimitadores

Para que el código sea más flexible, primero puede recorrer las filas y columnas e imprimir los datos uno por uno. Aquí, solo necesita cambiar los valores de las filas y columnas para convertir el tablero de ajedrez en un tablero de ajedrez. El orden de impresión aquí es imprimir los datos primero. en imprimir | luego en imprimir—,

for (i = 0; i < row; i++)		//遍历行
	{
    
    
		int j = 0;
		for (j = 0; j < col; j++)		//遍历列
		{
    
    
			printf(" %c ", board[i][j]);	//数据的打印,%c两边还有两空格让打印的数据更加美观
			if (j < col - 1)		//col - 1为了美观行会少打印最后一列
			 	printf("|");
		}
		printf("\n");		//第一行数据跟分隔符打印完换行
		if (i < row - 1)		//少打印最后一行---
		{
    
    
			int j = 0;
			for (j = 0; j < col; j++)		//换行后在打印---
			{
    
    
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}

1.3, playerMove (jugador jugando al ajedrez)

playerMove完整代码


//玩家下棋
void playerMove(char board[ROW][COL], int row, int col)
{
    
    
	//定义x,y坐标
	int x = 0;	
	int y = 0;
	printf("玩家走:>\n");

	while (1)		//死循环
	{
    
    
		printf("请输入下棋坐标:>");
		scanf("%d %d", &x, &y);
		//判断坐标合法
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
    
    
			//下棋
			//坐标是否被占用
			if (board[x - 1][y - 1] == ' ')		//数组下标是从0开始计算,正常人思维是从1开始计算,所以要-1
			{
    
    
				//x-1是之前x>1判断坐标是否被占用
				//玩家下棋
				board[x - 1][y - 1] = '*';
				break;		//下完一次退出
			}
			else
			{
    
    
				printf("坐标被占用,请重新输入\n");
			}
		}
		else
		{
    
    
			printf("坐标非法,请重新输入\n");
		}
	}
	
}

1.4, ComputerMove (ajedrez por computadora)

ComputerMove完整代码

//电脑随机下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
    
    
	int x = 0;
	int y = 0;

	printf("电脑下棋:>\n");
	//给电脑随机下棋坐标
	while (1)
	{
    
    
		//电脑自动下棋核心部分
		x = rand() % row;		//限制电脑x的坐标,假如row值为3,行随机范围为0-3,y同理
		y = rand() % col;

		if (board[x][y] == ' ')		
		{
    
    
			board[x][y] = '#';
			break;
		}
	}
	
}

1.5 Juzgar ganar o perder en base a los puntos más difíciles

Gana o pierde
jugador - 'x'
computadora gana - '#'
empate - 'Q'
continuar - 'C'

IsWin完整代码

//判断输赢
char IsWin(char board[ROW][COL], int row, int col)
{
    
    
	//赢
	//行
	int i = 0;
	for (i = 0; i < row; i++)
	{
    
    
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
		{
    
    
			return board[i][0];
		}
	}
	//列
	for (i = 0; i < row; i++)
	{
    
    
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
		{
    
    
			return board[0][i];

		}
	}
	//对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	if(board[0][2] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	//平局

	if (IsFull(board, row, col)==1)
	{
    
    
		return 'Q';
	}
	//继续
	return 'C';
}

1.5.1, fila

加张图有利于理解
inserte la descripción de la imagen aquí

Use un bucle para atravesar cada línea de ajedrez, y no puede ser igual a un espacio

//行
	int i = 0;
	for (i = 0; i < row; i++)
	{
    
    
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
		{
    
    
			return board[i][0];		//返回第一列遍历每行的值
		}
	}
	

1.5.2, columnas

加张图有利于理解
inserte la descripción de la imagen aquí

跟行同理

//列
	for (i = 0; i < row; i++)
	{
    
    
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
		{
    
    
			return board[0][i];

		}
	}
	

1.5.3, diagonales

加张图有利于理解
inserte la descripción de la imagen aquí

//对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];
	if(board[0][2] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
		return board[1][1];

1.5.4 Dibujar

棋盘下完返回Q

if (IsFull(board, row, col)==1)
	{
    
    
		return 'Q';
	}

IsFull完整代码

Si el tablero está vacío, devuelve 0, si el tablero está lleno, devuelve 1

int IsFull(char board[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 (board[i][j]==' ')
			{
    
    
				return 0;
			}
		}
	}
	return 1;
}

1.5.5, continuar

Ninguno de los casos anteriores devuelve directamente C

//继续
	return 'C';

Tercero, la llamada anidada de la función final.

El orden de los jugadores que juegan al ajedrez se puede invertir, y la impresión final de ganadores y perdedores se puede colocar fuera del ciclo while, por lo que no es necesario imprimir repetidamente.

char ret = 0;
	while (1)
	{
    
    
		//电脑下棋
		ComputerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);

		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')		//只要不等于C结束游戏
			break;

		//玩家下棋
		playerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);

		//判断输赢
		ret=IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
	}
	if (ret == '*')
		printf("玩家赢!\n");
	else if (ret == '#')
		printf("电脑赢!\n");
	else
		printf("平局!\n");

Resumir

El código de ajedrez de tres lunas es relativamente largo y la dificultad es moderada. Puede probar el conocimiento aprendido antes. Si hay algo que no se entiende bien, ¡avise!

Hay muchas palabras y hay errores tipográficos, puedes corregirlos en el área de comentarios.

espero ayudarte

Supongo que te gusta

Origin blog.csdn.net/m0_66977204/article/details/130590384
Recomendado
Clasificación