本文实例为大家分享了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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> //2.实现三子棋游戏。 #include<Windows.h> //Sleep() RAND_MAX 的头文件 void menu() //打印菜单 { printf ( "****************************\n" ); printf ( "**** 欢迎来到三子棋游戏 ****\n" ); printf ( "**** 1、 进入游戏 ****\n" ); printf ( "**** 0、 退出游戏 ****\n" ); printf ( "****************************\n" ); printf ( "请输入:->" ); } void print_chessboard( char coord[][3]) //打印棋盘函数 { //多维数组在传参时,接收数组的形参最多只能是第一个方括号里没有数字(下标范围) //否则就会出错(因为此时编译器不知道你要把传过来的数组的元素划分成几行几列, //但是当除第一个方括号的其他方括号都有值时,就可以经过计算知道第一个方括号的值是多少 int i = 0; int index_x = 0; int index_y = 0; for (i = 1; i <= 153; i++) { char out_ch = ' ' ; if ((i % 51 == 20) || (i % 51 == 26) || (i % 51 == 32) ) { out_ch = coord[index_x][index_y]; index_x++; if (index_x < 3) { index_x = 0; index_y++; } } else if ((i % 17 == 6) || (i % 17 == 12)) { out_ch = '|' ; } else if ( (i >= 35 && i <= 51 && i != 40 && i != 46) || \ (i >= 86 && i <= 102 && i != 91 && i != 97)) { out_ch = '_' ; } putchar (out_ch); if (i % 17 == 0) //每输出 17 个字符换下一行输出 { printf ( "\n" ); } } } void winer( char coord[][3], int *flag); //赢家判断函数的声明 int computer( char coord[][3]) //电脑下棋 { int flag = 0; int index_x2 = 0; int index_y2 = 0; srand ((unsigned) time (NULL)); while (1) { index_x2 = 2 * rand () / RAND_MAX; //产生 0--2 的随机数 index_y2 = 2 * rand () / RAND_MAX; if ((coord[index_x2][index_y2] != '*' ) && (coord[index_x2][index_y2] != 'o' )) { //判断该位置是否已有落子 coord[index_x2][index_y2] = 'o' ; winer(coord, &flag); if (flag == 1) { return 1; } return 0; } } } int player( char coord[][3], int index_x1, int index_y1) //玩家下棋 { int flag = 0; int ret = 0; if ((coord[index_x1][index_y1] == '*' ) || (coord[index_x1][index_y1] == 'o' )) { //判断该位置是否已有落子 printf ( "此位置已有棋子,请重下!\n" ); return 0; } else { coord[index_x1][index_y1] = '*' ; winer(coord, &flag); if (flag == 1) { return 1; } ret = computer(coord); if (ret == 1) { return 1; } print_chessboard(coord); //把打印棋盘放在是因为想在两人都走完一次后再打印当前棋盘状态 } return 0; } void winer( char coord[][3], int *flag) //判断是否产生赢家,赢家是谁 { char line_ch[8][4] = { { coord[0][0], coord[1][1], coord[2][2] }, { coord[0][0], coord[0][1], coord[0][2] }, \ { coord[0][0], coord[1][0], coord[2][0] }, { coord[0][1], coord[1][1], coord[2][1] }, \ { coord[0][2], coord[1][2], coord[2][2] }, { coord[1][0], coord[1][1], coord[1][2] }, \ { coord[2][0], coord[2][1], coord[2][2] }, { coord[0][2], coord[1][1], coord[2][0] } }; //把所有能赢的情况定义成一个字符串数组 int i = 0; for (i = 0; i < 8; i++) { if ( strcmp (line_ch[i], "***" ) == 0) //判断此时玩家已输入的落子能不能组成一个使玩家能赢的字符串 { print_chessboard(coord); //先打印棋盘,再判断谁胜谁负 printf ( "\n恭喜您赢了!\n" ); *flag = 1; //玩家赢,使最开始设置的赢的标志位为1,结束此次游戏 return ; } else if ( strcmp (line_ch[i], "ooo" ) == 0) { print_chessboard(coord); printf ( "\n很遗憾,您输了!\n" ); *flag = 1; return ; } else { ; } } } int main() { while (1) { int num = 0; //决定开始或退出游戏 int x = 0; int y = 0; int i = 4; //一次游戏最多的内层while循环可循环的次数 int ret = 0; //是否结束此次游戏的标志位 int is_play = 0; //是否再次玩游戏的标志位 char coordinate[3][3] = { ' ' , ' ' , ' ' , ' ' , ' ' , ' ' , ' ' , ' ' , ' ' }; //为了拓展游戏比较方便,可以把行和列定义成宏定义 menu(); scanf ( "%d" , &num); if (num == 0) { printf ( "5秒后退出程序!\n" ); Sleep(5000); exit (0); } computer(coordinate); //因为设计电脑智商低,所以游戏开始前先让电脑落一子 print_chessboard(coordinate); while ((i)) //因为总共有九个位置可以落子,已用一个,还剩八个,每次循环不结束的话会用掉两个 //所以最多循环四次 { printf ( "请输入 X、Y 的坐标(0--2)来确定你下棋的位置:" ); //也可以加一个判断输入是否合法 scanf ( "%d %d" , &x, &y); ret = player(coordinate, x, y); if (ret == 1) { break ; } i--; } printf ( "\n" ); printf ( "请选择接下来的操作:\n" ); printf ( "1、 再玩一次游戏 0、退出游戏系统\n" ); scanf ( "%d" , &is_play); if (is_play == 0) { printf ( "5秒后退出程序!\n" ); Sleep(5000); exit (0); } else { system ( "cls" ); } } system ( "pause" ); return 0; } |
程序一共设计了六个函数,一个主函数,五个自定义函数— 菜单打印函数、棋盘打印函数、电脑下棋函数、玩家下棋函数、赢家判断函数。
其中最难设计的就是棋盘打印函数和赢家判断函数。这两个函数需要完成的任务多,计算量大,逻辑设计麻烦。
下面来分析一下几个函数的设计思路:
1.菜单打印函数
这个函数很简单,一看就能明白,这儿就不多说了。
2.棋盘打印函数
首先得构思一下三子棋的棋盘应该是什么样
简单点,上图就可以作为三子棋棋盘(其实就是利用 putchar() 函数和 printf() 把显示在屏幕上的字符一个个,一行行打印上去)。设计时可把其分成四部分来看,(1) 短竖杠 ; (2) 短横杠 ; (3) 棋子(用一个二维字符数组来定义每一个棋子,用二维是因为方便输入的 X 和 Y 值与数组下标对应) ; (4) 空格(一开始打印的时候,因为还没有落子,所以把棋子也设计成空格)。 先确定要输入几行几列字符,以确定循环输出的次数,还有确定每个位置该输出的字符,这样就可以依靠循环和判断打印出棋盘了。
3 . 赢家判断函数
在每次落子后都要先进行一次判断,看是否已经产生赢家了。
因为会出现赢家的情况就八种———–
{ coord[0][0], coord[1][1], coord[2][2] }, { coord[0][0], coord[0][1], coord[0][2] },
{ coord[0][0], coord[1][0], coord[2][0] }, { coord[0][1], coord[1][1], coord[2][1] },
{ coord[2][0], coord[2][1], coord[2][2] }, { coord[1][0], coord[1][1], coord[1][2] },
{ coord[2][0], coord[2][1], coord[2][2] }, { coord[0][2], coord[1][1], coord[2][0] }
定义一个字符串数组,里面共有八个字符串,每一个字符串就是上面的一个花括弧里的内容,当某个字符串的内容与 * 或 ooo 相等,那么说明产生赢家了,否则不会产生赢家,那么就用一个循环,遍历字符串数组里的每一个字符串,判断是否会产生赢家。
4. 玩家下棋函数
玩家通过输入 x,y 坐标来确定落子的位置, x,y 对应的就是 定义的棋子二维字符数组的下标,每次先判断输入的 x,y 值对应数组下标的元素是否是 * 或 o ,是的话就说明此处已有落子,得重新输入,不是的话就落下该棋子,接着判断是否产生赢家,是的话就结束此次游戏,不是的话就判断棋盘上是否还有空位置没落子,有的话就轮到电脑继续落子,没有的话就结束此次游戏。
5. 电脑下棋函数
因为电脑是自动落子,所以得为电脑产生一个随机的 棋子二维数组下标值,使电脑随机落子,这个用srand((unsigned)time(NULL)); index_x2 = 2 * rand() / RAND_MAX; index_y2= 2 * rand() / RAND_MAX;来实现把它们放在一个while 死循环里,因为可能产生的两个随机下标那儿已经有棋子了,需要重新产生一次随机下标,当下标值与已落棋子不冲突时,就落下该棋子,接着判断是否产生赢家,是的话,就结束此次游戏,不是的话就判断棋盘上是否还有空位置没落子,有的话就轮到玩家继续落子,没有的话就结束此次游戏。
6. 主函数
在主函数里适当调用以上定义的几个函数,实现正确的逻辑功能。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/ljx_5489464/article/details/50342195