Today, I will play a small game of N-sub chess, which can be realized from 3x3,4x4 to NxN
Requirements: be able to play chess according to the input coordinates and judge whether to win or lose
First write out the general framework of the main function:
int main() { int input = 0; srand((unsigned)time(NULL)); do { menu(); printf("Please select:>"); scanf("%d", &input); switch (input) { case 1: { game(); break; } case 0: { printf("Exit the game\n"); break; } default: { printf("Selection error, please re select\n"); break; } } } while (input); return 0; }
srand is set up so that the computer can play chess randomly on the chessboard according to random numbers
1. Menu creation
void menu() { printf("**********************************\n"); printf("*********** 1.The game begins ***********\n"); printf("*********** 0.game over ***********\n"); printf("**********************************\n"); }
2. Preparation of game function
void game() { char out; //Store game internal data char board[ROW][COL]; //Initialize checkerboard (space) InBoard(board, ROW, COL); //Print chessboard PrintBoard(board, ROW, COL); while (1) { //Player action Player(board, ROW, COL); PrintBoard(board, ROW, COL); //Determine whether the game is over out = Win(board, ROW, COL); if (out != 'G') { break; } //Computer action PC(board, ROW, COL); PrintBoard(board, ROW, COL); //Determine whether the game is over out = Win(board, ROW, COL); if (out != 'G') { break; } } //Judge the outcome at the end of the game if (out == '*') { printf("Player victory\n"); } else if (out == '#') { printf("Computer victory\n"); } else { printf("it ends in a draw\n"); } }
Here, the data of the binary array I created to store the internal data of the game uses two constants. I define two global constants to change the size of the N-sub chess I want to play at any time
What I think here is that the chess played by players is "*" and the chess played by computers is "#"
Here, all functions are thought out in advance, and then the function contents of the implementation are written step by step
The overall process of the game:
1. Print an empty chessboard to the player first
2. Players can play chess on an empty chessboard by inputting coordinates, and then judge whether the game has the result of victory or defeat or draw after the player plays this move. The game should not continue, and then print out the chessboard after playing this sub again
3. Let the computer play chess randomly on an empty chessboard (I don't know how to write a more intelligent computer). At the same time, judge the game result after the computer plays this chess. Do you need to continue the game, and then print out the chessboard after playing this chess again
4. Finally, if the game is terminated, judge whether it is the result of player victory, computer victory or draw
1. First, you need to print an empty chessboard for players to see:
void InBoard(char board[ROW][COL], int row, int col) { int a = 0; int b = 0; for (a = 0; a < row; a++) { for (b = 0; b < col; b++) { board[a][b] = ' '; } } }
This function is used to initialize the chessboard first, and turn all the data stored in the game into spaces for players to see. If it is not initialized, the chessboard will be printed with random codes
void PrintBoard(char board[ROW][COL], int row, int col) { int a = 0; int b = 0; for (a = 0; a < row; a++) { for (b = 0; b < col; b++) { printf(" %c ", board[a][b]); if (b < col - 1) { printf("|"); } } printf("\n"); if (a < row - 1) { for (b = 0; b < col; b++) { printf("---"); if (b < col - 1) { printf("|"); } } } printf("\n"); } }
The chessboard printed here can be printed every time the numbers in the two-dimensional array are changed
Here, the chessboard format is printed according to the required chessboard size. If you want a 3x3 chessboard, you can print a tic tac toe chessboard. If you want a 4x4 chessboard, you can also print a larger one. You only need to change the value of the constant in the global constant (this function will be often used later)
2. Then the player can start entering coordinates to play chess on the chessboard
void Player(char board[ROW][COL], int row, int col) { int a = 0; int b = 0; printf("Player action\n"); while (1) { printf("Please enter coordinates:>"); scanf("%d %d", &a, &b); //Judge whether the entered coordinates are legal if (a >= 1 && a <= col && b >= 1 && b <= row) { if (board[a - 1][b - 1] == ' ') { board[a - 1][b - 1] = '*'; break; } else { printf("There are chess pieces in the entered coordinates, please re-enter\n"); } } else { printf("Coordinate input error, please re-enter\n"); } } }
When allowing players to input, it is necessary to judge the legitimacy of the coordinates entered by players:
1. Does it exceed the size of the chessboard
2. Is the position where the player wants to play chess empty and can play chess
Because the coordinates of the first grid in the player's chess game are "1 1", but the coordinates of the first grid in the two-dimensional array are "0 0", the coordinates of the stored grid should be - 1 for each number entered by the player to ensure the correctness of the input
If the coordinates entered by the player are legal, store "*" in the two-dimensional array at the corresponding position of the chessboard
(judge the progress of the game and write it after playing chess on the computer)
3. Computer chess
void PC(char board[ROW][COL], int row, int col) { printf("Computer action\n"); while (1) { int a = rand() % row; int b = rand() % col; if (board[a][b] == ' ') { board[a][b] = '#'; break; } } }
I use the coordinates of two random numbers for the computer. The random number adopts the random method of time stamp. Because the coordinates input by the computer are controllable, we don't need to judge the legitimacy of the coordinates input by the computer, but only whether there are elements in the coordinates input by the computer. And there is no need to prompt the computer, just keep cycling, find the empty coordinate and fill "#" into the two-dimensional array
4. Judge whether the game continues or not. If it does not continue, the outcome will be peace
Here, I judge the result of the game as follows:
Return * to win for the player
Return # to computer victory
Return N to draw
Return to G to continue the game
First, you need to judge whether a line is the same
char Win(char board[ROW][COL], int row, int col) { int a = 0; int b = 0; char c; //Judge a line for (a = 0; a < row; a++) { for (b = 0; b < col - 1; b++) { if ((board[a][b] == board[a][b + 1] && board[a][b + 1] == ' ') || board[a][b] != board[a][b + 1]) { break; } if (b == row - 2) { return board[a][b]; } } }
The character type c created earlier can be ignored first, and it should be used for later judgment
Here, I judge line by line. If the elements of a line are all the same, b in the nested for loop will reach the maximum value and return the elements in the last grid of that line (in this way, both players and computers can use this judgment function)
Then judge the same in one line
//Judge a column for (b = 0; b < col; b++) { //if (board[0][a] == board[1][a] && board[1][a] == board[2][a] && board[1][a] != ' ') //{ // return board[1][a]; //} for (a = 0; a < row - 1; a++) { if (board[a][b] == board[a + 1][b] && board[a + 1][b] == ' ' || board[a][b] != board[a + 1][b]) { break; } if (a == row - 2) { return board[a][b]; } } }
It is basically the same as the function logic of the above judgment line. The knowledge changes the changes of a and b
Then judge that the bevel angle is the same
//Judge the upper left to lower right diagonal while (1) { for (a = 0; a < row-1; a++) { for (b = 0; b < col-1; b++) { if (a == b && board[a][b] != ' ') { c = board[a][b]; if (c != board[a + 1][b + 1]) { goto right; } } if (a == b && board[a][b] == ' ') { goto right; } } } return board[a][b]; } right:
The judgment method I use is to judge whether the elements from the upper left corner to the lower right corner are different. First store the first element in 'c' and then compare it with the next Yuan Shu. If it is different or there are spaces in it, jump out of this judgment and go directly to the next judgment. The same is true from the upper right corner to the lower left corner below
//Judge the diagonal from top right to bottom left while (1) { for (a = 0; a < row-1; a++) { for (b = col-1; b > 0; b--) { if ((a + b) == (row - 1) && board[a][b] != ' ') { c = board[a][b]; if (c != board[a + 1][b - 1]) { goto third; } } if ((a + b) == (row - 1) && board[a][b] == ' ') { goto third; } } } return board[a][b]; } third:
The logic is the same, just change the direction of retrieval
After all these judgments are correct, they are the elements in the last grid of the returned search
Finally, judge the draw
int tmp = FULL(board, row, col); if (tmp == 1) { return 'N'; } return 'G'; }
Judge the draw here, I wrote another function. If the return value of the function is 1, it is the draw result. If it returns other games, it will continue
int FULL(char board[ROW][COL], int row, int col) { int a = 0; int b = 0; for (a = 0; a < row; a++) { for (b = 0; b < col; b++) { if (board[a][b] == ' ') { return 0;//The chessboard is not full } } } return 1; }
Because the above has judged all the ways that can win
So to judge a draw here, we only need to judge whether the chessboard is filled, and no one wins
If all the cells are not spaces after retrieval, it returns 1, and as long as there is another space, it returns 0
Finally, this judgment function is placed behind player actions and computer actions
while (1) { //Player action Player(board, ROW, COL); PrintBoard(board, ROW, COL); //Determine whether the game is over out = Win(board, ROW, COL); if (out != 'G') { break; } //Computer action PC(board, ROW, COL); PrintBoard(board, ROW, COL); //Determine whether the game is over out = Win(board, ROW, COL); if (out != 'G') { break; } }
If no one wins and the chessboard is not full, the function should return 'G', so that the game continues to cycle
If someone wins or draws, the function may return any one of '*', '#', and 'G', which will jump out of the while loop and come to the following to judge the result of the game
5. Final result judgment
//Judge the outcome at the end of the game if (out == '*') { printf("Player victory\n"); } else if (out == '#') { printf("Computer victory\n"); } else { printf("it ends in a draw\n"); }
At this time, you can distinguish what elements are stored in the out returned by the previous judgment
Then give feedback on the final results
Then the whole program will jump back to the main function at the beginning and judge again whether you want to play the game again
I think I'm still complicated in judging the winning or losing part of the game. The computer I wrote is not intelligent enough. I don't know how to optimize the winning or losing part. Can someone help me optimize it (accept guidance with an open mind)