创建项目及其代码分类 三子棋(井字棋)横竖斜三子连成线则获胜
test.c
- 游戏逻辑代码编写
game.h
- 游戏函数声明,符号定义,头文件的包含
game.c
- 游戏函数代码实现
主函数和菜单函数编写 在test.c
写入主函数main
使用do while
循环语句可以让程序一开始就执行一次
我们需要调用一个menu
函数用于游戏的开始界面
然后通过输入1或者0 开始游戏或退出游戏
输入非1和0的输需重新输入
开始游戏后调用game
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 int main () { int input = 0 ; do { menu(); printf ("请选择:>" ); scanf ("%d" ,&input); switch (input) { case 1 : printf ("开始三子棋游戏\n" ); printf ("游戏需要输入坐标(如:1 2 即第一行第二列)\n" ); game(); break ; case 0 : printf ("退出游戏\n" ); break ; default : printf ("选择错误,请重新选择\n" ); break ; } } while (input); return 0 ; }
在主函数上面定义一个menu
函数,完成游戏开始界面
1 2 3 4 5 6 7 void menu () { printf ("**********************************\n" ); printf ("********** 1.play **********\n" ); printf ("********** 0.exit **********\n" ); printf ("**********************************\n" ); }
游戏逻辑函数编写 开始游戏后,主函数内调用game
函数
我们在主函数上面定义一个game
函数
并创建一个二维数组
1 2 3 4 5 6 void game () { char board[ROW][COL]; }
然后在头文件game.h
中,使用#define
定义两个常量,行和列
1 2 3 #define ROW 3 #define COL 3
在game
函数中调用InitBoard
函数,用于初始化棋盘
1 2 3 4 5 6 7 void game () { char board[ROW][COL]; InitBoard(board,ROW,COL); }
初始化棋盘 在实现函数功能前,我们需要先在头文件game.h
里声明函数
1 2 void InitBoard (char board[ROW][COL], int row, int col) ;
然后再game.c
中进行实现初始化棋盘
就是把二维数组中的所有元素都变为空格
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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] = ' ' ; } } }
打印棋盘 然后我们需要制作一个棋盘,也就是打印一个棋盘
我们先在game
函数中调用函数DisplayBoard
,用来打印棋盘
1 2 3 4 5 6 7 8 9 void game () { char board[ROW][COL]; InitBoard(board,ROW,COL); DisplayBoard(board, ROW, COL); }
同样的,在头文件中进行声明
1 2 void DisplayBoard (char board[ROW][COL], int row, int col) ;
然后在game.c
进行实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 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 ("|" ); } else { printf ("\n" ); } } if (i < row -1 ) { for ( j = 0 ; j < col; j++) { printf ("---" ); if (j < col - 1 ) { printf ("|" ); } else { printf ("\n" ); } } } } }
头文件包含 我们可以将需要引入的c语言头文件放到我们自己创建的头文件game.h
中
这样我们只需要引用game.h
即可
1 2 3 #include <stdio.h> #include <string.h>
玩家下棋 在game
函数内进行循环,调用PlayerMove
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void game () { char board[ROW][COL]; InitBoard(board,ROW,COL); DisplayBoard(board, ROW, COL); while (1 ) { PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); } }
声明函数
1 2 void PlayerMove (char board[ROW][COL], int row, int col) ;
我们先需要判断我们输入的下标是否合法
然后判断我们输入的下标的位置是否已经有棋子,即是否为空格
是空格的话,下棋,不是的话,重新输入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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 ] = '*' ; break ; } else { printf ("该坐标已经有棋子咯,请重新输入\n" ); } } else { printf ("坐标非法,请重新输入\n" ); } } }
电脑下棋 玩家下完棋之后,电脑开始下棋
game
函数中调用ComputerMove
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void game () { char board[ROW][COL]; InitBoard(board,ROW,COL); DisplayBoard(board, ROW, COL); while (1 ) { PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); } }
声明函数
1 2 void ComputerMove (char board[ROW][COL], int row, int col) ;
接着在game.c
中实现
我们使用随机数的方式让电脑下棋
需要先在主函数中使用srand
然后在ComputerMove
函数中使用随机数rand
然后判断当前位置是否为空格
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 int main () { int input = 0 ; srand((unsigned int )time(NULL )); do { menu(); printf ("请选择:>" ); scanf ("%d" ,&input); switch (input) { case 1 : printf ("开始三子棋游戏\n" ); printf ("游戏需要输入坐标(如:1 2 即第一行第二列)\n" ); game(); break ; case 0 : printf ("退出游戏\n" ); break ; default : printf ("选择错误,请重新选择\n" ); break ; } } while (input); return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void ComputerMove (char board[ROW][COL], int row, int col) { printf ("电脑回合:>\n" ); while (1 ) { int x = rand() % row; int y = rand() % col; if (board[x][y] == ' ' ) { board[x][y] = '#' ; break ; } } }
别忘记了引入头文件
1 2 3 4 5 #include <stdio.h> #include <string.h> #include <time.h> #include <stdlib.h>
判断输赢 一共有四种情况
1.玩家赢了 - return * 2.电脑赢了 - return # 3.平局 - return Q 4.游戏继续 - return C
我们让电脑或玩家赢的时候返回自身的棋子的字符,比较方便
首先定义一个值ret
用于存储返回来的字符
game
函数中调用IsWin
,把其的返回值赋值给ret
如果返回值不为 C ,说明游戏已结束,退出循环
进行判断胜负
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 void game () { char board[ROW][COL]; InitBoard(board,ROW,COL); DisplayBoard(board, ROW, COL); 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 ("你赢了!!!\n" ); } else if (ret == '#' ) { printf ("你输了!!!\n" ); } else { printf ("平局\n" ); } }
然后开始编写IsWin
函数
先声明函数
1 2 char IsWin (char board[ROW][COL], int row, int col) ;
然后实现函数
我们通过循环判断行和列是否有相同的棋子
然后写一个函数IsFull
来判断两个对角线是否有相同的棋子
注意:这种方法只能用于3*3的三子棋
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 char 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 'C' ; } } } return 'Q' ; } 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][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[0 ][0 ] != ' ' ) { return board[0 ][0 ]; } if (board[0 ][2 ] == board[1 ][1 ] && board[1 ][1 ] == board[2 ][0 ] && board[0 ][2 ] != ' ' ) { return board[0 ][2 ]; } int ret = IsFull(board, ROW, COL); return ret; }
功能增加 其实代码还有很多地方可以优化,特别是最后进行判断的时候,只能用于3*3的三子棋,不过如果需要通用,要用到算法,过于困难了
这里就增加几个比较简单的功能
电脑下棋优化 我们可以让电脑下棋时把中间位置先占据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 void ComputerMove (char board[ROW][COL], int row, int col) { printf ("电脑回合:>\n" ); while (1 ) { int x = rand() % row; int y = rand() % col; if (board[x][y] == ' ' ) { if (board[row / 2 ][col / 2 ] == ' ' ) { board[row / 2 ][col / 2 ] = '#' ; break ; } else { board[x][y] = '#' ; break ; } } } }
先后手和重新开始游戏倒计时 在前面的代码里都是玩家先手,我们可以设置个随机数,随机让玩家或者电脑先手
然后在判断胜负后加上重新开始游戏的倒计时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 void game () { char board[ROW][COL]; InitBoard(board,ROW,COL); DisplayBoard(board, ROW, COL); char ret = 0 ; int n = rand() % 2 ; if (n) { 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 ; } } else { while (1 ) { ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C' ) break ; PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C' ) break ; } } if (ret == '*' ) { printf ("你赢了!!!\n" ); } else if (ret == '#' ) { printf ("你输了!!!\n" ); } else { printf ("平局\n" ); } DisplayBoard(board, ROW, COL); Sleep(1000 ); for (int i = 3 ; i > 0 ; i--) { printf ("倒计时后重新开始游戏:%d\n" , i); Sleep(1000 ); } system("cls" ); }
功能展示
代码展示 test.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 #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 board[ROW][COL]; InitBoard(board,ROW,COL); DisplayBoard(board, ROW, COL); char ret = 0 ; int n = rand() % 2 ; if (n) { 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 ; } } else { while (1 ) { ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C' ) break ; PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C' ) break ; } } if (ret == '*' ) { printf ("你赢了!!!\n" ); } else if (ret == '#' ) { printf ("你输了!!!\n" ); } else { printf ("平局\n" ); } DisplayBoard(board, ROW, COL); Sleep(1000 ); for (int i = 3 ; i > 0 ; i--) { printf ("倒计时后重新开始游戏:%d\n" , i); Sleep(1000 ); } system("cls" ); } int main () { int input = 0 ; srand((unsigned int )time(NULL )); do { menu(); printf ("请选择:>" ); scanf ("%d" ,&input); switch (input) { case 1 : printf ("开始三子棋游戏\n" ); printf ("游戏需要输入坐标(如:1 2 即第一行第二列)\n" ); game(); break ; case 0 : printf ("退出游戏\n" ); break ; default : printf ("选择错误,请重新选择\n" ); break ; } } while (input); return 0 ; }
game.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #pragma once #define ROW 3 #define COL 3 #include <stdio.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <windows.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) ;
game.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 #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 ("|" ); } else { printf ("\n" ); } } if (i < row -1 ) { for ( j = 0 ; j < col; j++) { printf ("---" ); if (j < col - 1 ) { printf ("|" ); } else { printf ("\n" ); } } } } } void PlayerMove (char board[ROW][COL], int row, int col) { int x = 0 ; int y = 0 ; printf ("玩家回合\n" ); while (1 ) { printf ("请输入下棋的坐标:>" ); while (getchar() != '\n' ) { } 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() % col; if (board[x][y] == ' ' ) { if (board[row / 2 ][col / 2 ] == ' ' ) { board[row / 2 ][col / 2 ] = '#' ; break ; } else { board[x][y] = '#' ; break ; } } } } char 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 'C' ; } } } return 'Q' ; } 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][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[0 ][0 ] != ' ' ) { return board[0 ][0 ]; } if (board[0 ][2 ] == board[1 ][1 ] && board[1 ][1 ] == board[2 ][0 ] && board[0 ][2 ] != ' ' ) { return board[0 ][2 ]; } int ret = IsFull(board, ROW, COL); return ret; }
三子棋程序下载链接 点击这里进行下载