c语言实现三子棋游戏

@[TOC]

三子棋游戏——C语言

大家好,今天给大家带来的是用C语言实现“三子棋游戏”的代码编写。
手把手教学,包教包会,童叟无欺哦~
若有不足或疑问,欢迎评论区指正交流。
我是黎明_CL,接下来我们进入主题。

创建文件

准备:

  • 首先打开编译器,创建工程。
  • 为了方便编写和管理,我们创建三个文件,分别如下:
    • 头文件game.h
      • 用来存放数与函数的声明,便于直观地阅读代码
      • 注:以下所有游戏函数的声明都放在该文件中
    • game.c
      • #include “game.h”引用头文件
      • 用来定义函数,存放函数实现的具体内容
      • 注:以下所有游戏定义都放在该文件中
    • 创建test.c文件,用来游戏的调试
      • main函数
      • #include “game.h”引用头文件
1
2
3
4
5
6
7
8
//test.c
#include "game.h"
//#include <stdio.h>在头文件中声明,此处只声明头文件即可
int mian()
{

return 0;
}

接下来让我为大家带来三子棋游戏内容的实现过程

游戏

  • 游戏菜单

用一个简单的printf函数打印菜单mune。

  • 当玩家键盘输入input为1时开始游戏,进入游戏部分,所以我们进入game()函数;
  • 输入input为0退出游戏;
  • 输入input为其它数字,退出游戏;
  • (使用switch语句多语句判断。为了使玩家玩多次,使用do…while循环
    。)
    代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int mian()
{
do
{
manu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("开始游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入:>\n");
break;
}
} while (input==1);
return 0;
}

游戏主体

  • 分析棋盘,我们发现可以采用二维数组board[3][3]来表示棋盘。但为了使程序可被复用,便于更改数据,扩展游戏,我们在头文件内定义宏COL与ROW来表示棋盘的行和列。
1
2
#define ROW 3	//行
#define COL 3 //列

1.初始化棋盘

  • 游戏刚开始时,要使棋盘中数据为空格字符’ ‘。所以要对数组board[ ROW ][COL]进行初始化。
    初始化棋盘InPut(board,ROW,COL);
1
2
3
4
5
6
7
8
9
10
11
12
13
//game.c
void InPut(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++)
{
board[i][j] =' ';
}
}
}

2.打印棋盘

  • 这时我们尝试打印棋盘,发现看不见棋盘,因为数组是空格。所以我们要在屏幕上打印分割线来显示棋盘。所以数字间用分割线来显示,定义显示棋盘函数void DisplayBoard(char board[ROW][COL], int row, int col)
    1. 打印数据
    2. 打印分割行
      效果如下:
      ![[attachments/e455e9b3030e2ac4f6c458f7402b5cd5_MD5.png]]
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
	int i = 0;
for (i = 0; i < row; i++)
{
//1.打印数据
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]); //数据
if (j < col - 1)
printf("|"); //分隔线
}
printf("\n");
//2.打印分割行
if (i < col - 1)
{
int i = 0;
for (i = 0; i < col; i++)
{
printf("---");
if (i < col - 1)
printf("|");
}
printf("\n");
}
}
}

3.玩家/电脑下棋

目标:![[attachments/fe3f9e41472b34457e8e17fd1fb832e8_MD5.png]]

  • 接下来【玩家下棋】,定义函数void PlayerMove(char board[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
25
void PlayerMove(char board[ROW][COL], int row, int col)
{
while(1)
{
printf("请输入坐标:>\n");
printf("输入行号列号,中间用空格隔开:>");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
//判断输入行列号是否符合数量
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断该行是否已经落子
if (board[x - 1][y - 1] == ' ') //玩家不是程序员,而数组是从0开始,故减去1;
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("该位置已落子,请重新输入\n");
}
else
printf("坐标错误,请重新输入\n");
}
}
  • 接下来【电脑下棋】,定义函数void ComputerMove(char board[ROW][COL], int row, int col);
  • 要求:随机输入
    • 调用rand()函数产生随机数,在头文件中包含#include <stdlib.h>
    • 在main函数中调用srand((int)time(NULL) 来生成时间戳,在头文件中包含#include <time.h>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋:>\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}

4.判断输赢

  • 定义char IsWin(char board[ROW][COL], int row, int col);函数在玩家和电脑每次下完后都来判断输赢,故使用while循环;
  • 通过返回字符判断,规则如下:
    • 结束游戏·
      1. 玩家赢 ‘*‘
      2. 玩家输 ‘#’
      3. 平局 ‘Q’ 如果棋盘满了,则平局
    • 继续游戏 ‘C’
  • 为简化判断,每次下完都有【继续游戏】或【结束游戏】两种结果,所以在主函数中判断是否继续;
  1. 即若返回’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
 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][0] != ' ')
return board[i][0];
}
//列元素相等
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
//对角元素相等
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][2] && board[1][2] == board[2][0] && board[0][2] != ' ')
return board[0][2];
//如果棋盘满了,则平局,所以判断棋盘是否放满。
//故定义函数int IsFull(char board[ROW][COL],int row,int col)
if (IsFull(board, row, col) == 1)
{
return 'Q';
}
return 'C';
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int IsFull(char board[ROW][COL],int row,int col)
{
//遍历每个元素,判断是否为空格。但凡有一个空格没放,则返回0;
//若没空格,则表示棋盘都满了,返回1;
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] ==' ')
{
return 0;
}
}
}
return 1;
}
  1. 如果结束游戏,则在main函数中跳出循环,进行输赢判断`
1
2
3
4
5
6
if (ret == '*')
printf("玩家赢\n");
else if (ret == '#')
printf("电脑赢\n");
else
printf("平局\n");

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//game.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3 //行
#define COL 3 //列
//打印菜单
void manu();
//初始化菜单
void InPut(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);
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
//test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void game()
{
char board[ROW][COL] = { 0 };
//初始化棋盘
InPut(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");

}

int main()
{
srand((unsigned int)time(NULL));
//打印菜单
int input = 0;//注意放在while循环外面
do
{
manu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("开始游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入:>\n");
break;
}

} while (input);
return 0;
}
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
//game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

void manu()
{
printf("***********************\n");
printf("****** 1. Play ******\n");
printf("****** 0. Exit ******\n");
printf("***********************\n");
}
void InPut(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++)
{
board[i][j] =' ';
}
}
}
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
//1.打印数据
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]); //数据
if (j < col - 1)
printf("|"); //分隔线
}
printf("\n");
//2.打印分割行
if (i < col - 1)
{
int i = 0;
for (i = 0; i < col; i++)
{
printf("---");
if (i < col - 1)
printf("|");
}
printf("\n");
}
}
}
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{

while(1)
{
printf("请输入坐标:>\n");
printf("输入行号列号,中间用空格隔开:>");
int x = 0;
int y = 0;
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)
{
int x = 0;
int y = 0;
printf("电脑下棋:>\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}

int IsFull(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++)
{
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][0] != ' ')
return board[i][0];
}
//列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
//对角
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][2] && board[1][2] == board[2][0] && board[0][2] != ' ')
return board[0][2];
if (IsFull(board, row, col) == 1)
{
return 'Q';
}
return 'C';
// 玩家赢 '*'
//玩家输 '#'
//平局 'Q'
//继续 'C'
}

写在最后

  • 以上即为这个游戏所有详细操作及解释,当然还有可优化的地方如下;

      1. 在game.c中判断时代码不具有很强的复用性,可在后期进行改进优化
       //判断输赢
       char IsWin(char board\[ROW]\[COL], int row, int col)
      2. 在界面上可以采用图形库,,让游戏界面更美观
    

感谢阅读!创作不易,如果觉得其中一点有帮助到您,还请关注我,一起进步。
当然来一个点赞也是可以的哦!
🚀Live long and Prosper!🖖🏼