[C Language] C Language Series - Implementation of Gobang

A backgammon program can be divided into four parts. The first part is the creation of the header file, which allows our functions to be well encapsulated. There are two details to pay attention to: one is to use define in the header file to define lines and Columns, so that when we want to make changes to rows and columns in the future, we only need to change this place of define. The second is to include stdio.h time.h and other header files in the game.h header file to avoid repeated inclusion.

The second part is the implementation of the test.c function logic, which contains the basic logic required to realize the game, including the printing of the menu, the initialization of the chessboard, the printing of the chessboard, the player and the computer playing chess, and the judgment of the game state.

The third part is the implementation of game-related functions. The front is the description of each specific function of the game, and the back is the general code.

The fourth part is the display of game effects. 

Part V: The overall implementation code of the game 

first part:

Contents of header files--declaration of game-related functions, declaration of symbols, inclusion of header files

#pragma once

//game.h  游戏相关函数的声明、符号的声明、头文件的包含

//符号的声明
#define ROW 5
#define COL 5

//头文件的包含
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

//函数的声明
//初始化棋盘
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);

//判断输赢
//游戏状态:*:玩家赢
//          #:电脑赢
//          Q:平局
//          C:游戏继续
char IsWin(char board[ROW][COL], int row, int col);

Part 2 - The logic of the mapping game test.c  

#define _CRT_SECURE_NO_WARNINGS 1

//test.c  测绘游戏的逻辑
//game.c  游戏相关函数的实现
//game.h  游戏相关函数的声明、符号的声明、头文件的包含
#define _CRT_SECURE_NO_WARNINGS 1    //解决VS中scanf不安全问题
#include"game.h"                     //自己创建的头文件用双引号
void menu()                          //菜单的实现
{
	printf("1.play\n");
	printf("0.exit\n");
}
void game()                          //游戏实现部分
{
	//定义数组--存储数据
	char board[ROW][COL] = { 0 };
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	char ret;      //判断游戏状态
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);   //判断游戏输赢
		if (ret != 'C')
			break;   
		//电脑下棋
		ComputerMove(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");
}
int main()
{
	int n = 0;
	srand((unsigned int)time(NULL));
	do 
	{
		menu();
		printf("请选择:->");
		scanf("%d", &n);
		switch (n)
		{
		case 1:game(); break;
		case 0:printf("退出游戏"); break;
		default:printf("选择错误,重新选择\n");
		}
	} while (n);
	return 0;
}

The third part - the implementation of game-related functions game.c

1. Checkerboard initialization (essentially array initialization)

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

2. Print the chessboard

//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0;
	for (i = 0; i < row; i++)           //打印每一行的的空格和竖线
	{
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		if (i < row - 1)
		{
			for (j = 0; j < col; j++)         //打印横线和竖线
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}

3. The player plays chess - it is necessary to judge whether the coordinates entered by the player are legal and whether the coordinates are occupied

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int m = 0, n = 0;
	printf("玩家走\n");

	while (1)              //如果坐标违法就重新输入
	{
		printf("请输入坐标->:");
		scanf("%d%d", &m, &n);
		//判断坐标合法性
		if (m <= ROW && m >= 1 && n <= COL && n >= 1)
		{
			//判断坐标是否被占用
			if (board[m - 1][n - 1] == ' ')     //玩家不知道数组下标从零开始,输入是从(1 1)开始的,所以要减一
			{
				board[m - 1][n - 1] = '*';
				break;
			}
			else
				printf("坐标被占用,请重新输入\n");
		}
		else
			printf("坐标非法,请重新输入\n");
	}
}

4. The computer plays chess --To let the computer generate a random coordinate within the range of the array, the random function value generation function rand() is used. At the same time, in order to ensure the randomness of the value, a seed needs to be set for it. Determine whether the coordinates are occupied.

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	int m = 0, n = 0;
	printf("电脑走\n");
	while (1)
	{
		m = rand() % row;
		n = rand() % col;
		//判断坐标是否被占用
		if (board[m][n] == ' ')
		{
			board[m][n] = '#';
			break;
		}
	}
}

5. Determine the state of the game -- :*: The player wins              

                                     #: Computer wins
                                     Q: Draw
                                     C: Game continues

//判断输赢
char IsWin(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1]
			&& board[i][1] == board[i][2]
			&& board[i][2] == board[i][3]
			&& board[i][3] == board[i][4]
			&& board[i][4] != ' ')
			return board[i][1];
	}
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i]
			&& board[0][i] == board[1][i]
			&& board[1][i] == board[2][i]
			&& board[2][i] == board[3][i]
			&& board[3][i] == board[4][i]
			&& board[4][i] != ' ')
			return board[1][i];
	}
	if (board[0][0] == board[1][1]
		&& board[1][1] == board[2][2]
		&& board[2][2] == board[3][3]
		&& board[3][3] == board[4][4]
		&& board[4][4] != ' ')
		return board[0][0];
	if (board[0][4] == board[1][1]
		&& board[1][1] == board[2][2]
		&& board[2][2] == board[3][3]
		&& board[3][3] == board[4][4]
		&& board[4][4] != ' ')
		return board[0][0];
	int ret = IsFull(board, row, col);
	if (ret)
		return 'Q';
	return 'C';
}

6. Judging the game state -- judging whether the board is full

in//判断棋盘是否满了
int IsFull(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0, flag = 1;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
			if (board[i][j] == ' ')

				flag = 0;
	}
	return flag;
}

7. The overall implementation of game.c

#define _CRT_SECURE_NO_WARNINGS 1

//game.c  游戏相关函数的实现
#include"game.h"

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

//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0;
	for (i = 0; i < row; i++)           //打印每一行的的空格和竖线
	{
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		if (i < row - 1)
		{
			for (j = 0; j < col; j++)         //打印横线和竖线
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int m = 0, n = 0;
	printf("玩家走\n");

	while (1)              //如果坐标违法就重新输入
	{
		printf("请输入坐标->:");
		scanf("%d%d", &m, &n);
		//判断坐标合法性
		if (m <= ROW && m >= 1 && n <= COL && n >= 1)
		{
			//判断坐标是否被占用
			if (board[m - 1][n - 1] == ' ')     //玩家不知道数组下标从零开始,输入是从(1 1)开始的,所以要减一
			{
				board[m - 1][n - 1] = '*';
				break;
			}
			else
				printf("坐标被占用,请重新输入\n");
		}
		else
			printf("坐标非法,请重新输入\n");
	}
}

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	int m = 0, n = 0;
	printf("电脑走\n");
	while (1)
	{
		m = rand() % row;
		n = rand() % col;
		//判断坐标是否被占用
		if (board[m][n] == ' ')
		{
			board[m][n] = '#';
			break;
		}
	}
}

//判断棋盘是否满了
int IsFull(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0, flag = 1;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
			if (board[i][j] == ' ')

				flag = 0;
	}
	return flag;
}

//判断输赢
char IsWin(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1]
			&& board[i][1] == board[i][2]
			&& board[i][2] == board[i][3]
			&& board[i][3] == board[i][4]
			&& board[i][4] != ' ')
			return board[i][1];
	}
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i]
			&& board[0][i] == board[1][i]
			&& board[1][i] == board[2][i]
			&& board[2][i] == board[3][i]
			&& board[3][i] == board[4][i]
			&& board[4][i] != ' ')
			return board[1][i];
	}
	if (board[0][0] == board[1][1]
		&& board[1][1] == board[2][2]
		&& board[2][2] == board[3][3]
		&& board[3][3] == board[4][4]
		&& board[4][4] != ' ')
		return board[0][0];
	if (board[0][4] == board[1][1]
		&& board[1][1] == board[2][2]
		&& board[2][2] == board[3][3]
		&& board[3][3] == board[4][4]
		&& board[4][4] != ' ')
		return board[0][0];
	int ret = IsFull(board, row, col);
	if (ret)
		return 'Q';
	return 'C';
}

Part 4 - Game Effects

1. The effect of the menu

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWy5Luj56CB55qE6aKc,size_20,color_FFFFFF,t_70,g_se,x_16

2. The effect of initializing the chessboard

911012b94d6546b59148f178781961a1.png

 3. The effect of the game

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWy5Luj56CB55qE6aKc,size_8,color_FFFFFF,t_70,g_se,x_16

4. The effect of game over

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWy5Luj56CB55qE6aKc,size_8,color_FFFFFF,t_70,g_se,x_16

The fifth part: the overall implementation code of the game.

game.h

#pragma once

//game.h  游戏相关函数的声明、符号的声明、头文件的包含

//符号的声明
#define ROW 5
#define COL 5

//头文件的包含
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

//函数的声明
//初始化棋盘
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);

//判断输赢
//游戏状态:*:玩家赢
//          #:电脑赢
//          Q:平局
//          C:游戏继续
char IsWin(char board[ROW][COL], int row, int col);

 test.c

#define _CRT_SECURE_NO_WARNINGS 1

//test.c  测绘游戏的逻辑
//game.c  游戏相关函数的实现
//game.h  游戏相关函数的声明、符号的声明、头文件的包含
#define _CRT_SECURE_NO_WARNINGS 1    //解决VS中scanf不安全问题
#include"game.h"                     //自己创建的头文件用双引号
void menu()                          //菜单的实现
{
	printf("1.play\n");
	printf("0.exit\n");
}
void game()                          //游戏实现部分
{
	//定义数组--存储数据
	char board[ROW][COL] = { 0 };
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	char ret;      //判断游戏状态
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);   //判断游戏输赢
		if (ret != 'C')
			break;   
		//电脑下棋
		ComputerMove(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");
}
int main()
{
	int n = 0;
	srand((unsigned int)time(NULL));
	do 
	{
		menu();
		printf("请选择:->");
		scanf("%d", &n);
		switch (n)
		{
		case 1:game(); break;
		case 0:printf("退出游戏"); break;
		default:printf("选择错误,重新选择\n");
		}
	} while (n);
	return 0;
}

 game.c

#define _CRT_SECURE_NO_WARNINGS 1

//game.c  游戏相关函数的实现
#include"game.h"

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

//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0;
	for (i = 0; i < row; i++)           //打印每一行的的空格和竖线
	{
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		if (i < row - 1)
		{
			for (j = 0; j < col; j++)         //打印横线和竖线
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int m = 0, n = 0;
	printf("玩家走\n");

	while (1)              //如果坐标违法就重新输入
	{
		printf("请输入坐标->:");
		scanf("%d%d", &m, &n);
		//判断坐标合法性
		if (m <= ROW && m >= 1 && n <= COL && n >= 1)
		{
			//判断坐标是否被占用
			if (board[m - 1][n - 1] == ' ')     //玩家不知道数组下标从零开始,输入是从(1 1)开始的,所以要减一
			{
				board[m - 1][n - 1] = '*';
				break;
			}
			else
				printf("坐标被占用,请重新输入\n");
		}
		else
			printf("坐标非法,请重新输入\n");
	}
}

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
	int m = 0, n = 0;
	printf("电脑走\n");
	while (1)
	{
		m = rand() % row;
		n = rand() % col;
		//判断坐标是否被占用
		if (board[m][n] == ' ')
		{
			board[m][n] = '#';
			break;
		}
	}
}

//判断棋盘是否满了
int IsFull(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0, flag = 1;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
			if (board[i][j] == ' ')

				flag = 0;
	}
	return flag;
}

//判断输赢
char IsWin(char board[ROW][COL], int row, int col)
{
	int i = 0, j = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1]
			&& board[i][1] == board[i][2]
			&& board[i][2] == board[i][3]
			&& board[i][3] == board[i][4]
			&& board[i][4] != ' ')
			return board[i][1];
	}
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i]
			&& board[0][i] == board[1][i]
			&& board[1][i] == board[2][i]
			&& board[2][i] == board[3][i]
			&& board[3][i] == board[4][i]
			&& board[4][i] != ' ')
			return board[1][i];
	}
	if (board[0][0] == board[1][1]
		&& board[1][1] == board[2][2]
		&& board[2][2] == board[3][3]
		&& board[3][3] == board[4][4]
		&& board[4][4] != ' ')
		return board[0][0];
	if (board[0][4] == board[1][1]
		&& board[1][1] == board[2][2]
		&& board[2][2] == board[3][3]
		&& board[3][3] == board[4][4]
		&& board[4][4] != ' ')
		return board[0][0];
	int ret = IsFull(board, row, col);
	if (ret)
		return 'Q';
	return 'C';
}

Guess you like

Origin blog.csdn.net/m0_62391199/article/details/122540210