On the simple realization of Sanzi chess game and the method of judging the victory of N-zi chess

Keywords: C Back-end

On the simple realization of Sanzi chess game and the method of judging the victory of N-zi chess

To realize the Sanzi chess game, the following requirements need to be realized: >

  • We need a chessboard. Since we need a chessboard, the chessboard is on a plane, so we need to create a two-dimensional array
  • Printing of chessboard
  • Players play chess with computers
  • Judge victory

Because in writing the Sanzi game, I divided two files, one is game.c and the other is test.c. game.c is mainly the implementation part of the game, and test.c is the main function test part,

And the corresponding game.h file is given to realize the definition of each declaration and identifier constant of the function.

game.h is given here to better understand the meaning of each identifier

#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);

char IsWin(char board[ROW][COL], int row, int col);

The following is the code content of test.c file:

#define _CRT_SECURE_NO_WARNINGS 1

#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];//? NO,we can't do it, because we are so hard to change relveant value;
	//First initialize the chessboard
	InitBoard(board, ROW, COL);
	//Next is printing the chessboard
	Displayboard(board, ROW, COL);
	//Next, players
	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("Player wins\n");
	}
	else if (ret == '#')
	{
		printf("Computer win\n");
	}
	else
	{
		printf("it ends in a draw\n");
	}
}


void test()
{
	int input = 0;
	do
	{
		menu();
		printf("Please select a number:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("Exit program\n");
			break;
		default:
			printf("Input error, please re-enter\n");
			break;
		}
	} while (input);

}

int main()
{
	srand((unsigned int)time(NULL));
	test();
	return 0;
}

Next, the code content of the game.c file:

#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;
	int 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 x = 0;
	int y = 0;
	while (1)
	{
		printf("Player down:>");
		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] = '*';
				break;
			}
			else
			{
				printf("This coordinate is occupied, please re-enter\n");
			}
		}
		else
		{
			printf("This coordinate is illegal, please re-enter\n");
		}
	}
}


void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("Under the computer:>\n");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}


int IsFull(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 1;
		}
	}
	return 0;
}



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][1] != ' ')
		{
			return board[i][1];
		}
	}
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
			return board[1][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[1][3] && board[1][1] != ' ')
	{
		return board[1][1];
	}
	int ret = IsFull(board, row, col);
	if (1 == ret)
	{
		return 'C';
	}
	else
	{
		return 'E';
	}
}

The first is the content in test.c:

The test function here is to store a function we want to implement that allows players to enter numbers to judge whether they enter the game. The srand function here is a prerequisite for computer chess in the following:

So now we come to our test function

First, the usual print menu function prompts the following players what to choose:

This is the result of the operation

Now that you have been prompted, you have to enter something next? Therefore, the scanf and do... While loops in the above figure are to adapt our choices, because the game is executed at least once. When you enter 1, you enter the game. After the game is over, while judges that the input is true and can re-enter the number. When the input is 0, the do... While loop is determined to be false. Directly exit the loop, exit the program, and re-enter when input enters other values. Now let's enter a few numbers to see the effect: (the game function in the figure below temporarily uses printf ("three piece chess game") instead.

Next, it's the game function, which is also the most important part today. Internally, we will realize the functions of Sanzi game through various functions. Let's look at the code first:

At first, the idea was to create a two-dimensional array first, right

But is it inappropriate to place the number three directly in the ROW and column? In case we want to play Gobang or even cross one day, we need to change the variables related to it one by one. Therefore, it is not appropriate here. Therefore, we define two identifier constants ROW and COL in game.h, which are rows and columns respectively, so that we can only change the values of ROW and COL each time (don't forget to include the header file)

After the array is defined, we need to initialize it. We write an Initboard function to implement it. First, let's see what the constructed three-dimensional chess board looks like.

The horizontal and vertical lines next to us are our decorations. It is obvious that we initialize each value of the array as a space, which is also for the later chess.

After writing an Initboard function, we declare it in game.h and define it in game.c

After initialization, we can print the chessboard. Before printing the chessboard, we divide the chessboard into two parts and print them respectively, as shown below

Divide% c | into one group and - | into another group for printing, and - | only print two groups, that is, row-1 group

Therefore, we write the Displayboard function like this

Why should we add if (J < col-1) condition in the first for loop in the inner layer? Because when we print |, each line only needs col-1, and here each line is 2 |. If you don't believe it, you can look at the figure of the Gobang at the top below. Similarly, the second for loop in the inner layer is the same, just print - | before the row-1 line. Please see the figure below

(figure from previous analysis)**

**After such processing, the result of program operation is:

We successfully printed it out.

Now that we have a chessboard, we have to play chess next. Let's write a PlayerMove function to implement it. Since it's playing chess, we can't just play it once, so we also need to write a loop

As shown in the figure below

Next, the implementation of the PlayerMove function

Here we set the character of the player playing chess as. If the player plays chess successfully, he will directly jump out of the cycle and do not need to continue. If the player loses wrong, he can re-enter. Why do we use board[x-1]y-1] is assigned as, because the subscript of the array starts from 0, but players generally think that the first row is the first row. Therefore, the actual coordinates are obtained than the input coordinates of - 1. Now let's see the effect**

Now that the player has finished playing, it should be the computer's turn. Here, we write a ComputerMove function to realize computer chess, as shown below

For x and y here, we let them generate 0 ~ 2 random values, which can correspond to the subscript of each element of the array. When the value corresponding to the following table of the array is a space, it is assigned as' #; directly jump out of the loop.

After the player finishes playing with the computer, we need to judge whether he wins. Therefore, we write the IsWin function to judge whether he wins. If he wins, we return the character playing chess at this time. If there is a draw, we return the character 'E'. If there is no draw or victory, we return the character 'C', which means that the game continues. The following is the specific implementation method of the IsWin function.

Here, after judging whether the diagonal elements of each row and column are the same, if they are different, it may be a draw. Therefore, we wrote an IsFull function to judge whether there are spaces in the chessboard. If there are spaces, it proves that there is no draw. Then we return 'C', otherwise, return 'E', which represents a draw. The implementation method of IsFull function:

The result of running is:

Here are some ways to improve the program:

In judging the victory, we actually wrote the program dead, that is, we can only judge the victory of Sanzi. Now I want to change the value to play Gobang, so in fact, this program can no longer be used. Therefore, I have the following thoughts on the judgment of victory: that is, calculate the total number of lines, columns and diagonals where the characters at that position are located

Now I'll draw a picture to show it

Next, make changes to the code

Because we have to judge every time we play chess, we can simply judge directly in chess. The program changes are as follows:

Change PlayerMove and ComputerMove to functions with return value types

IsWin function is added after ComputerMove and PlayerMove

The IsWin function implements what we just said to judge the winner by adding. Let's focus on how to implement it:

char IsWin(char board[ROW][COL], int x, int y)
{
	int total = 1;
	int i = 0;
	int j = 0;
	//Judge whether the number of elements in a row is 3
	for (i = y+1; i <= COL - 1; i++)
	{
		if (board[x][i] == board[x][y])
		{
			total++;
		}
	}
	for (i = y - 1; i >= 0; i--)
	{
		if (board[x][i] == board[x][y])
		{
			total++;
		}
	}
	if (total == ROW)
	{
		return board[x][y];
	}
	//Judge a column
	total = 1;
	for (i = x + 1; i <= ROW - 1; i++)
	{
		if (board[i][y] == board[x][y])
			total++;
	}
	for (i = x - 1; i >= 0; i--)
	{
		if (board[i][y] == board[x][y])
			total++;
	}
	if (total == COL)
	{
		return board[x][y];
	}
	total = 1;
	//Judge diagonal
	for (i = x - 1, j = y + 1; i >= 0 && j <= COL - 1; i--, j++)
	{
		if (board[i][j] == board[x][y])
			total++;
	}
	for (i = x +1, j = y -1; i<=ROW-1&&j>=0; i++,j--)
	{
		if (board[i][j] == board[x][y])
			total++;
	}
	if (total == COL)
	{
		return board[x][y];
	}
	total = 1;
	for (i = x - 1, j = y - 1; i >= 0 && j >= 0; i--, j--)
	{
		if (board[i][j] == board[x][y])
			total++;
	}
	for (i = x + 1, j = x + 1; i <= ROW - 1 && j <= COL - 1; i++, j++)
	{
		if (board[i][j] == board[x][y])
			total++;
	}
	if (total == COL)
	{
		return board[x][y];
	}
	int rec = IsFull(board,ROW,COL);
	if (rec == 1)
	{
		return 'E';
	}
	else
	{
		return 'C';
	}
}

Here is the judgment line. We pass the coordinates of the point where we play chess as parameter values, judge the same number of elements on the left and right, and define a variable total. In order to calculate the same number of elements, the chess we have played is also counted as 1 of the same number of elements, so it is assigned as 1,

The number of judgment columns is the same as above, as shown below

When judging the diagonal, there are two cases of the diagonal, which we need to consider separately. The first case is like this

There is another case:

Therefore, we can write the code of the same element and diagonal, but don't forget the IsFull function to judge the draw and continue. Just follow it directly

In this way, it will be written smoothly. Now let's take a look at the effect of Gobang

The end of this article.

Posted by rex9990 on Mon, 08 Nov 2021 12:23:32 -0800