Python:游戏:扫雷(附源码)

要为扫雷游戏布置地雷,如该位置不是地雷,游戏中如何产生地雷,游戏界面,仿照 XP 上的扫雷做的,这次我们基于 pygame 来做一个扫雷,文章中代码运行的环境为Windows下  Python 2.7.14

图片 7

 

图片 1

连锁博文推荐:

三、关键代码分析

  前置:

     将每一格封装成一个类:CGameCell

     用m_CellList记录整个画面中各样类的指标

     用mineList记录Bray的地方(所在的行,列)

(1)布雷:

图片 2

Bray的函数主体

思路:如在9*9~拾的等级里,供给自由陈设11个雷,那13个随机数必要在 [0 ~
八一)之间爆发,之后在对每一种随机数实行 r, c =divmod(index,
self.m_ColBoard)
取模、取余的操作,模代表该雷所在的行,余代表该雷所在的列,再用mineList对富有的雷的岗位进行记录。那样做的补益是,每回的Bray都是精准的,时间复杂度低。

(2)总括每格周边雷的数目:

图片 3

总计每格附近雷的数额

思路:在mineList记录了雷的地方,以各类雷为中央,向其分布的多少个样子(左上,正上,右上,正左,正右,左下,正下,右下)进行扩充(注意看清越界),判别该格是不是为雷,非雷的话对该格记录的多寡值+一。该做法比遵照每格举行遍历,功效高出数量级…..

(3)非递归实现用户翻转钦点格的效应,截图代码不完全,详细代码见后一章节:

图片 4

非递归完毕用户翻转格

思路:

新开四个数组一个是待检测列表(waitChecklist),二个是已检查评定数组(m_CellList);检查有个别地方,如x,y时,先把它Point(x,y)
append进待检查列表。然后循环while(待检查实验列表的长短>0){

count = round(point.x,point.y)

把point从待检测列表放到已经侧列表

假设count等于0,把point周围的八个point放进待检查测试列表

留意:假若已检测数组里面已经有特别point了,就绝不把它加到待检查评定列表里面,不然会死循环,可参看广搜的法则和2叉树的非递归遍历。也得以用递归实现,不过集团一般不让用递归…

       
要为扫雷游戏陈设地雷,扫雷游戏的扫雷面板能够用2维int数组表示。如某地点为地雷,则该职位用数字-一代表,
如该任务不是地雷,则权且用数字0表示。
编写程序完成在该二维数组中随便Bray的操作,程序读入2个参数:Bray面板的行数(r),列数(c),安顿的地雷个数(n),
且要满意0<n<r*c*0.75(即布置地雷的最大密度为四分之三),程序运转后将n个地雷随机地摆放在r*c的二维数组,安排到位后进行扫雷游戏。

初级分界面是:横竖各九格,共拾颗雷

要是未有全标识完,会有2个意义呈现周围1圈未被展开和标志的格子

二、须要的简约深入分析

(一)先在windows的附属类小部件里面把扫雷游戏展开,来多玩几盘

(二)整理整个娱乐供给的流程图:

图片 5

供给简要剖判流程图

注:初级9行*9列~10个雷,中级16*16~40,高级16*30~9玖,自定义行列尚未落到实处

import java.util.*;

public class Minesweeper {
    public static void main(String[] args) {
        Scanner scn = new Scanner(System.in);
        //输入行和列
        int r = Integer.parseInt(scn.nextLine());
        int c = Integer.parseInt(scn.nextLine());
        if(r<2 || c<2)
        {
            System.out.println("输入的行列无效。");
            return;
        }
        //定义一个二维数组来布雷
        int[][] a = new int[r][c];
        Random rnd = new Random();
        //随机给出雷的个数
        int n = rnd.nextInt((int)(r*c*0.75));
        System.out.println("雷的个数:"+n);
        while(n>0)
        {
            //随机的布雷,随机产生雷所在行和列
            int rr = rnd.nextInt(r);
            int cc = rnd.nextInt(c);
            if(a[rr][cc]!=-1)
            {
                a[rr][cc]=-1;
                n--;
            }
        }
        //扫雷
        for(int i=0;i<r;i++)
        {
            for(int j=0;j<c;j++)
            {
                int lei=0;
                if(a[i][j] == 0)
                {
                    if(i-1>=0 && j-1>=0 && a[i-1][j-1]==-1)
                        lei++;
                    if(i-1>=0 && a[i-1][j]==-1)
                        lei++;
                    if(j<c-1)
                    {
                        if(i-1>=0 && a[i-1][j+1]==-1)
                            lei++;
                        if(a[i][j+1]==-1)
                            lei++;
                    }
                    if(j-1>=0 && a[i][j-1]==-1)
                        lei++;
                    if(i<r-1)
                    {
                        if(j-1>=0 && a[i+1][j-1]==-1)
                            lei++;
                        if(a[i+1][j]==-1)
                            lei++;
                    }
                    if(i<r-1 && j<c-1)
                    {
                        if(i+1>=1 && j+1>=1 && a[i+1][j+1]==-1)
                            lei++;
                    }
                    a[i][j]=lei;
                }
            }
        }
        //输出
        for(int i=0;i<r;i++)
        {
            for(int j=0;j<c;j++)
            {
                System.out.print(a[i][j]+"\t");
            }
            System.out.println();
        }
    }
}

{//假使在雷区数组m_pMines[9][9]中的元素m_pMines[i][j]的天性不是地雷,那么将其性子修改为地雷

扫码关切自个儿的私有公众号,回复
“扫雷”获取源码。

正文针对会基本python语法的读者。

voidCMineWnd::LayMines(UINT row, UINT col)//布雷函数

那几个总括其实也便于,只要用递归就足以了,要是计算出周围的雷数为0,则递归总结周边七个任务的四周雷数,直到雷数不为0。

转载请申明,有标题能够留言一齐商讨。

}//通过该函数可成功Bray,达成游戏布雷的初步化

import sysimport timefrom enum import Enumimport pygamefrom pygame.locals import *from mineblock import *# 游戏屏幕的宽SCREEN_WIDTH = BLOCK_WIDTH * SIZE# 游戏屏幕的高SCREEN_HEIGHT = (BLOCK_HEIGHT + 2) * SIZEclass GameStatus:    readied = 1,    started = 2,    over = 3,    win = 4def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):    imgText = font.render(text, True, fcolor)    screen.blit(imgText, def main():    pygame.init()    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))    pygame.display.set_caption('扫雷')    font1 = pygame.font.Font('resources/a.TTF', SIZE * 2)  # 得分的字体    fwidth, fheight = font1.size('999')    red = (200, 40, 40)    # 加载资源图片,因为资源文件大小不一,所以做了统一的缩放处理    img0 = pygame.image.load('resources/0.bmp').convert()    img0 = pygame.transform.smoothscale(img0, (SIZE, SIZE))    img1 = pygame.image.load('resources/1.bmp').convert()    img1 = pygame.transform.smoothscale(img1, (SIZE, SIZE))    img2 = pygame.image.load('resources/2.bmp').convert()    img2 = pygame.transform.smoothscale(img2, (SIZE, SIZE))    img3 = pygame.image.load('resources/3.bmp').convert()    img3 = pygame.transform.smoothscale(img3, (SIZE, SIZE))    img4 = pygame.image.load('resources/4.bmp').convert()    img4 = pygame.transform.smoothscale(img4, (SIZE, SIZE))    img5 = pygame.image.load('resources/5.bmp').convert()    img5 = pygame.transform.smoothscale(img5, (SIZE, SIZE))    img6 = pygame.image.load('resources/6.bmp').convert()    img6 = pygame.transform.smoothscale(img6, (SIZE, SIZE))    img7 = pygame.image.load('resources/7.bmp').convert()    img7 = pygame.transform.smoothscale(img7, (SIZE, SIZE))    img8 = pygame.image.load('resources/8.bmp').convert()    img8 = pygame.transform.smoothscale(img8, (SIZE, SIZE))    img_blank = pygame.image.load('resources/blank.bmp').convert()    img_blank = pygame.transform.smoothscale(img_blank, (SIZE, SIZE))    img_flag = pygame.image.load('resources/flag.bmp').convert()    img_flag = pygame.transform.smoothscale(img_flag, (SIZE, SIZE))    img_ask = pygame.image.load('resources/ask.bmp').convert()    img_ask = pygame.transform.smoothscale(img_ask, (SIZE, SIZE))    img_mine = pygame.image.load('resources/mine.bmp').convert()    img_mine = pygame.transform.smoothscale(img_mine, (SIZE, SIZE))    img_blood = pygame.image.load('resources/blood.bmp').convert()    img_blood = pygame.transform.smoothscale(img_blood, (SIZE, SIZE))    img_error = pygame.image.load('resources/error.bmp').convert()    img_error = pygame.transform.smoothscale(img_error, (SIZE, SIZE))    face_size = int(SIZE * 1.25)    img_face_fail = pygame.image.load('resources/face_fail.bmp').convert()    img_face_fail = pygame.transform.smoothscale(img_face_fail, (face_size, face_size))    img_face_normal = pygame.image.load('resources/face_normal.bmp').convert()    img_face_normal = pygame.transform.smoothscale(img_face_normal, (face_size, face_size))    img_face_success = pygame.image.load('resources/face_success.bmp').convert()    img_face_success = pygame.transform.smoothscale(img_face_success, (face_size, face_size))    face_pos_x = (SCREEN_WIDTH - face_size) // 2    face_pos_y = (SIZE * 2 - face_size) // 2    img_dict = {        0: img0,        1: img1,        2: img2,        3: img3,        4: img4,        5: img5,        6: img6,        7: img7,        8: img8    }    bgcolor = (225, 225, 225)   # 背景色    block = MineBlock()    game_status = GameStatus.readied    start_time = None   # 开始时间    elapsed_time = 0    # 耗时    while True:        # 填充背景色        screen.fill        for event in pygame.event.get():            if event.type == QUIT:                sys.exit()            elif event.type == MOUSEBUTTONDOWN:                mouse_x, mouse_y = event.pos                x = mouse_x // SIZE                y = mouse_y // SIZE - 2                b1, b2, b3 = pygame.mouse.get_pressed()                if game_status == GameStatus.started:                    # 鼠标左右键同时按下,如果已经标记了所有雷,则打开周围一圈                    # 如果还未标记完所有雷,则有一个周围一圈被同时按下的效果                    if b1 and b3:                        mine = block.getmine                        if mine.status == BlockStatus.opened:                            if not block.double_mouse_button_down:                                game_status = GameStatus.over            elif event.type == MOUSEBUTTONUP:                if y < 0:                    if face_pos_x <= mouse_x <= face_pos_x + face_size \                            and face_pos_y <= mouse_y <= face_pos_y + face_size:                        game_status = GameStatus.readied                        block = MineBlock()                        start_time = time.time()                        elapsed_time = 0                        continue                if game_status == GameStatus.readied:                    game_status = GameStatus.started                    start_time = time.time()                    elapsed_time = 0                if game_status == GameStatus.started:                    mine = block.getmine                    if b1 and not b3:       # 按鼠标左键                        if mine.status == BlockStatus.normal:                            if not block.open_mine:                                game_status = GameStatus.over                    elif not b1 and b3:     # 按鼠标右键                        if mine.status == BlockStatus.normal:                            mine.status = BlockStatus.flag                        elif mine.status == BlockStatus.flag:                            mine.status = BlockStatus.ask                        elif mine.status == BlockStatus.ask:                            mine.status = BlockStatus.normal                    elif b1 and b3:                        if mine.status == BlockStatus.double:                            block.double_mouse_button_up        flag_count = 0        opened_count = 0        for row in block.block:            for mine in row:                pos = (mine.x * SIZE, (mine.y + 2) * SIZE)                if mine.status == BlockStatus.opened:                    screen.blit(img_dict[mine.around_mine_count], pos)                    opened_count += 1                elif mine.status == BlockStatus.double:                    screen.blit(img_dict[mine.around_mine_count], pos)                elif mine.status == BlockStatus.bomb:                    screen.blit(img_blood, pos)                elif mine.status == BlockStatus.flag:                    screen.blit(img_flag, pos)                    flag_count += 1                elif mine.status == BlockStatus.ask:                    screen.blit(img_ask, pos)                elif mine.status == BlockStatus.hint:                    screen.blit(img0, pos)                elif game_status == GameStatus.over and mine.value:                    screen.blit(img_mine, pos)                elif mine.value == 0 and mine.status == BlockStatus.flag:                    screen.blit(img_error, pos)                elif mine.status == BlockStatus.normal:                    screen.blit(img_blank, pos)        print_text(screen, font1, 30, (SIZE * 2 - fheight) // 2 - 2, '%02d' % (MINE_COUNT - flag_count), red)        if game_status == GameStatus.started:            elapsed_time = int(time.time() - start_time)        print_text(screen, font1, SCREEN_WIDTH - fwidth - 30, (SIZE * 2 - fheight) // 2 - 2, '%03d' % elapsed_time, red)        if flag_count + opened_count == BLOCK_WIDTH * BLOCK_HEIGHT:            game_status = GameStatus.win        if game_status == GameStatus.over:            screen.blit(img_face_fail, (face_pos_x, face_pos_y))        elif game_status == GameStatus.win:            screen.blit(img_face_success, (face_pos_x, face_pos_y))        else:            screen.blit(img_face_normal, (face_pos_x, face_pos_y))        pygame.display.update()if __name__ == '__main__':    main()

四、全部代码(第3遍用简书,代码粘贴进来多少离奇)

# -*- coding: gbk -*-

# Created by zhoullin on 2018-03-27

import random

LEVEL_ONE = 1

LEVEL_TWO = 2

LEVEL_THREE = 3

MINE_VALUE = -1

EMPTY_VALUE = 0

UNCOVER_STATUS = 1

COVER_STATUS = 0

INPUT_GAME_LEVEL_EQX56RO奥迪Q5 = ‘输入游戏编号错误’

USER_SELECT_TIPS = (“1、初级:10个雷,9*玖平铺网格\n”

                    “2、中级:40个雷,16*1六平铺网格\n”

                    “3、高级:99个雷,16*30平铺网格”)

LEVEL_DIC = {

    1: (9, 9, 10),

    2: (16, 16, 40),

    3: (16, 30, 99)

}

def CheckInputIsCorrect(levelStr):

    if len(levelStr) == 1 and levelStr[0].isdigit():

        levelInt = int(levelStr[0])

        if levelInt in (LEVEL_ONE, LEVEL_TWO, LEVEL_THREE):

            return True

    print INPUT_GAME_LEVEL_ERROR

    return False

def GetUserSelectedLevel():

    ”’

    获取用户选取的嬉戏等第

    ”’

    print USER_SELECT_TIPS

    while True:

        levelStr = raw_input(“请输入你要挑选的游戏品级编号:”).split()

        if CheckInputIsCorrect(levelStr):

            return int(levelStr[0])

    return -1

class CGameCore(object):

    def __init__(self, levelInt):

        self.m_RowBoard, self.m_ColBoard, self.m_MineNum =
LEVEL_DIC[levelInt]

        self.m_TotalCell = self.m_RowBoard * self.m_ColBoard

        self.m_CellList = [[CGameCell(r, c) for c in
range(self.m_ColBoard)] for r in range(self.m_RowBoard)]

        self.m_UncoverCount = 0

        # for test

        # print “self.m_CellList:”,self.m_CellList

        mineList = self.SetMinePosition()

        self.UpdateMineBoardData(mineList)

    def SetMinePosition(self):

        if self.m_MineNum >= self.m_TotalCell:  #
对mineNumber的参数是否创建实行判别

            print “Bray数量过多,不吻合游戏规则”

            return

        randomList = random.sample(range(self.m_TotalCell),
self.m_MineNum)  # 在[0,row*col]里面发生一个尺寸为mineNum的列表

        mineList = []

        if self.m_ColBoard == 0:

            return mineList

        for index in randomList:

            r, c = divmod(index, self.m_ColBoard)

            self.m_CellList[r][c].SetValue(MINE_VALUE)

            mineList.append([r, c])

        return mineList

    def UpdateMineBoardData(self, mineList):

        for mine in mineList:

            row, col = mine

            for i in range(row – 1, row + 2):

                for j in range(col – 1, col + 2):

                    if self.CheckRowAndColIsCorrect(i, j):

                        self.m_CellList[i][j].UpdateValue()

        #for test

        #print mineList

    def ShowBoard(self):

        for r in range(0, self.m_RowBoard + 1):

            for c in range(0, self.m_ColBoard + 1):

                if r == 0 or c == 0:

                    self.showBoardHeader(r, c)

                else:

                    self.m_CellList[r-1][c-1].PrintSelf()

            print ” “

        print ‘当前游戏雷数量:’, self.m_MineNum

    def showBoardHeader(self, row, col):

        if row == 0:

            if col == 0:

                print ”  “,

            else:

                if (col – 1) < 10:  # 为了体现对齐

                    print ‘ %d ‘ % (col – 1),

                else:

                    print ‘ %d’ % (col – 1),

        elif col == 0:

            if (row – 1) < 10:  # 为了显得对齐

                print ‘%d ‘ % (row – 1),

            else:

                print (row – 1),

    def UncoverPosition(self, row, col):

        # 对用户钦点的翻转格实行判断

        if self.m_CellList[row][col].GetStatus() ==
UNCOVER_STATUS:

            return 0

        if self.m_CellList[row][col].GetValue() == MINE_VALUE:

            return MINE_VALUE

        self.m_CellList[row][col].SetStatus(UNCOVER_STATUS)

        self.m_UncoverCount += 1

        waitChecklist = []

        waitChecklist.append((row, col))

        while len(waitChecklist) > 0:

            # for test

            print “waitChecklist:”,waitChecklist

            tempRow, tempCol = waitChecklist[0]

            if self.m_CellList[tempRow][tempCol].GetValue() ==
EMPTY_VALUE:

                # for test

                aroundList = self.GetAroundPosition(tempRow, tempCol)

                for around in aroundList:

                    i, j = around

                    if (self.m_CellList[i][j].GetValue() ==
EMPTY_VALUE and (i, j) not in waitChecklist and
self.m_CellList[i][j].GetStatus() == COVER_STATUS):

                        waitChecklist.append((i, j))

                    elif self.m_CellList[i][j].GetStatus() ==
COVER_STATUS:

                       
self.m_CellList[i][j].SetStatus(UNCOVER_STATUS)

                        self.m_UncoverCount += 1

            del waitChecklist[0]

        print “m_UncoverCount:”, self.m_UncoverCount

        return 0

    def GetAroundPosition(self, row, col):

        aroundList = []

        for i in range(max(0, row – 1), min(row + 2, self.m_RowBoard)):

            for j in range(max(0, col – 1), min(col + 2,
self.m_ColBoard)):

                aroundList.append((i, j))

        return aroundList

    def ShowAllMineInBoard(self):

        ”’

        展现全部的雷区

        ”’

        print “呈现全部的雷区”

        for r in range(0, self.m_RowBoard + 1):

            for c in range(0, self.m_ColBoard + 1):

                if r == 0 or c == 0:

                    self.showBoardHeader(r, c)

                else:

                    if self.m_CellList[r – 1][c – 1].GetValue() ==
MINE_VALUE:

                       
self.m_CellList[r-1][c-1].SetStatus(UNCOVER_STATUS)

                    self.m_CellList[r-1][c-1].PrintSelf()

            print ” “

    def CheckUncoverParameter(self,rowAndColStr):

        if len(rowAndColStr) == 2 and rowAndColStr[0].isdigit() and
rowAndColStr[1].isdigit():

            if self.CheckRowAndColIsCorrect(int(rowAndColStr[0]),
int(rowAndColStr[1])):

                return True

        return False

    def CheckRowAndColIsCorrect(self, row, col):

        if (0 <= row < self.m_RowBoard) and (0 <= col <
self.m_ColBoard):

            return True

        return False

    def MainLoop(self):

        ”’

        正式进入娱乐品级

        ”’

        while True:

            rowAndColStr =
raw_input(“请输入你要翻转格子所在的行与列(中间用空格分离):”).split()

            if self.CheckUncoverParameter(rowAndColStr) is False:

                print “输入的行或列错误!!!”

                continue

            result = self.UncoverPosition(int(rowAndColStr[0]),
int(rowAndColStr[1]))

            if result == MINE_VALUE:

                self.ShowAllMineInBoard()

                print ‘踩雷啦!!!游戏停止····’

                break

            else:

                self.ShowBoard()

                if (self.m_TotalCell – self.m_UncoverCount) ==
self.m_MineNum:

                    print “恭喜!恭喜!游戏通过啦!”

                    break

    def Run(self):

        self.ShowBoard()

        self.MainLoop()

class CGameCell(object):

    s_UncoverCount = 0

    def __init__(self, row, column, value=0, uncover=COVER_STATUS):

        self.m_Row = row

        self.m_Column = column

        self.m_Value = value

        self.m_Uncover = uncover

    def SetValue(self, value):

        self.m_Value = value

    def UpdateValue(self):

        if self.m_Value != MINE_VALUE:

            self.m_Value += 1

    def GetValue(self):

        return self.m_Value

    def SetStatus(self, uncover):

        self.m_Uncover = uncover

    def GetStatus(self):

        return self.m_Uncover

    def PrintSelf(self):

        if self.m_Uncover == COVER_STATUS:

            print ‘[-]’,

        else:

            if self.m_Value == 0:

                print ‘[ ]’,

            elif self.m_Value == MINE_VALUE:

                print ‘[*]’,

            else:

                print ‘[%d]’ % (self.m_Value),

if __name__ == “__main__”:

    levelInt = GetUserSelectedLevel()

    gameExample = CGameCore(levelInt)

    gameExample.Run()

图片 6

Python:游戏:300行代码实现俄罗丝四方

作品中代码运维的遭遇为Windows下  Python 二.柒.14

for(UINT index = 0; index//使用For循环来产生地雷

代码纵然不多,但增进注释和空行也会有350行,别的还有一部分图纸能源,就不全帖上来了,完整的代码和财富小编放到CSDN上了,感兴趣的小友人可以去下载一下。下载地址

壹、完结的简易意义

图片 7

pycharm上运营效果

        注: [-]:未翻转; [1] 周边的地雷数量; [*]地雷,[
]广阔未有地雷