python 扫雷游戏 代码

from tkinter import *
import tkinter.messagebox as messagebox
import random

class 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.mode_list = [(9, 9, 10), (16, 16, 40), (32, 16, 99)]
        self.mode = 2
        self.width = self.mode_list[self.mode][0]
        self.height = self.mode_list[self.mode][1]
        self.minenum = self.mode_list[self.mode][2]

        # 雷数的颜色
        self.colorlist = ['green',    # 绿色
                          'DodgerBlue',    # 浅蓝色
                          'goldenrod',# 
                          'blue',    # 蓝色
                          'red',    # 红色
                          'Chocolate4',    # 棕色
                          'grey',    # 灰色
                          'black']    # 黑色

        self.root = Tk()
        self.root.title('扫雷')

        winfoWt = 30 * self.width
        winfoHt = 31 * self.height
        x = int((self.root.winfo_screenwidth() - winfoWt) / 2)
        y = int((self.root.winfo_screenheight() - winfoHt) / 2 - 50)
        self.root.geometry('+{}+{}'.format(x, y))

        self.easyOrNo = Button(self.root, text='初级', command=self.EasyOrNo)
        self.easyOrNo.grid(row=0, column=self.width - 3, columnspan=3)
 
        self.setgui()



        self.root.mainloop()

    def setgui(self):
        # GUI界面

        self.mark = set()
        self.rest = self.minenum    # 剩余未标记的雷

        self.restlabel = Label(self.root, text=f'雷数:{self.minenum}')
        self.restlabel.grid(row=0, column=0, columnspan=3)

        self.restart = Button(self.root, text='重开', command=self.Restart)
        self.restart.grid(row=0, column=self.width - 7, columnspan=3)

        self.chgmode = Button(self.root, text='大小', command=self.chgMode)
        self.chgmode.grid(row=0, column=self.width - 5, columnspan=3)



        self.mineplace = random.sample( range(self.width * self.height), self.minenum )  # 随机抽取雷
        self.mineplace = [ ( x % self.width, x // self.width ) for x in self.mineplace ]    # 将雷的序号转变为坐标

        self.mines = {}
        self.index = -1

        for y in range(self.height):
            for x in range(self.width):
                # s = Style()
                # s.configure('myButton', font('SimHei', 12, 'bold'))
                self.mines[(x, y)] = self.minebtn(self.root, xy=(x,y), font=('黑体', 14, 'bold'), height=1, 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')
        # print(self.mines[(1, 1)].winfo_reqwidth(), self.mines[(1, 1)].winfo_reqheight())


    # 点开
    def _open(self, widget):
        # 确保第一次点击不碰到雷
        self.index += 1

        if self.index == 0:
            _sum = self.sum_around0(widget)
            if (widget.xy in self.mineplace) or _sum != 0:
                self.mineplace = random.sample( range(self.width * self.height), self.minenum )  # 随机抽取雷
                self.mineplace = [ ( x % self.width, x // self.width ) for x in self.mineplace ]    # 将雷的序号转变为坐标
                self.index = -1
                self._open(widget)
    


        xy = widget.xy
        x = xy[0]
        y = xy[1]   # 获取当前按钮的坐标



        # 如果已经点开了就什么也不做
        if widget._state == 1:
            return
        
        if widget._state == 2:
            return

        # 如果是雷则显示全部雷的位置
        if widget.xy in self.mineplace:
            self.showmine(widget)
            return

        widget.configure(relief='flat', bg='white')  # 更改当前按钮的样式
        
        widget._state = 1   # 按钮状态设为点开

        # 获取周围八个可能的雷的坐标  
                
        _sum, around_ = self.sum_around(widget)
        
        
        #如果周围没有雷则打开周围未标记的雷,直到有雷为止
        if _sum == 0:
            widget['text'] = '0'
            widget['fg'] = 'Lime'

            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:'?'}
        string = {0:'',2:'*',3:'?'}
        
        if widget._state == 0:
            widget._state = 2
            widget['text'] = string[2]
            widget['fg'] = 'black'
            self.rest -= 1
            self.restlabel['text'] = f'剩余:{self.rest}'
            self.mark.add(widget.xy)

            
        elif widget._state == 2:
            widget._state = 3
            widget['text'] = string[3]
            widget['fg'] = 'red'
            self.rest += 1
            self.restlabel['text'] = f'剩余:{self.rest}'
            self.mark.remove(widget.xy)
            
        elif widget._state == 3:
            widget._state = 0
            widget['text'] = string[0]
        self.display_messagebox()
        # print(self.mark)

    # 如果踩到雷,显示所有的雷
    def showmine(self, widget):
        self.rest = 0
        self.restlabel['text'] = f'雷数:{self.rest}'
        minePlace = set(self.mineplace)
        markErr = self.mark - minePlace
        mineRemain = minePlace - (self.mark & minePlace)

        for i, j in mineRemain:
            self.mines[(i, j)].configure(relief='flat', bg='white', text='ி', fg='purple')  # 更改当前按钮的样式
            self.mines[(i, j)]._state = 1
        # 高亮当前点错的位置
        widget.configure(relief='flat', bg='crimson', text='ி', fg='white')
        widget._state = 1
        curtClr = 0
        self.flash(markErr, curtClr)

      



    # 对于标记错误的, 在踩雷之后, 需要闪烁
    def flash(self, markErr, curtClr): 
       for i, j in markErr:
            self.mines[(i, j)]['fg'] = 'crimson'

    def sum_around(self, widget):
        # 获取周围八个可能的雷的坐标  
        x = widget.xy[0]
        y = widget.xy[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
        return (_sum, around_)

    def sum_around0(self, widget):
        # 获取周围八个可能的雷的坐标  
        x = widget.xy[0]
        y = widget.xy[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
        return _sum

    def Restart(self):
        easyOrNo = self.easyOrNo['text']
        for widget in self.root.winfo_children():
            widget.destroy()


        self.easyOrNo = Button(self.root, text=easyOrNo, command=self.EasyOrNo)
        self.easyOrNo.grid(row=0, column=self.width - 3, columnspan=3)
        self.setgui()

    def chgMode(self):

        easyOrNo = self.easyOrNo['text']
        for widget in self.root.winfo_children():
            widget.destroy()

        self.mode += 1
        self.mode = self.mode % 3
        self.width = self.mode_list[self.mode][0]
        self.height = self.mode_list[self.mode][1]
        self.minenum = self.mode_list[self.mode][2]


        self.easyOrNo = Button(self.root, text=easyOrNo, command=self.EasyOrNo)
        self.easyOrNo.grid(row=0, column=self.width - 3, columnspan=3)
 
        winfoWt = 30 * self.width
        winfoHt = 31 * self.height
        x = int((self.root.winfo_screenwidth() - winfoWt) / 2)
        y = int((self.root.winfo_screenheight() - winfoHt) / 2 - 50)
        self.root.geometry('+{}+{}'.format(x, y))


        self.setgui()
    
    def EasyOrNo(self):
        if self.easyOrNo['text'] == "初级":
            for widget in self.root.winfo_children():
                widget.destroy()
            self.easyOrNo = Button(self.root, text='中级', command=self.EasyOrNo)
            self.easyOrNo.grid(row=0, column=self.width - 3, columnspan=3)
            self.mode_list = [(9, 9, 16), (16, 16, 52), (32, 16, 128)]
            self.width = self.mode_list[self.mode][0]
            self.height = self.mode_list[self.mode][1]
            self.minenum = self.mode_list[self.mode][2]

        elif self.easyOrNo['text'] == "中级":
            for widget in self.root.winfo_children():
                widget.destroy()
            self.easyOrNo = Button(self.root, text='高级', command=self.EasyOrNo)
            self.easyOrNo.grid(row=0, column=self.width - 3, columnspan=3)
            self.mode_list = [(9, 9, 25), (16, 16, 64), (32, 16, 153)]
            self.width = self.mode_list[self.mode][0]
            self.height = self.mode_list[self.mode][1]
            self.minenum = self.mode_list[self.mode][2]

        elif self.easyOrNo['text'] == "高级":
            for widget in self.root.winfo_children():
                widget.destroy()
            self.easyOrNo = Button(self.root, text='初级', command=self.EasyOrNo)
            self.easyOrNo.grid(row=0, column=self.width - 3, columnspan=3)
            self.mode_list = [(9, 9, 10), (16, 16, 40), (32, 16, 99)]
            self.width = self.mode_list[self.mode][0]
            self.height = self.mode_list[self.mode][1]
            self.minenum = self.mode_list[self.mode][2]

        self.setgui()




    def display_messagebox(self): 
        if self.mark == set(self.mineplace):
    	    messagebox.showinfo(title='SUCCESS',
		    message='Congratulations!  You are so brilliant, let\'s try again ~ ~')
        else:
            pass

if __name__ == "__main__":
    main()

这个代码有个原始版本, 也是从别处copy的, 具体出处我已经忘了. 我在原始版基础上进行了魔改, 效果还可以, 想要一个本地版扫雷小游戏的可以copy下来试试.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值