上篇博客对三子棋进行了升级,但仅仅是扩展到了多子棋,电脑算法采用的还是伪随机数的方法,电脑还是个憨憨,那么今天就对三子棋的算法进行一次优化吧,多子棋算法优化改变相应模块的条件就可以实现


这次添加了两个函数check_computerjudge_player且对ComputerMovegame两个函数以及头文件做出了更改,头文件就添加了这两个新增函数的声明。

下面介绍两个新增函数。


电脑是否能赢

电脑是否能赢,在下过一两个或者多个回合的时候,这个函数真正起到作用,如果能赢就落子。

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
//判断电脑自己是否有机会赢,如果能赢,就落子,因为自己赢的优先级肯定大于拦截对手,对吧
char check_computer(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
int k = 0;

while (0 == k)
{

//判断电脑横行上是否有机会赢
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == '#' && board[i][2] == ' ')
{
board[i][2] = '#';
k = 1;
break;
}
if (board[i][0] == board[i][2] && board[i][0] == '#' && board[i][1] == ' ')
{
board[i][1] = '#';
k = 1;
break;
}
if (board[i][1] == board[i][2] && board[i][1] == '#' && board[i][0] == ' ')
{
board[i][0] = '#';
k = 1;
break;
}
}
break;

//判断电脑列上是否有机会赢
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == '#' && board[2][j] == ' ')
{
board[2][j] = '#';
k = 1;
break;
}

if (board[0][j] == board[2][j] && board[2][j] == '#' && board[1][j] == ' ')
{
board[1][j] = '#';
k = 1;
break;
}
if (board[1][j] == board[2][j] && board[2][j] == '#' && board[0][j] == ' ')
{
board[0][j] = '#';
k = 1;
break;
}
}
break;

//判断电脑在对角线上是否会赢,又加了一个while是为了让判断对角线的代码成块。
while (0 == k)
{
if (board[0][0] == board[1][1] && board[1][1] == '#' && board[2][2] == ' ')
{
board[2][2] = '#';
k = 1;
break;
}
if (board[0][0] == board[2][2] && board[2][2] == '#' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}

if (board[1][1] == board[2][2] && board[1][1] == '#' && board[0][0] == ' ')
{
board[0][0] = '#';
k = 1;
break;
}
if (board[0][2] == board[1][1] && board[0][2] == '#' && board[2][0] == ' ')
{
board[2][0] = '#';
k = 1;
break;
}

if (board[0][2] == board[2][0] && board[2][0] == '#' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}
if (board[1][1] == board[2][0] && board[2][0] == '#' && board[0][2] == ' ')
{
board[0][2] = '#';
k = 1;
break;
}
break;
}
}

//如果电脑没机会赢,那咱就考虑拦截对手吧。
k = judge_player(board, row, col, k);
return 'N';//返回给函数一个返回值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
//下面这个函数就是判断玩家是否有机会赢,如果能赢就堵住他
char judge_player(char board[ROW][COL], int row, int col, int k)
{
int i = 0;
int j = 0;

while (0 == k)
{
//判断玩家在横行上是否有机会赢
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == '*' && board[i][2] == ' ')
{
board[i][2] = '#';
k = 1;
break;
}

if (board[i][0] == board[i][2] && board[i][0] == '*' && board[i][1] == ' ')
{
board[i][1] = '#';
k = 1;
break;
}

if (board[i][1] == board[i][2] && board[i][1] == '*' && board[i][0] == ' ')
{
board[i][0] = '#';
k = 1;
break;
}
}
//判断玩家在竖列上是否会赢
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == '*' && board[2][j] == ' ')
{
board[2][j] = '#';
k = 1;
break;
}

if (board[0][j] == board[2][j] && board[2][j] == '*' && board[1][j] == ' ')
{
board[1][j] = '#';
k = 1;
break;
}

if (board[1][j] == board[2][j] && board[2][j] == '*' && board[0][j] == ' ')
{
board[0][j] = '#';
k = 1;
break;
}
}
break;
}

while (0 == k) //判断玩家在对角线上是否会赢,又加了一个while是为了让判断对角线的代码成块。
{
if (board[0][0] == board[1][1] && board[1][1] == '*' && board[2][2] == ' ')
{
board[2][2] = '#';
k = 1;
break;
}

if (board[0][0] == board[2][2] && board[2][2] == '*' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}

if (board[1][1] == board[2][2] && board[1][1] == '*' && board[0][0] == ' ')
{
board[0][0] = '#';
k = 1;
break;
}

if (board[0][2] == board[1][1] && board[0][2] == '*' && board[2][0] == ' ')
{
board[2][0] = '#';
k = 1;
break;
}

if (board[0][2] == board[2][0] && board[2][0] == '*' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}

if (board[1][1] == board[2][0] && board[2][0] == '*' && board[0][2] == ' ')
{
board[0][2] = '#';
k = 1;
break;
}
break;
}
return 'N';//返回字符N,表示电脑没机会赢,电脑也不用拦截,然后电脑就只有随机走了
}

电脑下棋

电脑下棋需要加一步,获取返回值,如果返回值为N,那么电脑只有乖乖的按照伪随机数来走啦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//电脑输入
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
int z = 0;
printf("电脑:我走过啦!!!到你啦!!!\n\n");

z = check_computer(board, row, col);

while ('N' == z)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
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
void game(void)
{
char ret = 0;
char board[ROW][COL] = { 0 };
//初始化棋盘
InitBoard(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
while (1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断玩家是否胜利
ret = Win(board, ROW, COL);
if (ret != 'C')
{
break;
}
//电脑下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断电脑是否胜利
ret = Win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}

if (ret == '*')
{
printf("恭喜你赢啦!!!哇哦,太棒了!没几个人能战胜我呢!)\n");
printf("\n");
}
else if (ret == '#')
{
printf("你输了!!!emmm,不过没关系,毕竟你是人类哇!\n");
printf("\n");
}
else
{
printf("平局!!!嗯嗯,你已经不错了,但还要加油哦!\n");
printf("\n");
}
}

完整程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//宏定义
#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 3
#define COL 3

//引用库函数
#include<stdio.h>
#include<stdlib.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 Win(char board[ROW][COL], int row, int col);
char Full(char board[ROW][COL], int row, int col);
char judge_player(char board[ROW][COL], int row, int col,int k);
char check_computer(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
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
#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 < col; i++)
{
if (i == 0)
{
printf(" %d ", i + 1);
}
else
{
printf("%d ", i + 1);
}
}
printf("\n");

for ( int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (j == 0)
{
printf("%d %c |",i+1,board[i][j]);
}
else if (j>0 && j < col - 1)
{
printf(" %c |", board[i][j]);
}
else
printf(" %c ", board[i][j]);
}
printf("\n");
if (i < row - 1)
{

for (int k = 0; k < col; k++)
{
if (k == 0)
{
printf(" ---|");
}
else if (k>0 && k < col - 1)
{
printf("---|");
}
else
{
printf("---");
}
}
}
printf("\n");
}
}

//玩家输入
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("系统提示:请输入您要下的坐标:>>>");

scanf("%d%d", &x, &y);
printf("\n");
//判断xy是否合法,一个是是否溢出,一个是是否被占用
if (x > 0 && x < row + 1 && y>0 && y < col + 1)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("电脑:这我下过了,你个憨憨。\n");
printf("\n");

}
}
else
{
printf("电脑:FBI warning 非法输入,非法输入!!!请您自觉点\n\n电脑:乖,咱重新输入!!!\n\n");
}
}
}

//电脑输入
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
int z = 0;
printf("电脑:我走过啦!!!到你啦!!!\n\n");

z = check_computer(board, row, col);

while ('N' == z)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}

//判断电脑自己是否有机会赢,如果能赢,就落子,因为自己赢的优先级肯定大于拦截对手,对吧
char check_computer(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
int k = 0;

while (0 == k)
{
//判断电脑横行上是否有机会赢
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == '#' && board[i][2] == ' ')
{
board[i][2] = '#';
k = 1;
break;
}
if (board[i][0] == board[i][2] && board[i][0] == '#' && board[i][1] == ' ')
{
board[i][1] = '#';
k = 1;
break;
}
if (board[i][1] == board[i][2] && board[i][1] == '#' && board[i][0] == ' ')
{
board[i][0] = '#';
k = 1;
break;
}
}
break;

//判断电脑列上是否有机会赢
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == '#' && board[2][j] == ' ')
{
board[2][j] = '#';
k = 1;
break;
}

if (board[0][j] == board[2][j] && board[2][j] == '#' && board[1][j] == ' ')
{
board[1][j] = '#';
k = 1;
break;
}
if (board[1][j] == board[2][j] && board[2][j] == '#' && board[0][j] == ' ')
{
board[0][j] = '#';
k = 1;
break;
}
}
break;

//判断电脑在对角线上是否会赢,又加了一个while是为了让判断对角线的代码成块。
while (0 == k)
{
if (board[0][0] == board[1][1] && board[1][1] == '#' && board[2][2] == ' ')
{
board[2][2] = '#';
k = 1;
break;
}
if (board[0][0] == board[2][2] && board[2][2] == '#' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}

if (board[1][1] == board[2][2] && board[1][1] == '#' && board[0][0] == ' ')
{
board[0][0] = '#';
k = 1;
break;
}
if (board[0][2] == board[1][1] && board[0][2] == '#' && board[2][0] == ' ')
{
board[2][0] = '#';
k = 1;
break;
}

if (board[0][2] == board[2][0] && board[2][0] == '#' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}
if (board[1][1] == board[2][0] && board[2][0] == '#' && board[0][2] == ' ')
{
board[0][2] = '#';
k = 1;
break;
}
break;
}
}

//如果电脑没机会赢,那咱就考虑拦截对手吧。
k = judge_player(board, row, col, k);

return 'N';//返回给函数一个返回值0,表示电脑也不能赢
}

//下面这个函数就是判断玩家是否有机会赢,如果能赢就堵住他
char judge_player(char board[ROW][COL], int row, int col, int k)
{
int i = 0;
int j = 0;

while (0 == k)
{
//判断玩家在横行上是否有机会赢
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == '*' && board[i][2] == ' ')
{
board[i][2] = '#';
k = 1;
break;
}

if (board[i][0] == board[i][2] && board[i][0] == '*' && board[i][1] == ' ')
{
board[i][1] = '#';
k = 1;
break;
}

if (board[i][1] == board[i][2] && board[i][1] == '*' && board[i][0] == ' ')
{
board[i][0] = '#';
k = 1;
break;
}
}
//判断玩家在竖列上是否会赢
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == '*' && board[2][j] == ' ')
{
board[2][j] = '#';
k = 1;
break;
}

if (board[0][j] == board[2][j] && board[2][j] == '*' && board[1][j] == ' ')
{
board[1][j] = '#';
k = 1;
break;
}

if (board[1][j] == board[2][j] && board[2][j] == '*' && board[0][j] == ' ')
{
board[0][j] = '#';
k = 1;
break;
}
}
break;
}

while (0 == k) //判断玩家在对角线上是否会赢,又加了一个while是为了让判断对角线的代码成块。
{
if (board[0][0] == board[1][1] && board[1][1] == '*' && board[2][2] == ' ')
{
board[2][2] = '#';
k = 1;
break;
}

if (board[0][0] == board[2][2] && board[2][2] == '*' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}

if (board[1][1] == board[2][2] && board[1][1] == '*' && board[0][0] == ' ')
{
board[0][0] = '#';
k = 1;
break;
}

if (board[0][2] == board[1][1] && board[0][2] == '*' && board[2][0] == ' ')
{
board[2][0] = '#';
k = 1;
break;
}

if (board[0][2] == board[2][0] && board[2][0] == '*' && board[1][1] == ' ')
{
board[1][1] = '#';
k = 1;
break;
}

if (board[1][1] == board[2][0] && board[2][0] == '*' && board[0][2] == ' ')
{
board[0][2] = '#';
k = 1;
break;
}
break;
}
return 'N';//返回字符N,表示电脑没机会赢,玩家也没机会赢(电脑不用拦截)然后电脑就只有随机走了
}

//判断胜负
char Win(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][1] != ' ')//行元素一样且不是空格
{
return board[i][1];
}
}
//判断列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')//列元素一样且不是空格
{
return board[1][i];
}
}
//判断对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')//对角线元素一样且不是空格
{
return board[1][1];
}
if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
{
return board[1][1];
}
//判断是否平局
if (1 == Full(board, ROW, COL))//平局判断,函数在下面,已在头文件中声明,位置就无所谓了
{
return 'Q';
}
return 'C';
}

//平局算法函数
char Full(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;
}
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
#include"game.h"

//游戏菜单
void menu(void)
{
printf("****************************************\n");
printf("*****1.开始游戏 0.退出游戏*****\n");
printf("****************************************\n");
}

void game(void)
{
char ret = 0;
char board[ROW][COL] = { 0 };
//初始化棋盘
InitBoard(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
while (1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断玩家是否胜利
ret = Win(board, ROW, COL);
if (ret != 'C')
{
break;
}
//电脑下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断电脑是否胜利
ret = Win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}

if (ret == '*')
{
printf("恭喜你赢啦!!!哇哦,太棒了!没几个人能战胜我呢!)\n");
printf("\n");
}
else if (ret == '#')
{
printf("你输了!!!emmm,不过没关系,毕竟你是人类哇!\n");
printf("\n");
}
else
{
printf("平局!!!嗯嗯,你已经不错了,但还要加油哦!\n");
printf("\n");
}
}

void test(void)
{
int input = 0;
do
{
menu();
printf("\n");
printf("系统提示:请选择:>>>");
scanf("%d", &input);
printf("\n");
switch (input)
{
case 1:
game();
break;
case 0:
printf("破游戏,俺不玩了。\n");
break;
default:
printf("电脑:FBI warning 非法输入,非法输入,请您自觉点。\n\n电脑:乖,咱重新输入!!!\n");
break;
}
} while (input);
}

int main(void)
{
test();
return 0;
}