本文实例为大家分享了C语言三子棋游戏简单设计的具体代码,供大家参考,具体内容如下
题目思想:
用 3×3 的二维数组表示棋盘
每一个棋子的格子,也就是每个元素表示三种状态:分别是
1.未落子 ‘ '
2.玩家落子 ‘X'
3.电脑落子 ‘O'
玩家通过输入数字作为落子位置的坐标(输入的行数与输入的列数)
直接上代码解析
1.创建出棋盘
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
|
#define _CRT_SECURE_NO_WARNINGS //利用宏定义行和列 #define MAX_ROW 3 #define MAX_COL 3 #include <stdio.h> #include <stdlib.h> // 将初始化行和列的 '0' 变为空格 ' ' void init( char board[MAX_ROW][MAX_COL]) { //行初始化,将数组 0-2输出为' ' for ( int row = 0; row < MAX_ROW; row++) { //列初始化 for ( int col = 0; col < MAX_COL; col++) { board[row][col] = ' ' ; } } } // 打印棋盘,定义printBoard,以二维数组的方式进行循环打印 void printBoard( char board[MAX_ROW][MAX_COL]) { for ( int row = 0; row < MAX_ROW; row++) { for ( int col = 0; col < MAX_COL; col++) { // 打印字符,使用 %c printf ( "%c" , board[row][col]); } //每次打印完一行,进行换行操作,变成3×3的数组形成的棋盘 printf ( "\n" ); } } int main() { // 首先创建棋盘并初始化 // 这里不要用board[3][3],防止后面 3 与 3 搞混,可以利用宏定义 char board[MAX_ROW][MAX_COL] = { 0 }; // 使用 init 函数 初始化二维数组{0}应当变成空格 ' ' // 此处也可以将 init函数定义中的双重 for 循环直接输入 // 但将二维数组初始化为 ' ',表示了一个固定功能的逻辑,比较适合用函数定义的方法完成 init(board); // 使用while循环,进行轮流落子 while (1) { //1.先打印棋盘内容 printBoard(board); //2.玩家落子 //3.电脑落子 //4.判定胜负 } system ( "pause" ); return 0; } |
确实打印出来了,但是由于初始化将二维数组中的元素变为了空格 ‘ '
,所以输出结果看不到。
2.修改棋盘,使之打印出的是 3×3 的带有方格的棋盘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
void printBoard( char board[MAX_ROW][MAX_COL]) { for ( int row = 0; row < MAX_ROW; row++) { //在打印每一行之前加入横线 printf ( "+--+--+--+\n" ); for ( int col = 0; col < MAX_COL; col++) { // 打印字符,使用 %c // 每打印一列,在打印之前加入| printf ( "| %c" , board[row][col]); } //打印之后加入|,形成 3 列。 printf ( "|" ); //每次打印完一行,进行换行操作,变成3×3的数组形成的纵线棋盘 printf ( "\n" ); } //打印完所有行之后在加入横线,形成横线棋盘 printf ( "+--+--+--+\n" ); } |
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 playerMove( char board[MAX_ROW][MAX_COL]) { printf ( "轮到玩家落子!\n" ); //加入while循环,保证用户输入错误时返回重新输入 while (1) { printf ( "请输入落子位置的坐标(row col):" ); //添加屏幕输入模块,输入行和列坐标 int row = 0; int col = 0; scanf ( "%d %d" , &row, &col); //输入完了之后,一定要验证输入的内容,防止输入例如(10,20)超过棋盘坐标 if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL) { printf ( "您输入的坐标有误,请重新输入!\n" ); continue ; //重新输入,继续循环 } // 当前位置不为 ' ' ,说明有子了,也需要重新输入 if (board[row][col] != ' ' ) { printf ( "当前位置有子,无法落子\n" ); continue ; } //玩家落子为 X ,结束当前循环 board[row][col] = 'X' ; break ; } } |
4.电脑落子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// 电脑落子 void computerMove( char board[MAX_ROW][MAX_COL]) { printf ( "轮到电脑落子!\n" ); while (1) { //电脑落子时,产生随机位置,用到随机数种子,使随机数范围在棋盘坐标以内 int row = rand () % MAX_ROW; int col = rand () % MAX_COL; if (board[row][col] != ' ' ){ // 如果行列不是空格,说明有子了,就随机生成随机数 continue ; } board[row][col] = 'O' ; break ; } } |
这里使用了清屏操作,让每次输入完后进行一次清屏,具体代码在总体代码里附上
5.判定胜负
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
|
//判断和棋的函数 int isFull( char board[MAX_ROW][MAX_COL]) { //如果在棋盘中找不到 ' ' ,就说明棋盘满了,只要找到 ' ' 说明没满 //约定满了返回1,没满返回0 for ( int row = 0; row < MAX_ROW; row++) { for ( int col = 0; col < MAX_COL; col++) { if (board[row][col] == ' ' ) { //没满 return 0; } } } return 1; } // 判定胜负,由于要返回胜负,使用char定义 // 如果是玩家赢返回 X ,电脑赢返回 O,平局返回 P,胜负未分返回 ' ' char checkwinner( char board[MAX_ROW][MAX_COL]) { //1.检测所有行 for ( int row = 0; row < MAX_ROW; row++) { if (board[row][0] != ' ' && board[row][0] == board[row][1] && board[row][0] == board[row][2]) { return board[row][0]; } } //2.检测所有列 for ( int col = 0; col < MAX_ROW; col++) { if (board[0][col] != ' ' && board[0][col] == board[1][col] && board[0][col] == board[2][col]) { return board[0][col]; } } //3.检测所有对角线 if (board[0][0] != ' ' && board[0][0] == board[1][1] && board[0][0] == board[2][2]) { return board[0][0]; } if (board[2][0] != ' ' && board[2][0] == board[1][1] && board[0][0] == board[0][2]) { return board[2][0]; } // 判定和棋 if (isFull(board)) { return 'p' ; } return ' ' ; } |
这个结果中很多人肯定看到了问题,玩家赢的同时还在显示电脑落子,怎么改?
6.注意还有一个问题:
如图,在主函数中先进行玩家落子,后进行电脑落子,在电脑落子之前玩家就赢了。修改程序如下:
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
|
int main() { // 首先创建棋盘并初始化 // 这里不要用board[3][3],防止后面 3 与 3 搞混,可以利用宏定义 char board[MAX_ROW][MAX_COL] = { 0 }; // 使用 init 函数 初始化二维数组{0}应当变成空格 ' ' // 此处也可以将 init函数定义中的双重 for 循环直接输入 // 但将二维数组初始化为 ' ',表示了一个固定功能的逻辑,比较适合用函数定义的方法完成 init(board); char winner = ' ' ; // 使用while循环,进行轮流落子 while (1) { //1.先打印棋盘内容 printBoard(board); //2.玩家落子 playerMove(board); winner = checkwinner(board); if (winner != ' ' ) { //胜负已分,结束循环 break ; } //3.电脑落子 computerMove(board); //4.判定胜负 winner = checkwinner(board); if (winner != ' ' ) { //胜负已分,结束循环 break ; } } if (winner = 'X' ) { printf ( "恭喜你,获胜了!\n" ); } else if (winner = 'O' ) { printf ( "很遗憾,你有点菜呀!\n" ); } else { printf ( "你和电脑五五开!\n" ); } system ( "pause" ); return 0; } |
全部函数
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
172
173
174
175
176
177
178
|
#define _CRT_SECURE_NO_WARNINGS //利用宏定义行和列 #define MAX_ROW 3 #define MAX_COL 3 #include <stdio.h> #include <stdlib.h> #include <time.h> // 将初始化行和列的 '0' 变为空格 ' ' void init( char board[MAX_ROW][MAX_COL]) { //行初始化,将数组 0-2输出为' ' for ( int row = 0; row < MAX_ROW; row++) { //列初始化 for ( int col = 0; col < MAX_COL; col++) { board[row][col] = ' ' ; } } //设置随机数种子,为电脑落子 //只要程序启动时,设置一次即可 srand ((unsigned int ) time (0)); } // 打印棋盘,定义printBoard,以二维数组的方式进行循环打印 void printBoard( char board[MAX_ROW][MAX_COL]) { //每次打印之前先清屏 system ( "cls" ); for ( int row = 0; row < MAX_ROW; row++) { //在打印每一行之前加入横线 printf ( "+--+--+--+\n" ); for ( int col = 0; col < MAX_COL; col++) { // 打印字符,使用 %c // 每打印一列,在打印之前加入| printf ( "| %c" , board[row][col]); } //打印之后加入|,形成 3 列。 printf ( "|" ); //每次打印完一行,进行换行操作,变成3×3的数组形成的纵线棋盘 printf ( "\n" ); } //打印完所有行之后在加入横线,形成横线棋盘 printf ( "+--+--+--+\n" ); } // 玩家落子 void playerMove( char board[MAX_ROW][MAX_COL]) { printf ( "轮到玩家落子!\n" ); //加入while循环,保证用户输入错误时返回重新输入 while (1) { printf ( "请输入落子位置的坐标(row col):" ); //添加屏幕输入模块,输入行和列坐标 int row = 0; int col = 0; scanf ( "%d %d" , &row, &col); //输入完了之后,一定要验证输入的内容,防止输入例如(10,20)超过棋盘坐标 if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL) { printf ( "您输入的坐标有误,请重新输入!\n" ); continue ; //重新输入,继续循环 } // 当前位置不为 ' ' ,说明有子了,也需要重新输入 if (board[row][col] != ' ' ) { printf ( "当前位置有子,无法落子\n" ); continue ; } //玩家落子为 X ,结束当前循环 board[row][col] = 'X' ; break ; } } // 电脑落子 void computerMove( char board[MAX_ROW][MAX_COL]) { printf ( "轮到电脑落子!\n" ); while (1) { //电脑落子时,产生随机位置,用到随机数种子,使随机数范围在棋盘坐标以内 int row = rand () % MAX_ROW; int col = rand () % MAX_COL; if (board[row][col] != ' ' ){ // 如果行列不是空格,说明有子了,就随机生成随机数 continue ; } board[row][col] = 'O' ; break ; } } //判断和棋的函数 int isFull( char board[MAX_ROW][MAX_COL]) { //如果在棋盘中找不到 ' ' ,就说明棋盘满了,只要找到 ' ' 说明没满 //约定满了返回1,没满返回0 for ( int row = 0; row < MAX_ROW; row++) { for ( int col = 0; col < MAX_COL; col++) { if (board[row][col] == ' ' ) { //没满 return 0; } } } return 1; } // 判定胜负,由于要返回胜负,使用char定义 // 如果是玩家赢返回 X ,电脑赢返回 O,平局返回 P,胜负未分返回 ' ' char checkwinner( char board[MAX_ROW][MAX_COL]) { //1.检测所有行 for ( int row = 0; row < MAX_ROW; row++) { if (board[row][0] != ' ' && board[row][0] == board[row][1] && board[row][0] == board[row][2]) { return board[row][0]; } } //2.检测所有列 for ( int col = 0; col < MAX_ROW; col++) { if (board[0][col] != ' ' && board[0][col] == board[1][col] && board[0][col] == board[2][col]) { return board[0][col]; } } //3.检测所有对角线 if (board[0][0] != ' ' && board[0][0] == board[1][1] && board[0][0] == board[2][2]) { return board[0][0]; } if (board[2][0] != ' ' && board[2][0] == board[1][1] && board[0][0] == board[0][2]) { return board[2][0]; } // 判定和棋 if (isFull(board)) { return 'p' ; } return ' ' ; } int main() { // 首先创建棋盘并初始化 // 这里不要用board[3][3],防止后面 3 与 3 搞混,可以利用宏定义 char board[MAX_ROW][MAX_COL] = { 0 }; // 使用 init 函数 初始化二维数组{0}应当变成空格 ' ' // 此处也可以将 init函数定义中的双重 for 循环直接输入 // 但将二维数组初始化为 ' ',表示了一个固定功能的逻辑,比较适合用函数定义的方法完成 init(board); char winner = ' ' ; // 使用while循环,进行轮流落子 while (1) { //1.先打印棋盘内容 printBoard(board); //2.玩家落子 playerMove(board); winner = checkwinner(board); if (winner != ' ' ) { //胜负已分,结束循环 break ; } //3.电脑落子 computerMove(board); //4.判定胜负 winner = checkwinner(board); if (winner != ' ' ) { //胜负已分,结束循环 break ; } } if (winner = 'X' ) { printf ( "恭喜你,获胜了!\n" ); } else if (winner = 'O' ) { printf ( "很遗憾,你有点菜呀!\n" ); } else { printf ( "你和电脑五五开!\n" ); } system ( "pause" ); return 0; } |
结果如下
我们的三子棋棋盘小游戏就算结束啦!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/lmh23333/article/details/120845463