菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
45
0

002.07 MineSweeper - PsSimleGUI 的应用

原创
05/13 14:22
阅读数 427

建檔日期: 2019/12/07

更新日期: None

语言: Python 3.7.2, PySimpleGUI 4.6.0

系统: Win10 Ver. 10.0.17763

主题: 002.07 MineSweeper - PsSimleGUI 的应用

还是用PySimpleGU来写一个常见的游戏MineSweeper, 其中PySimpleGUI Button没有提供鼠标右键功能下, 自己加了个event handler来处理, 其他没啥好说, 请见下文.

鼠标右键Event Handler

def right_click(self, event): # Right_click handler
 if self.state == 1:
 self.update(3)
 elif self.state == 3:
 self.update(1)
window[b[x][y].key].Widget.bind('<Button-3>', b[x][y].right_click)

游戏方法:

  • 鼠标左键点选, 显示数字或炸弹, 数字的意义为'周围有多少颗炸弹'.

  • 鼠标右键点选, 以旗子标记自己认为是炸弹的格子, 鼠标左键不可点选显示, 再点选则去除标记.

  • 上方记录炸弹总数, 已点到炸弹总数, 以及旗子总数, 后两者数目等于前者时, 游戏结束

游戏目标:

  • 以最少数点到的炸弹总数, 完成游戏.

游戏画面:

002.07  MineSweeper - PsSimleGUI 的应用

代码:

import PySimpleGUI as sg
import random
import sys
'''
Source code of MineSweeper Game
'''
font        = 'Courier 16 bold'
width       = 25
height      = 14
all         = 80
new_start   = True
size        = (30,30)
# 0: 0, 1: hidden card, 2: bomb card, 3: flag card, 4: shown card
im          = ['', 'blank.png', 'bomb.png', 'flag.png', '']
color       = [('grey', 'grey'), ('black', 'green'),
               ('black', 'green'), ('black', 'green'), ('black', 'grey')]

def binding_all():                  # Bind right button of mouse to cell object

    for x in range(width):
        for y in range(height):
            window[b[x][y].key].Widget.bind(
                '<Button-3>', b[x][y].right_click)

# Setting for top buttons
def button1(text, key=None, disabled=False, button_color=('white', 'green')):

    return sg.Button(text, pad=(10, 10), font=font, focus=False, key=key,
            disabled=disabled, button_color=button_color)

def button2(x, y):                  # define cell as instance of button and

    b[x][y] = button(x,y)           # bulid Button
    return b[x][y].button

def check_blank(x, y):              # Check if cell near 0-bomb cel

    if b[x][y].num==0: return False
    for i in [-1, 0, 1]:
        for j in [-1, 0, 1]:
            if i==0 and j==0: continue
            if ((0<=x+i<width) and (0<=y+j<height) and
                (b[x+i][y+j].num==0)): return True
    return False

def check_num():                    # check number of bombs, flags and hides

    bomb_count = flag_count = hide_count = 0
    for x in range(width):
        for y in range(height):
            if b[x][y].state == 1:
                hide_count += 1
            elif b[x][y].state == 2:
                bomb_count += 1
            elif b[x][y].state == 3:
                flag_count += 1
    return bomb_count, flag_count, hide_count

# Count number of bombs about cell
def count_bomb(x, y):

    global bomb
    if bomb[x][y]==10: return 10
    count = 0
    for i in [-1, 0, 1]:
        for j in [-1, 0, 1]:
            if i==0 and j==0: continue
            if ((0<=x+i<width) and (0<=y+j<height) and
                (bomb[x+i][y+j]==10)):
                count += 1
    return count

# set position for all boms
def deal():

    global bomb
    bomb_list   = random.sample(range(width*height), all)
    bomb        = [[0 for y in range(height)] for x in range(width)]

    for x in range(width):
        for y in range(height):
            if x*height+y in bomb_list: bomb[x][y]=10

    for x in range(width):
        for y in range(height):
            bomb[x][y] = count_bomb(x, y)

    return

def new_card():                     # refresh all cells to hidden card

    for x in range(width):
        for y in range(height):
            b[x][y].state = 1
            b[x][y].num = bomb[x][y]
            b[x][y].color = color[1]
            b[x][y].update(1)

def show_blank():                   # Show all cell not around by any bomb

    for x in range(width):
        for y in range(height):
            if b[x][y].num == 0:
                b[x][y].update(0)
            elif check_blank(x, y):
                b[x][y].update(4)

# Class for each button object
class button():

    def __init__(self, x, y):

        self.x          = x
        self.y          = y
        self.state      = 1
        self.color      = color[self.state]
        self.disabled   = False
        self.key        = 'Button{:0>2d}{:0>2d}'.format(x, y)
        self.num        = bomb[x][y]
        self.button     = sg.Button(' ',
            auto_size_button=False,
            border_width=2,
            button_color=self.color,
            disabled=self.disabled,
            focus=False,
            font=font,
            image_size=size,
            image_filename=im[self.state],
            key=self.key,
            pad=(1,1))

    def right_click(self, event):   # Right_click handler

        if self.state == 1:
            self.update(3)
        elif self.state == 3:
            self.update(1)

    def update(self, state):        # update state of cell

        self.state = state
        if state == 0:
            self.disabled = True
            text = ' '
        elif state in [1,2,3]:
            self.disabled = False
            text = ' '
        elif state == 4:
            self.disabled = True
            text = str(self.num)
        self.color = color[self.state]
        window[self.key].TKButton['disabledforeground'] = 'white'
        self.button.Update(text=text, disabled=self.disabled,
            image_filename=im[self.state], image_size=size,
            button_color=self.color)

# Check platform, only for Windows. Maybe wrok on other platform
if not sys.platform.startswith('win'):

    sg.popup_error('Sorry, you gotta be on Windows')
    sys.exit(0)

# set theme for window
sg.change_look_and_feel('DarkGreen')

deal()  # Initial position of bombs
b = [[0 for j in range(height)] for i in range(width)]

layout  = [[button1('New Game', key='-New Game-'),  # Layout of window
            button1('Game Over', key='-Game Over-'),
            button1('Target:'+str(all), key='-Target-'),
            button1('Bomb:0', key='-Count-Bomb-'),
            button1('Flag:0', key='-Count-Flag-')]]+[
            [button2(x, y) for x in range(width)] for y in range(height)]

window = sg.Window('MineSweeper', layout=layout).Finalize() # Create window
binding_all()       # Binding right button event handler of all cells
show_blank()        # Show all cells near no-bomb cell

new_start   = True  # Flag for new game
message     = False # Flag for game over message sent

while True:

    if new_start:   # Actions for new game

        deal()
        new_card()
        show_blank()
        message = False
        new_start = False
        pass

    event, values = window.read(timeout=100)    # read window event

    if event==None or event=='-Game Over-':     # Window close / Game over
        break

    elif event == '-New Game-':                 # New Game, set the flag
        new_start = True

    elif event[:6] == 'Button':                 # Left button clicked

        x, y = int(event[6:8]), int(event[8:10])
        if b[x][y].state == 1:
            if b[x][y].num == 10:
                b[x][y].update(2)
            else:
                b[x][y].update(4)

    # Update number onf bombs, flags
    bomb_num, flag_num, hide_num = check_num()
    window['-Count-Bomb-'].Update(text='Bomb:'+str(bomb_num))
    window['-Count-Flag-'].Update(text='Flag:'+str(flag_num))

    # Check if game over
    if hide_num==0 and (bomb_num+flag_num==all) and (not message):
        message = True
        sg.popup('Game Over', title='Note')

window.close()

链结
https://drive.google.com/open?id=1J9i_tUK3...

发表评论

0/200
45 点赞
0 评论
收藏
为你推荐 换一批