C language classic game of three chess (super detailed explanation + source code)

"Even if there is a strong wind, you will never give up in life. When the wind blows, you should strive for this life." Today, let's learn how to write a small game of backgammon in C language?

1. Introduction to game rules

"Sanziqi" is an ancient traditional folk game, also known as Reversi, Circle Chacha, Tic Tac Toe, One Dragon, Jiugong Chess, etc. The game is divided into two sides to play against each other. Both sides place pieces on the 9-grid chessboard in turn, and the side that first connects its three pieces into a line is regarded as the winner.
insert image description here

2. Game preparation

Here, we need to prepare three source files, which are test.c game.c game.h(the name is arbitrary, it is better to be as simple as possible). There may be doubts. Why do we need three source files here? Will it seem troublesome? In the previous study, we also mentioned that there will be more codes in the project in the future, and functions are generally declared in .h文件and .c文件implemented in .
Advantages of writing in separate files: 1. Facilitate multi-person collaboration 2. Protect code

Here we will introduce to you what each file does in the game of backgammon.
(1) Header files game.h, which are used to store function declarations, #define constant definitions, and library function references.
(2) Source file test.c, which contains the test logic of the game.
(3) Source file game.c, which contains the implementation logic (function implementation) of the game.

3. Realization of the game

3.1 Generate menu

Here, by switch语句giving the user a choice, when the user enters different numbers, our program will give different functions.

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void menu()//生成菜单的函数
{
    
    
	printf("******************************\n");
	printf("**********  1.play  **********\n");
	printf("**********  0.exit  **********\n");
	printf("******************************\n");
}
void game()//实现玩游戏的函数
{
    
    

}
int main()
{
    
    
	int input = 0;//用户选择
	do//利用循环可以便于用户进行多次游戏
	{
    
    
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
    
    
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("选择错误,重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}

Through the above code, we have built the basic framework:
insert image description here

3.2 The specific implementation of the game

We found that the code of the game implementation part is missing in the above framework code. Here, we are slowly refining the game process.
insert image description here

First of all, we can see that we need to construct a 3*3 chessboard first. Make each of the nine vacancies be in an empty state. Here we think of the concept of a two-dimensional array, let's try it together!

3.2.1 Initialize the chessboard

//game.h
#pragma once
# define ROW 3
# define COL 3
//初始化棋盘的函数的声明
void InitBoard(char board[ROW][COL],int row,int col);

//game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void InitBoard(char board[ROW][COL], int row, int col)//初始化棋盘函数的实现,让每个格子都为空
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
    
    
		for (j = 0; j < col; j++)
		{
    
    
			board[i][j] = ' ';
		}
	}
}

//test.c
void game()
{
    
    
	//最开始的时候数组的内容全是空格
	char board[ROW][COL]; 
	InitBoard(board, ROW, COL);
}

insert image description here

3.2.2 Print chessboard

After initializing the chessboard, we need to print the chessboard to be seen by the user, so we can also use it for循环to complete this step.

//game.h
//打印棋盘的函数声明
void DisplayBoard(char board[ROW][COL], int row, int col);

//game.c
void DisplayBoard(char board[ROW][COL], int row, int col)//打印棋盘函数的实现
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
    
    
		for (j = 0; j < col; j++)
		{
    
    
			printf("%c", board[i][j]);
		}
		printf("\n");
	}
}

//test.c
DisplayBoard(board, ROW, COL);

insert image description here
insert image description here
But we found that there is a large blank here, and the chessboard cannot be seen at all. Why? Because we have initialized the chessboard as a space, obviously we can't see it, and what we want is the appearance of a nine-square grid. Here we can -和|use form our chessboard.

//game.h
//打印棋盘的函数声明
void DisplayBoard(char board[ROW][COL], int row, int col);

//game.c
void DisplayBoard(char board[ROW][COL], int row, int col)//打印棋盘函数的实现
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
    
    
		printf(" %c | %c | %c \n", board[i][0], board[i][1],board[i][2]);
		printf("---|---|---\n");
	}
}

//test.c
DisplayBoard(board, ROW, COL);

However, we found that this chessboard still has shortcomings, and there is an extra line under it, so we need to adjust the loop statement of the for loop.
insert image description here
Here, we give the modified code and the running results:

//game.h
//打印棋盘的函数声明
void DisplayBoard(char board[ROW][COL], int row, int col);

//game.c
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]);
			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");
	}
}

//test.c
DisplayBoard(board, ROW, COL);

insert image description here
In this case, we # define ROW 3 # define COL 3change the size of the chessboard by modifying the value:
insert image description here

3.2.3 Players play chess (players play chess as O)

//game.h
//玩家下棋函数声明
void PlayerMove(char board[ROW][COL], int row, int col);

//game.c
//玩家下棋函数的实现
void PlayerMove(char board[ROW][COL], int row, int col)
{
    
    
	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开始,这里我们需要考虑进去
			{
    
    
				board[x - 1][y - 1] = 'O';
				break;
			}
			else
			{
    
    
				printf("该坐标已被占用,请重新下棋!\n");
			}
		}
		else
		{
    
    
			printf("坐标非法,请重新输入!\n");
		}
	}
}

//test.c
while (1)
	{
    
    
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);//将玩家下棋结果打印出来
	}

insert image description here

3.2.4 Computer chess (computer chess is X)

//game.h
//电脑下棋函数声明
void ComputerMove(char board[ROW][COL], int row, int col);

//game.c
//电脑下棋函数的实现
//电脑随机下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
    
    
	printf("电脑下棋\n");
	int x = 0;
	int y = 0;
	while (1)
	{
    
    
		x = rand() % row;//电脑随机产生坐标
		y = rand() % col;
		if (board[x][y] == ' ')
		{
    
    
			board[x][y] = 'X';
			break;
		}
	}
}

//test.c
while (1)
	{
    
    
		ComputerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);//将玩家下棋结果打印出来
	}

insert image description here
However, we are only thinking about making this game playable here. The computer playing chess just randomly generates some values, and there is no logic in it.

3.2.5 Judging winning or losing

The winning and losing situations are as follows:
1. The player wins - return to O
2. The computer wins - returns to X
3. Draw - returns to Q
4. The game continues - returns to C

//game.h
//判断输赢函数声明
char Is_win(char board[ROW][COL], int row, int col);

//game.c
//判断棋盘是不是满了的函数
static int Is_full(char board[ROW][COL], int row, int col)
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
    
    
		for (j = 0; j < col; j++)
		{
    
    
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}
//判断输赢函数的实现
char Is_win(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 < col; 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][0] && board[1][1] != ' ')//左低右高对角线相等
	{
    
    
		return board[1][1];
	}
	//平局(棋盘满了)
	if (Is_full(board, row, col))
	{
    
    
		return 'Q';
	}
	return 'C';
}

//test.c
if (ret == 'O')
	{
    
    
		printf("玩家赢!\n");
	}
		
	else if (ret == 'X')
	{
    
    
		printf("电脑赢!\n");
	}
	else
	{
    
    
		printf("平局!\n");
	}

insert image description here
insert image description here
insert image description here

3.2.6 Optimization of chessboard

We found that the program can basically run, but would it be better to add the operation of clearing the screen? Here, we can improve it.
Here we need to introduce it system("cls"), and it can realize the operation of clearing the screen!
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here

4. The complete code implementation of the game of backgammon (detailed source code)

game.h文件

#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.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);
//判断输赢函数声明
char Is_win(char board[ROW][COL], int row, int col);

game.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void InitBoard(char board[ROW][COL], int row, int col)//初始化棋盘,让每个格子都为空
{
    
    
	int i = 0;
	int 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;
	for (i = 0; i < row; i++)
	{
    
    
		int j = 0;
		for (j = 0; j < col; j++)
		{
    
    
			printf(" %c ", board[i][j]);
			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");
	}
}
//玩家下棋函数的实现
void PlayerMove(char board[ROW][COL], int row, int col)
{
    
    
	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] == ' ')
			{
    
    
				board[x - 1][y - 1] = 'O';
				break;
			}
			else
			{
    
    
				printf("该坐标已被占用,请重新下棋!\n");
			}
		}
		else
		{
    
    
			printf("坐标非法,请重新输入!\n");
		}
	}
}
//电脑下棋函数的实现
//电脑随机下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
    
    
	printf("电脑下棋\n");
	int x = 0;
	int y = 0;
	while (1)
	{
    
    
		x = rand() % row;//电脑随机产生坐标
		y = rand() % col;
		if (board[x][y] == ' ')
		{
    
    
			board[x][y] = 'X';
			break;
		}
	}
}
//判断棋盘是不是满了的函数
static int Is_full(char board[ROW][COL], int row, int col)
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
    
    
		for (j = 0; j < col; j++)
		{
    
    
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}
//判断输赢函数的实现
char Is_win(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 < col; 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][0] && board[1][1] != ' ')//左低右高对角线相等
	{
    
    
		return board[1][1];
	}
	//平局(棋盘满了)
	if (Is_full(board, row, col))
	{
    
    
		return 'Q';
	}
	return 'C';
}

test.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "game.h"
//创建菜单
void menu()
{
    
    
	printf("******************************\n");
	printf("**********  1.play  **********\n");
	printf("**********  0.exit  **********\n");
	printf("******************************\n");
}
void game()
{
    
    
	char ret = 0;
	//最开始的时候数组的内容全是空格
	char board[ROW][COL]; 
	InitBoard(board, ROW, COL);
	DisplayBoard(board, ROW, COL);
	while (1)
	{
    
    
		PlayerMove(board, ROW, COL);//玩家下棋函数调用
		DisplayBoard(board, ROW, COL);//将玩家下棋结果打印出来
		//判断输赢
		ret = Is_win(board, ROW, COL);
		if (ret != 'C')
		{
    
    
			break;
		}
		system("cls");//清屏
		DisplayBoard(board, ROW, COL);
		ComputerMove(board, ROW, COL);//电脑下棋函数调用
		DisplayBoard(board, ROW, COL);//将电脑下棋结果打印出来
		ret = Is_win(board, ROW, COL);
		if (ret != 'C')
		{
    
    
			break;
		}	
		system("cls");//清屏
		DisplayBoard(board, ROW, COL);
	}
	system("cls");//清屏
	DisplayBoard(board, ROW, COL);
	if (ret == 'O')
	{
    
    
		printf("玩家赢!\n");
	}
		
	else if (ret == 'X')
	{
    
    
		printf("电脑赢!\n");
	}
	else
	{
    
    
		printf("平局!\n");
	}
		
}
int main()
{
    
    
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
    
    
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
    
    
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("选择错误,重新选择!\n");
			break;
		}
	} while (input);
	return 0;
 }

The above is all the code about the game of backgammon! Of course, there is still room for optimization in this program (for example, whether the computer can be more intelligent when playing chess is still to be considered), and everyone is welcome to communicate in the comment area.

Guess you like

Origin blog.csdn.net/qq_73121173/article/details/132089189