目录

前言

实现思路

游戏框架的设计

游戏界面的设计

游戏操作的实现

功能函数

初始化函数

打印棋盘

布置雷

判断游戏是否结束

计算九宫格内雷的个数

扩展式排雷

标记雷

排查雷

源文件

game.h

game.c

test.c


前言

扫雷最原始的版本可以追溯到1973年一款名为“方块”的游戏。

不久,“方块”被改写成了游戏“Rlogic”。在“Rlogic”里,玩家的任务是作为美国海军陆战队队员,为指挥中心探出一条没有地雷的安全路线,如果路全被地雷堵死就算输。两年后,汤姆·安德森在“Rlogic”的基础上又编写出了游戏“地雷”,由此奠定了现代扫雷游戏的雏形。

1981年,微软公司的罗伯特·杜尔和卡特·约翰逊两位工程师在Windows3.1系统上加载了该游戏,扫雷游戏才正式在全世界推广开来。

这款游戏的玩法是在一个9*9(初级),16*16(中级),16*30(高级),或自定义大小的方块矩阵中随机布置一定量的地雷(初级为10个,中级为40个,高级为99个)。由玩家逐个翻开方块,以找出所有地雷为最终游戏目标。如果玩家翻开的方块有地雷,则游戏结束。

实现思路

我们在实现扫雷游戏时,首先应该掌握他的游戏规则。

以下图为例,我们选择红圈所在的位置,如果他不是雷,则会在该位置显示以他为中心的九宫格中所有雷的个数。如果他是雷,则游戏结束。如果这个位置显示n则表明在他周围的八个位置中存在n颗地雷。

以下图为例

小红旗处一定为雷,但数字2右边三块位置右下角那块不是雷,但上方两块位置谁是雷无法判断,我们可以先排查(4,3)这个位置,然后再进一步推理。

在掌握游戏规则之后,我们来实现这个程序。

游戏框架的设计

程序运行之后,我们要有一个主菜单,在游戏结束之后我们能够返回主菜单选择开始游戏或是退出游戏。

游戏界面的设计

游戏开始时,我们应该有一个雷区的界面(这里我采用9*9行的雷区,如果要改可以在头文件中修改ROW和COL的值),然后有一个选择操作的提示。为了方便玩家找到对应的位置,我在这里做了一个行和列号的输出。每次玩家操作完之后使用了 system(“cls”) 清屏函数。

在输出雷区界面之前,使用两个二维数组分别存贮地雷位置的信息mine[ROWS][COLS]和输出界面的字符show[ROWS][COLS]。(这里的ROWS = ROW + 2, COLS = COL + 2,目的是为了防止边界数组元素计算雷数时越界)

结束界面,扫雷成功或是失败都需要显示布雷图给玩家看,并给出相应提示,这里我用到了Sleep(3000)函数,让结束界面停留三秒。(Sleep()函数的参数在VC环境下单位是毫秒,而在Linux环境下单位是秒,这里应该注意一下)

游戏操作的实现

布置雷

在进行排查雷之前,首先应该随机在雷区内布置雷。(雷数不能超过雷区内的空间)这里使用到了时间戳来进行随机生成雷。通过time()获取时间戳,再通过srand()和rand()的配合使用产生伪随机数序列,进行雷的布置。

排查雷

首先应该明确只有未被排查过和未被标记过的位置可以排查。

如果排查到的位置为雷,则游戏结束。

若排查到的位置不是雷,则在该位置显示周围一圈雷的个数。

但在扫雷游戏中实际会有一个展开一片的功能,当要排查的位置周围一圈雷的个数为零时,会继续排查周围一圈八个位置,并显示那些位置周围的雷数。

标记雷

我们在判断出一个位置是地雷后,应该对其进行标记,防止下次排雷时踩到他。

所以设计出一个标记雷的函数。

1.我们只能对未被排查过的位置进行标记

2.标记后的位置无法排查

3.标记标记过的位置可以取消标记

游戏状态的判断

我们在进行扫雷的时候只有两种情况能够结束游戏:

1.玩家排查的位置是雷,则玩家被炸死,游戏结束

2.玩家将所有非雷的区域排查完,玩家获胜,游戏结束,即未排查的位置和标记过的位置总数等于所布置的地雷的总数。

功能函数

初始化函数

//多一个参数set便于布置雷和打印棋盘
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set)
{int i = 0, j = 0;for (i = 0; i < rows;i++){for (j = 0;j < cols;j++){arr[i][j] = set;}}
}

打印棋盘

void ShowBoard(char show[ROWS][COLS], int row, int col)
{printf("------------------扫雷------------------\n");int i = 0, j = 0;printf("   |");//打印行号for (i = 1;i <= row;i++){printf(" %d ", i);if (i<row){printf("|");}}printf("\n");for (i = 1;i <= row;i++){for (j = 0;j <= col;j++){printf("---");if (j < col){printf("|");}}//打印列号printf("\n %d |", i);//雷区for (j = 1;j <= col;j++){printf(" %c ", show[i][j]);if (j < col){printf("|");}}printf("\n");}printf("------------------扫雷------------------\n");
}

布置雷

void SetMine(char mine[ROWS][COLS], int row, int col)
{int count = MINES;int x = 0, y = 0;//每布置一个雷count自减1,直到雷布置完while (count){x = rand() % row + 1;y = rand() % row + 1;//只有该位置未布置雷才能布置if (mine[x][y] == '0'){mine[x][y] = '1';count--;}}
}

判断游戏是否结束

//玩家获胜,游戏结束返回0,游戏未结束返回1
int IsWin(char show[ROWS][COLS], int row, int col)
{int i = 0, j = 0;int count = 0;for (i = 1;i <= row;i++){for (j = 1;j <= col;j++){//只有该位置为*或者#,才记为剩余的可操作区域,//当剩余的可操作区域等于雷数时则游戏获胜if (show[i][j] == '*' || show[i][j] == '#'){count++;}}}//若未打开区域和标记区域等于雷数则返回0,否则返回1if (count == MINES)return 0;elsereturn 1;
}

计算九宫格内雷的个数

int GetMines(char mine[ROWS][COLS], int x, int y)
{//若为雷则该位置为字符1,减去八个字符0即可获得雷的个数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 ExpandMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{//如果该位置周围8快没雷,则对周围8块检索,展开if (GetMines(mine, x, y) == 0){//展开的位置都置为0show[x][y] = '0';int i = 0;int j = 0;for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++){//只有该位置未被打开才能检索,并且检索位置应在棋盘之内if (show[i][j] == '*' && i > 0 && i <= ROW && j > 0 && j <= COL){ExpandMine(mine, show, i, j);}}}}else{//不需要展开则显示附近雷的个数show[x][y] = GetMines(mine, x, y) + '0';}
}

标记雷

void SignMine(char show[ROWS][COLS], int row, int col)
{int x = 0, y = 0;printf("请输入坐标;>");scanf("%d %d", &x, &y);//标记雷if (show[x][y] == '*'){show[x][y] = '#';}//取消标记else if (show[x][y] == '#'){show[x][y] = '*';}//若该位置被打开则无法标记elseprintf("标记失败");
}

排查雷

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0, y = 0;while (IsWin(show, row, col)){int input = 0;//1.排查雷//2.标记雷//每次操作可以选择是排查雷还是标记雷do{printf("请选择操作1.排查雷 2.标记雷:>");scanf("%d", &input);switch (input){//排查雷case 1:printf("请输入坐标;>");scanf("%d %d", &x, &y);if (x > 0 && x <= row && y > 0 && y <= col && show[x][y] != '#'){if (mine[x][y] == '1'){system("cls");printf("很遗憾你被炸死了\n");ShowBoard(mine, ROW, COL);Sleep(3000);//被炸死直接退出return ;}else{ExpandMine(mine, show, x, y);system("cls");ShowBoard(show, ROW, COL);}}else{//如果该位置被标记则无法排查if (show[x][y] == '#'){printf("该位置被标记为雷,请重新输入\n");}//如果排查位置越界则报错elseprintf("坐标非法,请重新输入\n");}break;//标记雷case 2:SignMine(show, row, col);system("cls");ShowBoard(show, ROW, COL);break;default:break;}} while (IsWin(show, row, col));//当玩家获胜或是踩雷时循环结束}//如果玩家扫雷成功,则显示布雷图if (!IsWin(show, row, col)){system("cls");printf("恭喜您扫雷成功!:>\n");ShowBoard(mine, ROW, COL);Sleep(3000);}
}

源文件

game.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
//雷数需小于等于ROW*COL
#define MINES 80//1.标记
//2.展开一片//初始化棋盘
void InitBoard(char arr[ROWS][COLS], int row, int col, char set);//打印棋盘
void ShowBoard(char show[ROWS][COLS], int row, int col);//布置雷
void SetMine(char show[ROWS][COLS], int row, int col);//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//标记雷
void SignMine(char show[ROWS][COLS], int row, int col);

game.c

#include"game.h"//初始化棋盘
//多一个参数set便于布置雷和打印棋盘
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set)
{int i = 0, j = 0;for (i = 0; i < rows;i++){for (j = 0;j < cols;j++){arr[i][j] = set;}}
}//打印棋盘
void ShowBoard(char show[ROWS][COLS], int row, int col)
{printf("------------------扫雷------------------\n");int i = 0, j = 0;printf("   |");for (i = 1;i <= row;i++){printf(" %d ", i);if (i<row){printf("|");}}printf("\n");for (i = 1;i <= row;i++){for (j = 0;j <= col;j++){printf("---");if (j < col){printf("|");}}printf("\n %d |", i);for (j = 1;j <= col;j++){printf(" %c ", show[i][j]);if (j < col){printf("|");}}printf("\n");}printf("------------------扫雷------------------\n");
}//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{int count = MINES;int x = 0, y = 0;//每布置一个雷count自减1,直到雷布置完while (count){x = rand() % row + 1;y = rand() % row + 1;if (mine[x][y] == '0'){mine[x][y] = '1';count--;}}
}//判断游戏是否结束
int IsWin(char show[ROWS][COLS], int row, int col)
{int i = 0, j = 0;int count = 0;for (i = 1;i <= row;i++){for (j = 1;j <= col;j++){//只有该位置为*或者#,才记为剩余的可操作区域,//当剩余的可操作区域等于雷数时则游戏获胜if (show[i][j] == '*' || show[i][j] == '#'){count++;}}}//若未打开区域和标记区域等于雷数则返回0,否则返回1if (count == MINES)return 0;elsereturn 1;
}//计算周围雷的个数
int GetMines(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 ExpandMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{//如果该位置周围8快没雷,则对周围8块检索,展开if (GetMines(mine, x, y) == 0){//展开的位置都置为0show[x][y] = '0';int i = 0;int j = 0;for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++){//只有该位置未被打开才能检索,并且检索位置应在棋盘之内if (show[i][j] == '*' && i > 0 && i <= ROW && j > 0 && j <= COL){ExpandMine(mine, show, i, j);}}}}else{//不需要展开则显示附近雷的个数show[x][y] = GetMines(mine, x, y) + '0';}
}//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0, y = 0;while (IsWin(show, row, col)){int input = 0;//1.排查雷//2.标记雷//每次操作可以选择是排查雷还是标记雷do{printf("请选择操作1.排查雷 2.标记雷:>");scanf("%d", &input);switch (input){//排查雷case 1:printf("请输入坐标;>");scanf("%d %d", &x, &y);if (x > 0 && x <= row && y > 0 && y <= col && show[x][y] != '#'){if (mine[x][y] == '1'){system("cls");printf("很遗憾你被炸死了\n");ShowBoard(mine, ROW, COL);Sleep(3000);//被炸死直接退出return ;}else{ExpandMine(mine, show, x, y);system("cls");ShowBoard(show, ROW, COL);}}else{//如果该位置被标记则无法排查if (show[x][y] == '#'){printf("该位置被标记为雷,请重新输入\n");}//如果排查位置越界则报错elseprintf("坐标非法,请重新输入\n");}break;//标记雷case 2:SignMine(show, row, col);system("cls");ShowBoard(show, ROW, COL);break;default:break;}} while (IsWin(show, row, col));//当玩家获胜或是踩雷时循环结束}//如果玩家扫雷成功,则显示布雷图if (!IsWin(show, row, col)){system("cls");printf("恭喜您扫雷成功!:>\n");ShowBoard(mine, ROW, COL);Sleep(3000);}
}//标记雷
void SignMine(char show[ROWS][COLS], int row, int col)
{int x = 0, y = 0;printf("请输入坐标;>");scanf("%d %d", &x, &y);//标记雷if (show[x][y] == '*'){show[x][y] = '#';}//取消标记else if (show[x][y] == '#'){show[x][y] = '*';}//若该位置被打开则无法标记elseprintf("标记失败");
}

test.c

#include"game.h"
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);//展示隐藏的雷区ShowBoard(Show, ROW, COL);//若需作弊,可以直接显示布置后的雷区/*ShowBoard(Mine, ROW, COL);*///游戏操作函数FindMine(Mine, Show, ROW, COL);system("cls");
}
//主菜单
void menu()
{printf("+---------------------------+\n");printf("|          1. play          |\n");printf("|          0. exit          |\n");printf("+---------------------------+\n");
}
//测试函数
void test()
{int input = 0;srand((unsigned int)time(NULL));do{menu();printf("请选择:>\n");scanf("%d", &input);switch (input){case 1:system("cls");game();break;case 0:printf("退出游戏\n");break;default:break;}} while (input);
}
int main()
{test();return 0;
}

文章到此就结束了,感谢大家的阅读。

扫雷游戏的实现(C语言详细版)相关推荐

  1. c语言扫雷游戏计时功能_C语言实现扫雷游戏(可以自动展开)

    前言 本篇博客主要介绍如何使用C语言实现扫雷游戏. 一.游戏规则 在一张ROW行COL列的地图上存在MINE_COUNT个地雷.玩家输入坐标翻开格子,若没有踩雷,则计算此格子周围8个格子的地雷总数,并 ...

  2. 【编程之路(007)扫雷游戏】(C语言实现)

    目录 引言 菜单的打印 初始化棋盘 棋盘的打印 布置雷区 确定周围雷数量值 标记雷 取消标记 递归展开空白安全区 统计被正确标记的雷数 扫雷的具体过程 源码 引言 扫雷这个游戏想必大家都不陌生.如果你 ...

  3. c语言程序设计扫雷游戏实验报告,C语言程序设计扫雷游戏实验报告.doc

    C语言程序设计扫雷游戏实验报告 中南大学 程序设计基础实践报告 题 目 设计一个和window系统类似的小游戏[挖地雷] 学生姓名 张兰兰 学 院 信息科学与工程学院 专业班级 物联网工程1301班 ...

  4. c语言程序设计扫雷游戏实验报告,C语言程序设计扫雷游戏实验报告.pdf

    中南大学 程序设计基础实践报告 题 目 设计一个和window系统类似的小游戏[挖地雷] 学生姓名 张兰兰 学 院 信息科学与工程学院 专业班级 物联网工程1301班 完成时间 2014.1 < ...

  5. c语言程序设计扫雷游戏实验报告,C语言程序设计扫雷游戏实验报告-20210415215509.pdf-原创力文档...

    中南大学 程序设计基础实践报告 题 目 设计一个和 window 系统类似的小游戏 [挖地雷] 学生姓名 张兰兰 学 院 信息科学与工程学院 专业班级 物联网工程 1301 班 完成时间 2014.1 ...

  6. 游戏领域的测试流程(详细版+问答)

    一.游戏测试与软件测试流程的区别 1.1 区别对比    游戏测试的流程与软件测试流程的区别大同小异,但仍然会根据公司的情况做出不同的策略和应对方式,在体验方面会存在较大的差异    (这里只单纯阐述 ...

  7. c语言扫雷显示坐标周围,C语言实现扫雷 - osc_kas7094m的个人空间 - OSCHINA - 中文开源技术交流社区...

    实现用C语言编写一个扫雷游戏 大家想必都玩过扫雷,无论那个版本都有难度供已选择,下面来分享一个自己用C语言编写的扫雷游戏吧! 编写语言:C语言 编写软件:visual studio 2017 1.首先 ...

  8. C语言编写扫雷游戏【W5+字详细教学版,包教包会】

    目录 前言 一.扫雷游戏 二.整体分析 三.游戏的实现 1.实现test文件 2.实现game.h文件 3.实现game.c文件 3.1 初始化棋盘 3.2 打印棋盘 3.3 埋放地雷 3.4 判断行 ...

  9. 超详细分解c 语言——实现扫雷游戏(详解)

    之前利用三子棋程序,介绍探讨了 c语言简单游戏编写主要模块及使用方法. 今天,我们就利用这个经典扫雷游戏,来加强对于程序思路的编写及思路. 目录 前引 游戏规则介绍 一.基本游戏思路(游戏实现方法) ...

最新文章

  1. TensorFlow学习笔记(一):数据操作指南
  2. C++中const与指针
  3. python递归算法案例教案_python教案
  4. 关于解决jdbc版本错误问题
  5. qt c++ 图片预览_Qt多语言国际化
  6. html播放切片,[Html/Css]网页切片
  7. e盾服务端源码_原罪西游源码发布!!!
  8. chrome postman插件_接口测试工具之Postman(原创)
  9. 自动生成数据同步存储过程的存储过程
  10. Java数组转Json数组
  11. spring5、springboot和springcloud的区别
  12. matlab使用parpool加速蒙特卡洛仿真
  13. 劳务派遣计算机信息管理系统,劳务派遣人员信息管理系统
  14. 微信公众号教程—记录个人公众号运营(待更新)
  15. Github推荐--PC端下载bilibili视频
  16. 智加助力解放完成“自动变道”国标验证,唯一量产自动驾驶重卡过考
  17. 读书有益——》民间治咳偏方
  18. Spring Kafka消费模式(single, batch)及确认模式(自动、手动)示例
  19. Cousera-Introduction to Data Science in Python Assignment1-4答案
  20. smart计算机英语作文,关于科技的英语作文(精选5篇)

热门文章

  1. 一个简单的macOS剪贴板管理程序
  2. C语言系列(1) --- C语言实现经典扫雷小游戏
  3. 1.JeeSite 基础—JeeSite4.x技术选型、JeeSite4.x工程搭建—导入工程、下载依赖、配置数据库、启动项目
  4. 十多年后人类将登陆火星,这项任务总共分几步
  5. 浅水方程的的精确黎曼求解器——推导浅水方程(一)
  6. c语言二级软件破解,C语言二级题库
  7. 计算机毕业设计Java的创意项目众筹平台的设计与开发(源码+系统+mysql数据库+lw文档)
  8. android手柄设置在哪里设置,android蓝牙游戏手柄怎样设置
  9. “君君臣臣父父子子”与从职责的角度来分析软件
  10. html自定义图例,javascript – ChartJS v2.0的自定义图例