本文实例为大家分享了C语言实现三子棋游戏的具体代码,供大家参考,具体内容如下
初始工作,通过#define 定义一个标识符来表示一个常量(棋盘的横纵坐标)
(因为在代码的编写中,会有多处需要用到坐标。那么,在阅读代码时就可能会导致读者疲于理解当前的值到底是代表什么,即会对代码的解读造成困扰。所以,在该代码中通过使用宏定义解决了这个问题,同时也方便后续更改棋盘的大小。)
1
2
|
#define MAX_ROW 3
#define MAX_COL 3
|
游戏创建流程
1. 创建棋盘
创建棋盘(二维数组),并将其初始化(空白,无子状态)。
1
2
3
4
5
6
7
8
9
|
//1. 棋盘初始化
void init( char chessBoard[MAX_ROW][MAX_COL]) {
for ( int row = 0; row < MAX_ROW; row++) {
for ( int col = 0; col < MAX_COL; col++) {
//将这个棋盘(二维数组)每个位置都初始化为空
chessBoard[row][col] = ' ' ;
}
}
}
|
2. 打印棋盘
打印棋盘,令玩家能够看到此时棋盘的状态。
1
2
3
4
5
6
7
8
9
10
11
|
//2. 打印棋盘
void printChessBoard( char chessBoard[MAX_ROW][MAX_COL]) {
printf ( "+---+---+---+\n" );
for ( int row = 0; row < MAX_ROW; row++) {
printf ( "|" );
for ( int col = 0; col < MAX_COL; col++) {
printf ( " %c |" , chessBoard[row][col]);
}
printf ( "\n+---+---+---+\n" );
}
}
|
3. 玩家落子
玩家将通过输入坐标(row, col)落子。
注意:在玩家选择坐标后需要做合法性检验,即判断玩家落子的位置是否已经有子,如果有,则玩家需要重新输入坐标落子。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
//3. 玩家落子
void playMove( char chessBoard[MAX_ROW][MAX_COL]) {
while (1) {
int row = 0, col = 0;
printf ( "请玩家通过输入坐标落子:" );
scanf ( "%d %d" , &row, &col);
//检验玩家是否输入错误
if (row < 0 || col < 0 || row >= MAX_ROW || col >= MAX_COL) {
printf ( "输入错误!请重新输入" );
continue ;
}
// 检验玩家输入的位置 是否已经有子(判断位置是否为空,不为空即有子)
else if (chessBoard[row][col] != ' ' ) {
printf ( "该位置已经有子,请重新输入" );
continue ;
}
else {
//没问题,落子,标记为'x',并退出当前循环
chessBoard[row][col] = 'x' ;
break ;
}
}
}
|
4. 判定此时胜负情况
4.1 判断当前胜负情况,有四种获胜的方式:
1)横着3个都是一样的字符;
2)竖着3个都是一样的字符;
3)1,3象限对角线的3个位置都是一样的字符;
4)2,4象限对角线的3个位置都是一样的字符。
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
|
//4. 判定胜负情况,检查棋盘的所有位置,是否符合胜利的4种情况
//玩家获胜,返回x; 电脑获胜,返回o; 和棋返回p;
char chessWin( char chessBoard[MAX_ROW][MAX_COL]) {
//判断横着的3个位置
for ( int row = 0; row < MAX_ROW; row++) {
if (chessBoard[row][0] != ' ' && chessBoard[row][0] == chessBoard[row][1] && chessBoard[row][0] == chessBoard[row][2]) {
return chessBoard[row][0];
}
}
//判断竖着的3个位置
for ( int col = 0; col < MAX_COL; col++) {
if (chessBoard[0][col] != ' ' && chessBoard[0][col] == chessBoard[1][col] && chessBoard[0][col] == chessBoard[2][col] ){
return chessBoard[0][col];
}
}
//判断2,4象限对角线的3个位置
if (chessBoard[0][0] != ' ' && chessBoard[0][0] == chessBoard[1][1] && chessBoard[0][0] == chessBoard[2][2]) {
return chessBoard[0][0];
}
//判断1,3象限对角线的3个位置
if (chessBoard[2][0] != ' ' && chessBoard[2][0] == chessBoard[1][1] && chessBoard[2][0] == chessBoard[0][2]) {
return chessBoard[2][0];
}
if (isFull(chessBoard)) {
return 'p' ;
}
return ' ' ;
}
|
4.2 胜负情况判断后有4种情况,分别是:
1)玩家获胜,返回 ‘x' ;
2)电脑获胜,返回 ‘o' ;
3)和棋,棋盘下满了,但是没有分出胜负,返回 ‘p' ;
4)棋盘还有位置是空着的,下棋继续,返回 ‘ ' ;
我们在主函数中定义一个字符变量,用来判断程序结束返回的是什么,继而判断是玩家获胜、电脑获胜、和棋还是游戏未结束。
根据字符型变量的值得知游戏的结果(具体过程如后主函数内容所示)。
4.3 判断是否和棋的函数为:
1
2
3
4
5
6
7
8
9
10
11
|
//4.3 判断是否和棋(棋盘满了,但未分胜负),返回1表示棋盘满了,返回0表示棋盘未满
int isFull( char chessBoard[MAX_ROW][MAX_COL]) {
for ( int row = 0; row < MAX_ROW; row++) {
for ( int col = 0; col < MAX_COL; col++) {
if (chessBoard[row][col] == ' ' ) {
return 0;
}
}
}
return 1;
}
|
5. 电脑落子(电脑随机落子)
通过 rand() 函数实现电脑的随机落子。
(取余运算是很好的截短方法,在这里,我们通过取余运算将横纵坐标的值控制在了[0,2]之间。)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//5. 电脑落子(随机)
void computerPlayMove( char chessBoard[MAX_ROW][MAX_COL]) {
while (1) {
//控制落子的坐标 x,y 在[0,2]之间
int row = rand () % MAX_ROW;
int col = rand () % MAX_COL;
//判断电脑想落子的位置是否为空(即是否已经有子),如若已经有子,继续循环
if (chessBoard[row][col] != ' ' ) {
continue ;
}
//如果电脑想落子的位置为空,则将 ‘o' 赋给该位置,并结束循环
chessBoard[row][col] = 'o' ;
break ;
}
}
|
6. 判定此时胜负情况
同过程4。
7. 主函数
注意,我们将 字符型二维数组棋盘 写在了主函数中,而非整个程序的开头。
原因是:如果写在开头,那么这个变量就是全局变量了。
全局变量的生命周期是整个程序,会占用更多的内存,而且如果在程序中间已经使用完毕这个变量,也是不能释放内存的。
此外,全局变量的作用域是整个工程。如果在哪里将它改动后,整体都会受到影响,在查问题出在哪里的时候会很麻烦。
所以,本着尽量不使用全局变量的原则,将这个变量写在了主函数中。当其他函数需要这个参数的时候,再进行传参使用即可。
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
|
int main() {
char chessBoard[MAX_ROW][MAX_COL];
char winner = ' ' ;
//1. 棋盘初始化
init(chessBoard);
while (1) {
//2. 打印棋盘,令玩家观察此时棋盘的状态
printChessBoard(chessBoard);
//3. 玩家落子
playMove(chessBoard);
//4. 判断胜负情况
winner = chessWin(chessBoard);
if (winner != ' ' ) {
//已经有非空返回值,游戏结束
break ;
}
//5. 电脑落子
computerPlayMove(chessBoard);
//4. 判断胜负情况
winner = chessWin(chessBoard);
if (winner != ' ' ) {
//已经有非空返回值,游戏结束
break ;
}
}
if (winner == 'x' ) {
printChessBoard(chessBoard);
printf ( "恭喜玩家获胜!" );
}
else if (winner == 'o' ) {
printChessBoard(chessBoard);
printf ( "惜败,电脑获胜了哦~" );
}
else {
printChessBoard(chessBoard);
printf ( "哎呀,你和电脑打成平手了呢~" );
}
system ( "pause" );
return 0;
}
|
以上就是我在写三子棋游戏的思路、代码以及一些需要注意的点。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/qq_43503979/article/details/117793096