python游戏之生命游戏

直接看效果:

背景:

一个基于Tkinter的“生命游戏”(Game of Life),这是一个由数学家约翰·康威提出的细胞自动机模型。生命游戏的基本规则是,细胞在一个二维网格中根据周围邻居的状态进行繁殖和死亡。每个细胞可以是“活”的(1)或“死”的(0),并且细胞的状态在每个时间步长中会根据邻居的数量进行更新。

代码首先定义了一个Lifes类,该类负责管理游戏的状态,包括细胞的布局、历史记录和游戏的运行状态。类中包含多个方法,例如reset_life用于随机初始化细胞状态,reproduce用于根据生命游戏的规则更新细胞状态,is_stable用于检查游戏是否进入稳定状态。

在图形界面部分,使用Tkinter创建了一个窗口,并在窗口中绘制了一个36x36的网格,表示细胞的状态。用户可以通过按钮控制游戏的开始、暂停、随机初始化和清空细胞状态。每当游戏运行时,细胞的状态会根据规则进行更新,并在界面上实时显示。

当细胞状态达到稳定状态时,程序会弹出消息框提示用户,告知游戏的当前状态。这种可视化的生命游戏不仅展示了细胞自动机的基本原理,还为用户提供了一个互动的体验,帮助他们理解复杂系统的动态变化。

直接上代码:

import tkinter as tk
import random
import tkinter.messagebox as msgbox

class Lifes:
    def __init__(self, rows=38, cols=38):
        self.row = rows
        self.col = cols
        self.items = [[0] * self.col for _ in range(self.row)]
        self.histroy = []
        self.histroySize = 30
        self.running = False
        self.runningSpeed = 100

    def reset_life(self, rate=0.1):
        self.histroy = []
        for i in range(self.row):
            for j in range(self.col):
                rnd = random.random()
                if rnd > 1 - rate:
                    self.items[i][j] = 1

    def reproduce(self):
        new = [[0] * self.col for _ in range(self.row)]
        self.add_history()
        if len(self.histroy) > self.histroySize:
            self.histroy.pop(0)
        for i in range(self.row):
            for j in range(self.col):
                if i * j == 0 or i == self.row - 1 or j == self.col - 1:
                    new[i][j] = 0
                else:
                    lifes = 0
                    for m in range(i - 1, i + 2):
                        for n in range(j - 1, j + 2):
                            if m == i and n == j:
                                continue
                            lifes += self.items[m][n]
                    if self.items[i][j]:
                        if lifes == 2 or lifes == 3:
                            new[i][j] = 1
                        else:
                            new[i][j] = 0
                    else:
                        if lifes == 3:
                            new[i][j] = 1
        for idx, narray in enumerate(new):
            self.items[idx] = narray

    def is_stable(self):
        if len(self.histroy) < self.histroySize:
            return False
        arr = []
        for i in self.histroy:
            if i not in arr:
                arr.append(i)
        if len(arr) < 10:
            return True

    def add_history(self, Items=None):
        arr = []
        if Items is None:
            Items = self.items[:]
        for item in Items:
            b = 0
            for i, n in enumerate(item[::-1]):
                b += n * 2 ** i
            arr.append(b)
        self.histroy.append(arr)

def drawLifes():
    R, XY = 8, [50 + i * 20 for i in range(36)]
    if Life.running:
        for i, x in enumerate(XY):
            for j, y in enumerate(XY):
                if Life.items[i + 1][j + 1]:
                    tv.itemconfig(rect[i][j], fill='green', outline='green')
                else:
                    tv.itemconfig(rect[i][j], fill='lightgray', outline='lightgray')
        tv.update()
        Life.reproduce()
        if Life.is_stable():
            Life.running = False
            if sum(sum(Life.items, [])):
                msgbox.showinfo('Message', '生命繁殖与湮灭进入稳定状态!!!')
            else:
                msgbox.showinfo('Message', '生命已全部湮灭,进入死亡状态!!!')
    win.after(Life.runningSpeed, drawLifes)

def drawCanvas():
    global tv, rect
    tv = tk.Canvas(win, width=win.winfo_width(), height=win.winfo_height())
    tv.pack(side="top")
    for i in range(36):
        coord = 40, 40, 760, i * 20 + 40
        tv.create_rectangle(coord)
        coord = 40, 40, i * 20 + 40, 760
        tv.create_rectangle(coord)
    rect = [[0] * 36 for _ in range(36)]
    for i in range(36):
        for j in range(36):
            rect[i][j] = tv.create_rectangle(50 + i * 20 - 8, 50 + j * 20 - 8, 50 + i * 20 + 8, 50 + j * 20 + 8, tags=('imgButton1'))
            tv.itemconfig(rect[i][j], fill='lightgray', outline='lightgray')

def start_life():
    Life.running = True
    drawLifes()

def pause_game():
    Life.running = False

def random_life():
    Life.reset_life(rate=0.1)
    drawLifes()

def clear_life():
    Life.items = [[0] * Life.col for _ in range(Life.row)]
    drawLifes()

def quit():
    win.destroy()

if __name__ == '__main__':
    win = tk.Tk()
    X, Y = win.maxsize()
    W, H = 1024, 800
    winPos = f'{W}x{H}+{0}+{(Y - H) // 2}'
    win.geometry(winPos)
    win.resizable(True, True)
    win.title('生命游戏')
    win.update()
    drawCanvas()
    Life = Lifes()

    tLabel = tk.Label(win, width=30, height=20, background='lightgray')
    tLabel.place(x=780, y=38)
    tLabel.config(text='游戏规则:细胞根据周围细胞的状态进行繁殖与死亡。')
    tLabel.config(justify=tk.LEFT, anchor="nw", borderwidth=10, wraplength=210)

    bX, bY, dY = 835, 458, 50
    tButton0 = tk.Button(win, text='开始', command=start_life)
    tButton0.place(x=bX, y=bY + dY * 0, width=120, height=40)
    tButton1 = tk.Button(win, text='暂停', command=pause_game)
    tButton1.place(x=bX, y=bY + dY * 1, width=120, height=40)
    tButton2 = tk.Button(win, text='随机', command=random_life)
    tButton2.place(x=bX, y=bY + dY * 2, width=120, height=40)
    tButton3 = tk.Button(win, text='清空', command=clear_life)
    tButton3.place(x=bX, y=bY + dY * 3, width=120, height=40)

    win.protocol("WM_DELETE_WINDOW", quit)
    win.mainloop()


  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LucianaiB

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值