扫雷都涉及到哪些自定义扫雷函数

扫雷外挂的设计与实现
我的图书馆
扫雷外挂的设计与实现
TOP_MARGIN = 55;&&&&&&&&&&&&&&& //
BOTTOM_MARGIN = 8;&&&&&&&&&&&&& //
LEFT_MARGIN = 12;&&&&&&&&&&&&&& //
RIGHT_MARGIN = 8;&&&&&&&&&&&&&& //
CELL_WIDTH = 16;&&&&&&&&&&&&&&& //
CELL_HEIGHT = 16;&&&&&&&&&&&&&& //
MAX_COLUMN_COUNT = 30;&&&&&&&&& //
MAX_ROW_COUNT = 24;&&&&&&&&&&&& //
MineWnd: HWND;&&&&&&&&&&&&&&&&& //
MineDC: HDC;&&&&&&&&&&&&& &&&&&&//
clSilver: Cells[i, j] := csU&&&& //
clRed: Cells[i, j] := csM&&&&&&&&&& //
clBlack: Cells[i, j] := csP&&&&& //
clSilver: Cells[i, j] := cs0;&&& //
clBlue: Cells[i, j] := cs1;&&&&& //
clGreen: Cells[i, j] := cs2;&&&& //
clRed: Cells[i, j] := cs3;&&&&&& //
clNavy: Cells[i, j] := cs4;&&&&& //
&&&&&clMaroon: Cells[i, j] := cs5;&&& //
clTeal: Cells[i, j] := cs6;&&&&& //
clBlack: Cells[i, j] := cs7;&&&& //
clGray: Cells[i, j] := cs8;&&&&& //
downMsg, upMsg: C&&&& //
wparam, lparam: I&&&&& //
clickCount: I&&&&&&&&& //
TA的推荐TA的最新馆藏
喜欢该文的人也喜欢扫雷总结完整_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
扫雷总结完整
&&总结了一下,扫雷程序的编写思路,是用c#语言在unity中实现
阅读已结束,下载文档到电脑
想免费下载本文?
定制HR最喜欢的简历
你可能喜欢扫二维码下载作业帮
2亿+学生的选择
下载作业帮安装包
扫二维码下载作业帮
2亿+学生的选择
C语言编一个9*9的扫雷游戏程序,跟网上那些不一样,数组的使用实验目的:1)掌握数组的定义与使用;2)掌握函数的使用;3)掌握随机函数的使用;4)掌握递归方法的使用;实验内容:实现字符界面下的地雷游戏具体要求: 1)利用二维数组(9*9)存储整个游戏界面,采用‘*’表示地雷,每次游戏开始需要进行随机布雷; 2)游戏时,通过输入希望打开格子的行号和列号; 3)对于没有打开的各自使用字符‘#’,表示未打开; 4)对于已经打开的格子若没有地雷,在该格子中显示周围有多少个地雷;5)源程序压缩以后提交.命名方式:学号专业班级序号.rar实验指导:1.布雷;1)如何表示地雷:定义数组 mine[9][9]={0};2)如何布雷:一个地雷的设置:Row=rand()%9; Col=rand()%9;ming[Row][Col]=‘*’;避免重复布雷;3)计算无地雷格子的周围的地雷数:普通情况,为周围8格;特殊情况(边,角),注意数组朝界;2.表示游戏状态1)设置表示游戏状态的数组,game[9][9]={0}1 表示格子格子已经打开;0 表示没有打开;2)显示当前状态定义一个函数用于输出当前状态;该函数需要控制每行输出9次,共输出9次根据game中元素的值选择输出结果:首先测试格子是否已经打开;若打开判定该格子是否是地雷3 1)游戏开始后输入希望打开格子的行号和列号;2)判定指定格子是否是地雷:若是地雷,游戏结束;不是地雷,显示该格子周围的8个格子;若格子中地雷数为0,展开该格子周围8个格子:分为三种情况:有雷的格子:保持原样;无地雷但非0的格子,显示数字;无地雷但为0的格子,显示0,并展开该格子周围8各格子,该过程递归进行,注意递归结束的条件.
扫二维码下载作业帮
2亿+学生的选择
太复杂,我分成几部分试着做一下首先是画棋盘,定义两个二维数组来表示每个棋子的状态和棋子周围的雷数,用于显示.//画棋盘 a表示棋子是否已被翻开,b表示附近的雷数bool MakeMap(bool a[9][9],int b[9][9]){&&&&int i=0,j=0;&&&&for(i=0;i&9;i++)&&&&{&&&&&&&&for(j=0;j&9;j++)&&&&&&&&{&&&&&&&&&&&&if(a[i][j]) printf("%d ",b[i][j]);&&&&&&&&&&&&else printf("# ");&&&&&&&&}&&&&&&&&printf("\n");&&&&}&&&&}
这个不完全啊!!
贴代码太复杂了,我贴图片吧把邮箱给我我把代码发给你,这里贴代码太不方便结果:
为您推荐:
扫描下载二维码自动扫雷算法的具体实现
自动扫雷程序主要由三个模块构成:欢迎模块WELCOME()、智能模块ANALYZE()和
控制模块GAME_CONTRO()。三个模块通过一些全局变量交互一些信息。下面是一些重要的全局变量:
//记录棋盘上被打开的格子数,即被点击过的格子数,其
&&&&&&&&&&&&&&&&&&
//初值为Height* Width,每打开一个格子,其值-1
Height,W&&&
//棋盘的高度和宽度
Mine_&&&&&&&&&
//雷的数量
char **mine_
//这个数组记录实际的布雷情况,这个数组中元素为* 的地
//方表示该位置是雷,为数字的地方指示该位置周围有多少雷,这个数组并不显示给用户
**score_&&
//在ANALYZE函数中,用于记录每一个格子的分值
**view_& //这个数组是记录程序扫雷的状态,显示在屏幕上
下面,就每一个模块的功能和其中的主要函数进行说明
一、WELCOME()模块
函数原型:void WELCOME();
这个模块的主要功能是显示欢迎界面,由用户输入棋盘大小,完成布雷等初始化工作。
主要的函数是随机设置地雷位置的函数void
set_mine(char**&board)
set_mine(char**&board)的功能是在mine_board
上随机设置N个地雷(N=Mine_num),将mine_board有雷的相应位置标识为‘*’,然后计算非雷的格子周围有多少雷,并用数字标识在mine_board的相应位置。
(1).设置地雷
产生两个个随机数,映射到一个横坐标和一个纵坐标,如果该位置已经被标记为雷,则重复上述操作,否则,将该位置标记为‘*’。以上步骤循环多遍,直到设置的雷数达到Mine_
函数具体实现如下:
for(count=0;count&Mine_count++)
i=rand()%H
j=rand()%W
while(board[i][j]=='*');
board[i][j]='*';
(2)计算非雷格子相邻的雷的数目
遍历mine_board中所有格子,当遇到‘*’的格子时(即遇到标记为雷的格子时),将其左上、上方、右上、左边、右边、左下方、下方、右下方所有不是雷的格子的数值都+1
二、GAME_CONTROL()模块
函数原型:
void GAME_CONTROL(int
&lin_current,int& col_current,int
lin_des,int col_des,char cmd)
这个模块负责对ANALYZE()模块给出的命令予以实现。这个模块主要的
工作是实现光标的移动控制,以及根据点击的不同的位置做出反应。
(1)光标的移动控制
为了达到比较友好的程序界面,本程序用‘?’来表示当前光标的位置。
参数lin_current 和 col_current
是当前光标的行号和列号,参数 lin_des 和 col_des是目标位置的行号和列号。
程序首先比较当前光标位置和目标光标位置是否相同,如果相同,则说明光标到达点击位置,直接向 命令处理模块 给出
点击命令‘n’,否则比较光标现在位置和目标位置的差距,分别向命令处理模块给出向上移动的‘w’命令,向下的‘s’, 向左移动的
‘a’命令,向右的‘d’命令。然后更新光标当前 ,不断循环直至当前光标位置和目标位置重合。
具体实现是:
if(lin_current!=lin_des)
if(lin_current&lin_des)
lin_current++;&&&&&&&&&&
temp_cmd='s';
lin_current--;&&&&
temp_cmd='w';
if(col_current!=col_des)
if(col_current&col_des)
col_current++; temp_cmd='d';
col_current--;&&&&
temp_cmd='a';
temp_cmd=&&&&&
flag=//设置终止循环的标志
(2)命令处理模块
命令处理模块对命令进行处理并将结果反映到view_board上显示出来。
1如果遇到方向命令,如w,a,s,d,程序进行下面的操作(以遇到w命令为例):
W命令使光标向上移动,则程序因完成这些工作:
0.判断光标是否能够向上移动,如果已经到达顶端,则下面的步骤跳过不做
1.光标向上移动后,恢复光标所在位置的内容
2.由于光标向上移动会覆盖棋盘上面一格的内容,因此要将上面一格的内容用一个变量保存起来
3.将上面一格的内容赋值为‘?’
4.将屏幕清空
5.输出改变之后view_board 的内容
具体实现是这样的:
view_board[i0][j0]=
temp=view_board[i0-1][j0];
view_board[--i0][j0]='?';
system("cls");
print_board(view_board);
2如果遇到点击命令 ‘n’,程序进行下面的操作:
首先根据mine_board判断点击位置的内容,如果点击位置为非0数字,则在view_board的相应位置显示该数字,将Open_block的值减1;如果点击位置为0,则将改格子进行展开;如果点击位置为‘*’,说明触雷,则显示触雷信息。
具体实现是:
其中,将为0的格子展开比较重要。当点击到的点为0时,应该将与其相邻的所有0也展开,然后对其相邻的0也执行展开操作,以此递归,直到展开的点非0为止。本程序中,运用的是深度优先搜索的方法,具体实现就是下面这样:
void merge(int i0,int
j0)&&&&&&&&&
//展开棋盘i0,j0那一点
view_board[i0][j0]=mine_board[i0][j0];&
//将view_board对应点赋值
Opened_block--;&&&&&&&&&&&&&&&&&&&
// 打开格子数-1
if(view_board[i0][j0]&='1'&&view_board[i0][j0]&='8')&
//如果该格子非0,则
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// 递归结束
if(get_value(view_board,i0-1,j0,value)&&'.'==value)//展开上方格子
merge(i0-1,j0);
if(get_value(view_board,i0+1,j0,value)&&'.'==value)//展开下方格子
merge(i0+1,j0);
if(get_value(view_board,i0,j0-1,value)&&'.'==value)//展开左边格子
merge(i0,j0-1);
if(get_value(view_board,i0,j0+1,value)&&'.'==value)//展开右边格子
merge(i0,j0+1);
if(get_value(view_board,i0-1,j0-1,value)&&'.'==value)//展开左上格子
merge(i0-1,j0-1);
if(get_value(view_board,i0-1,j0+1,value)&&'.'==value)//展开右上格子
merge(i0-1,j0+1);
if(get_value(view_board,i0+1,j0-1,value)&&'.'==value)//展开左下格子
merge(i0+1,j0-1);
if(get_value(view_board,i0+1,j0+1,value)&&'.'==value)//展开右下格子
merge(i0+1,j0+1);
其中bool get_value(char**
&board,int i,int j,char
&value)函数用于取board[i][j]的值并赋值给value并返回true,如果改点不在数组内,如i&0或j&0,则返回false
三、 ANALYZE()& 模块
函数原型:void ANALYZE(int lin_current, int
col_current, int
&lin_des,&&&&&&
int &col_des, &char
这个模块要完成的主要工作是通过对当前棋盘情况的分析,确定下一个点击位置。方法是通过3次的循环遍历(这是我觉得程序效率比较低的地方),计算出每个格子的分值(分值=每个格子有雷的概率x
10000),记录在二维数组
int **score_board
中。分值最低的格子的位置即为下一个点击位置。如果分值最低的格子有多个,则距离当前光标最近的那个即为下一个点击位置。
第一遍循环遍历
将棋盘中,将肯定有雷的格子的分值标记为10000
具体的方法是遍历至view_board中为数字的格子时,如果它周围未被点击的格子数等于该格子的数值,则说明这些空格上肯定是雷。将该格子的分值标记为-1(说明这是一个无法点击的点),再将它周围的空格在score_board的对应格子分值标记为10000。
具体的实现如下:
for(lin=0;lin&Hlin++)
for(col=0;col&Wcol++)
if(get_value(view_board,lin,col,temp)&&temp&'0'&&temp&'9')
neighbor(view_board,lin,col,count_empty,count_mine,count_notmine);
//上面的函数功能为计算view_board[lin][col]这个格子周围有多少
//空格(count_empty),多少已经标记过的雷(count_mine),多少
//已经标记过肯定不是雷的格子(count_notmine)
if(count_empty==(view_board[lin][col]-'0'))//空格数等于该格子数值
score_board[lin][col]=-1;//将这个格子赋值-1
//然后将其周围所有的空格分值赋值为10000
if(get_value(view_board,lin-1,col-1,score)&&score=='.')//左上
{score_board[lin-1][col-1]=10000;}
if(get_value(view_board,lin-1,col,score)&&score=='.')//上
{score_board[lin-1][col]=10000;}
if(get_value(view_board,lin-1,col+1,score)&&score=='.')//右上
{score_board[lin-1][col+1]=10000;}
if(get_value(view_board,lin,col-1,score)&&score=='.')//左
{score_board[lin][col-1]=10000;}
if(get_value(view_board,lin,col+1,score)&&score=='.')//右
{score_board[lin][col+1]=10000;}
if(get_value(view_board,lin+1,col-1,score)&&score=='.')//左下
{score_board[lin+1][col-1]=10000;}
if(get_value(view_board,lin+1,col,score)&&score=='.')//下
{score_board[lin+1][col]=10000;}
if(get_value(view_board,lin+1,col+1,score)&&score=='.')//右下
{score_board[lin+1][col+1]=10000;}
经过这样的遍历就将肯定是雷的格子标记出来了
第二次循环遍历
计算所有“数字相邻格”的分值。所谓的“数字相邻格”,是指该格子与数字相邻。如下图中
用红色记号标记的格子就是数字相邻格,之所以要首先计算它们的分值,是因为只有在确定数字相邻格的数量和棋盘中已打开的格子的数量之后,才能够计算棋盘中剩下的空白格子中有雷的概率。
P=&1-&(1-(A[k].number-A[k].mine)/(A[k].empty-A[k].mine-A[k].notmine))
&&&(k=1 to
,立即将这个格子的分值赋值为0,表示这个点不可能有雷,并跳出循环
(1-(3-1)/(4-1))&(1-(1/3))=7/9
具体的实现过程是:
for(lin=0;lin&Hlin++)
for(col=0;col&Wcol++)
score_board[lin][col]=set_score(lin,col);//计算每一点的分值
if(score_board[lin][col]==10000)&&&&
如果该点为雷&
{signed_mine++;}&&&&&&&&&&&&&&&&&&&&&&&
// 则将已标记的雷数+1
if(score_board[lin][col]== score_empty)& //& 如果该点为空格
{empty_block++;}&&&&&&&&&&&&&&&&&&&&&&&
将空格数+1
其中set_score()函数即是通过上述的方法计算每一点的分值。
经过上面的循环,就可以确定那些不与任何数字相邻的空格有雷的概率为
P=(Mine_num-signed_mine)/(empty_block)
分值为score_empty=
(Mine_num-signed_mine)/(empty_block)*10000
第三遍循环遍历
第三遍循环要做的工作是将
不与任何数字相邻的空格(以下叙述中,简
将空格的分值赋给一个临时变量
for(col=0;col&Wcol++)
score_board[lin][col]=set_score(lin,col);//再一次计算每一点的分值
if(score_board[lin][col]==temp_score)& //如果该格子为空格
{score_board[lin][col]=score_}&&
//将它的分值进行更新
//分值为负的点为不可点击点,不考虑
if(score_board[lin][col]==min)& //将最小分值的点都存入数组
&&&&&&&&&&&&&
min_blocks[index].lin=
&&&&&&&&&&&&&
min_blocks[index++].col=&&&&&&&&&&&&&&&&&&&
if(score_board[lin][col]&min)
&&&&&&&&&&&&&
min=score_board[lin][col];
&&&&&&&&&&&&&
&&&&&&&&&&&&&
min_blocks[index].lin=
&&&&&&&&&&&&&
min_blocks[index++].col=
&&&&&&&&&&&&&
如果说明这个数组中所有的格子都可确定不是雷,要做的事就是从中选出距离当前光标位置最近的格子,这个格子就是下一个要点击的格子。
程序每个模块的介绍基本就是这样。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。Java 8 函数式接口扫雷指南
Java 8 函数式接口扫雷指南
java 8 Functionaml Interfaces在前文中我们复习了Lambdas表达式和一些基本的函数式接口。在本文中将重点讨论一下函数式接口,重点讨论以一下两点:什么是函数式接口?函数式接口使用时方方面面什么是函数式接口?函数式接口(Functional Interface)是Java 8对一类特殊类型的接口的称呼。这类接口有且只有一个抽象方法的接口(除了隐含的Object对象的公共方法),因此最开始也就做SAM类型的接口(Single Abstract Method)。为什么会单单从接口中定义出此类接口呢?原因是在Java Lambda的实现中,开发组不想再为Lambda表达式单独定义一种特殊的Structural函数类型,称之为箭头类型(arrow type),依然想采用Java既有的类型系统(class, interface, method等),原因是增加一个结构化的函数类型会增加函数类型的复杂性,破坏既有的Java类型,并对成千上万的Java类库造成严重的影响。权衡利弊,因此最终还是利用SAM接口作为Lambda表达式的目标类型。函数式接口代表的一种契约,一种对某个特定函数类型的契约。在它出现的地方,实际期望一个符合契约要求的函数。Lambda表达式不能脱离上下文而存在,它必须要有一个明确的目标类型,而这个目标类型就是某个函数式接口。Java 8 新增了一个注解@FunctionalInterface表示SAM接口。如果一个接口符合&函数式接口&定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。另外函数式编程中记着要纯哦!加个这个注解先把函数式的标签给贴上吧。只说不练的教程都是耍流氓!先定义一个FunctionInterface:Function interface函数式接口使用时方方面面东:有且只有一个抽象方法SAM接口不一定是FunctionalInterface,但FunctionalInterface一定是SAM接口。南:@FunctionalInterface 注解可省略东南解释:加上注解,如果出现两个以上抽象方法时,就会报错~西:default 方法是完全支持的北:对java.lang.Object方法的@Override不算是抽象方法Happy Work!
本文仅代表作者观点,不代表百度立场。系作者授权百家号发表,未经许可不得转载。
百家号 最近更新:
简介: 人力资源 心理学 人力资源管理
作者最新文章}

我要回帖

更多关于 扫雷667自定义通关 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信