云计算百科
云计算领域专业知识百科平台

C语言扫雷游戏

文章目录

  • 前言
  • 一、扫雷游戏的分析和设计
    • 1.1扫雷游戏的功能和说明
    • 1.2游戏的分析和设计
      • 1.2.1数据结构的分析
      • 1.2.2文件结构设计
  • 二、扫雷游戏的代码实现
    • 2.1`game.h`文件
    • 2.2`game.c`文件
      • 2.2.1`menu()`函数打印游戏菜单
      • 2.2.2`InitBoard()`初始化棋盘
      • 2.2.3`DisplayBoard()`打印函数
      • 2.2.4`SetMine()`布置雷
      • 2.2.5`GetMineCount()`统计单个格子周围的雷的总个数
      • 2.2.6`FindMine()`用来处理用户要探索的格子
    • 2.3`test.c`文件
  • 三、总结

前言

扫雷游戏用到的有C语言中二维数组和循环分支结构还有函数的使用

一、扫雷游戏的分析和设计

1.1扫雷游戏的功能和说明

在这里插入图片描述

  • 1.在9*9的棋盘中布置了10个雷
  • 2.点击棋盘上的方格
  • 3.如果是雷,就会被炸死,game over
  • 4.如果不是雷,就得显示周围8个格子中的总雷数
  • 5.直到你把非雷的格子全部给找出来,游戏胜利

1.2游戏的分析和设计

1.2.1数据结构的分析

问题1: 统计一个坐标周围八个坐标的雷的个数时,可能会有越界问题,如下图所示: 在这里插入图片描述 统计(8,6)坐标周围的雷的个数时,下面三个黄色的格子就会越界。

解决方法: 我们只需要给棋盘加一个边界就行,棋盘是通过二维数组实现的,所以只需要在定义二维数组时,使一维(行)和二维(列)都扩大2就行。 如图: 在这里插入图片描述 问题2: 发现一个坐标附近有一个雷时,这个信息该如何存储和打印呢? 我们可以用-1来表示雷,0来表示非雷,雷的个数直接存储,如果是这样的话,未找过的点和找过的点就会混为一谈(0表示的是未找过还是周围没有雷呢?),同时也会将雷的位置直接展示出来了。

解决方法: 定义两个数组,一个数组mine用来表示雷的位置,1表示雷,0表示非雷(用户不能看到,所以不打印);一个数组show,用*初始化,用户要探索哪个格子,就将对应的格子中的*更新为周围的雷的个数,然后再将整个show数组打印出来,告诉用户已经探索了哪些格子和这些格子周围的情况。 在这里插入图片描述 在这里插入图片描述

1.2.2文件结构设计

#mermaid-svg-epQkGdLuHOgJ9i8X{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-epQkGdLuHOgJ9i8X .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-epQkGdLuHOgJ9i8X .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-epQkGdLuHOgJ9i8X .error-icon{fill:#552222;}#mermaid-svg-epQkGdLuHOgJ9i8X .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-epQkGdLuHOgJ9i8X .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-epQkGdLuHOgJ9i8X .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-epQkGdLuHOgJ9i8X .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-epQkGdLuHOgJ9i8X .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-epQkGdLuHOgJ9i8X .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-epQkGdLuHOgJ9i8X .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-epQkGdLuHOgJ9i8X .marker{fill:#333333;stroke:#333333;}#mermaid-svg-epQkGdLuHOgJ9i8X .marker.cross{stroke:#333333;}#mermaid-svg-epQkGdLuHOgJ9i8X svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-epQkGdLuHOgJ9i8X p{margin:0;}#mermaid-svg-epQkGdLuHOgJ9i8X .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-epQkGdLuHOgJ9i8X .cluster-label text{fill:#333;}#mermaid-svg-epQkGdLuHOgJ9i8X .cluster-label span{color:#333;}#mermaid-svg-epQkGdLuHOgJ9i8X .cluster-label span p{background-color:transparent;}#mermaid-svg-epQkGdLuHOgJ9i8X .label text,#mermaid-svg-epQkGdLuHOgJ9i8X span{fill:#333;color:#333;}#mermaid-svg-epQkGdLuHOgJ9i8X .node rect,#mermaid-svg-epQkGdLuHOgJ9i8X .node circle,#mermaid-svg-epQkGdLuHOgJ9i8X .node ellipse,#mermaid-svg-epQkGdLuHOgJ9i8X .node polygon,#mermaid-svg-epQkGdLuHOgJ9i8X .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-epQkGdLuHOgJ9i8X .rough-node .label text,#mermaid-svg-epQkGdLuHOgJ9i8X .node .label text,#mermaid-svg-epQkGdLuHOgJ9i8X .image-shape .label,#mermaid-svg-epQkGdLuHOgJ9i8X .icon-shape .label{text-anchor:middle;}#mermaid-svg-epQkGdLuHOgJ9i8X .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-epQkGdLuHOgJ9i8X .rough-node .label,#mermaid-svg-epQkGdLuHOgJ9i8X .node .label,#mermaid-svg-epQkGdLuHOgJ9i8X .image-shape .label,#mermaid-svg-epQkGdLuHOgJ9i8X .icon-shape .label{text-align:center;}#mermaid-svg-epQkGdLuHOgJ9i8X .node.clickable{cursor:pointer;}#mermaid-svg-epQkGdLuHOgJ9i8X .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-epQkGdLuHOgJ9i8X .arrowheadPath{fill:#333333;}#mermaid-svg-epQkGdLuHOgJ9i8X .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-epQkGdLuHOgJ9i8X .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-epQkGdLuHOgJ9i8X .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-epQkGdLuHOgJ9i8X .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-epQkGdLuHOgJ9i8X .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-epQkGdLuHOgJ9i8X .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-epQkGdLuHOgJ9i8X .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-epQkGdLuHOgJ9i8X .cluster text{fill:#333;}#mermaid-svg-epQkGdLuHOgJ9i8X .cluster span{color:#333;}#mermaid-svg-epQkGdLuHOgJ9i8X div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-epQkGdLuHOgJ9i8X .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-epQkGdLuHOgJ9i8X rect.text{fill:none;stroke-width:0;}#mermaid-svg-epQkGdLuHOgJ9i8X .icon-shape,#mermaid-svg-epQkGdLuHOgJ9i8X .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-epQkGdLuHOgJ9i8X .icon-shape p,#mermaid-svg-epQkGdLuHOgJ9i8X .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-epQkGdLuHOgJ9i8X .icon-shape .label rect,#mermaid-svg-epQkGdLuHOgJ9i8X .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-epQkGdLuHOgJ9i8X .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-epQkGdLuHOgJ9i8X .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-epQkGdLuHOgJ9i8X :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

game.h

game.c

test.c

game.h:是自定义头文件,存放函数声明、宏定义、结构体、类型重命名;通过#include包含公共需要的系统头文件,供game.c与test.c引用。 game.c:完成各个游戏函数的具体实现代码,文件开头写#include "gane.h"。 test.c:main:程序入口,存放main()主函数,调用游戏模块提供的函数逻辑,文件开头写#include "game.h"。

二、扫雷游戏的代码实现

2.1game.h文件

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h> //用到printf(),scanf()
#include <stdlib.h> //SetMine要生成随机数,进行随机布置雷,用到rand()获取随机数,srand()设置随机数种子
#include <time.h> //SetMine要生成随机数,进行随机布置雷,用到时间种子

#define ROW 9 //棋盘真正的行数
#define COL 9 //棋盘真正的列数
#define ROWS ROW + 2 //棋盘的行数增加边界
#define COLS COL + 2 //棋盘的列数增加边界

//打印菜单
void menu();

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int r, int c, char set);

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int r, int c);

//布置雷
void SetMine(char board[ROWS][COLS], int r, int c);

//发现雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int r, int c);

2.2game.c文件

2.2.1menu()函数打印游戏菜单

void menu()
{
printf("—————–\\n");
printf("—–1.play——\\n");
printf("—–0.exit——\\n");
printf("—————–\\n");
}

在这里插入图片描述 1表示玩,0表示退出。

2.2.2InitBoard()初始化棋盘

void InitBoard(char board[ROWS][COLS], int r, int c, char set)
{
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
{
board[i][j] = set;
}
}

用来将mine全部初始化为0,之后会将0更新为1,用来表示地雷。 用来将show全部初始化为*,,用于表示未知,需要用户自己探索

2.2.3DisplayBoard()打印函数

void DisplayBoard(char board[ROWS][COLS], int r, int c)
{
for (int i = 0; i <= c; i++)
{
printf("%d ", i);
}
printf("\\n");

for (int i = 1; i <= r; i++)
{
printf("%d ", i);
for (int j = 1; j <= c; j++)
{
printf("%c ", board[i][j]);
}
printf("\\n");
}
}

用于打印show数组,告知用户探索情况 在这里插入图片描述 这是还未开始探索 在这里插入图片描述 表示(6,6)周围有一个空格是雷,需要小心

2.2.4SetMine()布置雷

void SetMine(char board[ROWS][COLS], int r, int c)
{
int count = 10;

while (count)
{
int x = rand() % r + 1;
int y = rand() % c + 1;

if (x >= 1 && x <= r && y >= 1 && y <= c && board[x][y] == '0')
{
board[x][y] = '1';
count;
}
}
}

就是将mine数组中的随机十个0更新为1,表示生成了十个雷

2.2.5GetMineCount()统计单个格子周围的雷的总个数

size_t GetMineCount(char board[ROWS][COLS], int x, int y)
{
return board[x][y 1] + board[x][y + 1] + board[x 1][y 1] + board[x 1][y] + board[x 1][y + 1] + board[x + 1][y 1] + board[x + 1][y] + board[x + 1][y + 1] 8 * '0';
}

此函数会被FindMine()用到

2.2.6FindMine()用来处理用户要探索的格子

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int r, int c)
{
int win = 0;
int x = 0;
int y = 0;

while (win < ROW * COL 10)
{
printf("请输入你要点的坐标(先行后列):");
scanf("%d%*c%d", &x, &y);

if (x >= 1 && x <= r && y >= 1 && y <= c)
{
if (mine[x][y] == '1')
{
printf("很遗憾!你不小心踩到了雷,再接再厉!\\n");
DisplayBoard(mine, ROW, COL);
break;
}
if (show[x][y] == '*')
{
show[x][y] = (char)GetMineCount(mine, x, y) + '0';
DisplayBoard(show, ROW, COL);
win++;
}
else
{
printf("该坐标已经被排查过,不用重复排查\\n");
}
}
else
{
printf("输入错误\\n");
}
}

if (win == ROW * COL 10)
{
printf("恭喜你,通关了!\\n");
}
}

如果用户探索的格子不是雷,此函数就会调用GetMineCount()来统计周围的雷的个数,更新show数组,最后调用DisplayBoard()函数来打印实时情况供用户判断;如果用户探索的格子是雷,就会gane over;如果把所有的雷都找出来了,游戏通关;也会处理输入错误的问题。

2.3test.c文件

#include "game.h"

//用game函数实现对各个函数的使用
void game()
{
char mine[ROWS][COLS];//存放的是雷的信息
char show[ROWS][COLS];//存放的是排查出的雷的信息

//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');

//打印棋盘
DisplayBoard(show, ROW, COL);

//布置雷
SetMine(mine, ROW, COL);

//排雷
FindMine(mine, show, ROW, COL);
}

int main()
{
int input = 0;
srand((unsigned int)time(NULL));

//do-while循环控制游戏进行的次数
do
{
menu();
printf("请选择:\\n");
scanf("%d", &input);

switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\\n");
break;
default:
printf("输入错误,请重新输入\\n");
break;
}
} while (input);

return 0;
}

三、总结

以上就是今天要完成的内容,一个简单的扫雷程序,本文仅仅简单介绍了二维数组和各个函数的使用还有各文件的联系,如果上述有任何问题,请懂哥指教,不过没关系,主要是自己能坚持,更希望有一起学习的同学可以帮我指正。

赞(0)
未经允许不得转载:网硕互联帮助中心 » C语言扫雷游戏
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!