




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第C语言实现扫雷小游戏完整算法详解(附完整代码)目录前言1.算法基本思路2.算法详解1.初始化数组与打印数组2.设置雷3.排查与标记4.CountMine函数计算周围雷的个数5.ExpandMine函数递归展开周围所有安全区域3.完整代码!!!总结
前言
扫雷是一个常见小游戏,那么如何用C语言实现扫雷呢?学习了二维数组之后,我们可将扫雷的网格区域存储为二维数组,从而使用C语言实现扫雷。
1.算法基本思路
首先,用一个二维数组存储雷的分布,雷的分布在游戏期间从始至终不变,下文称为mine数组。用另一个二维数组存储排查出的雷的信息,在游戏期间展示给玩家,下文称为show数组。程序所要实现的几个主要功能是:1.初始化数组。2.打印数组。3.随机设置雷。4.排查雷。5.计算某个坐标周围雷的个数。6.玩家选择一个坐标后,展开周围坐标直至周围有雷的坐标。
由于计算一个坐标周围雷的个数时,会计算周围八个坐标中雷的个数之和。因此,为了防止当坐标在边角时,计算周围雷的个数时发生数组越界的现象,mine数组和show数组都应在扫雷盘面的大小基础上各增加两行或两列。
因此,常量定义为:
#defineROW9//可自由设置,扫雷盘面的行数
#defineCOL9//可自由设置,扫雷盘面的列数
#defineROWSROW+2//数组的行数
#defineCOLSCOL+2//数组的列数
#defineMINE10//地雷个数,可以自由设置
2.算法详解
1.初始化数组与打印数组
将mine数组中的各元素均初始化为0,将show数组中的各元素均初始化为*,初始化与打印均可以由简单的遍历二维数组实现。
2.设置雷
设置雷可由rand()函数随机生成。
别忘了!使用rand()之前需要调用srand()生成时间戳,使用系统时间初始化!
注意!srand()不能写在随机数生成的循环中,因此可以将srand()放在主函数中,生成一次随机数种子即可。
intx=rand()%row+1;//rand()取模row范围在0-row-1之间,+1则范围为1-row
inty=rand()%col+1;//rand()取模row范围在0-col-1之间,+1则范围为1-col
3.排查与标记
在扫雷游戏中,可以通过插小旗标记雷(再次点击取消标记),也可以通过点击方格翻开周围没有雷的区域。接受用户输入,通过分支选择进入标记(若想进入标记,则输入1)或是排查(若想排查,则输入0)。
而标记是有上限的,玩家最多标记个数即为该局游戏中雷的个数。若标记达到上限,玩家只有取消之前的标记才能继续添加标记。
玩家开始游戏时,则进入循环,游戏结束可以跳出循环。跳出循环时,要么是玩家已经展开除雷外的所有区域,游戏成功;要么是玩家踩到了雷,游戏结束。
玩家每排除一个坐标,则会翻开周围所有的安全区域(展开周围坐标直至周围有雷的坐标),这个功能可以由递归实现(ExpandBoard函数),后续讲解。
若坐标的周围有雷,则坐标会显示周围雷的个数,由CountMine函数实现,后续讲解。
4.CountMine函数计算周围雷的个数
一个坐标周围的坐标由八个坐标组成。因此,若该坐标周围有雷,排查该坐标后,该坐标应该显示周围八个坐标中雷的个数之和。
intCountMine(charboard[ROWS][COLS],introw,intcol)
intnum=0;
num=board[row-1][col+1]+board[row-1][col]+board[row-1][col-1]+board[row][col-1]+
board[row+1][col-1]+board[row+1][col]+board[row+1][col+1]+board[row][col+1]-8*'0';
/*注意:二维数组中所存的值是字符型,通过将周围的八个字符型加起来后减去八个‘0'的ARC2码值将其
转换为整型*/
returnnum;
}
5.ExpandMine函数递归展开周围所有安全区域
传统的扫雷游戏中,当你点击一个坐标,若该坐标没有雷,则会展开该坐标周围所有的安全区域,直到周围有雷的坐标,上述过程可由递归实现。
1.若该坐标没有雷,则赋值为空格。之后,判断周围八个坐标的周围是否有雷,周围没有雷的坐标同样赋值为空格,周围没有雷的坐标则继续向外展开,直到遇到周围有雷的坐标或达到了扫雷盘面的边缘,则停止递归。
2.若该坐标有雷,则直接赋值为周围雷的个数。
因此,该函数代码如下:
voidExpandBoard(charmine[ROWS][COLS],charshow[ROWS][COLS],intx,inty,int*win)
intcount=CountMine(mine,x,y);
if(count==0)
show[x][y]='';//没有雷的坐标赋值为空格
(*win)++;
//递归周围的八个格子
if(show[x-1][y-1]=='*'x-10x-1ROWSy-10y-1COLS)
ExpandBoard(mine,show,x-1,y-1,win);
if(show[x-1][y]=='*'x-10x-1ROWSy0yCOLS)
ExpandBoard(mine,show,x-1,y,win);
if(show[x-1][y+1]=='*'x-10x-1ROWSy+10y+1COLS)
ExpandBoard(mine,show,x-1,y+1,win);
if(show[x][y-1]=='*'x0xROWSy-10y-1COLS)
ExpandBoard(mine,show,x,y-1,win);
if(show[x][y+1]=='*'x0xROWSy+10y+1COLS)
ExpandBoard(mine,show,x,y+1,win);
if(show[x+1][y-1]=='*'x+10x+1ROWSy-10y-1COLS)
ExpandBoard(mine,show,x+1,y-1,win);
if(show[x+1][y]=='*'x+10x+1ROWSy0yCOLS)
ExpandBoard(mine,show,x+1,y,win);
if(show[x+1][y+1]=='*'x+10x+1ROWSy+10y+1COLS)
ExpandBoard(mine,show,x+1,y+1,win);
else
show[x][y]=count+'0';
}
3.完整代码!!!
由于代码很多,为了让代码更加易读、逻辑性更强,将代码分为test.c,game.c,game.h三个文件编写。
1.test.c源文件
#define_CRT_SECURE_NO_WARNINGS
#include"game.h"
//扫雷游戏
voidmenu()
printf("***************************\n");
printf("***1.play***\n");
printf("***0.exit***\n");
printf("***************************\n");
voidgame()
charmine[ROWS][COLS]={0};//存放雷的信息
charshow[ROWS][COLS]={0};//排查雷的信息
//初始化数组,没有布置雷时,mine均为0,show均为*
InitBoard(mine,ROWS,COLS,'0');
InitBoard(show,ROWS,COLS,'*');
//打印数组
SetMine(mine,ROW,COL);
//DisplayBoard(mine,ROW,COL);
DisplayBoard(show,ROW,COL);
FindMine(mine,show,ROW,COL);
intmain()
intinput=0;
srand((unsignedint)time(NULL));
menu();
printf("请选择——
scanf("%d",input);
switch(input)
case1:
game();
break;
case0:
printf("祝您天天开心\n");
break;
default:
printf("输入不合法,请重新输入!\n");
break;
}while(input);
return0;
}
2.game.h头文件
#pragmaonce
#includestdio.h
#includetime.h
#includestdlib.h
#defineROW9//可自由设置
#defineCOL9//可自由设置
#defineROWSROW+2
#defineCOLSCOL+2
#defineMINE10//地雷个数,可以自由设置
voidInitBoard(charboard[ROWS][COLS],introw,intcol,charset);
voidDisplayBoard(charboard[ROWS][COLS],introw,intcol);
voidSetMine(charboard[ROWS][COLS],introw,intcol);
voidFindMine(charmine[ROWS][COLS],charshow[ROWS][COLS],introw,intcol);
intCountMine(charboard[ROWS][COLS],introw,intcol);
voidExpandBoard(charmine[ROWS][COLS],charshow[ROWS][COLS],intx,inty,int*win);
3.game.c源文件
#define_CRT_SECURE_NO_WARNINGS
#include"game.h"
voidInitBoard(charboard[ROWS][COLS],introw,intcol,charset)
inti=0;
intj=0;
for(i=0;irow;i++)
for(j=0;jcol;j++)
board[i][j]=set;
voidDisplayBoard(charboard[ROWS][COLS],introw,intcol)
inti=0;
intj=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");
voidSetMine(charboard[ROWS][COLS],introw,intcol)
intcount=MINE;
while(count)
intx=rand()%row+1;//rand()取模row范围在0-row-1之间,+1则范围为1-row
inty=rand()%col+1;//rand()取模row范围在0-col-1之间,+1则范围为1-col
if(board[x][y]=='0')
board[x][y]='1';
count--;
voidFindMine(charmine[ROWS][COLS],charshow[ROWS][COLS],introw,intcol)
intx=0;
inty=0;
intinput=0;
intwin=0;
inti=1;//判断是否踩到了雷
intmark=0;//标记的次数,标记次数最多为雷的个数。
while((winrow*col-MINE)i)
printf("****1.标记****\n");
printf("****0.排查****\n");
printf("请选择-
scanf("%1d",input);
switch(input)
case1:
printf("请输入想要标记的坐标:(选择已标记的坐标则会取消标记)\n");
scanf("%d%d",x,
if(x=1x=rowy=1y=col)
if(show[x][y]=='')
printf("该坐标已标记过!将取消该坐标的标记!\n");
mark--;
show[x][y]='*';
DisplayBoard(show,ROW,COL);
else
if(markMINE)//标记个数小于雷的个数时,才可以继续标记
printf("已标记该坐标!\n");
show[x][y]='';
DisplayBoard(show,ROW,COL);
mark++;
else
printf("标记个数已达上限!只有取消之前标记,才可以继续标记!\n");
break;
else
printf("输入不合法,请重新输入!\n");
break;
case0:
printf("请输入想要排查的坐标:\n");
scanf("%d%d",x,
if(x=1x=rowy=1y=col)
if((show[x][y]!='*')(show[x][y]!=''))
printf("该坐标已排查过!\n");
else
if(mine[x][y]=='1')
i=0;
else
win++;
ExpandBoard(mine,show,x,y,win);
DisplayBoard(show,ROW,COL);
else
printf("输入不合法,请重新输入!\n");
break;
default:
printf("输入不合法,请重新输入!\n");
break;
if(win==row*col-MINE)
printf("恭喜你!排雷成功!你可真是个排雷小天才!\n\n");
else
printf("很不幸,您踩到了地雷!游戏结束!\n\n");
DisplayBoard(mine,ROW,COL);//展示设置的雷
intCountMine(charboard[ROWS][COLS],introw,intcol)
intnum=0;
num=board[row-1][col+1]+board[row-1][col]+board[row-1][col-1]+board[row][col-1]+
board[row+1][col-1]+board[row+1][col]+board[row+1][col+1]+board[row][col+1]-8*'0';
/*注意:二维数组中所存的值是字符型,通过将周围的八个字符型加起来后减去八个‘0'的ARC2码值将其
转换为整型*/
returnnum;
voidExpandBoard(charmine[ROWS][COLS],charshow[ROWS][COLS],intx,inty,int*win)
intcount=CountMine(mine,x,y);
if(count==0)
show[x][y]='';//没有雷的坐标赋值为空格
(*win)++;
//递归周围的八个格子
if(show[x-1][y-1]=='*'x-10x-1ROWSy-10y-1COLS)
ExpandBo
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 敬老院五保户合同协议书
- 木工承包合同协议书
- 物流公司劳务合同协议书
- 离职协议合同协议书
- 松树的承包合同协议书
- 艺术培训服务合同协议书
- 贷款合同协议书
- 爆破合同协议书范本
- 场地项目经理合同协议书
- 地板打蜡合同协议书范本
- 微博运营方案及工作计划
- 《体育精神》-体育故事与体育精神培养教案
- 部编本一年级下册1、吃水不忘挖井人名师公开课获奖课件百校联赛一等奖课件
- 投资合同:有限公司投资协议
- 四川大学华西口腔医院临床研究医学伦理审查申请表【模板】
- 拖欠房租通知书范文
- 年产万吨的氯乙烯合成工段的工艺设计
- 2024年湖北省中考历史试卷附答案
- 2024年银行校园招聘入职考试模拟试题及答案(共三套)
- 2024年新疆乌鲁木齐市中考化学适应性试卷
- 民法典之合同篇课件
评论
0/150
提交评论