今天给大家大家带来一个用c语言实现的扫雷游戏
首先说一下用c语言实现的扫雷游戏的特点:
1.打印扫雷棋盘
2.玩家选择点开(扫雷)坐标
3.选中雷 --> 游戏结束
没选中 --> 打印棋盘并提示刚才坐标周围的雷数(八个方向)
再说下我的程序功能:
1.游戏过程中,如果选的坐标八个方向都没有雷则展开这九个坐标并提示雷数
2.如果坐标四周没有雷则不进行提示显示空格
3.选中雷则在同一张棋盘上打印出所有雷的位置和先前的游戏记录
4.记录游戏时间
5.计分功能
6.提供标记雷和去标记的功能
如果对您有帮助或者启发不妨给我点一个赞或者关注哦~
游戏视频如下:
注意:
扫雷游戏实现分三步
1 初始化
2 布置雷
3 扫雷
注意:
1)首先要清楚,扫雷棋盘上的元素:1)提示信息 2)雷 而我们在打印棋盘时不能将雷的位置打印出来。
所以,我么们就需要两个棋盘分别存贮这两种信息
2)扫雷时我们要给玩家在被点开处一个周围雷数的提示(0~8)。这个提示基于四周雷的个数,所以要对四周的坐标做出判断。
因此就出现了一个问题:在棋盘边角的元素如何判断?直接判断可能会造成溢出,所以我们给棋盘增加2行2列
3)字符和整型的转化问题
由于我是用vs分三个文件写的,想测试我的代码的朋友不妨如下图方式打开:
下面带大家具体看看我的函数的实现:
1. 游戏过程中,如果选的坐标八个方向都没有雷则展开这九个坐标并提示雷数
static int Stretch(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) {
int count = 0;//记录周围没有雷的点的个数
if (HintMine(mine, x, y) == '0')
count++;
if (HintMine(mine, x - 1, y) == '0')
count++;
if (HintMine(mine, x - 1, y-1) == '0')
count++;
if (HintMine(mine, x - 1, y+1) == '0')
count++;
if (HintMine(mine, x + 1, y) == '0')
count++;
if (HintMine(mine, x + 1, y-1) == '0')
count++;
if (HintMine(mine, x + 1, y+1) == '0')
count++;
if (HintMine(mine, x , y+1) == '0')
count++;
if (HintMine(mine, x , y-1) == '0')
count++;
if (count == 9) {
show[x][y] = ' ';
show[x-1][y] = ' ';
show[x-1][y-1] = ' ';
show[x-1][y+1] = ' ';
show[x+1][y] = ' ';
show[x+1][y-1] = ' ';
show[x+1][y+1] = ' ';
show[x][y-1] = ' ';
show[x][y+1] = ' ';
return 0;
}
else
return 1;
//如果是count = 9说明输入的坐标周围的点的周围都没有雷,则将这个区域全部亮出
//否则,返回1执行操作
}
static char HintMine(char board[ROWS][COLS], int x, int y) {
return (board[x - 1][y] + board[x - 1][y - 1] + board[x - 1][y + 1]
+ board[x + 1][y] + board[x + 1][y - 1] + board[x + 1][y + 1]
+ board[x][y - 1] + board[x][y + 1] - 7 * '0');
//因为棋盘上没有雷就是‘0’,有雷就是‘1’,所以他们的ASCII值加起来减去8个‘0’的ASCII值就是周围的雷数,
//雷数在加上一个‘0’的ACSII值就是之个数对应的ASCII值
}
2.如果坐标四周没有雷则不进行提示显示空格
if (HintMine(mine, x, y) == '0') {
show[x][y] = ' ';
}
else
show[x][y] = HintMine(mine, x, y);
3.选中雷则在同一张棋盘上打印出所有雷的位置和先前的游戏记录
void FailBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int i = 0;
int j = 0;
for (i = 1; i <=row; i++) {
for (j = 1; j <= col; j++) {
if (mine[i][j] == '1')
show[i][j] = '!';
}
}
}
6.提供标记雷和去标记的功能
printf("是否执行操作?1.是 0.否 ->");
scanf("%d", &choose);
while (choose) {
printf("1.标记地雷 2.取消标记 0.退出 -> ");
scanf("%d", &mark);
switch (mark) {
case 1:
printf("请输入坐标:->");
scanf("%d %d", &x, &y);
if (show[x][y] == '*')
show[x][y] = '#';
else
printf("非法操作!\n");
DisplayBoard(show, ROW, COL);
break;
case 2:
printf("请输入坐标:->");
scanf("%d %d", &x, &y);
if (show[x][y] == '#')
show[x][y] = '*';
else
printf("非法操作!\n");
DisplayBoard(show, ROW, COL);
break;
case 0:
choose = 0;
break;
default:
printf("选择错误请重新选择!\n");
}}
下面就是我的程序源代码
首先我们来看一下头文件game.h,这里基本包含这个程序所有的函数:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
#include<time.h>
#define ROW 4
#define COL 4
#define ROWS ROW+2
#define COLS COL+2
#define INIT_MINE '0'//这样后面的提示函数会比较好写
#define INIT_SHOW '*'
#define MARK '#'//标记地雷
#define MINENUM 15 //生成雷的个数
void InitBoard(char board[ROWS][COLS], int row, int col,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);//开始扫雷
char HintMine(char board[ROWS][COLS], int x, int y);//生成提示
int Stretch(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);//展开坐标周围
void FailBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//失败棋盘
游戏函数实现模块:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[ROWS][COLS], int row, int col,char set) {
int i = 0;
int j = 0;
//这里初始化一定要全部初始化,方便后面判断。
for (i = 0; i <row; i++) {
for (j = 0; j <col; j++) {
board[i][j] = set;
}
}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col){
int i = 0;
int j = 0;
int choose = 0;
printf("本局地雷数:%d\n",MINENUM);
printf(" ");
for (i = 1; i <= col; i++) {
printf("%d ", i);
}
printf("\n-------------------------------------\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 x = 0;
int y = 0;
int count = MINENUM;
while (count) {
x = rand() % row + 1;//这里row是9 一个随机数模9为0~8
y = rand() % col + 1;
if (board[x][y] == '0') {//字符和整型要分清,只有位置上是0才进行赋值,防止重复
board[x][y] = '1';
count--;
}
}
}
//文件内部调用的函数可以加上static
static int Stretch(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) {
int count = 0;//记录周围没有雷的点的个数
if (HintMine(mine, x, y) == '0')
count++;
if (HintMine(mine, x - 1, y) == '0')
count++;
if (HintMine(mine, x - 1, y-1) == '0')
count++;
if (HintMine(mine, x - 1, y+1) == '0')
count++;
if (HintMine(mine, x + 1, y) == '0')
count++;
if (HintMine(mine, x + 1, y-1) == '0')
count++;
if (HintMine(mine, x + 1, y+1) == '0')
count++;
if (HintMine(mine, x , y+1) == '0')
count++;
if (HintMine(mine, x , y-1) == '0')
count++;
if (count == 9) {
show[x][y] = ' ';
show[x-1][y] = ' ';
show[x-1][y-1] = ' ';
show[x-1][y+1] = ' ';
show[x+1][y] = ' ';
show[x+1][y-1] = ' ';
show[x+1][y+1] = ' ';
show[x][y-1] = ' ';
show[x][y+1] = ' ';
return 0;
}
else
return 1;
//如果是count = 9说明输入的坐标周围的点的周围都没有雷,则将这个区域全部亮出
//否则,返回1执行操作
}
static char HintMine(char board[ROWS][COLS], int x, int y) {
return (board[x - 1][y] + board[x - 1][y - 1] + board[x - 1][y + 1]
+ board[x + 1][y] + board[x + 1][y - 1] + board[x + 1][y + 1]
+ board[x][y - 1] + board[x][y + 1] - 7 * '0');
//因为棋盘上没有雷就是‘0’,有雷就是‘1’,所以他们的ASCII值加起来减去8个‘0’的ASCII值就是周围的雷数,
//雷数在加上一个‘0’的ACSII值就是之个数对应的ASCII值
}
void FailBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int i = 0;
int j = 0;
for (i = 1; i <=row; i++) {
for (j = 1; j <= col; j++) {
if (mine[i][j] == '1')
show[i][j] = '!';
}
}
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int x = 0;
int y = 0;
int count = row*col;
double begin = 0;//开始时间
double end = 0;//结束时间
int choose = 0;//选项
int mark = 0;//选项
int score = 0;//计分
begin = (double)clock();
while (count-MINENUM) {
printf("是否执行操作?1.是 0.否 ->");
scanf("%d", &choose);
while (choose) {
printf("1.标记地雷 2.取消标记 0.退出 -> ");
scanf("%d", &mark);
switch (mark) {
case 1:
printf("请输入坐标:->");
scanf("%d %d", &x, &y);
if (show[x][y] == '*')
show[x][y] = '#';
else
printf("非法操作!\n");
DisplayBoard(show, ROW, COL);
break;
case 2:
printf("请输入坐标:->");
scanf("%d %d", &x, &y);
if (show[x][y] == '#')
show[x][y] = '*';
else
printf("非法操作!\n");
DisplayBoard(show, ROW, COL);
break;
case 0:
choose = 0;
break;
default:
printf("选择错误请重新选择!\n");
}
}
rechoose:
printf("请亮出输入坐标:->");
scanf("%d %d", &x, &y);
if (show[x][y] == '#') {
printf("这是您标记的地雷!确定要打开吗?->1.是 0.否");
scanf("%d", &choose);
if (choose == 0)
goto rechoose;
}
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (mine[x][y] == '1') {
end = (double)clock();
printf("可惜,你被炸死了! 用时%.1f秒 得分:%d分\n", (end - begin) / CLOCKS_PER_SEC,score);//使用clock()计时需要一个差,除以CLOCKS_PER_SEC转化单位为秒
FailBoard(mine,show, ROW, COL);
DisplayBoard(show, ROW, COL);
break;
}
else {
if (show[x][y] == '*') {
if (Stretch(mine, show, x, y)) {
if (HintMine(mine, x, y) == '0') {
show[x][y] = ' ';
}
else
show[x][y] = HintMine(mine, x, y);
DisplayBoard(show, ROW, COL);
count--;
score++;
}
else {
count -= 9;//x,y周围都被亮出,棋盘上减少了9个数
score += 9;
DisplayBoard(show, ROW, COL);
}
}
else
printf("这个坐标您已经检查过了!请重新输入\n");
}
}
else
printf("输入坐标非法!请重新输入\n");
}
if (!(count - MINENUM)) {
end = (double)clock();
printf("恭喜你!获得胜利! 用时%.1f秒\n 得分:%d分", (end - begin) / CLOCKS_PER_SEC,score);
}
}
main函数所在的test.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu() {
printf("\n ==================================\n");
printf(" * 欢迎来到扫雷游戏 ! *\n");
printf(" * 请输入选项: *\n");
printf(" * 1. play *\n");
printf(" * 0. exit *\n");
printf(" * *\n");
printf(" ==================================\n\n");
}
void game() {
char mine[ROWS][COLS];//定义放置雷的数组
char show[ROWS][COLS];//定义防止提示的数组
srand((unsigned)time(NULL));
InitBoard(mine,ROWS,COLS,INIT_MINE);//初始化雷
InitBoard(show, ROWS, COLS,INIT_SHOW);//初始化提示
//DisplayBoard(mine,ROW,COL);
DisplayBoard(show, ROW, COL);
SetMine(mine, ROW, COL);
FindMine(mine, show, ROW, COL);
}
void test() {
int Input = 0;
do {
menu();
scanf("%d", &Input);
switch (Input) {
case 1:
game();
break;
case 0:
printf("再见!\n");
break;
default:
printf("选择错误!请重新选择\n");
break;
}
} while (Input);
}
int main() {
test();//游戏测试
return 0;
}
以上
谢谢观看