C++扫雷

C++扫雷
C++扫雷

扫雷

1.1.游戏实现

扫雷,是附带在Window里面的游戏,是个简单的游戏。因此我们就从扫雷开始我们的游戏旅程。很多人都玩过这个游戏,只是不知道怎么用程序实现。不过还有人不知道怎么玩,下面就先说说游戏的规则:

●开始:按左键开始游戏,按按钮或菜单重新开始。

●左键:按下时,是雷则结束,非雷则显示数字。

●数字:代表此数字周围一圈八格中雷的个数。

●右键:奇次按下表示雷,偶数按下表示对上次的否定。

●结束:左键按到雷结束,找出全部雷结束。

接下来就该介绍游戏的编程过程了。不过要先交代一下一些内容。

●添加位图。

●添加全局变量。

●画初始界面。

●添加函数。

为什么要按这种次序呢?因为我们在画初始界面时,可能要用到位图或变量,而变量的定义又可能要对位图进行定义。这样的步骤的好处还有:在做一步之后都可以运行,有错就改,无错就做下一步。

上图是扫雷的一个画面。

下面就一步一步地演示,以编程的思路进行,当然,由于编程过程中有一些函数中的代码是分成两三次写的,我们就不重复,全部代码在第一次讲到时列出,而后面讲到时就只是提一下。

新建单文档工程2_1。

2.2.资源编辑

添加位图:

前十二幅是在雷区的,后四幅是按钮。为了便于加载,必须各自保证其连续性。另外,为什么不添加一个按钮而用位图呢?是因为即使我们添加了按钮也要添加四幅位图!

位图的ID号:

按扭位图:30*30 IDB_ANNIU1、IDB_ANNIU 2、IDB_ANNIU3、IDB_ANNIU4 雷区位图:14*14 ID号按下图依次为:IDB_BITMAP14。。。。。。IDB_BITMAP25

位图:下图(图2-1)。

图2-1

位图的ID号:

按扭位图30*30 IDB_BITMAP1、IDB_BITMAP2、IDB_BITMAP3、IDB_BITMAP4 雷区位图14*14 ID号按下图依次为:IDB_BITMAP5……IDB_BITMAP16

1234

5678910

111213141516

icon

3.3.变量函数

定义新类:

对于雷,我们是单独定义一个类,这样有利于程序的操作。

class Lei Mine

{

public:

//显示哪一个位图

int weitu; bitmap

//这个位置相应的值

int shumu; index

};

并有如下规定(图2-2):

图2-2

视图类变量:

接着是在View类添加变量和函数:

//剩下雷数

int leftnum;

//雷数

int leinum; minenum

//结束

int jieshu; endflag

//计时

short second;

//开始计时

int secondstart;

//位图数组

CBitmap m_Bitmap[12]; bitmap

//按扭位图数组

CBitmap m_anniu[4]; button

//雷区行数

int m_RowCount; row

//雷区列数

int m_ColCount; line

//最大雷区

Lei lei[50][50]; Mine mine

//这个位置周围雷数为0

void leizero();

//计时器函数

afx_msg void OnTimer(UINT nIDEvent);

//鼠标按下左键

afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

//鼠标按下右键

afx_msg void OnRButtonDown(UINT nFlags, CPoint point);

//初始化函数

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

//鼠标左键松开

afx_msg void OnLButtonUp(UINT nFlags, CPoint point);

4.4.具体实现

删去状态栏和工具栏:

开始执行程序,就能见到一个有状态栏和工具栏的大的单文档,与上图不同,所以我们第一步就是整理框架:

打开下面函数,把里面的一些语句去掉。如下所示:

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

return -1;

/* if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP

| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FL YBY | CBRS_SIZE_DYNAMIC) ||

!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

{

TRACE0("Failed to create toolbar\n");

return -1; // fail to create

}

if (!m_wndStatusBar.Create(this) ||

!m_wndStatusBar.SetIndicators(indicators,

sizeof(indicators)/sizeof(UINT)))

{

TRACE0("Failed to create status bar\n");

return -1; // fail to create

}

// TODO: Delete these three lines if you don't want the toolbar to

// be dockable

m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

EnableDocking(CBRS_ALIGN_ANY);

DockControlBar(&m_wndToolBar);

*/

return 0;

}

设置窗口大小:

运行附加的代码,还能看到扫雷游戏的框架是不能调大小的,而且总是显示在最前面,这又是怎么实现的呢?

在下面函数里添加语句,你能说出前三句是什么意思吗?注释已经被我去掉了,如果不知道,不如按一下F1。

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

if( !CFrameWnd::PreCreateWindow(cs) )

return FALSE;

// TODO: Modify the Window class or styles here by modifying

// the CREA TESTRUCT cs

cs.dwExStyle=cs.dwExStyle|WS_EX_TOPMOST; //

cs.style=WS_SYSMENU|WS_OVERLAPPED|WS_MINIMIZEBOX;//;

//设置窗口大小:400*340

cs.cx=400;

cs.cy=340;

return TRUE;

}

构造函数:

由于构造函数是程序运行时就执行的,所以,除了对变量赋值之外,我们还可以把游戏的核心结构即内部数组赋值:先是把全部格子的位图和雷数赋值为0,然后调用随机函数按指定雷数赋值为-1,最后把不是雷的格子的雷数赋值为相应的值。

CMy2_1View::CMy2_1View()

{

// TODO: add construction code here

for(int ii=0;ii<16;ii++)

m_Bitmap[ii].LoadBitmap(IDB_BITMAP14+ii);

for(int jj=0;jj<4;jj++)

m_anniu[jj].LoadBitmap(IDB_ANNIU1+jj);

//计时

second=0;

//1时开始计时

secondstart=0;

//行数

m_RowCount=25;

//列数

m_ColCount=16;

//雷数

leinum=80;

//剩余雷数

leftnum=leinum;

//jieshu=1时停止

jieshu=0;

int aa=0;

//初始化为0

for(int i=0;i

{

for(int j=0;j

{

lei[i][j].shumu=0;

lei[i][j].weitu=0;

}

}

//获取当前时间

CTime time=GetCurrentTime();

int s;

//获取秒数

s=time.GetSecond();

//设置40个雷

do

{

//以当前秒数为产生随机算法

int k=(rand()*s)%m_RowCount;

int l=(rand()*s)%m_ColCount;

//为了避免一个位置同时算两个雷

//只允许当前位置不是雷时赋值为雷

if(lei[k][l].shumu!=-1)

{

lei[k][l].shumu=-1;

aa++;

}

}while(aa!=leinum);

//给方格赋值,计算雷数

for(int a=0;a

for(int b=0;b

if(lei[a][b].shumu==0)

{

for(int c=a-1;c

for(int d=b-1;d

if(c>=0&&c=0&&d

if(lei[c][d].shumu==-1)

lei[a][b].shumu++;

}

}

界面函数:

现在,可以开始画界面了。如下函数:

很明显,前面部分是用画的方法画出整个界面,但是,后面for循环显示的位图并不是现在画界面的内容,为什么要写呢?

这是为了用户框重画的需要,当我们的游戏玩了一半后最小化,或是把部分窗口移出屏幕,或是执行了新的应用程序覆盖了原来的程序时,必须重画。我们调用重画函数,它都要重新执行OnDraw(CDC* pDC)函数,那么,此时它就必须把已经显示出来的位图也显示出来。而开始时雷区位图是不可见的,并不影响界面的初始化。

void CMy2_1View::OnDraw(CDC* pDC)

{

CMy2_1Doc* pDoc = GetDocument();

ASSERT_V ALID(pDoc);

// TODO: add draw code for native data here

//画背景

CBrush mybrush1;

mybrush1.CreateSolidBrush(RGB(192,192,192));

CRect myrect1(0,0,1200,800);

pDC->FillRect(myrect1,&mybrush1);

//画黑框

CBrush mybrush;

mybrush.CreateSolidBrush(RGB(0,0,0));

CRect myrect(20,10,70,40);

pDC->FillRect(myrect,&mybrush);

CRect myrect2(325,10,375,40);

pDC->FillRect(myrect2,&mybrush);

CPen mypen;

CPen*myoldPen;

mypen.CreatePen(PS_SOLID,2,RGB(255,255,255));

myoldPen=pDC->SelectObject(&mypen);

//画黑框的白线

pDC->MoveTo(20,40);

pDC->LineTo(70,40);

pDC->LineTo(70,10);

pDC->MoveTo(325,40);

pDC->LineTo(375,40);

pDC->LineTo(375,10);

//画雷区边线

//左上角是白线,右下角是黑线,以显示立体感

for(int i=0;i

for(int j=0;j

{

pDC->MoveTo(10+i*15,50+j*15+14);

pDC->LineTo(10+i*15,50+j*15);

pDC->LineTo(10+i*15+14,50+j*15);

}

pDC->SelectObject(myoldPen);

CPen mypen2;

CPen*myoldPen2;

mypen2.CreatePen(PS_SOLID,1,RGB(0,0,0));

myoldPen2=pDC->SelectObject(&mypen2);

for(int ii=0;ii

for(int jj=0;jj

{

pDC->MoveTo(10+ii*15,50+jj*15+14);

pDC->LineTo(10+ii*15+14,50+jj*15+14);

pDC->LineTo(10+ii*15+14,50+jj*15);

}

pDC->SelectObject(myoldPen2);

CDC Dc;

if(Dc.CreateCompatibleDC(pDC)==FALSE)

AfxMessageBox("Can't create DC");

//显示按钮

Dc.SelectObject(m_anniu[0]);

pDC->BitBlt(180,10,160,160,&Dc,0,0,SRCCOPY);

//判断显示什么位图

//weitu=1已按下的数字区

//weitu=2显示旗

//weitu=3显示问号

for(int a=0;a

for(int b=0;b

{

if(lei[a][b].weitu==1)

{

Dc.SelectObject(m_Bitmap[lei[a][b].shumu]);

pDC->BitBlt(a*15+10,b*15+50,160,160,&Dc,0,0,SRCCOPY);

}

if(lei[a][b].weitu==2)

{

Dc.SelectObject(m_Bitmap[9]);

pDC->BitBlt(a*15+10,b*15+50,160,160,&Dc,0,0,SRCCOPY);

}

if(lei[a][b].weitu==3)

{

Dc.SelectObject(m_Bitmap[10]);

pDC->BitBlt(a*15+10,b*15+50,160,160,&Dc,0,0,SRCCOPY);

}

//结束

if(jieshu==1&&lei[a][b].shumu==-1)

{

Dc.SelectObject(m_Bitmap[11]);

pDC->BitBlt(a*15+10,b*15+50,160,160,&Dc,0,0,SRCCOPY);

Dc.SelectObject(m_anniu[3]);

pDC->BitBlt(180,10,160,160,&Dc,0,0,SRCCOPY);

}

}

//显示黑框里的数字

int nOldDC=pDC->SaveDC();

pDC->SetTextColor(RGB(255,0,0));

pDC->SetBkColor(RGB(0,0,0));

CFont font;

if(0==font.CreatePointFont(160,"Comic Sans MS"))

{

AfxMessageBox("Can't Create Font");

}

pDC->SelectObject(&font);

CString str;

//利用判断显示位数,不够三位前面加0

if(leftnum<10)

str.Format("00%d",leftnum);

else

str.Format("0%d",leftnum);

pDC->TextOut(25,10,str);

if(second<10)

str.Format("00%d",second);

else if(second<100)

str.Format("0%d" ,second);

else

str.Format("%d" ,second);

pDC->TextOut(330,10,str);

pDC->RestoreDC(nOldDC);

}

运行一下,外观已经出来了,只是还不能玩。那我们就来添加一些功能函数,使它可以玩。

当然,如果你对程序已经有一定的经验的话,你就会指出上面的函数太长了。这并不太符合我们编程的要求。我们编程有一个讲究,就是尽量使函数的代码少,一般为一页左右,便于查看。那么,我们可以把上面的函数细分为几个小函数,然后在这个函数里面分别调用。

按下鼠标左键:

用if语句判断,如果在按钮上面,则显示按钮按下位图;如果在扫雷区,先把按钮位图改为张口位图,再判断按下的是否是雷,是就结束,重画,以显示所有的雷;否则,重画相应格子以显示数字。

void CMy2_1View::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

//获取指针pdc

CDC *pDC=GetDC();

CDC Dc;

if(Dc.CreateCompatibleDC(pDC)==FALSE)

AfxMessageBox("Can't create DC");

//显示按下按钮

if(point.x>180&&point.x<210&&point.y>10&&point.y<40)

{

Dc.SelectObject(m_anniu[3]);

pDC->BitBlt(180,10,160,160,&Dc,0,0,SRCCOPY);

}

if((point.x>=10)&&(point.x<=385)&&(point.y>=50)&&(point.y<=290))

{

if(jieshu==1)

return;

//显示张口按钮

Dc.SelectObject(m_anniu[1]);

pDC->BitBlt(180,10,160,160,&Dc,0,0,SRCCOPY);

// secondstart为1时计时有效

secondstart=1;

//鼠标坐标转换为数组坐标

int a=(point.x-10)/15;

int b=(point.y-50)/15;

if(lei[a][b].weitu==0||lei[a][b].weitu==3)

{

if(lei[a][b].shumu==-1)

{

jieshu=1;

//结束时,释放Timer

KillTimer(1);

//重画,因为这次重画将显示全部的雷,

//不能用部分重画

Invalidate();

}

else

{

lei[a][b].weitu=1;

CRect rect;

rect.left=a*15+10;

rect.right=a*15+25;

rect.top=b*15+50;

rect.bottom=b*15+65;

InvalidateRect(&rect);

}

}

} CView::OnLButtonDown(nFlags, point);

}

如果你现在运行的话,你会发现按下按钮时并不还原,这就涉及到鼠标函数:OnLButtonUp(UINT nFlags, CPoint point)

松开鼠标左键:

松开左键时,显示按钮没有按下的位图;再判断,如果结束,就要显示失败的位图;另外,如果是在按钮上松开按钮,即表示我们已经按下了重新开始的按钮,必须调用重新开始函数OnStart()。

由于OnStart()函数是与菜单里的开始共有的,此处先保留不说,若有必要运行,可以先去掉最后两行。

void CMy2_1View::OnLButtonUp(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

CDC *pDC=GetDC();

CDC Dc;

if(Dc.CreateCompatibleDC(pDC)==FALSE)

AfxMessageBox("Can't create DC");

//显示按钮

Dc.SelectObject(m_anniu[0]);

pDC->BitBlt(180,10,160,160,&Dc,0,0,SRCCOPY);

if(jieshu==1)

{

//显示按扭位图

Dc.SelectObject(m_anniu[2]);

pDC->BitBlt(180,10,160,160,&Dc,0,0,SRCCOPY);

}

//如果按下的是按扭,重新开始

if(point.x>180&&point.x<210&&point.y>10&&point.y<40)

OnStart();

CView::OnLButtonUp(nFlags, point);

}

按下鼠标右键:

如果是雷,我们按右键,显示旗子,并减少一个剩下雷数;如果我们认为那旗子的格子不是雷,我们按右键,显示问号,并在剩下雷数加上1。有关函数:

void CMy2_1View::OnRButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

//结束,返回

if(jieshu==1)

return;

if((point.x>=10)&&(point.x<=385)&&(point.y>=50)&&(point.y<=290))

{

int a=(point.x-10)/15;

int b=(point.y-50)/15;

if(lei[a][b].weitu==0||lei[a][b].weitu==3)

{

lei[a][b].weitu=2;

leftnum--;

}

else

if(lei[a][b].weitu==2)

{

lei[a][b].weitu=3;

leftnum++;

}

//重画剩下雷数

CRect rect2;

rect2.left=20;

rect2.right=70;

rect2.top=10;

rect2.bottom=40;

InvalidateRect(&rect2);

//重画打击格子

CRect rect;

rect.left=a*15+10;

rect.right=a*15+25;

rect.top=b*15+50;

rect.bottom=b*15+65;

InvalidateRect(&rect);

}

CView::OnRButtonDown(nFlags, point);

}

显示没有雷的区域:

运行,玩一下,你会发现当按下的是一个周围没有雷的格子是它并不会象Window里面的扫雷游戏一样显示它周围的格子雷数。怎么实现呢?

添加一个如下函数:

//扫描,如果是已经被按下且雷数为0,显示它周围的八个格,并重画

void CMy2_1View::leizero()

{

for(int i=0;i

for(int j=0;j

if(lei[i][j].shumu==0&&lei[i][j].weitu==1)

{

for(int n=i-1;n

for(int m=j-1;m

if(n>=0&&n<25&&m>=0&&m

if(lei[n][m].shumu!=-1&&lei[n][m].weitu==0)

{

lei[n][m].weitu=1;

CRect rect;

rect.left=n*15+10;

rect.right=n*15+25;

rect.top=m*15+50;

rect.bottom=m*15+65;

InvalidateRect(&rect);

}

}

}

再运行,效果是有的,只是它只显示一部分,即这个周围的几个。那么我们应该怎样使它显示全部呢?可以利用计时器函数。

计时器函数:

OnTimer(UINT nIDEvent)函数,同时也可以实现计时显示。添加OnCreate(LPCREATESTRUCT lpCreateStruct)和OnTimer(UINT nIDEvent):

int CMy2_1View::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

if (CView::OnCreate(lpCreateStruct) == -1)

return -1;

// TODO: Add your specialized creation code here

//20次为一秒

SetTimer(1,50,NULL);

return 0;

}

void CMy2_1View::OnTimer(UINT nIDEvent)

{

// TODO: Add your message handler code here and/or call default

//结束,返回

if(jieshu==1)

return;

//显示个数为0的方格

leizero();

//计时

if(secondstart>0)

secondstart++;

//二十次为一秒

if(secondstart==20)

{

secondstart=1;

second++;

//重画时间

CRect rect3;

rect3.left=325;

rect3.right=375;

rect3.top=10;

rect3.bottom=40;

InvalidateRect(&rect3);

}

CView::OnTimer(nIDEvent);

}

扫雷游戏就这样就是了。下面是附加内容,它将说明菜单的添加和重新开始函数的算法。

5.5.附加内容

修改菜单:

游戏已经可以玩了,只是点到雷之后就完了,无法重新开始。还有,菜单还没有改。下面就修改菜单并实现重新开始功能:

把菜单改为如下图2-3。

图2-3

并在View()函数中按下图添加OnStart()函数(图2-4):

图2-4

开始函数:

OnStart()函数其实只是构造函数的再版。

void CMy2_1View::OnStart()

{

SetTimer(1,50,NULL);

// TODO: Add your command handler code here

second=0;//计时

secondstart=0;//1时开始计时

// num=0;

leftnum=leinum;//剩余雷数

jieshu=0;//jieshu=1时停止

int aa=0;

//初始化0

for(int i=0;i

{

for(int j=0;j

{

lei[i][j].shumu=0;

lei[i][j].weitu=0;

}

}

//设置leinum个雷

do

{

int k=rand()%m_RowCount;

int l=rand()%m_ColCount;

if(lei[k][l].shumu!=-1)

{

lei[k][l].shumu=-1;

aa++;

}

}while(aa!=leinum);

//给方格赋值

for(int a=0;a

for(int b=0;b

if(lei[a][b].shumu==0)

{

for(int c=a-1;c

for(int d=b-1;d

if(c>=0&&c=0&&d

if(lei[c][d].shumu==-1)

lei[a][b].shumu++;

}

Invalidate();

}

这样,整个程序完成了。

6.6.小结

当然,这个游戏比Window自带的简单。但就目前来说,离它其实也不远。添加菜单项,并相应修改参数值:m_RowCount、m_ColCount、leinum,并重新初始化界面就行了。

本书的例子都只是一些最基本的游戏算法,它教你怎样去实现游戏,而至于游戏的扩展,我只是提一些建议,让你自己去实现。

java_扫雷游戏课程设计报告

一、设计任务与要求 扫雷游戏的基本要求 Windows 2000/XP系统提供的扫雷游戏是一个很有趣的游戏。本章的课程设计使用Java语言编写一个与其类似的扫雷游戏。具体要求如下: (1) 扫雷游戏分为初级、中级和高级三个级别,扫雷英雄榜存储每个级别的最好成绩,即挖出全部的地雷且用时最少者。单击游戏菜单可以选择“初级”、“中级”和“高级”或“查看英雄版”。 (2) 选择级别后将出现相应级别的扫雷区域,这是用户使用鼠标左键单击雷区中任何一个方块便启动计时器。 (3) 用户要揭开某个方块,可单击它。若所揭方块下有泪,用户便输了这一局,若所揭方块下五雷,则显示一个数字,该数字代表方块的周围的8个方块中共有多少颗雷。 (4) 如果用户认为某个方块下埋着雷,单击右键可以在方块上标识一个用户认为是雷的图标,即给出一个扫雷标记。用户每标记出一个扫雷标记(无论用户的标记是否正确),程序将显示的剩余雷数减少一个。 (5) 扫雷胜利后(用时最少者),程序弹出保存成绩的对话框。 (6)用户可以选择标记疑问的方块,用可以勾选游戏菜单下的标记(或者用快捷键alt+G 然后M)即可,此时双击右键并可出现“?”标记。另有颜色选项,当用户勾选此项时,游戏将以最低图像像素来显示。 (7)如果用户需要即使提示声,并可选中声音选项,此时将听到计时的卡塔声。当用户点中雷时,将有爆炸声产生,胜利时,将有凯旋的旋律播放,此时企鹅出现欢悦表情。 二、需求分析 1、扫雷游戏概述 扫雷是一种具有迷惑性的对记忆和推理能力的简单测试,它是长久以来最受欢迎的Windows游戏之一。游戏目标:找出空方块,同时避免触雷。 2、扫雷的操作方法 游戏主区域由很多个方格组成。使用鼠标随机点击一个方格,方格即被打开并显示出方格中的数字;方格中数字则表示其周围的8个方格隐藏了几颗雷;如果点开的格子为空白格,即其周围有0颗雷,则其周围格子自动打开。 例如,方格中出现1,说明上下左右及斜角合计有一颗雷,依次类推,2则有2颗,3则有3颗。 3、需实现的主要功能 (1)用户可以自定义级别并且可以任意输入雷数; (2)具有计时功能,即显示用户完成移动盘子所花费的时间; (3)用户可以选择是否有音效;

经典游戏:扫雷的技巧攻略

经典游戏:扫雷的技巧攻略 扫雷作为策略游戏,需要游戏者精确的判断。现在扫雷高级的官方最快纪录是33.95秒,中级则是由一个波兰玩家保持的8.5秒。而初级纪录是1秒,世界上很多人达到了这一点。在1秒的时间里完成初级扫雷,据测算概率在0.00058%至0.00119%之间(属于运气题),最可能的方法是直接点击四个角的方块。而本文所作的事情,则是将雷与雷之间的规律给你揪出来,并且深入思考其中的内涵。让你以后面对扫雷时,缩短与记录的差距,战无不胜! 从简单雷区入手下图是一个初级的雷区,并且标注了两颗雷的位置,你能将剩下的地雷扫描出来吗? 经过逐一排查,可以很轻松的确定雷区中的6颗地雷所在位置:

再来看一个简单的“雷区”: 通过逐步扫描每一个方块会发现:首先最左边的和最右边的两个格子都一定是地雷,从左数第二个空格子和从右数第二个空格子也都是地雷,由于数字1的关系,从左数第3个格子和从右数第3个格子都不是地雷,翻开一定是数字1……这样一直下去,最后你会发现最中间的两个空格子,不管有没有地雷,都和周围格子上的数字不符。也就是说这样的雷区有bug,是无解的。雷区中的逻辑门怎么判断一个雷区是否有bug?又怎么判断雷区中地雷的具体位置呢?难道一定要从头到尾将雷区扫描一遍吗?其实这些雷区里其实藏着一个规律。我们用数学方法来分析了上例的雷区:在之前提到的这两个雷区里,把还没有翻开的格子交叉标记上字母x和x’。可以看到:当x的格子有雷时,x’格子一定没有地雷,反之亦然。如果将最左边的空格子作为输入,把最右边的格子作为输出,输入结果和输出结果一定是一样或者相反的。如果是相反的,这相当于一个NOT (“非”)门电子元件。如果是一样的,就有趣了,这样的一片雷区就具备了电路导线的性质!

c语言课程设计——扫雷

扫雷设计 网101 陈超张艳 1.游戏规则 设计1010格区域,单击鼠标后,该格显示数字,则表示它周围8个空格内含有的地雷数,周围没有地雷的显示空白,则不能再单击了.如果是地雷,则游戏结束.如果判断是地雷,可以单击鼠标右键标出,显示红旗,要取消红旗标志则单击鼠标右键,当所有地雷都标出时,每个空格都处理过了,则胜利结束。 2.设计思路 扫雷程序主要用了一个10行10列的二维数组,数组的每个元素都是结构体类型,结构体中的num代表格内当前处于什么状态,值1表示有雷,值0表示已经变成空白格或者显示过数字,roundnum 统计每个格子周围有多少地雷,flag是鼠标右键的标志,如果flag为1表示格子显示红旗,这样鼠标左键点击在这个格子上无效。 在程序一开始统计好每个格子周围有多少地雷,然后当鼠标左键点击在没有地雷的格子上时进行两种判断,如果格子周围没有地雷,就在原来的格子位置显示空白格,然后用递归的方法同样判断周围的8个格子;如果格子周围有地雷,就在该空格显示具体的雷数。 在递归判断8个格子时,如果格子上有雷或者格子已经显示过雷数或者空白,以及格子上有红旗标志的话,就不再对格子进行任何判断。 具体函数流程图如下:

(1)main()主函数 定义使用到的常数,全局变量,函数原型说明。然后初始化图形系统,调用游戏控制函数,按任意键结束游戏,关闭图形系统,游戏结束。 (2)Control()游戏控制函数 调用函数GameBegain()显示游戏初始化界面,调用

GamePlay()函数具体实现游戏操作,该函数的返回值有可能有两种:一是正在玩中,提前结束游戏;一是玩完,要么失败,要么胜利。如果是前者,则重新开始游戏。如果是后者,则判断是否单击了笑脸,是则重新开始,否则结束程序。 (3)GameBegin()画初始界面 这个函数完成初始界面的设计以及随机生成地雷。初始界面的主要工作是确定图的位置和方格显示的位置。外边框的左上角为(190,60),右上角坐标为(390,290),显示笑脸和地雷数的区域为(190,60)~(390,90),每个方格的宽度和高度均为16. (4)DrawSmile()画笑脸 利用画椭圆的函数fillellipse()和bar()画笑脸,设置好填充模式。 (5)DrawEmpty()两种格子的显示 函数的参数为四个,确定格子的坐标i和j模式,颜色。格子有两种:一是可以单击的格子;一是已经显示空白的格子,比前一种格子小,通过参数模式和颜色来控制。 (6)DrawFlag()显示红旗 用单击鼠标右键表示起地雷,起雷后显示一个小红旗 (7)GamePlay()游戏控制 游戏过程主要是对鼠标按键的处理,集体算法实现如下: a.如果单击了鼠标左键则判断 如果单击了笑脸,则游戏重新开始‘

项目11:Windows程序的功能设计——“扫雷”游戏

项目11:Windows程序的功能设计——“扫雷”游戏 一、教学内容及要求 能力培养: 1、理解基于Windows的应用程序的基本概念 2、掌握Windows窗体和控件的常用属性。 3、掌握一些常用的Windows窗体控件的使用。 4、学会创建较为复杂的Windows应用程序。。 核心技能点: 1、Windows 窗体应用程序中窗体、控件、事件的基本概念。 2、Windows 窗体控件的共同特性。 3、常用的Windows 窗体控件。 扩展技能点: 1、Windows窗体和控件的常用属性 2、Windows窗体的设计和创建 3、各种控件的综合应用 教学内容: 1、项目介绍。 任务1:“扫雷”游戏(5分钟) 2、案例演示:程序流程 任务2:讲解程序设计流程。(15分钟) 3、案例演示:主要功能实现 任务3:讲解主要功能的实现方法。(30分钟) 4、课内实践: 任务4:利用C#/WinForms编程,编写一个小游戏“扫雷”。(130分钟) (1) 游戏功能和Window中的扫雷功能相同。 (2) 程序界面显示当前剩余地雷数和用时。点击中间的按钮可以重新开始游戏。 (3) 左键点击每一个小方框,如果没有地雷,则显示其上下左右及对角线共8个小方框中的地雷数。1代表上下左右及斜角合计有一颗雷,依次类推,2则有2颗,3则有3颗,如果其周围没有雷(0),则不显示,并将和其相临(上下左右及对角线共8个小方框)中地雷数为0的方框都显示出来。如果该方框是地雷,则游戏结束,并显示所有雷的位置。在确定是炸弹的方格上点右键出现一个旗子,表示你认为这是一个雷,上方显示的地雷数减1。在有旗子的方框中再点击将出现问号,表示你不确定这里有没有炸弹。再点击将取消标志。

探索扫雷游戏中的数学奥秘

探索扫雷游戏中的数学奥秘 ■■■_ j■ 趣 味 数 寸 中学生数学?2010年5月上?第393期(高中) 扫雷游戏中的数学曩 江苏省常州市北环中学(213017)邹浩芳 一 ,游戏规则 游戏主区域由很多个方格组成,方格的种类 有三种,(1)空白的;(2)有数字的;(3)没有打 开的.空白的方格表示它周嗣的8个方格中没有 地雷;有数字的方格表示它周围的8个方格中含 有地雷的个数;没打开的方格表示其中可能有地 雷,也可能没有地雷.扫雷就是要把所有非地雷 的格子揭开即胜利;踩到地雷格子就算失败. 二,活动一 例题1首先在扫雷游戏的任意位置用鼠 标左键单击两个方格,图中就会产生两个数字 1和3,分别表示在1的周围的8个小方格中有 1个地雷,在3的周围的8个小方格中有3个 地雷.接下去的你会选择从哪里YI:始人手呢? (如图1)

ABCDEF~ttIABCDEfCttI 图1图2 解析由于1的周围的8个小方格中有 个地雷,在3的周围的8个小方格中有三个地雷.也就是说,在1和3的周围踩到地雷的概率10 分别为÷和昔,所以应该先从1的周围开始扫00 雷.在1的周围用鼠标左键随机单击一个空位, 则可能会出现图2,下面又该如何操作呢? 说明参考我们教室里排座位方法,以后 我们从左往右的竖列数记作A,B,C,D,E,F, G,H,f,将由下往上的横排数记作1,2,3,4,5, 6,7,8,9,如:我们将图1中的"1"记作E6,表示 第五组第6张座位;将其中的"3"记作E3,表示 第五组第3张座位(如图1). 解析根据C8的1和D6的1,我们可以 知道在它们的周围只有一颗雷,所以B9和E5 .一 定都是雷(如图2);接下来根据I5的1可以 知道J4和H4中只有一颗雷,根据H5的1可 以知道Jr4,H4和(24中也只有一颗雷,所以G4 一 定不是雷(如图3);N-根据G5的2可以知道 F4和H4这两个都是雷(如图4),N-根据G4的 2可以知道F3,G3和H3这三个都不是雷(如图4).最终从右下角的位置按顺时针的方向一路过去就可以完成这次的扫雷任务了(如图4). A11CDEFHI 图3 ^BCDEFCHI

C语言实现扫雷游戏

C语言实现扫雷游戏运行环境:Windows系统,V isualC++6.0 _head.h #ifndef _HEAD_H_ #define _HEAD_H_ #define XX 40 #define YY 20 typedef struct { char boom; char flag; //默认为0,1代表标记为雷,2代表翻牌 char recursionMark; //默认为0,1代表已经被递归} Node; extern Node node[YY][XX]; void randomBoom(int width, int high, int num); void gotoxy(int x, int y); int clear_boom(int width, int high, int y, int x); void myPrint(int i); #endif clear_boom.c #include #include #include #include"_head.h" /* 功能:递归翻牌 参数:int width, high 雷区的宽度和高度 int y, x 要翻牌的坐标 返回值:int 返回 1 代表输了 */ int clear_boom(int width, int high, int y, int x) { node[y][x].recursionMark=1; node[y][x].flag=2; //本方格标记为翻牌 gotoxy(2*x, y);

if(node[y][x].boom=='*')//如果是雷就输出字符'*',否则输出数字 printf("%-2c\b\b", node[y][x].boom); else myPrint(node[y][x].boom);//调用输出双字符函数 if(node[y][x].boom=='*') return 1; //返回1代表输了 else if(node[y][x].boom==0) //说明周围8个方向的方格没有雷,在8个方向上做上翻牌标记 { if(y-1>=0) //在该方格上面的雷区做翻牌标记 { if(x-1>=0 && node[y-1][x-1].flag==0) //标记左上方 { node[y-1][x-1].flag=2; //2代表翻牌,1代表地雷 gotoxy(2*(x-1), y-1); //跳转到方格处并翻牌 if(node[y-1][x-1].boom=='*')//如果是雷就输出字符'*',否则输出数字 printf("%-2c\b\b", node[y-1][x-1].boom); else myPrint(node[y-1][x-1].boom);//调用输出双字符函数 if(node[y-1][x-1].boom==0 && node[y-1][x-1].recursionMark==0)//递归调用 clear_boom(width, high, y-1, x-1); } if(node[y-1][x].flag==0) { node[y-1][x].flag=2; //标记正上方 gotoxy(2*x, y-1); //跳转到方格处并翻牌 if(node[y-1][x].boom=='*')//如果是雷就输出字符'*',否则输出数字 printf("%-2c\b\b", node[y-1][x].boom); else myPrint(node[y-1][x].boom);//调用输出双字符函数 if(node[y-1][x].boom==0 && node[y-1][x].recursionMark==0)//递归调用 clear_boom(width, high, y-1, x); } if(x+1

扫雷游戏技巧

1.边角的1对应的角肯定是雷,如下图。这也是扫雷中最常见的情形。 2. 2 2.边上的两个2并排对应的两个块肯定是雷,如下图。 3. 3 3.边角的3对应的3个块肯定是雷,如下图。 4. 4 4.孤立的3对应的3个块肯定是雷,如下图。

5. 5 5.孤立的4对应的4个块肯定是雷,如下图。 6. 6 6.孤立的5对应的5个肯定是雷,如下图。 7.7

7.两个1夹一个2的1,两个1下面对应的块肯定是雷,如下图。 8.孤立的2对应的两个块肯定是雷,如下图。 9.如下图,已知3的左边两个是雷,那么3的下边两个中肯定有一个是雷,所以第二个1下边的那个块肯定不是雷。 10.如下图,已知2的左边一个是雷,所以2的下边两个中肯定有一个是雷,所以1的右边3个块都不是雷。 11.如下图,上边那个1对应的两个角块中有一个是雷,所以下边那个1下边的3个块都不是雷。

12.如下图,两个并排的3对应的3个块都是雷。 13.如下图,两个并排的2,已知左边那个2的左边是雷,则右边那个2的右下角那个肯定也是雷。 14.如下图,已知右边两个竖着的1的左边两个块中有个个是雷,则左边那两个1下方的两个块都不是雷。 15.如下图,1和2孤立地排在一起,则2要从下方3个块中选两个,肯定不会是左边两个,所以2的右下角那个肯定是雷,而1和2下边两个块中有1个是雷,所以1左下角那个肯定不会是雷。

16.如下图,一个3和一个2并排在一起,已知3上边那个是雷,则3左下角那个块肯定是雷,而2右下角那个块肯定不是雷。 17.如下图,两个2并排在一起,且已知右边那个2正上方那个块是雷,则它的左边两个中肯定只有一个是雷,并且左边那个2的左边3个块都不是雷。 一夹二,一有雷; 二夹一,心有雷; 二夹三,全有雷; 二二边,都有雷; 三连一,中有雷; 四连一,边有雷。

简版扫雷代码

#include #include #include #define MAX 100 //最大范围为100x100 struct place{ int show;//显示状态(-1为不显示,0为显示@,1为显示status ) char status;//身份(数字为周围8位地雷数,*为地雷,#号为边界标志) }; /*显示函数*/ void print_all(place mine_area[][MAX+2]){ for(int i=0;i<=MAX+1;i++){ for(int j=0;j<=MAX+1;j++){ if(mine_area[i][j].status<=8) printf("%d",mine_area[i][j].status+48); else if(mine_area[i][j].status=='#') printf("#"); else if(mine_area[i][j].status=='*') printf("*"); printf(":%d ",mine_area[i][j].show); } printf("\n"); } } void print_all(place mine_area[][MAX+2],int length,int width){ for(int i=0;i

扫雷的课程设计报告

西安文理学院信息工程学院课程设计报告 设计名称:数据结构课程设计 设计题目:实现一个N*M的扫雷游戏 学生学号:1402130407 专业班级:软件13级四班 学生姓名:樊秀琳 学生成绩: 指导教师(职称):谢巧玲(讲师) 课题工作时间:2015.6.22 至2015.7.3

说明: 1、报告中的任务书、进度表由指导教师在课程设计开始前填写并发给每个 学生。 2、学生成绩由指导教师根据学生的设计情况给出各项分值及总评成绩。 3、所有学生必须参加课程设计的答辩环节,凡不参加答辩者,其成绩一律 按不及格处理。答辩由指导教师实施。 4、报告正文字数一般应不少于3000字,也可由指导教师根据本门综合设 计的情况另行规定。 5、平时表现成绩低于6分的学生,取消答辩资格,其本项综合设计成绩按 不及格处理。

信息工程学院课程设计任务书 指导教师:院长: 日期:2015年6月22日

信息工程学院课程设计进度安排表 学生姓名:樊秀琳学号:1402130407 专业:软件工程班级:13级四班 指导教师签名: 2014年6月22日

成绩评定表 学生姓名:樊秀琳学号:1402130407 专业:软件工程班级:13级四班

摘要 摘要: 扫雷游戏是Windows操作系统自带的一款小游戏,在过去的几年里,Windows操作系统历经数次换代更新,变得越来越庞大、复杂,功能也越来越强大,但是这款小游戏依然保持原来的容貌,可见这款小游戏受到越来越多人的喜爱。扫雷游戏是比较经典的一款小游戏,实现它的方法很多,可以用很多不同算法设计和语言实现,如C,C++,VB,JAVA等。我利用eclipse编写了与它功能相似的扫雷游戏,寓学于乐。 程序的功能是随机生成地雷数,通过鼠标操作玩游戏,不接受键盘,按任意键结束程序。单击屏幕上的笑脸可以重新开始游戏。所有地雷标出后胜利,当鼠标左键单击到地雷时提示游戏失败。其功能类似于Windows操作系统自带的扫雷游戏。论文首先介绍了进行该游戏课程设计的目的,然后是任务描述和设计的相关要求,最后是最重要的需求分析和设计方案。重点介绍了在游戏过程中各事件的处理,其中又以鼠标事件和清除未靠近地雷区方块这两方面最为最要,鼠标事件是利用鼠标所发出的信息了解用户的意图,进而做出相对应的动作。清除未靠近地雷区的方块较为复杂。 关键词:算法设计;事件;Eclipse

C语言扫雷源代码

C语言扫雷源代码.txt如果背叛是一种勇气,那么接受背叛则需要更大的勇气。爱情是块砖, 婚姻是座山。砖不在多,有一块就灵;山不在高,守一生就行。 #include #include #include #include /*鼠标信息宏定义*/ #define WAITING 0xff00 #define LEFTPRESS 0xff01 #define LEFTCLICK 0xff10 #define LEFTDRAG 0xff19 #define RIGHTPRESS 0xff02 #define RIGHTCLICK 0xff20 #define RIGHTDRAG 0xff2a #define MIDDLEPRESS 0xff04 #define MIDDLECLICK 0xff40 #define MIDDLEDRAG 0xff4c #define MOUSEMOVE 0xff08 struct { int num;/*格子当前处于什么状态,1有雷,0已经显示过数字或者空白格子*/ int roundnum;/*统计格子周围有多少雷*/ int flag;/*右键按下显示红旗的标志,0没有红旗标志,1有红旗标志*/ }Mine[10][10]; int gameAGAIN=0;/*是否重来的变量*/ int gamePLAY=0;/*是否是第一次玩游戏的标志*/ int mineNUM;/*统计处理过的格子数*/ char randmineNUM[3];/*显示数字的字符串*/ int Keystate; int MouseExist; int MouseButton; int MouseX; int MouseY; int up[16][16],down[16][16],mouse_draw[16][16],pixel_save[16][16]; void MouseMath()/*计算鼠标的样子*/ {int i,j,jj,k; long UpNum[16]={ 0x3fff,0x1fff,0x0fff,0x07ff, 0x03ff,0x01ff,0x00ff,0x007f, 0x003f,0x00ff,0x01ff,0x10ff,

扫雷定式附图教程

21定式(或称12定式) `在直排上出现连续的21序列时,可判定为雷,不是雷。 实例集 当出现21序列时,可判断2旁边的是雷,1旁边的不是雷。 以下所有定式均为在附加雷、靠边等条件下,由11定式和21定式演变而来。 边部11定式 如图在右方靠边的情况下,由靠边假设和11定式可知另一边不是雷。 挖坑定式 如图在直排上打开一个方格数字为1,而靠上的数字也是1,由11定式可知下方三个不是雷。 假如点开中间的后仍是1,由11定式可知,下方的三个也不是雷。 边部211定式

如图在右方靠边的情况下,由边部11定式可知不是雷。 假如处不是雷,则只有左边一个无法满足数字,故和左边的是雷,右边的不是雷。 夹雷22定式 在如图两个雷中间出现22序列时,由附加雷假设可知这其实是11定式,则两个要么都是雷要么都不是雷。 靠雷21定式 在如图在雷旁出现21序列时,由附加雷假设可知这其实是11定式,则两个要么都是雷要么都不是雷。 【21定式的变形】 121定式 在如图在直排上出现121序列时,用21定式分析左边四排可知右边的是雷,分析右边四排可知左边的 是雷。 212定式 在如图在直排上出现212序列时,用21定式分析左边四排可知右边的不是雷,分析右边四排可知左边的不是雷。再由中间的1得知是雷。

靠雷221定式 在如图在雷旁边上出现221序列时,由附加雷假设可知这其实是121定式。则两个都是雷。 靠雷31定式 在如图在雷旁出现31序列时,由附加雷假设可知这其实是21定式,则左边的是雷,右边的不是雷。 靠雷41定式 在如图在雷旁出现41序列时,由附加雷假设可知这其实是21定式,则左边的是雷,右边的不是雷。

扫雷

大连科技学院 Java课程设计报告 题目扫雷小游戏 学生姓名 XXX 专业班级软件工程12-1 指导教师史原职称讲师 所在单位大连科技学院 教研室主任刘瑞杰 完成日期 2015年6月12日

目录 1.总体设计 (1) 1.1本系统的主要功能 (1) 1.2系统包含的类及类之间的关系 (1) 2.详细设计 (2) 2.1 MineGame.java(主类): (2) 2.2 MineArea.java: (2) 2.3 Block.java: (3) 2.4 BlockView.java (3) 2.5 LayMines.java: (3) 2.6 Record.java: (4) 2.7 ShowRecord: (4) 3.运行效果 (5) 3.1 系统主界面 (5) 3.2初级录入界面 (5) 3.3中级录入界面 (6) 3.4高级录入界面 (6) 3.5游戏结束录入界面 (7) 3.6游戏英雄榜界面 (7) 参考文献 (8) 附录1 软件源程序 (8) 课程设计实践总结: (25)

1.总体设计 1.1本系统的主要功能 (1)本系统用户可以自定义级别并且可以任意输入雷数; (2)具有计时功能,即显示用户完成移动盘子所花费的时间; (3)自动保存扫雷英雄榜; 1.2系统包含的类及类之间的关系 本系统共包括7个java源文件。 如图1-1所示。 图1-1 类之间的关系

2.详细设计 2.1 MineGame.java(主类): (1)成员变量 bar和fileMenu 提供菜单操作,单击菜单操作中的选项为“初级”,“中级”,“高级”或“扫雷英雄榜”;mineArea 是扫雷区域,提供有关雷的主要功能;英雄榜”负责存放三个级别的扫雷最好成绩;showHeroRecord负责显示英雄榜中的数据(2)方法 MineGame()是构造窗口,负责完成窗口的初始化。 ActionPerformed(ActionEvent)方法是MineGame类实现的ActionListener接口中的方法,该方法负责执行菜单发出的有关命令。用户选择菜单中的菜单项可触发ActionEvent事件,导致actionPerformed(ActionEvent)方法执行相应的操作。 Main(String[])方法是程序运行的入口方法。 (3)源代码见文件MineGame.java 2.2 MineArea.java: (1)成员变量 block和Block类型的数组,用来确定雷区有多少需进行扫雷的方块; blockView是BlockView类型的数组,负责block数组中Block对象提供视图; lay是LayMines类型的对象,负责设置block数组中的哪些方块不是雷; record负责提供保存成绩的界面,是一个对话框,默认为不可见,用户只有扫雷成功后,才可以看见该对话框; reStart是一个按钮对象,用户单击它重新开始游戏; time是计时器对象,负责计算用户用时。 (2)方法 initMineArea(int,int,int,int)方法可根据参数提供的数据设置雷区的宽度,高度,类的数目以及雷区的级别。 actionPerformed(actionEvent)是MineArea类实现的ActionListener接口中的方法。当用户单击blockView中的某个方块时actionPerformed(actionEvent)执行有关算法。 Show()方法是一个递归方法,actionPerformed(actionEvent)方法执行将调用show 方法进行扫雷。 mousePressed(mouseEvent)方法是MineArea类实现的MouseListener接口中的方

吃鸡技巧-6 战术技巧

绝地求生刺激战场攻略大全 前期起跳飞行攻略 飞机飞行路线如果是沿四周飞行的话,向图中间飞行找目的地是良策 分析:现在改版后最大飞行距离(长距离飞行姿势大家都知道)加长,飞行+开伞最后移动距离可以超过一格半距离长度, 边侧飞行时,距离边缘基本是一格至一格半的距离。 这样思考下来,往中间飞行的玩家密集度是相对较小的,利于前期捡装备自卫存活 飞机飞行路线如果是版图倾斜飞行、中间飞行,目的地相对自由

摆明正确认知: 大城市虽然人多一点,但是房子多,可以苟、可以偷; 零散的小屋子虽然装备少,但是出现三级甲之类的概率也不低; 最主要的是快速落地,不是四排大小城市都是可以的 中期技巧攻略 利用建筑结构 绝地求生刺激战场很多二层、三层、公寓楼结构的屋子,他们外面都有水平突出的一段构造,都是可以通过窗户跳到上面站立行走的,然后利用右上角小地图的脚步提示误导敌人,最后趁机嘿嘿嘿…

(典型代表建筑:带车库的白色二层建筑,屡试不爽…) 设诱饵攻略(大众常用) 守盒法:淘汰别的玩家后,躲到一处,守盒,别人来舔,打死(这里注意时间点,基本ok) 守空投法:贴脸空投尽量别舔完,留点物资让它继续冒红烟,等鱼儿上钩 守物资法: 代表性建筑,通过对面高处可以看到部分二层楼面及外面阳台,上面都会有物资,看到有人进屋就可以开镜进行大体的预瞄,不成功也会有一定伤害值; 守残血法攻略:放长线钓大鱼的方法,适用于二排、四排

击倒一人后,放弃补枪,等他队友来施救,葫芦娃救爷爷╮(╯▽╰)╭ 诱饵篇注意事项: 别长时间开镜预瞄,因为你无法确定是否有别人注意到你,所以不开镜时,利用自由视角观察四周,有人接近诱饵时开镜袭击; 射击时候如果没有消音、消焰之类配件,同样建议别长时间开镜射击有掩体的敌人,理由同上 车辆规避攻略 正面钢枪法:距离不是特别近时,有车接近,可以选择打爆车胎,或者直接射击驾驶位 走位攻略:

扫雷的技巧攻略

经典游戏:扫雷的技巧攻略 ?浏览:3718 ?| ?更新:2013-09-16 13:54 扫雷作为策略游戏,需要游戏者精确的判断。现在扫雷高级的官方最快纪录是 33.95秒,中级则是由一个波兰玩家保持的8.5秒。而初级纪录是1秒,世界上 很多人达到了这一点。在1秒的时间里完成初级扫雷,据测算概率在0.00058%至0.00119%之间(属于运气题),最可能的方法是直接点击四个角的方块。而本文所作的事情,则是将雷与雷之间的规律给你揪出来,并且深入思考其中的内涵。让你以后面对扫雷时,缩短与记录的差距,战无不胜! 从简单雷区入手下图是一个初级的雷区,并且标注了两颗雷的位置,你能将剩下的地雷扫描出来吗? 经过逐一排查,可以很轻松的确定雷区中的6颗地雷所在位置: 再来看一个简单的“雷区”: 通过逐步扫描每一个方块会发现:首先最左边的和最右边的两个格子都一定是地雷,从左数第二个空格子和从右数第二个空格子也都是地雷,由于数字1的关系,从左数第3个格子和从右数第3个格子都不是地雷,翻开一定是数字1……这样

一直下去,最后你会发现最中间的两个空格子,不管有没有地雷,都和周围格子上的数字不符。也就是说这样的雷区有bug,是无解的。雷区中的逻辑门怎么判断一个雷区是否有bug?又怎么判断雷区中地雷的具体位置呢?难道一定要从头到尾将雷区扫描一遍吗?其实这些雷区里其实藏着一个规律。我们用数学方法来分析了上例的雷区:在之前提到的这两个雷区里,把还没有翻开的格子交叉标记上字母x和x’。可以看到:当x的格子有雷时,x’格子一定没有地雷,反之亦然。如果将最左边的空格子作为输入,把最右边的格子作为输出,输入结果和输出结果一定是一样或者相反的。如果是相反的,这相当于一个NOT (“非”)门电子元件。如果是一样的,就有趣了,这样的一片雷区就具备了电路导线的性质! 在这里,雷区被看成了一个数字逻辑电路。执行这些“或”、“与”、“非”等逻辑运算的电路则被称为——逻辑门。任何复杂的逻辑电路都可由这些逻辑门组成。逻辑门是集成电路上的基本组件。简单的逻辑门可由晶体管组成。这些晶体管的组合可以使代表两种型号的高低电平在通过它们后产生信号。而高低电平可以分别代表逻辑上的真假或二进制中的0和1,从而实现逻辑运算。具体到扫雷游戏里,也就是说,逻辑门可以用于判断一系列格子中的地雷的具体位置,而且它如同电路传导一样,精确而迅速。常见的(也是扫雷中用到的)逻辑门包括“与”门、“或”门、“非”门等。将它们组合使用就可以实现更复杂的运算——完成复杂情形下的扫雷,这种方法比按照规则缓慢推进的扫雷方法要节省很多时间。

c语言实现扫雷程序模拟

本人写的扫雷程序,由于时间紧迫,写的比较粗糙,但经过c编译可运行,下面是源代码: /*name:kaituozhe001saolei1125.cpp*/ #include #include #include #define N 9 int mine[N][N],game[N][N]; int row=0,col=0,a,b; void main() { void putmine(int n1); int expand(int row,int col); int Remain(); void myprintf1(); void myprintf2(); int aroundmine(int row,int col); /* 提示说明 */ printf(" -------------------------------------------------------------------\n* 您接下来要玩一个%d*%d的扫雷游戏。 *\n* 请按提示操作(否则会出意外的), *\n* 在这个游戏中“*”代表地雷,“#”代表未打开的盒子。 *\n* 当您将全部非雷盒子打开后,您就赢了! *\n* 谢谢参与游 戏!》》开拓者制作bo《《 *\n -------------------------------------------------------------------",N,N); int n1,i=0,j=0;

/*初始化雷区*/ for(i=0;i> ",N,N,N*N); scanf("%d",&n1); printf("\n下面是所布雷阵>> \n"); putmine(n1); myprintf1(); for(i=0;i> \n"); myprintf1(); while(Remain()!=n1) { printf("\n请输入扫雷坐标,以“,”分开>> "); scanf("%d,%d",&row,&col); for(i=0;i

扫雷 魔方公式图解

扫雷公式: 一夹二,一有雷。二夹一,心有雷。二夹三,全有雷。 二二边,都有雷。三连一,中有雷。四连一,边有雷。 新魔方新手教程 前言 我们常见的魔方是3x3x3的三阶魔方,英文名Rubik's cube。是一个正6 面体,有6种颜色,由26块组成,有8个角块;12个棱块;6个中心块(和中心轴支架相连)见下图: (图1) 学习魔方首先就要搞清它的以上结构,知道角块只能和角块换位,棱块只能和棱块换位,中心块不能移动。 魔方的标准色: 国际魔方标准色为:上黄-下白,前蓝-后绿,左橙-右红。(见图2)注:(这里以白色为底面,因为以后的教程都将以白色为底面,为了方便教学,请都统一以白色为准)。

(图2) 认识公式 (图3)(图4)公式说明:实际上就是以上下左右前后的英文的单词的头一个大写字母表示 (图5)

(图6) (图7)

(图8) 步骤一、完成一层 首先要做的是区分一层和一面:很多初学者对于“一面”与“一层”缺乏清楚的认识,所以在这里特别解释一下。所谓一层,就是在完成一面(如图2的白色面)的基础上,白色面的四条边,每条边的侧面只有一种颜色,图(2). 如图(1)中心块是蓝色,则它所在面的角和棱全都是蓝色,是图(2)的反方向 图(3)和(4)则是仅仅是一面的状态,而不是一层! (1)(2) (3)(4) 注:图(2)和(4)分别是图(1)和(3)的底面状态 想完成魔方,基础是最重要的,就像建筑一样,魔方也如此,基础是最重要的。 由于上文提到过中心块的固定性,这一性质,在魔方上实质起着定位的作用,简单的说就是中心块的颜色就代表它所在的面的颜色。 一、十字(就是快速法中的CROSS) 第一种情况如图所示:

扫雷游戏教程技巧大全

扫雷游戏教程技巧大全 扫雷软件可以在Windows的“开始”—“程序”—“附件”—“游戏”中找到。进入扫雷界面,会出现一大片方格: 先介绍一下操作吧:鼠标左键可以打开方格,鼠标右键可以把方格标记为地雷,打开的方格里的数字表示本方格周围有几颗地雷。如果一个方格周围已经标出的地雷数量和方格内数字相同,在方格上同时按左键和右键可以打开其 余方格。如果不幸踩雷,可以按按钮重新来过,不想用鼠标的话可以按键盘 上的F2键。操作介绍完了,现在我们实际演练一盘,就先初级的开始吧: 咱先从这个阵学习先从简单学起,请看左下角的 如果会玩的一看当然就知道左下角的那个不是雷,为什么会知道呢?这里有一个规律当方格子里有 1 时就表示它周围的 8 个格子里肯定有一个是雷,从这个分析 看中间的 1 它周围有 5 个空就表示有 5 个格子不是雷,看它左面的和下,的 1 也表示这两个不是雷,那么现在咱可以知道中间的 1 周围 8 个格子里有 7 个不是雷,下面咱就可以知道左下角的肯定是雷

在看最左面中间的那个 1 再看周围 8 个格子里可是他周围不是 8 个所以就考虑剩下的 6 个 还继续看那个 1 它周围有一个小红旗表示已经有一个雷了,就表示它的周围已经有一个雷了所以剩下的几个格子都不是雷 咱就可以得到 你已经学会了最简单的部分了,下面咱再分析左上的那部分 先用我上面给你介绍的那种方法,把下面三个 1 上面的两个格子解出来 可以得到 这时你是不是有点迷惘不知道怎么点了?别着急咱继续分析,看到这块右面的下面的 2 了吗?,它就表示它的周围有 2 颗雷但咱已经分析出已经有一个是雷了,还有它周围还剩下 1 个未知的格子还有6个已知的格子,所以咱就可以判断出刚才那个雷的上面还是个雷,咱们就可以得到 再看左边的那个 2 这时它周围已经有两个雷了,所以咱就可以把剩下的三个格点开,咱就可以知道 这时 2 上面还是 2 并且它周围已经有两颗雷 我们就可以把这部分解出来

扫雷教程

大家好。许多人现在都在玩一些刺激的网游,但许多人忽视了许多别的游戏。 现在,我开始教大家玩扫雷。
扫雷软件可以在 Windows 的“开始”—“程序”—“附件”—“游戏”中找到。 推荐大家使用 Minesweeper Clone 0.97,好处多多哦
可以从这里下载:https://www.360docs.net/doc/b012679108.html,/Download/Minesweeper_Clone_0.97.exe
进入扫雷界面,会出现一大片方格:
先介绍一下操作吧: 鼠标左键可以打开方格 鼠标右键可以把方格标记为地雷 打开的方格里的数字表示本方格周围有几颗地雷。 如果一个方格周围已经标出的地雷数量和方格内数字相同,在方格上同时按左键和右键可以打开其余方格。
如果不幸踩雷,可以按
按钮重新来过,不想用鼠标的话可以按键盘上的 F2 键。
操作介绍完了,现在我们实际演练一盘,就先初级的开始吧:
咱先从这个阵学习先从简单学起

请看左下角的
如果会玩的一看当然就知道左下角的那个不是雷 为什么会知道呢? 这里有一个规律 当方格子里有 1 时就表示它周围的 8 个格子里肯定有一个是雷 从这个分析
看中间的 1 它周围有 5 个空 就表示有 5 个格子不是雷 看它左面的和下面的 1 也表示这两个不是雷 那么现在咱可以知道中间的 1 周围 8 个格子里有 7 个不是雷 下面咱就可以知道左下角的肯定是雷
你猜对了 咱知道这个了
在看最左面中间的那个 1 再看周围 8 个格子里 可是他周围不是 8 个 所以就考虑剩下的 6 个 还继续看那个 1 它周围有一个小红旗 表示已经有一个雷了 就表示它的周围已经有一个雷了所以剩下的几个格子都不是雷 咱就可以得到
你已经学会了最简单的部分了 下面咱再分析左上的那部分

阅读扫雷法

考研英语阅读选题技巧 (扫雷法) 创作人:徐佳鹏注:此方法基于能确定部分正确答案,并可以排除部分错误选项。(用语篇分析做题最好)下面用11年考研英语阅读理解做示范 (由于不方便在选项上打√和打×,所以用红色字体代表确定的正确选项,蓝色代表确定的错误选项,黑色代表不确定选项) 制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨人:杨旭制作人:杨旭制作人:杨旭:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:制作人:杨杨旭旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:华丽分割线杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨人:杨旭制作人:杨旭制作人:杨旭:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭旭:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制作人:杨旭制 1、20个题用语篇分析做,确定对的打√,确定错的打×,不确定的不动。(一定要确保判断的准确率,这是基础,要不然和不会的全蒙一个选项的正确率相同) 以6题正确选对,6题排除两个错误选项,6题排除一个错误选项,两题完全没有头绪为标准,将数据随机排列。 (此处选1、5、8、11、13、19题为确定选项,2、3、6、9、14、15、20为排除两个错误选 2、每道题前后答案不一致,根据已经确定的6个正确答案排除此题上下题要排除的选项。

相关文档
最新文档