目录
工程分布
由于扫雷游戏的实现较为复杂,要把该项目分为三个部分,分别用来测试,函数的实现,头文件,在以下文章称为test.c,game.c,game.h
游戏开始前界面的设计
-
设计菜单
-
用do..while实现多次游戏
-
让玩家选择“开始游戏”/“离开”
test.c:
void menu()
{
printf("******************\n");
printf("****1.开始游戏****\n");
printf("******0.离开******\n");
printf("******************\n");
}
int main()
{
srand((unsigned)time(NULL));//初始化随机数
int input = 0;
do
{
printf("-----扫雷游戏-----\n");
menu();
printf("请选择\n");
scanf("%d", &input);
system("cls");//清屏,使游戏界面更加美观
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏,游戏结束\n");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
} while (input);
return 0;
}
游戏的主体框架
-
设置两个二维数组
1.设置两个二维数组,一个是展示给玩家的,一个是来储存雷的信息的
扫雷的过程中,要统计输入位置周围8个位置的雷的个数,可能会出现统计所经位置超出边界,为了避免这样的情况发生,要让数组比实际看到的数组大一圈
test.c:
void game()
{
char show[rows][cols];//玩家实际看到的数组
char mine[rows][cols];//储存雷信息的数组
initboard(show, rows, cols, '*');
initboard(mine, rows, cols, '0');
setmine(mine, row, col);
display(show, row, col);
findmine(show, mine, row, col);
}
2.在头文件定义数组的行和列
game.h:
#define row 9//实际看到的行
#define col 9//实际看到的列
#define rows row + 2//数组实际的行
#define cols col + 2//数组实际的列
注意:将以下函数的声明放在game.h文件中,在test.c和game.h的前面使用头文件#include “game.h”(若文件名称不同自行更改)
#include "game.h"
test.c :
void initboard(char arr[rows][cols], int x, int y, char n);
void setmine(char mine[rows][cols], int x, int y);
void display(char show[rows][cols], int x, int y);
int getminecount(char mine[rows][cols], int x, int y);
void findmine(char show[rows][cols], char mine[rows][cols], int x, int y);
-
数组的初始化
用两个for循环将show数组和mine数组分别初始化为‘*’和‘0’
game.c:
void initboard(char arr[rows][cols], int x, int y, char n)
{
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
arr[i][j] = n;
}
}
}
-
雷的放置
1.确定雷的个数
game.h:
#define minecount 10
2.初始化随机数
要实现随机放置雷,那么需要随机数
test.c:
srand((unsigned)time(NULL));//初始化随机数
还要对应的头文件
game.h:
#include <stdlib.h>
#include <time.h>
3.放置雷
game.c:
void setmine(char mine[rows][cols], int x, int y)
{
int m = minecount;//由于常量不能使用后置--,所以创建临时变量
while (m)
{
int a = rand() % x + 1;//使雷放置在9*9的范围内
int b = rand() % y + 1;
if (mine[a][b] == '0')//避免重复放置
{
mine[a][b] = '1';
m--;
}
}
}
-
棋盘的显示
为了方便玩家定位,要标上行和列的编号
game.c:
void display(char show[rows][cols], int x, int y)
{
int i = 0;
int j = 0;
for (i = 0; i <= x; i++)//列的编号
{
printf("%d ", i);
}
printf("\n");
for (i = 0; i <= x; i++)//行的编号
{
printf("%d ", i);
for (j = 1; j <= y; j++)
{
printf("%c ", show[i][j]);
}
printf("\n");
}
效果演示:
-
统计周围雷的个数
(x-1,y-1) | (x-1,y-1) | (x-1,y-1) |
(x,y-1) | (x,y) | (x,y+1) |
(x+1,y-1) | (x+1,y) | (x+1,y+1) |
由Ascll码值可知:
‘0’ - ‘0’ == 0;
‘1’ - ‘0’ == 1;
‘2’ - ‘0’ == 2;
‘3’ - ‘0’ == 3;
......
那么雷的个数可由以下代码得出:
game.c :
int getminecount(char mine[rows][cols], int x, int y)
{
return (mine[x - 1][y - 1] + mine[x - 1][y]
+ mine[x - 1][y + 1] + mine[x][y - 1] +
mine[x][y + 1] + mine[x + 1][y - 1] +
mine[x + 1][y] + mine[x + 1][y + 1]) - 8 * '0';
-
雷的排查
- 用while循环实现多次输入
- 判断输入是否有效
- 对输入结果进行处理,若踩雷,游戏结束;反之,对该位置进行赋值,并用display函数显示出来,继续输入
- 若排查完所有安全的位置,则游戏胜利
void findmine(char show[rows][cols], char mine[rows][cols], int x, int y)
{
int i = 0;
int j = 0;
int k = 0;
int g = x * y - minecount;//安全位置的个数
while (k < g)
{
scanf("%d%d", &i, &j);
system("cls");//清屏,使游戏界面更加美观
if (i > 0 && i <= i && j > 0 && j <= j)//使输入坐标在合理范围内
{
if (mine[i][j] == '1')
{
printf("很遗憾,你被炸死了\n");
display(mine, x, y);
break;//直接结束游戏
}
else
{
if (show[i][j] == '*')
{
show[i][j] = getminecount(mine, i, j) + '0';
;//由于getminecount函数的返回值是数字,
//而show函数是字符型,为了保证赋值成功
// ,要把返回值加上'0',从而将数字变为
// 对应的字符,进行赋值
k++;
}
else
{
printf("输入重复,请重新输入\n");
display(show, x, y);
}
}
}
else
{
printf("输入有误,请重新输入\n");
display(show, x, y);
}
}
if (k == g)
{
printf("恭喜你,排雷成功\n");
display(mine, x, y);
}
}
完整代码
test.c:
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void game()
{
char show[rows][cols];//玩家实际看到的数组
char mine[rows][cols];//储存雷信息的数组
initboard(show, rows, cols, '*');
initboard(mine, rows, cols, '0');
setmine(mine, row, col);
display(show, row, col);
findmine(show, mine, row, col);
}
void menu()
{
printf("******************\n");
printf("****1.开始游戏****\n");
printf("******0.离开******\n");
printf("******************\n");
}
int main()
{
srand((unsigned)time(NULL));//初始化随机数
int input = 0;
do
{
printf("-----扫雷游戏-----\n");
menu();
printf("请选择\n");
scanf("%d", &input);
system("cls");//清屏,使游戏界面更加美观
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏,游戏结束\n");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
} while (input);
return 0;
}
game.c:
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void initboard(char arr[rows][cols], int x, int y, char n)
{
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
arr[i][j] = n;
}
}
}
void setmine(char mine[rows][cols], int x, int y)
{
int m = minecount;//由于常量不能使用后置--,所以创建临时变量
while (m)
{
int a = rand() % x + 1;//使雷放置在9*9的范围内
int b = rand() % y + 1;
if (mine[a][b] == '0')//避免重复放置
{
mine[a][b] = '1';
m--;
}
}
}
void display(char show[rows][cols], int x, int y)
{
int i = 0;
int j = 0;
for (i = 0; i <= x; i++)//列的编号
{
printf("%d ", i);
}
printf("\n");
for (i = 0; i <= x; i++)//行的编号
{
printf("%d ", i);
for (j = 1; j <= y; j++)
{
printf("%c ", show[i][j]);
}
printf("\n");
}
}
int getminecount(char mine[rows][cols], int x, int y)
{
return (mine[x - 1][y - 1] + mine[x - 1][y]
+ mine[x - 1][y + 1] + mine[x][y - 1] +
mine[x][y + 1] + mine[x + 1][y - 1] +
mine[x + 1][y] + mine[x + 1][y + 1]) - 8 * '0';
}
void findmine(char show[rows][cols], char mine[rows][cols], int x, int y)
{
int i = 0;
int j = 0;
int k = 0;
int g = x * y - minecount;//安全位置的个数
while (k < g)
{
scanf("%d%d", &i, &j);
system("cls");//清屏,使游戏界面更加美观
if (i > 0 && i <= i && j > 0 && j <= j)//使输入坐标在合理范围内
{
if (mine[i][j] == '1')
{
printf("很遗憾,你被炸死了\n");
display(mine, x, y);
break;//直接结束游戏
}
else
{
if (show[i][j] == '*')
{
show[i][j] = getminecount(mine, i, j) + '0';
;//由于getminecount函数的返回值是数字,
//而show函数是字符型,为了保证赋值成功
// ,要把返回值加上'0',从而将数字变为
// 对应的字符,进行赋值
k++;
}
else
{
printf("输入重复,请重新输入\n");
display(show, x, y);
}
}
}
else
{
printf("输入有误,请重新输入\n");
display(show, x, y);
}
}
if (k == g)
{
printf("恭喜你,排雷成功\n");
display(mine, x, y);
}
}
game.h:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define row 9//玩家实际看到的行
#define col 9//玩家实际看到的列
#define rows row + 2//数组实际的行
#define cols col + 2//数组实际的列
#define minecount 10
void initboard(char arr[rows][cols], int x, int y, char n);
void setmine(char mine[rows][cols], int x, int y);
void display(char show[rows][cols], int x, int y);
int getminecount(char mine[rows][cols], int x, int y);
void findmine(char show[rows][cols], char mine[rows][cols], int x, int y);
若有错误,请各位大佬指出