作者:野客 来源:Python技术 扫雷是一款益智类小游戏,最早于1992年由微软在Windows上发行,游戏适合于全年龄段,规则简单,即在最短的时间内找出所有非雷格子且在中间过程中不能踩到雷,踩到雷则失败,需重新开始。 本文我们使用Python来实现扫雷游戏,主要用的Python库是pygame。实现 游戏组成比较简单,主要包括:小方格、计时器、地雷等。 首先,我们初始化一些常量,比如:横竖方块数、地雷数、鼠标点击情况等,如下所示:BLOCKWIDTH30BLOCKHEIGHT16块大小SIZE20地雷数MINECOUNT66未点击normal1已点击opened2地雷mine3标记为地雷flag4标记为问号ask5踩中地雷bomb6被双击的周围hint7正被鼠标左右键双击double8readied1,started2,over3,win4 接着定义一个地雷类,类中定义一些基本属性(如:坐标、状态等)及get、set方法,代码实现如下:classMine:definit(self,x,y,value0):self。xxself。yyself。value0self。aroundminecount1self。statusnormalself。setvalue(value)defrepr(self):returnstr(self。value)defgetx(self):returnself。xdefsetx(self,x):self。xxxproperty(fgetgetx,fsetsetx)defgety(self):returnself。ydefsety(self,y):self。yyyproperty(fgetgety,fsetsety)defgetvalue(self):returnself。valuedefsetvalue(self,value):ifvalue:self。value1else:self。value0valueproperty(fgetgetvalue,fsetsetvalue,doc0:非地雷1:雷)defgetaroundminecount(self):returnself。aroundminecountdefsetaroundminecount(self,aroundminecount):self。aroundminecountaroundminecountaroundminecountproperty(fgetgetaroundminecount,fsetsetaroundminecount,doc四周地雷数量)defgetstatus(self):returnself。statusdefsetstatus(self,value):self。statusvaluestatusproperty(fgetgetstatus,fsetsetstatus,docBlockStatus) 再接着定义一个MineBlock类,用来处理扫雷的基本逻辑,代码实现如下:classMineBlock:definit(self):self。block〔〔Mine(i,j)foriinrange(BLOCKWIDTH)〕forjinrange(BLOCKHEIGHT)〕埋雷foriinrandom。sample(range(BLOCKWIDTHBLOCKHEIGHT),MINECOUNT):self。block〔iBLOCKWIDTH〕〔iBLOCKWIDTH〕。value1defgetblock(self):returnself。blockblockproperty(fgetgetblock)defgetmine(self,x,y):returnself。block〔y〕〔x〕defopenmine(self,x,y):踩到雷了ifself。block〔y〕〔x〕。value:self。block〔y〕〔x〕。statusbombreturnFalse先把状态改为openedself。block〔y〕〔x〕。statusopenedaroundgetaround(x,y)sum0fori,jinaround:ifself。block〔j〕〔i〕。value:sum1self。block〔y〕〔x〕。aroundminecountsum如果周围没有雷,那么将周围8个未中未点开的递归算一遍ifsum0:fori,jinaround:ifself。block〔j〕〔i〕。aroundminecount1:self。openmine(i,j)returnTruedefdoublemousebuttondown(self,x,y):ifself。block〔y〕〔x〕。aroundminecount0:returnTrueself。block〔y〕〔x〕。statusdoublearoundgetaround(x,y)周围被标记的雷数量sumflag0fori,jingetaround(x,y):ifself。block〔j〕〔i〕。statusflag:sumflag1周边的雷已经全部被标记resultTrueifsumflagself。block〔y〕〔x〕。aroundminecount:fori,jinaround:ifself。block〔j〕〔i〕。statusnormal:ifnotself。openmine(i,j):resultFalseelse:fori,jinaround:ifself。block〔j〕〔i〕。statusnormal:self。block〔j〕〔i〕。statushintreturnresultdefdoublemousebuttonup(self,x,y):self。block〔y〕〔x〕。statusopenedfori,jingetaround(x,y):ifself。block〔j〕〔i〕。statushint:self。block〔j〕〔i〕。statusnormal 我们接下来初始化界面,首先生成由小方格组成的面板,主要代码实现如下:forrowinblock。block:formineinrow:pos(mine。xSIZE,(mine。y2)SIZE)ifmine。statusopened:screen。blit(imgdict〔mine。aroundminecount〕,pos)openedcount1elifmine。statusdouble:screen。blit(imgdict〔mine。aroundminecount〕,pos)elifmine。statusbomb:screen。blit(imgblood,pos)elifmine。statusflag:screen。blit(imgflag,pos)flagcount1elifmine。statusask:screen。blit(imgask,pos)elifmine。statushint:screen。blit(img0,pos)elifgamestatusoverandmine。value:screen。blit(imgmine,pos)elifmine。value0andmine。statusflag:screen。blit(imgerror,pos)elifmine。statusnormal:screen。blit(imgblank,pos) 看一下效果: 再接着添加面板的head部分,包括:显示雷数、重新开始按钮(笑脸)、显示耗时,主要代码实现如下:printtext(screen,font1,30,(SIZE2fheight)22,02d(MINECOUNTflagcount),red)ifgamestatusstarted:elapsedtimeint(time。time()starttime)printtext(screen,font1,SCREENWIDTHfwidth30,(SIZE2fheight)22,03delapsedtime,red)ifflagcountopenedcountBLOCKWIDTHBLOCKHEIGHT:gamestatuswinifgamestatusover:screen。blit(imgfacefail,(faceposx,faceposy))elifgamestatuswin:screen。blit(imgfacesuccess,(faceposx,faceposy))else:screen。blit(imgfacenormal,(faceposx,faceposy)) 看一下效果: 再接着添加各种点击事件,代码实现如下:foreventinpygame。event。get():ifevent。typeQUIT:sys。exit()elifevent。typeMOUSEBUTTONDOWN:mousex,mouseyevent。posxmousexSIZEymouseySIZE2b1,b2,b3pygame。mouse。getpressed()ifgamestatusstarted:鼠标左右键同时按下,如果已经标记了所有雷,则打开周围一圈;如果还未标记完所有雷,则有一个周围一圈被同时按下的效果ifb1andb3:mineblock。getmine(x,y)ifmine。statusopened:ifnotblock。doublemousebuttondown(x,y):gamestatusoverelifevent。typeMOUSEBUTTONUP:ify0:iffaceposxmousexfaceposxfacesizeandfaceposymouseyfaceposyfacesize:gamestatusreadiedblockMineBlock()starttimetime。time()elapsedtime0continueifgamestatusreadied:gamestatusstartedstarttimetime。time()elapsedtime0ifgamestatusstarted:mineblock。getmine(x,y)按鼠标左键ifb1andnotb3:ifmine。statusnormal:ifnotblock。openmine(x,y):gamestatusover按鼠标右键elifnotb1andb3:ifmine。statusnormal:mine。statusflagelifmine。statusflag:mine。statusaskelifmine。statusask:mine。statusnormalelifb1andb3:ifmine。statusdouble:block。doublemousebuttonup(x,y) 我们来看一下最终实现效果: 总结 本文我们通过Python简单的实现了扫雷游戏,大家有兴趣的话,可以实际操作一下,看看自己能否排除全部的雷。