前言
三子棋又叫九宫棋、圈圈叉叉、一条龙、井字棋等。
三子棋游戏规则:三子连成一片即为赢,如果双方都没有连成线,即为平局。
一、如何实现?
1.棋盘大小如何确定?
我们要实现一个3×3的棋盘,就需要定义一个3行3列的数组,但是数组的下标从0开始,玩家选择落子坐标很不方便,所以要定义一个4×4的数组,第0行第0列不使用,如下图红框内的行和列不使用。这样就方便玩家选择落子坐标。
2.如何判定输赢?
三子棋的规则很简单,只要判断每一行、每一列、对角线中是否有连成线的,即为赢。
代码思路:
1、判断是否有相同的行并且不能为空格(数组初始化为空格)。
2、判断是否有相同的列并且不能为空格。
3、判断主次对角线是否相同并且不能为空格。
4、棋盘下满后是否为平局。
代码如下:
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
|
//判断谁赢,'X'表示玩家赢,'0'表示电脑赢,'p'表示平局 char IsWin( char map[ROWS][COLS], int row, int col) { int i = 0; int j = 0; int ret = IsFull(map, ROWS, COLS); //判断行 for (i = 1; i < row; i++) { if (map[i][1] == map[i][2] && map[i][2] == map[i][3] && map[i][1] != ' ' ) { return map[i][1]; } } //判断列 for (j = 1; j < col; j++) { if (map[1][j] == map[2][j] && map[2][j] == map[3][j] && map[1][j] != ' ' ) { return map[1][j]; } } //判断主对角线 if (map[1][1] == map[2][2] && map[2][2] == map[3][3] && map[1][1] != ' ' ) { return map[1][1]; } //判断次对角线 if (map[1][3] == map[2][2] && map[2][2] == map[3][1] && map[1][3] != ' ' ) { return map[1][3]; } //判断是否为平局 if (ret == 0) { return 'p' ; } else { return ' ' ; //防止编译器报错 } } |
注意:
1、三个值比较时不可以使用连等,==是关系操作符,==是从左到右进行运算的,计算表达式 a == b == c 时,首先会进行逻辑运算 a == b得出逻辑值1或0,得到的结果作为返回值,然后进行逻辑运算 “返回值” == c 得出逻辑值1或0,作为整个表达式的返回值。所以不能这样用。
2、判断完是否平局后,要加一个else,返回一个字符,不然编译器会报错:
因为编译器认为还有一种情况:当所有的if都不满足时,没有返回值,所以要加一个else返回一个对结果没有影响的字符。
二、具体代码实现
1.头文件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
|
#include<stdio.h> #include<stdlib.h> #include<time.h> #include<string.h> #define ROW 3 #define COL 3 #define ROWS ROW+1 #define COLS COL+1 //初始化棋盘 void InitMap( char map[][COLS], int row, int col); //打印棋盘 void DisplayMap( char map[][COLS], int row, int col); //玩家落子 void PlayerMove( char map[][COLS], int row, int col); //电脑落子 void ComputerMove( char map[][COLS], int row, int col); //判断棋盘是否满,0表示满,1表示未满 int IsFull( char map[][COLS], int row, int col); //判断谁赢,'X'表示玩家赢,'0'表示电脑赢,'p'表示平局 char IsWin( char map[][COLS], int row, int col); |
2.主函数main.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
|
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void menu() { printf ( "***********************************************\n" ); printf ( "******** 三子棋 *********\n" ); printf ( "***********************************************\n" ); printf ( "*************** 1.play **************\n" ); printf ( "*************** 0.exit **************\n" ); printf ( "***********************************************\n" ); } void game() { char map[ROWS][COLS]; char ret = ' ' ; //用来接收IsWin()的返回值 InitMap(map, ROWS, COLS); //初始化棋盘 DisplayMap(map, ROWS, COLS); //打印棋盘 do { PlayerMove(map, ROWS, COLS); //玩家落子 ret = IsWin(map, ROWS, COLS); if (ret == 'X' ) { printf ( "玩家赢......\n" ); break ; } else if (ret == 'p' ) { printf ( "平局......\n" ); break ; } ComputerMove(map, ROWS, COLS); //电脑落子 ret = IsWin(map, ROWS, COLS); if (ret == '0' ) { printf ( "电脑赢......\n" ); break ; } } while (IsFull(map,ROWS,COLS)); //棋盘已满,结束循环 } void test() { int input = 0; srand ((unsigned) time (NULL)); do { menu(); printf ( "请输入操作代码->" ); scanf ( "%d" , &input); switch (input) { case 1: game(); break ; case 0: printf ( "退出游戏成功......\n" ); break ; default : printf ( "选择错误,请重新输入->\n" ); break ; } } while (input); } int main() { test(); return 0; } |
3.函数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
|
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void InitMap( char map[][COLS], int row, int col) { int i = 0; int j = 0; for (i = 1; i < row; i++) { for (j = 1; j < col; j++) { map[i][j] = ' ' ; } } } void DisplayMap( char map[][COLS], int row, int col) { int i = 0; int j = 0; for (i = 1; i < row; i++) { for (j = 1; j <= col; j++) { printf ( "%3c" ,map[i][j]); if (j < col - 1) { printf ( " | " ); } } printf ( "\n" ); if (i < row - 1) { for (j = 1; j < col; j++) { printf ( " --- " ); } } printf ( "\n" ); } } void PlayerMove( char map[][COLS], int row, int col) { int x = 0; int y = 0; printf ( "玩家走->\n" ); while (1) { printf ( "请选择落子坐标->" ); scanf ( "%d %d" , &x, &y); if (x >= 1 && x <= 3 && y >= 1 && y <= 3) { if (map[x][y] == ' ' ) { map[x][y] = 'X' ; break ; //落子成功就跳出循环 } else { printf ( "该位置已被占用请重新输入->\n" ); } } else { printf ( "坐标非法,请重新输入......\n" ); } } DisplayMap(map, ROWS, COLS); } void ComputerMove( char map[][COLS], int row, int col) { int x = 0; int y = 0; printf ( "电脑走->\n" ); while (1) { x = rand () % 3 + 1; //1-3 y = rand () % 3 + 1; //1-3 if (map[x][y] == ' ' ) { map[x][y] = '0' ; break ; } } DisplayMap(map, ROWS, COLS); } //判断棋盘是否满,0表示满,1表示未满 int IsFull( char map[][COLS], int row, int col) { int i = 0; int j = 0; int count = 0; //计算落子过的格子 for (i = 1; i < row; i++) { for (j = 1; j < col; j++) { if (map[i][j] == 'X' || map[i][j] == '0' ) { count++; } } } if (count == ROW * COL) { return 0; //满 } else { return 1; } } //判断谁赢,'X'表示玩家赢,'0'表示电脑赢,'p'表示平局 char IsWin( char map[ROWS][COLS], int row, int col) { int i = 0; int j = 0; int ret = IsFull(map, ROWS, COLS); //判断行 for (i = 1; i < row; i++) { if (map[i][1] == map[i][2] && map[i][2] == map[i][3] && map[i][1] != ' ' ) { return map[i][1]; } } //判断列 for (j = 1; j < col; j++) { if (map[1][j] == map[2][j] && map[2][j] == map[3][j] && map[1][j] != ' ' ) { return map[1][j]; } } //判断主对角线 if (map[1][1] == map[2][2] && map[2][2] == map[3][3] && map[1][1] != ' ' ) { return map[1][1]; } //判断次对角线 if (map[1][3] == map[2][2] && map[2][2] == map[3][1] && map[1][3] != ' ' ) { return map[1][3]; } //判断是否为平局 if (ret == 0) { return 'p' ; } else { return ' ' ; //防止编译器报错 } } |
4、运行结果示例
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/qq_43477157/article/details/111195878