Project requirements :

The preview interface of Sanzi chess is as follows : Players play chess with computers , Same for each row or same for each column or diagonal symbol , Win .

thinking :

We first create three files in the project :test.c( Test game logic ) game.h( Declare functions and define symbols ) game.c( Define function )
stay test.c in , Let's get out the simple menu function interface first , Just go up and do it , Just one do
while loop . Then analyze , The game should be played over and over again , Using clever design , Put the input value input As while Judgment part of , If the input value is 0 Then jump out of the loop , If it is a different value, continue the loop . use switch Statement .

test.c
void menu() // menu { printf("****************************\n"); printf("*******
1. Start the game *******\n"); printf("******* 0. End the game *******\n");
printf("****************************\n"); } void game()// Game function {} int main() {
int input; do { menu();// Call menu function scanf("%d",&input); switch (input) { case 1:
printf(" Please enter coordinate arrangement x column y\n"); game();// Game function break; case 0: printf(" End the game \n"); break;
default: printf(" Input error , Please re-enter \n"); } } while
(input);// If input 0 Just jump out of the loop , End program , If input 1 Just continue the game return 0;
Then we run , Error report found , No reference header file . for convenience , Let's put the header file in game.h inside , Then in test.c Reference it inside
game.h:
#include<stdio.h>
test.c:
#include "game.h"  Call and use of custom header file ”” contain
Then we came to game() Function part , Because we need to enter two coordinate values , So define a two-dimensional array to store :
char board[ROW][COL];
We may have to do more than Gobang , It could also be n Sub chess , So you can't write the code dead , Therefore, the constant is defined to realize one change and all change
stay game.h Inside definition ROW and COL by 3:
define ROW 3; define COL 3;

With data storage , We can format the chessboard , That is, the data of the two-dimensional array is filled with spaces , To achieve a beautiful effect , Otherwise, the printed effect will be garbled ( Random value ). stay game Line in function , column , Pass the array : Write an initialization function
InitBoard(board,ROW,COL);
Then in game.h Function declared in file
// Initialize chessboard void InitBoard(char board[ROW][COL],int row,int col);
After declaring the function , I'm going game.c Functions defined in , Store each data in a space , nesting for Loop can be realized :
void InitBoard(char board[ROW][COL], int row, int col)// Format chessboard { int i, j; for
(i = 0; i < row; i++)// Arrays are accessed with subscripts , So the subscript of the line is 0~row-1 { for (j = 0; j < col;
j++)// Column homology { board[i][j] = ' ';// Save space } }
After formatting the chessboard , We need to print out the chessboard , stay game Calling middle note function in function
DisplayBoard(board, ROW, COL);
Then in game.h Declare it in
// Print chessboard void DisplayBoard(char board[ROW][COL], int row, int col);
Then in game.c Define this print function in :
Analyze the chessboard effect we want

    |  |
—|—|—
    |  |
—|—|—
    |  |
For the first line , Will print ( Space , data , Space ), Then print one ’|’
After printing a line , Then wrap , Print —|—|—

game.c void DisplayBoard(char board[ROW][COL], int row, int col)// Print chessboard { int
i,j; for (i = 0; i < row;i++)// We first use the most intuitive method to initialize the chessboard { printf(" %c | %c | %c
\n",board[i][0],board[i][1],board[i][2]);// Print line if(i<row-1)// The last line does not need to print split lines
printf("---|---|---\n");// Print split lines }
Although this method is very intuitive , But we wrote the rows and columns of the program to death , If you want to be 10 Sub chess , Columns always have only three rows , So it's not right , It must be written in a different way .
We just need to %c Disassemble printing , Then disassemble the dividing line and print
Instant printing ( Space , data , Space ), Then print one ’|’ This operation is treated as a set of data , Print — And printing | This operation is treated as a set of data , Print separately . void
DisplayBoard(char board[ROW][COL], int row, int col)// Print chessboard { int i,j; for (i =
0; i < row; i++) { for (j = 0; j < col; j++) { printf(" %c
",board[i][j]);// Print spaces if(j<col-1)// The last column does not need to be printed | of printf("|"); }
printf("\n");// Wrap after printing , Enter split line section if (i < row - 1)// We split the original print into two parts , The last line does not need to print split lines
{ for (j = 0; j < col; j++) { printf("---"); if(j<col-1)// The last column does not need to be printed | of
printf("|"); } printf("\n"); } } }
We will ROW,COL Change to 10,10, The operation results are as follows :

That's perfect. Yes , Now that the chessboard is printed , Then the next step is for the player to enter a coordinate and move
At the same time, what we want to achieve is that players should be able to move all the time , Until the winner is decided , So in game A dead loop is given in the function while(1), Call the player action function here
PlayerMove(board, ROW, COL); The player prints a chessboard at the end of each action , You need to add a print function after it DisplayBoard(board, ROW,
COL);
Then in game.h Player action function declared in
// Players play chess
void PlayerMove(char board[ROW][COL], int row, int col);
Then in game.c Player action function defined in
void PlayerMove(char board[ROW][COL], int row, int col)// Players enter coordinates , use * Fill into array { int
x, y;// Abscissa x And ordinate y printf(" Player movement :\n"); while (1) { scanf("%d %d", &x, &y); if
(x>=1&&x <= row &&y>=1&&y <= col)// Judge the legitimacy of the input coordinates { if (board[x - 1][y - 1] == '
')// Judge whether the coordinates are occupied { board[x - 1][y - 1] = '*';// If the player enters 3 3, Then the corresponding subscript should be 2
2, Arrays are accessed in the form of subscripts , Therefore, it should be reduced 1 break; } else { printf(" Coordinates occupied \n"); } } else {
printf(" Illegal input value , Please re-enter \n"); } } } After the player moves the computer , So in game Call the computer action function in the middle note function. ComputerMove(board,
ROW, COL); Print the chessboard after the computer moves , Call print function DisplayBoard(board, ROW, COL); Then in game.h Declare this function in
// Computer chess void ComputerMove(char board[ROW][COL], int row, int col);
stay game.c Define this function in
For PC mobility , We can put it in a random position , Give the limit range directly , Therefore, it is not necessary to judge whether the value of the computer is within the range , But we have to judge whether the value is occupied . And then this random coordinate , Can be rand Function to give ,rand Function we are guessing numbers. The item has been introduced , Give random values .srand Function definition rand Start of , Parameter type is unsigned integer , Its function header file stdlib.h. Timestamp function time() The return value of can be used as a parameter to increase the randomness , Its function header file time.h.srand Use with timestamp , The maximum randomness can be guaranteed only by defining it once , So we define it in the main function srand. In the main function part, add
srand((unsigned int)time(NULL));

game.c void ComputerMove(char board[ROW][COL], int row, int col)// Computer mobile {
printf(" Computer action \n"); while (1) { int x = rand()%row; int y =
rand()%col;// Surplus row What you get is row-1, If our ROW by 3, So what you get is just the range of the subscript 0~2 Yes if (board[x][y] == '
')// If not occupied { board[x][y] = '#'; break; } } }

Then you just need to judge whether you win or lose , The location of each element needs to be discussed , You also need to pass the two-dimensional array , Judge the return value of the function . There will be four situations :# Computer win ,* Player wins ,Q it ends in a draw ,C Continue the game
So we were game Function call judgment function IsWin(board, ROW, COL);
Define a char Type ret Used to accept the return value of the judgment function , stay game Function .
stay game.h Declaration judgment function :
// Determine whether the game has won or lost
char IsWin(char board[ROW][COL], int row, int col);
stay game.c Functions defined in :
int IsFull(char board[ROW][COL], int row, int col)// Determine whether the element is filled : If the chessboard is full , return 1, Dissatisfaction return 0
{ int i, j; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if
(board[i][j] == ' ')// The chessboard is not full return 0; } } return 1; } char IsWin(char
board[ROW][COL], int row, int
col)// Judge whether the function wins or loses , that 's ok , Wiring pair , If the columns are the same , Win , And a draw , A draw means that everything is filled , Then it's time to continue the game { int i,j; for (i = 0; i
< row; i++) { if (board[i][0] == board[i][1] && board[i][1] ==
board[i][2]&&board[i][1]!=' ')// Row equality , At the same time, the line cannot contain spaces { 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] != ' ')// Equal columns { return
board[0][i]; } } // Diagonal equality 1 if (board[0][0] == board[1][1]&&board[1][1] ==
board[2][2]&&board[0][0]!=' ') { return board[0][0]; } if (board[2][0] ==
board[1][1]&&board[1][1] == board[0][2]&&board[2][0]!=' ') { return
board[2][0]; }
// Although it can run Sanzi perfectly , But in fact, this code is written very close , Because it's dead , And if we want to achieve n Sub chess , This code doesn't work at all , So we need to according to the above code , Improve and optimize ( I'll come back and optimize when my technology gets better
// Draw situation : If all elements are filled , All filled in, that is, there is no space , Return a Q int ret = IsFull(board, row,
col);// If the chessboard is full , return 1, Dissatisfaction return 0 if (ret == 1) { return 'Q'; } // If not for the above situations , Then continue the game , Return a C
return 'C'; }
Execute a judgment after the player and the computer move each time
ret = IsWin(board, ROW, COL); if (ret != 'C') break;
After jumping out of the loop , That means the results have come out , There's going to be a discussion :
if (ret == '*') { printf(" The player won \n"); } else if(ret=='#') { printf(" The computer won \n"); }
else { printf(" it ends in a draw \n"); }

The basic idea of the program is roughly the same , Then we found that the judgment of winning or losing is still dead , Impossible to achieve 10*10, And the computer plays chess at random , Computers are hard to win , Such games are boring to play . I'll improve my skills when I come back .
The full source code is as follows :

test.c
// Test the logic of the game #include "game.h" void menu() // menu {
printf("****************************\n"); printf("******* 1. Start the game *******\n");
printf("******* 0. End the game *******\n"); printf("****************************\n"); }
void game()// Game function { // Storing data with a two-dimensional array char
board[ROW][COL];// We may have to do more than Gobang , It could also be n Sub chess , So you can't write the code dead , Therefore, the constant is defined to realize one change and all change char
ret;// Return value storage , Accept game status , Judge whether to win or lose // Format chessboard , That is, the data of each array is filled with spaces , So know how many lines it has , How many columns , Then pass the array
InitBoard(board,ROW,COL); // Print chessboard DisplayBoard(board, ROW, COL); while (1) {
// Players play chess : Players can only move after entering coordinates , Then we need to judge whether the coordinates are legal , So we need to pass in two-dimensional array rows and columns PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL); // Judge whether to win or lose : The location of each element needs to be discussed , You also need to pass the two-dimensional array , Judge the return value of the function
// There will be four situations :# Computer win ,* Player wins ,Q it ends in a draw ,C Continue the game ret =IsWin(board, ROW, COL); if (ret !=
'C')// If the return value is not C, Just jump out of the loop break; // Computer mobile : The computer does not need to enter coordinates , But we need to pass in the row and column of the two-dimensional array and assign a qualified value to it
ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL);
system("cls");// Clear screen after moving DisplayBoard(board, ROW, COL); printf(" Please enter row x column y\n");
// Judge whether the computer wins the game ret = IsWin(board, ROW, COL); if (ret != 'C') break; }
// Jump out of loop , explain ret!=C Yes if (ret == '*') { printf(" The player won \n"); } else if(ret=='#') {
printf(" The computer won \n"); } else { printf(" it ends in a draw \n"); } } int main() { int input;
srand((unsigned int)time(NULL)); do { menu(); scanf("%d",&input); switch
(input) { case 1: printf(" Please enter coordinate arrangement x column y\n"); game(); break; case 0:
printf(" End the game \n"); break; default: printf(" Input error , Please re-enter \n"); } } while
(input);// If input 0 If it's false, jump out of the loop , End program , If input 1 Just continue the game return 0; }
game.h
#define _CRT_SECURE_NO_WARNINGS 1 // Inclusion of header file #include <stdio.h>
#include<stdlib.h> #include<time.h> // Definition of symbols #define ROW 10 #define COL 10
// Declaration of function // The parameter passing of a two-dimensional array needs to be clear about how many columns it has , Lines can be omitted // Initialize chessboard void InitBoard(char
board[ROW][COL],int row,int col); // Print chessboard void DisplayBoard(char
board[ROW][COL], int row, int col); // Players play chess void PlayerMove(char
board[ROW][COL], int row, int col); // Computer chess void ComputerMove(char
board[ROW][COL], int row, int col); // Judge whether the game wins or loses char IsWin(char board[ROW][COL],
int row, int col);
game.c
#include "game.h" void InitBoard(char board[ROW][COL], int row, int
col)// Format chessboard { int i, j; for (i = 0; i < row; i++)// Arrays are accessed with subscripts , So the subscript of the line is 0~row-1 {
for (j = 0; j < col; j++)// Column homology { board[i][j] = ' '; } } } // This is the chessboard initialization effect we want to achieve
//printf(" | | \n") //printf("---|---|---\n"); //printf(" | | \n");
//printf("---|---|---\n"); //printf(" | | \n");
// Analyze the initialization effect , To print the chessboard : For the first line is print ( Space , data , Space ), Then print one '|', At the same time, we found that , Of the third data '|' There is no need to print , So we need to combine the data with | Print separately
// After printing this , Then wrap , Print --- Bring one |, hold --- and | As a data , We found , Of the third data '|' It also does not need to be printed void
DisplayBoard(char board[ROW][COL], int row, int col)// Print chessboard { int i,j; /*for (i
= 0; i < row;i++)// We first use the most intuitive method to initialize the chessboard { printf(" %c | %c | %c
\n",board[i][0],board[i][1],board[i][2]);// Print data for each line if(i<row-1)// The last line does not need to print split lines
printf("---|---|---\n"); }
Although this method is intuitive , But we found out , It's dead , If you want to be 10 Sub chess , Columns always have only three rows , So it's not right , Put it another way .*/
// We just need to %c Just take it apart for printing , Then you can define rows and columns , Disassemble and print each data . for (i = 0; i < row; i++) { for (j = 0;
j < col; j++) { printf(" %c ",board[i][j]);// Print spaces if(j<col-1)// The last column does not need to be printed | of
printf("|"); } printf("\n");// Wrap after printing , Enter split line section if (i < row -
1)// We split the original print into two parts , The last line does not need to print split lines { for (j = 0; j < col; j++) { printf("---");
if(j<col-1)// The last column does not need to be printed | of printf("|"); } printf("\n"); } } } void
PlayerMove(char board[ROW][COL], int row, int col)// Players enter coordinates , use * Fill into array { int x,
y;// Abscissa x And ordinate y printf(" Player movement :\n"); while (1) { scanf("%d %d", &x, &y); if (x>=1&&x
<= row &&y>=1&&y <= col)// Judge the legitimacy of the input coordinates { if (board[x - 1][y - 1] == '
')// Judge whether the coordinates are occupied { board[x - 1][y - 1] = '*';// If the player enters 3 3, Then the corresponding subscript should be 2
2, Arrays are accessed in the form of subscripts , Therefore, it should be reduced 1 break; } else { printf(" Coordinates occupied \n"); } } else {
printf(" Illegal input value , Please re-enter \n"); } } } void ComputerMove(char board[ROW][COL], int
row, int col) { printf(" Computer action \n");
// For computers , We can put it in a random position , We can give the limit range directly , Therefore, it is not necessary to judge whether the value of the computer is within the range , But we have to judge whether the value is occupied while (1) {
int x =
rand()%row;//rand Function we are guessing numbers. The item has been introduced , Give random values .srand The argument type of the function is unsigned integer , Its function is to define rand Start of , Function header file stdlib.h. Timestamp function time() The return value of can be used as a parameter to increase the randomness , Function header file time.h.srand Use with timestamp , The maximum randomness can be guaranteed only by defining it once , So we define it in the main function srand
int y = rand()%col;// Surplus row What you get is row-1, If our ROW by 3, So what you get is just the range of the subscript 0~2 Yes if
(board[x][y] == ' ') { board[x][y] = '#'; break; } } } int IsFull(char
board[ROW][COL], int row, int col)// Determine whether the element is filled : If the chessboard is full , return 1, Dissatisfaction return 0 { int i, j; for
(i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == '
')// The chessboard is not full return 0; } } return 1; } char IsWin(char board[ROW][COL], int row,
int col)// Judge whether the function wins or loses , that 's ok , Pair wiring , If the columns are the same , Win , And a draw , A draw means that everything is filled , Then it's time to continue the game { int i,j; for (i =
0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][1] ==
board[i][2]&&board[i][1]!=' ')// Row equality , At the same time, the line cannot contain spaces { 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] != ' ')// Equal columns { return
board[0][i]; } } // Diagonal equality 1 if (board[0][0] == board[1][1]&&board[1][1] ==
board[2][2]&&board[0][0]!=' ') { return board[0][0]; } if (board[2][0] ==
board[1][1]&&board[1][1] == board[0][2]&&board[2][0]!=' ') { return
board[2][0]; }
// Although it can run Sanzi perfectly , But in fact, this code is written very close , Because it's dead , And if we want to achieve n Sub chess , This code doesn't work at all , So we need to according to the above code , Optimize ( I'll come back and optimize when my technology gets better
// Draw situation : If all elements are filled , All filled in, that is, there is no space , Return a Q int ret = IsFull(board, row,
col);// If the chessboard is full , return 1, Dissatisfaction return 0 if (ret == 1) { return 'Q'; } // If not for the above situations , Then continue the game , Return a C
return 'C'; }

Technology