您当前的位置:首页 > IT编程 > python
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:python用tkinter开发的扫雷游戏

51自学网 2021-10-30 22:34:52
  python
这篇教程python用tkinter开发的扫雷游戏写得很实用,希望能帮到您。

1.实现效果

2.实现代码

# 导入所需库from tkinter import *import randomclass main:    # 定义一个类,继承 tkinter 的 Button    # 用来保存按钮的状态和在网格布局中的位置    class minebtn(Button):        def __init__(self,master,xy,**kw):            Button.__init__(self,master,**kw)            self.xy = xy            self._state = 0            # 状态            # 0: 未点开            # 1: 已点开            # 2: 标记            # 3: 问号                def __init__(self):        # 定义规格及雷数        self.width = 9        self.height = 9        self.minenum = 10        # Windows 7 默认的三种规格和雷数        # 9*9,10        # 16*16,40        # 16*32,99                self.rest = self.minenum    # 剩余未标记的雷				# 雷数的颜色        self.colorlist = ['green',	# 绿色                          'DodgerBlue',	# 浅蓝色                          'DarkOrange1',# 橙色                          'blue',	# 蓝色                          'red',	# 红色                          'Chocolate4',	# 棕色                          'grey',	# 灰色                          'black']	# 黑色                self.setgui()    def setgui(self):        # GUI界面        self.root = Tk()        self.root.title('扫雷')        self.restlabel = Label(self.root,text=f'剩余:{self.minenum}')        self.restlabel.grid(row=0,column=0,columnspan=3)        self.mineplace = random.sample(range(self.width*self.height),self.minenum)  # 随机抽取雷        self.mineplace = [(x%self.width,x//self.height) for x in self.mineplace]    # 将雷的序号转变为坐标        self.mines = {}        for y in range(self.height):            for x in range(self.width):                self.mines[(x,y)] = self.minebtn(self.root,xy=(x,y),font=('黑体',8,'bold'),width=2,bd=1,relief='ridge')                self.mines[(x,y)].bind('<ButtonRelease-1>',lambda event:self._open(event.widget))   # 左键单击点开                self.mines[(x,y)].bind('<ButtonRelease-3>',lambda event:self.make(event.widget))    # 右键单击事件                self.mines[(x,y)].grid(row=y+1,column=x,sticky='nswe')        self.root.mainloop()    # 点开    def _open(self,widget):        xy = widget.xy        x = xy[0]        y = xy[1]   # 获取当前按钮的坐标        # 如果是雷则显示全部雷的位置        if widget.xy in self.mineplace:            self.showmine()            return        # 如果已经点开了就什么也不做        if widget._state == 1:            return                widget.configure(relief='flat',bg='white')  # 更改当前按钮的样式                widget._state = 1   # 按钮状态设为点开        # 获取周围八个雷的坐标        around = [(x-1,y-1),                (x,y-1),                (x+1,y-1),                (x-1,y),                (x+1,y),                (x-1,y+1),                (x,y+1),                (x+1,y+1)]                _sum = 0        around_ = []                for o, p in around:            # 排除掉在雷区之外的雷            if 0 <= o <= self.width - 1 and 0 <= p <= self.height - 1:                around_.append((o,p))                # 计算周围的雷数                if self.mines[(o,p)].xy in self.mineplace:                    _sum += 1        #如果周围没有雷则打开周围未标记的雷,直到有雷为止        if _sum == 0:            widget['text'] = ''            for i, j in around:                                if self.mines[(i,j)]._state == 0:                    self._open(self.mines[(i,j)])        else:            widget['text'] = _sum   # 显示雷数            # 对应数字设置对应颜色            widget['fg'] = self.colorlist[_sum-1]    # 右键单击设置标记/问号    def make(self,widget):        string = {0:'',2:'♀',3:'?'}                if widget._state == 0:            widget._state = 2            widget['text'] = string[2]            self.rest -= 1            self.restlabel['text'] = f'剩余:{self.rest}'                    elif widget._state == 2:            widget._state = 3            widget['text'] = string[3]            self.rest += 1            self.restlabel['text'] = f'剩余:{self.rest}'                    elif widget._state == 3:            widget._state = 0            widget['text'] = string[0]    # 如果踩到雷,显示所有的雷    def showmine(self):        for i, j in self.mineplace:            self.mines[(i,j)].configure(text='ி',fg='red')                main()

3.另一种精致一点的实现

项目地址

需要导入额外的图片和字体资源,在上面的项目地址里可以下载到

代码

import sysimport timeimport randomimport pygamefrom pygame.locals import *BLOCK_WIDTH = 30BLOCK_HEIGHT = 16# 块大小SIZE = 20# 地雷数MINE_COUNT = 66# 未点击normal = 1# 已点击opened = 2# 地雷mine = 3# 标记为地雷flag = 4# 标记为问号ask = 5# 踩中地雷bomb = 6# 被双击的周围hint = 7# 正被鼠标左右键双击double = 8readied = 1,started = 2,over = 3,win = 4class Mine:    def __init__(self, x, y, value=0):        self._x = x        self._y = y        self._value = 0        self._around_mine_count = -1        self._status = normal        self.set_value(value)    def __repr__(self):        return str(self._value)    def get_x(self):        return self._x    def set_x(self, x):        self._x = x    x = property(fget=get_x, fset=set_x)    def get_y(self):        return self._y    def set_y(self, y):        self._y = y    y = property(fget=get_y, fset=set_y)    def get_value(self):        return self._value    def set_value(self, value):        if value:            self._value = 1        else:            self._value = 0    value = property(fget=get_value, fset=set_value, doc='0:非地雷 1:雷')    def get_around_mine_count(self):        return self._around_mine_count    def set_around_mine_count(self, around_mine_count):        self._around_mine_count = around_mine_count    around_mine_count = property(fget=get_around_mine_count, fset=set_around_mine_count, doc='四周地雷数量')    def get_status(self):        return self._status    def set_status(self, value):        self._status = value    status = property(fget=get_status, fset=set_status, doc='BlockStatus')class MineBlock:    def __init__(self):        self._block = [[Mine(i, j) for i in range(BLOCK_WIDTH)] for j in range(BLOCK_HEIGHT)]        # 埋雷        for i in random.sample(range(BLOCK_WIDTH * BLOCK_HEIGHT), MINE_COUNT):            self._block[i // BLOCK_WIDTH][i % BLOCK_WIDTH].value = 1    def get_block(self):        return self._block    block = property(fget=get_block)    def getmine(self, x, y):        return self._block[y][x]    def open_mine(self, x, y):        # 踩到雷了        if self._block[y][x].value:            self._block[y][x].status = bomb            return False        # 先把状态改为 opened        self._block[y][x].status = opened        around = _get_around(x, y)        _sum = 0        for i, j in around:            if self._block[j][i].value:                _sum += 1        self._block[y][x].around_mine_count = _sum        # 如果周围没有雷,那么将周围 8 个未中未点开的递归算一遍        if _sum == 0:            for i, j in around:                if self._block[j][i].around_mine_count == -1:                    self.open_mine(i, j)        return True    def double_mouse_button_down(self, x, y):        if self._block[y][x].around_mine_count == 0:            return True        self._block[y][x].status = double        around = _get_around(x, y)        # 周围被标记的雷数量        sumflag = 0        for i, j in _get_around(x, y):            if self._block[j][i].status == flag:                sumflag += 1        # 周边的雷已经全部被标记        result = True        if sumflag == self._block[y][x].around_mine_count:            for i, j in around:                if self._block[j][i].status == normal:                    if not self.open_mine(i, j):                        result = False        else:            for i, j in around:                if self._block[j][i].status == normal:                    self._block[j][i].status = hint        return result    def double_mouse_button_up(self, x, y):        self._block[y][x].status = opened        for i, j in _get_around(x, y):            if self._block[j][i].status == hint:                self._block[j][i].status = normal# 返回 (x, y) 周围的点坐标def _get_around(x, y):    return [(i, j) for i in range(max(0, x - 1), min(BLOCK_WIDTH - 1, x + 1) + 1)            for j in range(max(0, y - 1), min(BLOCK_HEIGHT - 1, y + 1) + 1) if i != x or j != y]# 游戏屏幕的宽SCREEN_WIDTH = BLOCK_WIDTH * SIZE# 游戏屏幕的高SCREEN_HEIGHT = (BLOCK_HEIGHT + 2) * SIZEdef print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):    imgText = font.render(text, True, fcolor)    screen.blit(imgText, (x, y))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 = readied    # 开始时间    start_time = None    # 耗时    elapsed_time = 0    while True:        screen.fill(bgcolor)        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 == started:                    # 鼠标左右键同时按下,如果已经标记了所有雷,则打开周围一圈;如果还未标记完所有雷,则有一个周围一圈被同时按下的效果                    if b1 and b3:                        mine = block.getmine(x, y)                        if mine.status == opened:                            if not block.double_mouse_button_down(x, y):                                game_status = 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 = readied                        block = MineBlock()                        start_time = time.time()                        elapsed_time = 0                        continue                if game_status == readied:                    game_status = started                    start_time = time.time()                    elapsed_time = 0                if game_status == started:                    mine = block.getmine(x, y)                    # 按鼠标左键                    if b1 and not b3:                        if mine.status == normal:                            if not block.open_mine(x, y):                                game_status = over                    # 按鼠标右键                    elif not b1 and b3:                        if mine.status == normal:                            mine.status = flag                        elif mine.status == flag:                            mine.status = ask                        elif mine.status == ask:                            mine.status = normal                    elif b1 and b3:                        if mine.status == double:                            block.double_mouse_button_up(x, y)        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 == opened:                    screen.blit(img_dict[mine.around_mine_count], pos)                    opened_count += 1                elif mine.status == double:                    screen.blit(img_dict[mine.around_mine_count], pos)                elif mine.status == bomb:                    screen.blit(img_blood, pos)                elif mine.status == flag:                    screen.blit(img_flag, pos)                    flag_count += 1                elif mine.status == ask:                    screen.blit(img_ask, pos)                elif mine.status == hint:                    screen.blit(img0, pos)                elif game_status == over and mine.value:                    screen.blit(img_mine, pos)                elif mine.value == 0 and mine.status == flag:                    screen.blit(img_error, pos)                elif mine.status == 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 == 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 = win        if game_status == over:            screen.blit(img_face_fail, (face_pos_x, face_pos_y))        elif game_status == 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()

以上就是python用tkinter开发的扫雷游戏的详细内容,更多关于python 扫雷游戏的资料请关注51zixue.net其它相关文章!


Pytorch GPU内存占用很高,但是利用率很低如何解决
python plt.plot bar 如何设置绘图尺寸大小
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。