在写三子棋之前,我们要先了解三子棋的一个大概的图形,以便于我们整理思路。
首先我们要分模块写代码,不要全部写在主函数里面,模块化的代码便于理解,而且给人一种赏心悦目的感觉,如:
game.h
game.c
test.c
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
|
#pragma once //头文件的包含 #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 IsWin( char board[ROW][COL], int row, int col); |
这样的好处是:例如后期想在这个代码的基础上改成十乘十的棋盘的时候,我们只需将头文件中的函数声明处的宏定义改为十即可 ,而不需要在每次传参以及定义处更改,这样便于节省很多不必要的步骤,大大提高写程序的效率。
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
|
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void menu() { printf ( "***********************\n" ); printf ( "******* 1.play ********\n" ); printf ( "******* 2.exit ********\n" ); printf ( "***********************\n" ); } void game() { //存储数据 - 二维数组 char board[ROW][COL]; //初始化棋盘 - 初始化空格 InitBoard(board, ROW, COL); //打印棋盘 - 本质是打印数组的内容 DisplayBoard(board, ROW, COL); char ret = 0; //接收游戏状态 while (1) { //玩家下棋 PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); //判断玩家是否赢的游戏 ret = IsWin(board, ROW, COL); if (ret != 'c' ) break ; //电脑下棋 ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); //判断电脑是否赢的游戏 ret = IsWin(board, ROW, COL); if (ret != 'c' ) break ; } if (ret == '*' ) { printf ( "玩家赢了\n" ); } else if (ret == '#' ) { printf ( "电脑赢了\n" ); } else { printf ( "平局\n" ); } DisplayBoard(board, ROW, COL); } int main() { int input = 0; srand ((unsigned int ) time (NULL)); do { menu(); printf ( "请选择:>" ); scanf ( "%d" , &input); switch (input) { case 1: game(); break ; case 2: printf ( "退出游戏!\n" ); break ; default : printf ( "选择错误!\n" ); break ; } } while (1); return 0; } |
建议:我们在写代码的时候,每个步骤前可以适当的加一些注释,这样即使代码很长,当我们运行有错误的时候,或者后期回顾的时候,可以很容易的找出错误点,而且能够很清晰的看出哪一块代码是在实现什么功能,不仅方便自己复习,当朋友借鉴的时候也可以让朋友通俗易懂,能够快速产生共鸣。
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
|
#define _CRT_SECURE_NO_WARNINGS 1 #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] = ' ' ; } } } // 打印棋盘 void DisplayBoard( 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++) { 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 ( "请输入下棋的坐标:>\n" ); 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; //0-2 int y = rand () % col; //0-2 //判断坐标被占用 if (board[x][y] == ' ' ) { board[x][y] = '#' ; break ; } } } // 判满 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 IsWin( 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[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ' ) { return board[1][1]; } //判断平局 int ret = IsFull(board, row, col); if (ret == 1) { return 'Q' ; } //继续 else return 'c' ; } |
思考提升
从代码中可以看出初始化棋盘没有写死,而判断输赢的时候,代码写死了,这里留给大家思考。
例子:提供三行改成多行的代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/xaiobit_hl/article/details/121255267