- 1. game.h:游戏代码的声明
- 2. test.c:测试游戏的逻辑
- 2.1 menu()
- 2.2 game()
- 3. game.c:游戏代码的实现
- 3.1 初始化棋盘
- 3.2 打印棋盘
- 3.3 设置雷
- 3.4 排查雷
- 4. 完整代码
#include#include #include #define ROW 9 //定义棋盘的行 #define COL 9 //定义棋盘的列 #define ROWS ROW+2 #define COLS COL+2 #define EASY_COUNT 10 //定义雷的数量 //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set); //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col); //设置雷 void SetMine(char board[ROWS][COLS], int row, int col); //排查雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
1.为什么要用#define宏定义?
宏定义棋盘的行、列以及雷的数量,是为了方便对其进行修改,后面若想改变棋盘的大小和雷的数量,只需将宏定义处的数据改变即可。
2.为什么要定义ROWS和COLS?
统计一个坐标周围8个坐标雷的个数时,如果要统计的坐标在边界,就会出现数组越界的情况,所以为了边界坐标的统计,又将9*9的棋盘扩大了一周,变成了ROW+2和COL+2。
#include "game.h"
void menu()
{
printf("************************n");
printf("***** 1.play *****n");
printf("***** 0.exit *****n");
printf("************************n");
}
int main()
{
int intput = 0;
srand((unsigned int)time(NULL)); //设置产生随机数的种子,后面会用到
do
{
menu();
printf("请输入:");
scanf("%d", &intput);
switch (intput)
{
case 1:
game();
break;
case 0:
printf("退出游戏n");
break;
default:
printf("选择错误n");
break;
}
} while (intput);
return 0;
}
设置菜单样式,输入数字进行选择,1进入游戏,0退出游戏,输入其他数字显示选择错误,重新进行选择。
1.为什么这里的头文件是用" "而不是<>?
自定义的头文件要用" ",而这里的game.h头文件是我们自定义的。
2.为什么用do....while()循环语句?
1.选择错误时可重新进行选择
2.可多次玩扫雷游戏,直至选择0退出游戏,跳出循环
void game()
{
char mine[ROWS][COLS] = { 0 }; //存放布置好的雷的信息
char show[ROWS][COLS] = { 0 }; //存放排查出的雷的信息
InitBoard(mine, ROWS, COLS, '0'); //初始化布置雷的棋盘
InitBoard(show, ROWS, COLS, '*'); //初始化排查雷的棋盘
SetMine(mine, ROW, COL); //设置雷
DisplayBoard(show, ROW, COL); //打印排查出的雷的信息
FindMine(mine, show, ROW, COL); //排查雷
}
定义两个二维数组分别用来存放布置好的雷的信息和存放排查出的雷的信息,初始化数组的内容为指定的内容,mine 数组在没有布置雷的时候,都是’0’,show 数组在没有排查雷的时候,都是’*'。
3. game.c:游戏代码的实现 3.1 初始化棋盘#include "game.h"
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
3.2 打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("------扫雷游戏------n");
for (j = 0; j <= col; j++)
{
printf("%d ", j); //打印出9*9棋盘的横坐标
}
printf("n");
for (i = 1; i <= row; i++)
{
printf("%d ", i); //打印出9*9棋盘的纵坐标
for (j = 1; j <= col; j++)
{
printf("%c ",board[i][j]); //打印初始化好内容的棋盘
}
printf("n");
}
printf("------扫雷游戏------n");
}
为了容易观看棋盘,给棋盘打印了横纵坐标。
为什么形参这样定义char board[ROWS][COLS], int row, int col?
我们棋盘用的是11 ,* 11的,但我们真正要取的是其中的9 * 9的,也就是我们要打印出来的棋盘是9*9,没扩大之前的。
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
//1~9
//1~9
int x = rand() % row + 1; //产生随机值
int y = rand() % row + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
用while循环,每随机布置一个雷’1’,雷的总数减1,直至总数减到0,跳出循环。
对srand((unsigned int)time(NULL)),rand()有疑问的点击下面三子棋详解链接,其中的电脑下棋模块有讲解
三子棋详解
int get_mine_count(char board[ROWS][COLS], int x, int y) //计算一个坐标周围8个坐标的雷的总数
{
return (board[x - 1][y] +
board[x - 1][y - 1] +
board[x][y - 1] +
board[x + 1][y - 1] +
board[x + 1][y] +
board[x + 1][y + 1] +
board[x][y + 1] +
board[x - 1][y + 1] - 8 * '0');
}
//另一种方法计算一个坐标周围雷的总数
//int get_mine_count(char board[ROWS][COLS], int x, int y)
//{
// int i = 0;
// int j = 0;
// int count = 0;
// for (i = x - 1; i <= x + 1; i++)
// {
// for (j = y - 1; j <= y + 1; j++)
// {
// if (board[i][j] == '1')
// count++;
// }
// }
// return count;
//}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) //排查雷
{
int win = 0;
int x = 0;
int y = 0;
while (win < row*col- EASY_COUNT)
{
printf("请输入坐标:");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] != '*')
{
printf("该坐标已排查过,请重新输入坐标!n");
}
else
{
if (mine[x][y] == '1')
{
printf("你被炸死了!n");
DisplayBoard(show, ROW, COL);
}
else
{
win++;
int count = get_mine_count(mine, x, y);
show[x][y] = count +'0';
DisplayBoard(show, ROW, COL);
}
}
}
else
{
printf("坐标非法,请重新输入!n");
}
if (win == row*col-EASY_COUNT)
{
printf("恭喜你,排雷成功!n");
DisplayBoard(show, ROW, COL);
}
}
}
输入一个坐标,如果在9 * 9棋盘范围内,不等于 ’ * ’ ,代表坐标已排查过,要重新输入坐标,如果等于’1’,你就被炸死了,否则就代表不是雷,变量win加1,并显示出一个字符,代表这个坐标周围有几个雷将这个棋盘打印出来,如果输入的坐标不在9 * 9棋盘范围内,会显示坐标非法重新输入坐标,一直循环,直至win=棋盘上的所有坐标-雷总数的坐标,显示恭喜你,排雷成功,打印出棋盘后,跳出棋盘。
1.为什么一个坐标的周围的其他8个坐标的字符相加-8*‘0’?
存放布置好的雷的棋盘里坐标对应的都是 ‘0’ 或 ‘1’ , ‘0’ 的ASCII值是48,‘1’ 的ASCII值是49,‘1’ - ‘0’ = 1 , 而这个数字1就代表着有1个雷,8个字符相加-8个’0’=这个坐标周围雷的总数。
2.为什么坐标周围雷的总数count又要+'0'?
show[x][y] = count +'0';
我们棋盘上存放的是字符,不是数,而count的值是数字,我们需要转换成字符,这时只需加上’0’就可以得到我们想要的字符了,因为’0’~'9’的ASCII值为’48‘ ~‘57’。
4. 完整代码game.h
#include#include #include #define ROW 9 //定义棋盘的行 #define COL 9 //定义棋盘的列 #define ROWS ROW+2 #define COLS COL+2 #define EASY_COUNT 10 //定义雷的数量 //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set); //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col); //设置雷 void SetMine(char board[ROWS][COLS], int row, int col); //排查雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
test.c
#include "game.h"
void menu()
{
printf("************************n");
printf("***** 1.play *****n");
printf("***** 0.exit *****n");
printf("************************n");
}
void game()
{
char mine[ROWS][COLS] = { 0 }; //存放布置好的雷的信息
char show[ROWS][COLS] = { 0 }; //存放排查出的雷的信息
InitBoard(mine, ROWS, COLS, '0'); //初始化布置雷的棋盘
InitBoard(show, ROWS, COLS, '*'); //初始化排查雷的棋盘
SetMine(mine, ROW, COL); //设置雷
DisplayBoard(show, ROW, COL); //打印排查出的雷的信息
DisplayBoard(mine, ROW, COL); //打印排查出的雷的信息
FindMine(mine, show, ROW, COL); //排查雷
}
int main()
{
int intput = 0;
srand((unsigned int)time(NULL)); //设置产生随机数的种子
do
{
menu();
printf("请输入:");
scanf("%d", &intput);
switch (intput)
{
case 1:
game();
break;
case 0:
printf("退出游戏n");
break;
default:
printf("选择错误n");
break;
}
} while (intput);
return 0;
}
game.c
#include "game.h"
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("------扫雷游戏------n");
for (j = 0; j <= col; j++)
{
printf("%d ", j);
}
printf("n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ",board[i][j]);
}
printf("n");
}
printf("------扫雷游戏------n");
}
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % row + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
int get_mine_count(char board[ROWS][COLS], int x, int y) //计算一个坐标周围雷的总数
{
return (board[x - 1][y] +
board[x - 1][y - 1] +
board[x][y - 1] +
board[x + 1][y - 1] +
board[x + 1][y] +
board[x + 1][y + 1] +
board[x][y + 1] +
board[x - 1][y + 1] - 8 * '0');
}
//int get_mine_count(char board[ROWS][COLS], int x, int y)
//{
// int i = 0;
// int j = 0;
// int count = 0;
// for (i = x - 1; i <= x + 1; i++)
// {
// for (j = y - 1; j <= y + 1; j++)
// {
// if (board[i][j] == '1')
// count++;
// }
// }
// return count;
//}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) //排查雷
{
int win = 0;
int x = 0;
int y = 0;
while (win < row*col- EASY_COUNT)
{
printf("请输入坐标:");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] != '*')
{
printf("该坐标已排查过,请重新输入坐标!n");
}
else
{
if (mine[x][y] == '1')
{
printf("你被炸死了!n");
DisplayBoard(show, ROW, COL);
}
else
{
win++;
int count = get_mine_count(mine, x, y);
show[x][y] = count +'0';
DisplayBoard(show, ROW, COL);
}
}
}
else
{
printf("坐标非法,请重新输入!n");
}
if (win == row*col-EASY_COUNT)
{
printf("恭喜你,排雷成功!n");
DisplayBoard(show, ROW, COL);
}
}
}
game.h和test.c以及game.c都是需要自己创建的哦!



