
三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏规则是双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利。但因棋盘太小,三子棋在很多时候会出现和棋的局面。
先开一个test.c文件用来进行游戏的逻辑测试,再开一个game.h头文件和game.c文件分别用来进行函数声明和实现游戏的逻辑,然后就是打印菜单、生成棋盘、实现玩家下棋、实现电脑下棋、判断游戏的输赢、游戏优化。
test.c
- void menu()
- {
- printf("***************************\n");
- printf("******** 1.play ********\n");
- printf("******** 2.exit ********\n");
- printf("***************************\n");
- }
-
- 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");
- }
- } while (input);
- return 0;
- }
我们可以用空格将每一个格子初始化。
test.c文件:
- board[ROW][COL] = { 0 };
- InitBoard(board, ROW, COL);
game.c文件:
- void InitBoard(char board[ROW][COL], int row, int col)
- {
- for (int i = 0; i < row; i++)
- {
- for (int j = 0; j < col; j++)
- {
- board[i][j] = " ";
- }
- }
- }
其中的ROW和COL是两个宏定义。
game.h
- #define ROW 3
- #define COL 3
打印棋盘时我们可以一些符号隔开不同的空格,这样就会使我们的棋盘更加美观。比如我们可以使用“|”将同一行的空格分开,用“-”将不同行的空格分开,这样我们就可以得到一个如下的九宫格了。

game.c文件:
- void DisplayBoard(char board[ROW][COL], int row, int col)
- {
- for (int i = 0; i < row; i++)
- {
- for (int j = 0; j < col; j++)
- {
- printf(" ");
- if (j < col - 1)
- {
- printf("|");
- }
- }
- printf("\n");
- if (i < row - 1)
- {
- for (int j = 0; j < col; j++)
- {
- printf("---");
- if (j < col - 1)
- printf("|");
- }
- printf("\n");
- }
- }
- }
为了游戏的可实行性,当玩家或电脑下完一个棋子后我们需要考虑以下两点:
1.玩家或电脑所下的坐标是否在棋盘的范围内。
2.玩家或电脑所下的位置是否已经被下过棋子了。
依据上面的两点条件的我们需要分别写一个条件语句,判断玩家是否合法下棋。
game.c文件:
- void PlayerMove(char board[ROW][COL], int row, int col)
- {
-
- int x = 0, 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] = '*';
- break;
- }
- else
- {
- printf("输入的坐标已被占用,请重新输入\n");
- }
- }
- else
- {
- printf("坐标非法,请重新输入\n");
- }
- }
- }
思路:
我们可以在让电脑生成随机数,这样就可以使其随机生成一个坐标下棋子,那么我们就可以简单的实现电脑下棋的效果了。
随机数的生成则可以使用rand函数、srand函数以及time函数。
game.c文件:
- void ComputerMove(char board[ROW][COL], int row, int col)
- {
- printf("电脑下棋:>\n");
- while (1)
- {
- int x = rand() % row;
- int y = rand() % row;
- if (x <= row && x >= 1 && y <= row && y >= 1)
- {
- if (board[x][y] == ' ')
- {
- board[x][y] = '#';
- break;
- }
- }
-
- }
- }
test.c文件:
srand((unsigned int)time(UNLL))
game.h文件:
- #include
- #include
为了实现玩家下一个棋,然后电脑下一个棋的功能我们还需加上一个while循环。如下:
test.c文件:
- while(1)
- {
- //玩家下棋
- PlayerMove(board, ROW, COL);
- DisplayBoard(board, ROW, COL);
- //电脑下棋
- ComputerMove(board, ROW, COL);
- DisplayBoard(board, ROW, COL);
- }

思路:
此游戏无非只有三种结果:要么玩家赢,要么电脑赢,要么平局。所以我们可以写一个函数判断是这几种结果的哪一种,然后规定如果是玩家赢此函数返回“*”,如果是电脑赢则返回“#”,平局则返回“Q”,这几种都不是就说明游戏继续,那么就返回“C”.
要判断是否有赢的一方,无非就是判断是否出现了三个相同的棋子练成一条直线,而棋子连成的线无非就只有三种情况:竖线、横线、对角线。所以我们只需要判断是否出现了这三种情况的其中一种就可以了。而要判断是平局,则判断九宫格是否还有没有空格。
game.c文件:
- int ItFull(char board[ROW][COL], int row, int col)
- {
- for (int i = 0; i < row; i++)
- {
- for (int j = 0;j < col; j++)
- {
- if (board[i][j] == ' ')
- {
- return 0;
- }
- }
- }
- return 1;
- }
- char ItWin(char board[ROW][COL], int row, int col)
- {
- //行
- for (int i = 0; i < row; i++)
- {
- if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')
- return board[i][1];
- }
- //列
- for (int j = 0; j < col; j++)
- {
- if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
- return board[1][j];
- }
- //对角线
- if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != 0)
- {
- return board[1][1];
- }
- if (ItFull(board, row, col))
- {
- return 'Q';
- }
- return 'C';
- }
test.c文件:
- //玩家下棋
- PlayerMove(board, ROW, COL);
-
- DisplayBoard(board, ROW, COL);
- //判断输赢
- char ret = ItWin(board, ROW, COL);
- if (ret != 'C')
- {
- if (ret == '*')
- {
- printf("玩家赢了!!!\n");
- }
- break;
- }
- //电脑下棋
- ComputerMove(board, ROW, COL);
-
- DisplayBoard(board, ROW, COL);
- //判断输赢
- ItWin(board, ROW, COL);
- if (ret != 'C')
- {
- if (ret == '#')
- {
- printf("电脑赢了!!!\n");
- }
- break;
- }
game.h文件:
-
- #include
- #include
- #include
-
- #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 ItWin(char board[ROW][COL], int row, int col);
test.c文件:
- #include"game.h"
-
- void menu()
- {
- printf("***************************\n");
- printf("******** 1.play ********\n");
- printf("******** 2.exit ********\n");
- printf("***************************\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);
- //判断输赢
- char ret = ItWin(board, ROW, COL);
- if (ret != 'C')
- {
- if (ret == '*')
- {
- printf("玩家赢了!!!\n");
- }
- break;
- }
- //电脑下棋
- ComputerMove(board, ROW, COL);
-
- DisplayBoard(board, ROW, COL);
- //判断输赢
- ItWin(board, ROW, COL);
- if (ret != 'C')
- {
- if (ret == '#')
- {
- printf("电脑赢了!!!\n");
- }
- break;
- }
- }
- }
- int main()
- {
- srand((unsigned int)time(NULL));
- int input = 0;
-
- do
- {
- menu();
- printf("请选择>:");
- scanf("%d", &input);
- switch (input)
- {
- case 1:
- game();
- break;
- case 0:
- printf("退出游戏.\n");
- break;
- default:
- printf("输入有误,请重新输入.\n");
- }
- } while (input);
- return 0;
- }
game.c文件:
- #include"game.h"
-
- void InitBoard(char board[ROW][COL], int row, int col)
- {
- for (int i = 0; i < row; i++)
- {
- for (int j = 0; j < col; j++)
- {
- board[i][j] = ' ';
- }
- }
- }
-
- void DisplayBoard(char board[ROW][COL], int row, int col)
- {
- for (int i = 0; i < row; i++)
- {
- for (int j = 0; j < col; j++)
- {
- printf(" %c ",board[i][j]);
- if (j < col - 1)
- printf("|");
- }
- printf("\n");
- if (i < row - 1)
- {
- for (int 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, 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] = '*';
- break;
- }
- else
- {
- printf("输入的坐标已被占用,请重新输入\n");
- }
- }
- else
- {
- printf("坐标非法,请重新输入\n");
- }
- }
- }
-
- void ComputerMove(char board[ROW][COL], int row, int col)
- {
- printf("电脑下棋:>\n");
- while (1)
- {
- int x = rand() % row;
- int y = rand() % row;
- if (x <= row && x >= 1 && y <= row && y >= 1)
- {
- if (board[x][y] == ' ')
- {
- board[x][y] = '#';
- break;
- }
- }
-
- }
- }
-
- int ItFull(char board[ROW][COL], int row, int col)
- {
- for (int i = 0; i < row; i++)
- {
- for (int j = 0;j < col; j++)
- {
- if (board[i][j] == ' ')
- {
- return 0;
- }
- }
- }
- return 1;
- }
- char ItWin(char board[ROW][COL], int row, int col)
- {
- //行
- for (int i = 0; i < row; i++)
- {
- if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')
- return board[i][1];
- }
- //列
- for (int j = 0; j < col; j++)
- {
- if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
- return board[1][j];
- }
- //对角线
- if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != 0)
- {
- return board[1][1];
- }
- if (ItFull(board, row, col))
- {
- return 'Q';
- }
- return 'C';
- }

让电脑生成一个数的方式来实现一个电脑下棋的效果,肯定是没有什么可玩性的,等后面学习算法之后,我们就加入一些算法将其变为一个棋艺高超的棋手了。