本文实例为大家分享了C语言实现简单三子棋游戏的具体代码,供大家参考,具体内容如下
创建文件
只要弄清了二维数组的相关知识,我们就可以去实现简单的三子棋。对于初学者可谓是成就感满满~~
首先我们会创建三个文件夹分别是game.h 、geme.c 、test.c 。其中game.h中我们会引用所有需要的头文件(test.c和game.c中#include "game.h"即可);对常用量进行宏定义;还有对封装的函数进行申明和注释,使代码可读性更高、更好进行管理。
准备环节
1.菜单打印
既然是玩游戏,玩家又要有所选择。菜单就要先蹦出来。思路:创建input变量后,执行do.while语句展示菜单,通过scanf函数来接受玩家的选择,switch语句决定退出游戏or继续游戏,如果玩家选择错误就要重新选择。
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
29void menu() //打印菜单 { printf("***********************n"); printf("******** 1.play *******n"); printf("******** 0.exit *******n"); printf("***********************n"); } int main() { int input = 0; do { menu(); //打印菜单 printf("请选择:>n"); scanf("%d", &input); switch (input) { case 1: game(); //后面将对game函数进行丰富 break; case 0: printf("退出游戏n"); break; default: printf("选择错误,重新选择n"); } } while (input); return 0; }
2.初始化棋盘
记得在.h文件中宏定义行列数,这样后期需要对棋盘大小进行修改时,直接在头文件修改即可。否则后期棋盘大小若发生变化,数组下标、函数参数,就全部要进行修改,堪比一次大手术,费时费力。
看看在game.h中的宏定义:
1
2#define ROW 3 #define COL 3
初始化棋盘:创建char数组,不选择int 类型是为了把内容全部赋值 空格 ,便于后期展示棋盘。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17void 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 game() { char Board[ROW][COL]; //创建二维数组 InitBoard(Board, ROW, COL); //初始化棋盘 }
3.打印棋盘
玩家需要落子在棋盘里 ,那么直接打印二维数组内容显然不合适。那么只要左右成员之间用"|“相隔,上下成员用”-"相隔,井字格就能打印
low版本
1
2
3
4
5
6
7
8
9
10
11//low版本 void DisplayBoard(char Board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { printf(" %c | %c | %c n", Board[i][0], Board[i][1], Board[i][2]); //左右用"|"分隔 if (i<row-1) printf("---|---|---n"); //每一行之间的分隔 } }
为什么要说这是low版本呢,循环中每一行的打印都只能展示二维数组的前三个成员,或者说只有显示三个落子位置,for循环中的i只能对行数做到限制。如果后期扩展棋盘,做成五子棋,只有行会延伸,列不会,它每一次的打印是手动完成,就是说要改进这一句话:printf("—|---|—n"); 。low版本的拓展性不好。
拓展后效果:
better版
要控制行列,那么用上i、j就好。每一行中,打印一个成员(左右有空格)就打印一个"|",打印到每一行最后一个时,不再需要分隔号,那么添加if条件判断语句就好:只要不是每一行对后一个成员,那么打印"|"。if语句就像一个关口,条件满足就通行,反之拦截。上下成员的分离和前面的循环同理,不过是"—"代替了成员打印,换汤不换药。
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
31void DisplayBoard(char Board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; //打印棋 for (j = 0; j < col; j++) { printf(" %c ", Board[i][j]); if (j < col - 1) { printf("|"); } } printf("n"); //完成一行后转行 //打印隔板 if (i < row - 1) { for (j = 0; j < col; j++) { printf("---"); if (j < col - 1) { printf("|"); } } printf("n"); //完成一行后转行 } } }
拓展前:
拓展后效果:
落子环节
玩家落子记为' * ‘,电脑落子记为' # '。
玩家落子
接受玩家坐标,确保坐标合法性,有一点需要注意,人输入的坐标是从1开始计数,而二维数组是从0开始,所以在二维数组的成员时需要减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
27void 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"); } } }
电脑落子
电脑落子是通过随机值模上棋盘行列数,同样需要合法性判断。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15void ComputerMove(char Board[ROW][COL], int row, int col) { srand((unsigned int)time(NULL)); printf("电脑走:>n"); while (1) { int x = rand() % row; //确保落子再棋盘内 int y = rand() % col; if (Board[x][y] == ' ') //是否可以落子 { Board[x][y] = '#'; break; //落完子就退出循环 } } }
输赢判断
一场游戏的结局只有三种可能:输、赢、平局。现在我们只考虑棋盘大小为三的情况,即使通过if语句暴力解开,也不那么费劲。满足了横向、竖向、斜向三个子之后,直接返回三个棋中任意一个,game()函数接受返回值后判断输赢打印结果。如果棋盘满了还没有分出胜负,就要有平局的判断,额外封装IsFull()函数。
非常感谢看到这里。
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//判断棋盘是否填满 //返回1为满 static int 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 0; //有一个空格就返回0 } } return 1; //遍历所有都未返回,说明没有空位,棋盘已满,返回1 } //输赢判断 char CheckWin(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]; } } //竖向三子 int j = 0; for (j = 0; j < col; j++) { if (Board[0][j] == Board[1][j] && Board[1][j] == Board[2][j] && Board[0][j] != ' ') { return Board[0][j]; } } //斜向三子 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 a = IsFull(Board, row, col); if (1 == a) { return 'Q'; } //继续游戏 return 'C'; } //game()函数接受 oid game() { char ret = 0; char Board[ROW][COL]; InitBoard(Board, ROW, COL); DisplayBoard(Board, ROW, COL); while (1) //没出结果就一直下棋 { PlayerMove(Board, ROW, COL); DisplayBoard(Board, ROW, COL); ret = CheckWin(Board, ROW, COL); if (ret != 'C') { break; } ComputerMove(Board, ROW, COL); DisplayBoard(Board, ROW, COL); ret = CheckWin(Board, ROW, COL); if (ret != 'C') { break; } } if (ret == '*') { printf("玩家赢了n"); } else if (ret == '#') { printf("电脑赢了n"); } else if (ret == 'Q') { printf("平局n"); } DisplayBoard(Board, ROW, COL); }
代码汇总
有嫌麻烦的同学想直接看三子棋的运行效果,直接创建文件、复制代码即可。
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
28#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 3 #define COL 3 //初始化棋盘 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 CheckWin(char Board[ROW][COL], int row, int col); //返回'*' 玩家胜利 //返回'#' 电脑胜利 //返回'Q' 平局 //返回'C' 继续游戏
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#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] = ' '; } } } low版本 //void DisplayBoard(char Board[ROW][COL], int row, int col) //{ // int i = 0; // for (i = 0; i < row; i++) // { // printf(" %c | %c | %c n", Board[i][0], Board[i][1], Board[i][2]); // if (i<row-1) // printf("---|---|---n"); // } //} void DisplayBoard(char Board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; //打印棋 for (j = 0; j < col; j++) { printf(" %c ", Board[i][j]); if (j < col - 1) { printf("|"); } } printf("n"); //打印隔板 if (i < row - 1) { for (j = 0; j < col; j++) { printf("---"); if (j < col - 1) { printf("|"); } } printf("n"); } } } 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"); } } } 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为满 static int 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 0; } } return 1; } char CheckWin(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]; } } //竖向三子 int j = 0; for (j = 0; j < col; j++) { if (Board[0][j] == Board[1][j] && Board[1][j] == Board[2][j] && Board[0][j] != ' ') { return Board[0][j]; } } //斜向三子 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 a = IsFull(Board, row, col); if (1 == a) { return 'Q'; } //继续游戏 return 'C'; }
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#include "game.h" void menu() { printf("***********************n"); printf("******** 1.play *******n"); printf("******** 0.exit *******n"); printf("***********************n"); } void game() { char ret = 0; char Board[ROW][COL]; InitBoard(Board, ROW, COL); DisplayBoard(Board, ROW, COL); while (1) { PlayerMove(Board, ROW, COL); DisplayBoard(Board, ROW, COL); ret = CheckWin(Board, ROW, COL); if (ret != 'C') { break; } ComputerMove(Board, ROW, COL); DisplayBoard(Board, ROW, COL); ret = CheckWin(Board, ROW, COL); if (ret != 'C') { break; } } if (ret == '*') { printf("玩家赢了n"); } else if (ret == '#') { printf("电脑赢了n"); } else if (ret == 'Q') { printf("平局n"); } DisplayBoard(Board, ROW, COL); } int main() { //电脑下棋随机数 srand((unsigned int)time(NULL)); int input = 0; do { menu(); printf("请选择:>n"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏n"); break; default: printf("选择错误,重新选择n"); } } while (input); return 0; }
战术总结
好的代码一定是提前构思好,做好规划,可扩展性,函数之间互相独立封装,才是便于调试和移植的好代码。如果想这个游戏更有意思,可以加上电脑和玩家先手问题。电脑下棋是随机值,可以说太笨了,我现在还没学习相关算法,还没法赋予其智能。前面的路还很长。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持靠谱客。
最后
以上就是无私枫叶最近收集整理的关于利用C语言实现简单三子棋游戏的全部内容,更多相关利用C语言实现简单三子棋游戏内容请搜索靠谱客的其他文章。
发表评论 取消回复