三子棋游戏-C语言实现(可自定义为n子棋)

下面来以我自己的理解讲解如何用C语言来实现三子棋
(可拓展棋盘,改变棋子数为n字棋)

对于一款游戏,首先我们必须要有一个可视化的菜单,供玩家选择进入游戏或者退出游戏。

void Menu_Game()
{
printf("*****************************************\n");
printf("********* 1.开始游戏 *********\n");
printf("********* 0.结束游戏 *********\n");
printf("*****************************************\n");
}
1
2
3
4
5
6
7
同时我们需要接收玩家的输入,进行相应的操作,我们可以运用switch语句来完成这个菜单。同时,当玩家输入错误时我们应该让他重新输入,而当他游戏结束时,也应当让他选择继续游戏或者进行下一次游戏

do
{
Menu_Game();
printf("请输入您的选择:\n");
scanf("%d", &n);

switch (n)
{
case 1:
Game(Checkerboard, ROW, COL);
break;
case 0:
printf("结束游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}

} while (n);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
如果想用C语言来实现三子棋,我们可以想到用一个二维数组来作为这个三子棋的棋盘,为了方便棋盘的拓展,我们可以用宏来定义棋盘的行数和列数以及棋子数

#define ROW 3
#define COL 3
#define CHESS_NUMBER 3
1
2
3
下面就可以开始具体来写游戏的实现方法,首先我们需要给数组初始化,让棋盘置空,可以遍历一次数组来让所有元素都为空格。

void Init_Checkerboard(char Checkerboard[ROW][COL], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
Checkerboard[i][j] = ' ';
}
}
}
1
2
3
4
5
6
7
8
9
10
11
然后我们需要一个函数,能够显示我们的棋盘,让我们能够看清游戏的局势,当然这个棋盘也要有一定的美观。
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019101020453066.png

void Show_Checkerboard(char Checkerboard[ROW][COL], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
{
printf("---");
printf("|");
}
printf("\n");
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", Checkerboard[i][j]);
printf("|");
}
printf("\n");
for (j = 0; j < col; j++)
{
printf("---");
printf("|");
}
printf("\n");
}
}
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 Player_Move(char Checkerboard[ROW][COL], int row, int col)
{
int x, y;
while (1)
{
printf("请输入您要下的位置:\n");
scanf("%d%d", &x, &y);
if (x > 0 && x <= ROW && y > 0 && y <= COL)
{

if (Checkerboard[x - 1][y - 1] == ' ')
{
Checkerboard[x - 1][y - 1] = '*';
break;
}
else
{
printf("该坐标已被输入\n");
}
}
else
{
printf("输入错误,请重新输入\n");
}
}

}
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
接下来就应该写电脑的落子,对于电脑的落子,我们需要保证其具有一定的随机性,所以我们需要用到几个函数,rand(),time(),srand(),。
rand 提供随机数
time 为随机数设置范围
srand 作为随机数的设置器,保证数字每一次都不同
同时我们还需要引入对应头文件

#include<stdlib.h>
#include<time.h>
1
2
我们用 rand()分别与行数列数取余数,得到随机的位置,并对其判断是否被占用,如果被占用则重新取随机数。当成功时,将一个#符号作为电脑的棋子保存入棋盘。
代码如下:

void Computer_Move(char Checkerboard[ROW][COL], int row, int col)
{
int x, y;
while (1)
{
x = rand() % ROW;
y = rand() % COL;
if (Checkerboard[x][y] == ' ')
{
Checkerboard[x][y] = '#';
break;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
下棋的步骤完成了,下面就应该判断游戏的结束条件。游戏的结束条件有三种,胜利,失败,平局。而平局的标准就是所有棋子下满但没有人取得胜利,所以我们可以先从这方面入手,我们只需要遍历棋盘,查看棋盘是否存在空位置,若不存在则为下满,我们可以返回一个N 既NOT,若下满则返回F 既FULL。

char Full_Checkerboard(char Checkerboard[ROW][COL], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
if (Checkerboard[i][j] == ' ')
return 'N';
return 'F';
}
1
2
3
4
5
6
7
8
9
然后我们接下来就可以判断究竟是电脑获胜还是玩家获胜,首先,要连成三子,我们可以行,可以列,可以左右对角线四种情况,当连成三子且不为空位置时,返回其中一个棋子,根据返回的是代表玩家的*还是代表电脑的#来判断胜负。
首先来写行的判断
为了能拓展至n子,我们要考虑其的泛用性,所以我们需要一个flag变量作为计数器,当达成

Checkerboard[i][j] == Checkerboard[i + 1][j]) && (Checkerboard[i][j] != ' '
1
这个条件时,计数器加一,而不达成时,计数器清空,这样就可以保证为连续的子.因为我们每一次与下一项进行对比,则需要判断棋子数-1次达成条件,所以当计数器与我们的棋子数-1相同时,则说明达成胜利条件,返回其中一个子。
同理对于列我们需要判断

Checkerboard[i][j] == Checkerboard[i + 1][j]) && (Checkerboard[i][j] != ' '
1
对于左对角线

Checkerboard[i][j] == Checkerboard[i + 1][j + 1]) && (Checkerboard[i][j] != ' '
1
右对角线

Checkerboard[i][j] == Checkerboard[i + 1][j - 1]) && (Checkerboard[i][j] != ' '
1
当以上四个条件没有达成时,我们还需要判断是否下满,既平局,如果所有条件没有达成,则说明游戏没有结束,返回一个N
代码如下:

char Win_Game(char Checkerboard[ROW][COL], int row, int col)
{
int i, j, flag = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 1; j++)
{
if ((Checkerboard[i][j] == Checkerboard[i][j + 1]) && (Checkerboard[i][j] != ' '))
{
flag++;
}
else if (flag == CHESS_NUMBER - 1)
return Checkerboard[i][j];
else
{
flag = 0;
}
}
}
//判断行是否三子

for (i = 0; i < row - 1; i++)
{
for (j = 0; j < col; j++)
{
if ((Checkerboard[i][j] == Checkerboard[i + 1][j]) && (Checkerboard[i][j] != ' '))
{
flag++;
}
else
{
flag = 0;
}
if (flag == CHESS_NUMBER - 1)
return Checkerboard[i][j];
}
}
//判断列是否三子

flag = 0;
for (i = 0, j = 0; i < row - 1, j < col - 1; i++, j++)
{
if ((Checkerboard[i][j] == Checkerboard[i + 1][j + 1]) && (Checkerboard[i][j] != ' '))
{
flag++;
}
else
{
flag = 0;
}
if (flag == CHESS_NUMBER - 1)
return Checkerboard[i][j];
}
//判断左对角线是否三子

flag = 0;
for (i = 0, j = row - 1; i < row - 1, j>0; i++, j--)
{
if ((Checkerboard[i][j] == Checkerboard[i + 1][j - 1]) && (Checkerboard[i][j] != ' '))
{
flag++;
}
else
{
flag = 0;
}
if (flag == CHESS_NUMBER - 1)
return Checkerboard[i][j];
}
//判断右对角线是否三子

if (Full_Checkerboard(Checkerboard, ROW, COL) == 'F')
return 'F';
//判断棋盘是否下满

return 'N';
}
//判断游戏胜负情况
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
这样,所有的游戏函数完成了,我们就要开始游戏控制函数的编写。
我们需要一个循环,让玩家和电脑下棋,当游戏没有结束的时候循环就不会跳出。而每一次我们需要让玩家和电脑分别下棋,并且显示棋盘的情况,以及判断是否胜利,因为前面我们完成了所有的游戏函数的编写,在这里直接调用就可以完成了

void Game(char Checkerboard[ROW][COL], int row, int col)
{
char flag = 'N';
srand((unsigned int)time(NULL));
//设置随机数
Init_Checkerboard(Checkerboard, ROW, COL);
Show_Checkerboard(Checkerboard, ROW, COL);
while (1)
{
printf("现在是你的回合\n");
Player_Move(Checkerboard, ROW, COL);
Show_Checkerboard(Checkerboard, ROW, COL);
if ((flag = Win_Game(Checkerboard, ROW, COL)) != 'N')
break;

printf("现在是对手的回合\n");
Computer_Move(Checkerboard, ROW, COL);
Show_Checkerboard(Checkerboard, ROW, COL);
if ((flag = Win_Game(Checkerboard, ROW, COL)) != 'N')
break;

}
if (flag == '*')
{
printf("玩家获胜\n");
}
else if (flag == '#')
{
printf("电脑获胜\n");
}
else if (flag == 'F')
{
printf("棋盘满,平局\n");
}
}
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
到这里游戏就彻底完成了

如果需要改成n子棋,我们只需要在头文件中修改棋子数量和棋盘大小即可
如8x8的五子棋

下面展示完整的代码

头文件head.h

#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
#define CHESS_NUMBER 3

void Menu_Game();

void Init_Checkerboard(char Checkerboard[ROW][COL], int row, int col);

void Show_Checkerboard(char Checkerboard[ROW][COL], int row, int col);

void Player_Move(char Checkerboard[ROW][COL], int row, int col);

void Computer_Move(char Checkerboard[ROW][COL], int row, int col);

char Full_Checkerboard(char Checkerboard[ROW][COL], int row, int col);

char Win_Game(char Checkerboard[ROW][COL], int row, int col);

void Game(char Checkerboard[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
游戏文件 game.c

#include "head.h"

void Menu_Game()
{
printf("*****************************************\n");
printf("********* 1.开始游戏 *********\n");
printf("********* 0.结束游戏 *********\n");
printf("*****************************************\n");
}

void Init_Checkerboard(char Checkerboard[ROW][COL], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
Checkerboard[i][j] = ' ';
}
}
}
//初始化棋盘

void Show_Checkerboard(char Checkerboard[ROW][COL], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
{
printf("---");
printf("|");
}
printf("\n");
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", Checkerboard[i][j]);
printf("|");
}
printf("\n");
for (j = 0; j < col; j++)
{
printf("---");
printf("|");
}
printf("\n");
}
}
//显示棋盘


void Player_Move(char Checkerboard[ROW][COL], int row, int col)
{
int x, y;
while (1)
{
printf("请输入您要下的位置:\n");
scanf("%d%d", &x, &y);
if (x > 0 && x <= ROW && x > 0 && x <= ROW)
{

if (Checkerboard[x - 1][y - 1] == ' ')
{
Checkerboard[x - 1][y - 1] = '*';
break;
}
else
{
printf("该坐标已被输入\n");
}
}
else
{
printf("输入错误,请重新输入\n");
}
}

}
//玩家移动

void Computer_Move(char Checkerboard[ROW][COL], int row, int col)
{
int x, y;
while (1)
{
x = rand() % ROW;
y = rand() % COL;
if (Checkerboard[x][y] == ' ')
{
Checkerboard[x][y] = '#';
break;
}
}

 

}
//电脑移动

char Full_Checkerboard(char Checkerboard[ROW][COL], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
if (Checkerboard[i][j] == ' ')
return 'N';
return 'F';
}
//判断棋盘是否下满

char Win_Game(char Checkerboard[ROW][COL], int row, int col)
{
int i, j, flag = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 1; j++)
{
if ((Checkerboard[i][j] == Checkerboard[i][j + 1]) && (Checkerboard[i][j] != ' '))
{
flag++;
}
else if (flag == CHESS_NUMBER - 1)
return Checkerboard[i][j];
else
{
flag = 0;
}
}
}
//判断行是否三子

for (i = 0; i < row - 1; i++)
{
for (j = 0; j < col; j++)
{
if ((Checkerboard[i][j] == Checkerboard[i + 1][j]) && (Checkerboard[i][j] != ' '))
{
flag++;
}
else
{
flag = 0;
}
if (flag == CHESS_NUMBER - 1)
return Checkerboard[i][j];
}
}
//判断列是否三子

flag = 0;
for (i = 0, j = 0; i < row - 1, j < col - 1; i++, j++)
{
if ((Checkerboard[i][j] == Checkerboard[i + 1][j + 1]) && (Checkerboard[i][j] != ' '))
{
flag++;
}
else
{
flag = 0;
}
if (flag == CHESS_NUMBER - 1)
return Checkerboard[i][j];
}
//判断左对角线是否三子

flag = 0;
for (i = 0, j = row - 1; i < row - 1, j>0; i++, j--)
{
if ((Checkerboard[i][j] == Checkerboard[i + 1][j - 1]) && (Checkerboard[i][j] != ' '))
{
flag++;
}
else
{
flag = 0;
}
if (flag == CHESS_NUMBER - 1)
return Checkerboard[i][j];
}
//判断右对角线是否三子

if (Full_Checkerboard(Checkerboard, ROW, COL) == 'F')
return 'F';
//判断棋盘是否下满

return 'N';
}
//判断游戏胜负情况

void Game(char Checkerboard[ROW][COL], int row, int col)
{
char flag = 'N';
srand((unsigned int)time(NULL));
//设置随机数
Init_Checkerboard(Checkerboard, ROW, COL);
Show_Checkerboard(Checkerboard, ROW, COL);
while (1)
{
printf("现在是你的回合\n");
Player_Move(Checkerboard, ROW, COL);
Show_Checkerboard(Checkerboard, ROW, COL);
if ((flag = Win_Game(Checkerboard, ROW, COL)) != 'N')
break;

printf("现在是对手的回合\n");
Computer_Move(Checkerboard, ROW, COL);
Show_Checkerboard(Checkerboard, ROW, COL);
if ((flag = Win_Game(Checkerboard, ROW, COL)) != 'N')
break;

}
if (flag == '*')
{
printf("玩家获胜\n");
}
else if (flag == '#')
{
printf("电脑获胜\n");
}
else if (flag == 'F')
{
printf("棋盘满,平局\n");
}
}
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
测试文件 test.c

#include "head.h"

int main()
{
int n;
char Checkerboard[ROW][COL] = { 0 };
srand((int)time(NULL));
do
{
Menu_Game();
printf("请输入您的选择:\n");
scanf("%d", &n);

switch (n)
{
case 1:
Game(Checkerboard, ROW, COL);
break;
case 0:
printf("结束游戏\n");(http://www.my516.com)
break;
default:
printf("输入错误,请重新输入\n");
break;
}

} while (n);

return 0;
}

posted @ 2019-10-12 13:42  李艳艳665  阅读(543)  评论(0编辑  收藏  举报