游戏是第一生产力!Python实现生命游戏的示例代码(tkinter版)

news2024/11/17 21:16:29

文章目录

    • 生命游戏(Game of Life)
      • 游戏概述
      • 生存定律
      • 图形结构
    • 代码实现
    • 运行界面
    • 使用简介
    • 后续改进
      • 关于Python技术储备
        • 一、Python所有方向的学习路线
        • 二、Python基础学习视频
        • 三、精品Python学习书籍
        • 四、Python工具包+项目源码合集
        • ①Python工具包
        • ②Python实战案例
        • ③Python小游戏源码
        • 五、面试资料
        • 六、Python兼职渠道


生命游戏(Game of Life)

由剑桥大学约翰·何顿·康威设计的计算机程序。美国趣味数学大师马丁·加德纳(Martin Gardner,1914-2010)通过《科学美国人》杂志,将康威的生命游戏介绍给学术界之外的广大渎者,一时吸引了各行各业一大批人的兴趣,这时细胞自动机课题才吸引了科学家的注意。

游戏概述

用一个二维表格表示“生存空间”,空间的每个方格中都可放置一个生命细胞,每个生命细胞只有两种状态:“生”或“死”。用绿色方格表示该细胞为“生”,空格(白色)表示该细胞为“死”。或者说方格网中绿色部分表示某个时候某种“生命”的分布图。生命游戏想要模拟的是:随着时间的流逝,这个分布图将如何一代一代地变化。死亡太沉重,我想称它为“湮灭”状态。

生存定律

生存空间的每个方格都存在一个细胞,它的周边紧邻的8个方格上的称为邻居细胞。

(1)当前细胞为湮灭状态时,当周围有3个存活细胞时,则迭代后该细胞变成存活状态(模拟繁殖)。

(2)当前细胞为存活状态时,当周围的邻居细胞少于2个存活时,该细胞变成湮灭状态(数量稀少)。

(3)当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成湮灭状态(数量过多)。

(4)当前细胞为存活状态时,当周围有2个或3个存活细胞时,该细胞保持原样。

简单来说,活细胞Cell看作是‘1’,死Cell看作‘0’,8个邻居的累加和Sum决定了下一轮的状态:

“繁殖”:Cell=0,若Sum=3,则Cell=1。

“稀少”:Cell=1,若Sum<2,则Cell=0。

“过多”:Cell=1,若Sum>3,则Cell=0。

“正常”:Cell=1,若Sum=2或3,则Cell=1。

生存空间中生命的繁殖和湮灭,如下图所示:

图形结构

在游戏进行中,杂乱无序的细胞会逐渐演化出各种精致、有形的图形结构;这些结构往往有很好的对称性,而且每一代都在变化形状。一些形状一经锁定就不会逐代变化。有时,一些已经成形的结构会因为一些无序细胞的“入侵”而被破坏。但是形状和秩序经常能从杂乱中产生出来。

通常会有以下四种状态:

不动点(fixed points):变化终结于恒定图像

交替态(alternation):图像出现周期性变化

随机态(randomness):图像变化近乎随机

复杂态(complexity):图像存在某种复杂规律

常见的不动结构:

周期变化的结构:

逐步趋向湮灭的结构:

由一根10个连续细胞演化出来的周期结构:

动态变化后全部湮灭的结构:

移动的飞船:周期变化且逐渐向右平移

飞船到了边界变成向对角线移动的“滑翔者”,滑翔者到了边界成为不动的方块

更多有趣的图形结构有待发现,用代码来辅助这项工作还是比较方便的…

代码实现

用tkinter库实现了软件界面,画布、按钮、标签等控件都是配角,全是为表现生命繁殖演化的核心代码类方法 Lifes.reproduce() 作帮手的,源代码lifegame.pyw如下:

from tkinter import messagebox as msgbox
import tkinter as tk
import webbrowser
import random
 
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 rndinit(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\_histroy()
        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\_histroy(self, Items=None):
        arr = \[\]
        if Items==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 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)
    coord = 38, 38, 760, 760
    tv.create\_rectangle(coord,width=2)
    coord = 39, 39, 760, 760
    tv.create\_rectangle(coord,width=2)
    coord = 38, 38, 762, 762
    tv.create\_rectangle(coord,width=2)
    R,XY = 8,\[50+i\*20 for i in range(36)\]
    rect = \[\[0\]\*36 for \_ in range(36)\]
    for i,x in enumerate(XY):
        for j,y in enumerate(XY):
            rect\[i\]\[j\] = tv.create\_rectangle(x-R,y-R,x+R,y+R,tags=('imgButton1'))
            tv.itemconfig(rect\[i\]\[j\],fill='lightgray',outline='lightgray')
    tv.tag\_bind('imgButton1','<Button-1>',on\_Click)
 
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 StartLife():
    if sum(sum(Life.items,\[\])):
        Life.histroy = \[\]
        Life.running = True
    else:
        msgbox.showinfo('Message','请点击小方块填入生命细胞,或者使用随机功能!')
 
def BreakLife():
    Life.running = not Life.running
    if Life.running:
        Life.histroy.clear()
        Life.add\_histroy()
 
def RandomLife():
    Life.rndinit()
    Life.running = True
 
def ClearLife():
    Life.running = False
    Life.histroy = \[\]
    Life.items = \[\[0\]\*38 for \_ in range(38)\]
    for x in range(36):
        for y in range(36):
            tv.itemconfig(rect\[x\]\[y\],fill='lightgray',outline='lightgray')
 
def on\_Enter(event):
    tCanvas.itemconfig(tVisit, fill='magenta')
 
def on\_Leave(event):
    tCanvas.itemconfig(tVisit, fill='blue')
 
def on\_Release(event):
    url = 'https://blog.csdn.net/boysoft2002?type=blog'
    webbrowser.open(url, new=0, autoraise=True)
 
def on\_Click(event):
    x,y = (event.x-40)//20,(event.y-40)//20
    if not Life.running:
        if Life.items\[x+1\]\[y+1\]:
            tv.itemconfig(rect\[x\]\[y\],fill='lightgray',outline='lightgray')
        else:
            tv.itemconfig(rect\[x\]\[y\],fill='red',outline='red')
        Life.items\[x+1\]\[y+1\] = not Life.items\[x+1\]\[y+1\]
 
def on\_Close():
    if msgbox.askokcancel("Quit","Do you want to quit?"):
        Life.running = False
        print(Copyright())
        win.destroy()
 
def Introduce():
    txt = '''【生命游戏】\\n\\n生存定律:
    (1)当前细胞为湮灭状态时,当周围有3个存活细胞时,则迭代后该细胞变成存活状态(模拟繁殖)。
    (2)当前细胞为存活状态时,当周围的邻居细胞少于2个存活时,该细胞变成湮灭状态(数量稀少)。
    (3)当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成湮灭状态(数量过多)。
    (4)当前细胞为存活状态时,当周围有2个或3个存活细胞时,该细胞保持原样。'''
    return txt
 
def Copyright():
    return 'Lifes Game Ver1.0\\nWritten by HannYang, 2022/08/01.'
 
 
if \_\_name\_\_ == '\_\_main\_\_':
 
    win = tk.Tk()
    X,Y = win.maxsize()
    W,H = 1024,800
    winPos = f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}'
    win.geometry(winPos)
    win.resizable(False, False)
    win.title('生命游戏 Ver1.0')
    win.update()
    drawCanvas()
    Life = Lifes()
    drawLifes()
 
    tLabel = tk.Label(win, width=30, height=20, background='lightgray')
    tLabel.place(x=780, y=38)
    tLabel.config(text='\\n\\n\\n'.join((Introduce(),Copyright())))
    tLabel.config(justify=tk.LEFT,anchor="nw",borderwidth=10,wraplength=210)
 
    bX,bY,dY = 835, 458, 50
    tButton0 = tk.Button(win, text=u'开始', command=StartLife)
    tButton0.place(x=bX, y=bY+dY\*0 ,width=120,height=40)     
    tButton1 = tk.Button(win, text=u'暂停', command=BreakLife)
    tButton1.place(x=bX, y=bY+dY\*1 ,width=120,height=40) 
    tButton2 = tk.Button(win, text=u'随机', command=RandomLife)
    tButton2.place(x=bX, y=bY+dY\*2 ,width=120,height=40)
    tButton3 = tk.Button(win, text=u'清空', command=ClearLife)
    tButton3.place(x=bX, y=bY+dY\*3 ,width=120,height=40)
 
    tCanvas = tk.Canvas(win, width=200, height=45)
    tCanvas.place(x=800,y=716)
    tVisit = tCanvas.create\_text((88, 22), text=u"点此访问Hann's CSDN主页!")
    tCanvas.itemconfig(tVisit, fill='blue', tags=('btnText'))
    tCanvas.tag\_bind('btnText','<Enter>',on\_Enter)
    tCanvas.tag\_bind('btnText','<Leave>',on\_Leave)
    tCanvas.tag\_bind('btnText','<ButtonRelease-1>',on\_Release)
    win.protocol("WM\_DELETE\_WINDOW", on\_Close)
    win.mainloop()

编译命令

D:\> pyinstaller -F lifegame.pyw --noconsole

运行界面

使用简介

在生存空间里点击方格种植细胞(甚至可以画出你要表达的图形),然后点击开始;点下暂停键,则可以任意编辑生命图形,再点开始继续运行;点随机键则由软件随机生成细胞位置;清空键可以在任何时候清空生存空间,进入暂停编辑状态。

后续改进

Lifes类预留了histroy属性,后续可以增加回退功能;代码缺点是生存空间的行列被我写死了,以后版本中可以改进成任意定义行列数;另一个缺点是对稳定状态的判断比较简单,之后可以增加计算变化周期的功能。

优点就是可以任意编辑你的图形,最后以一张自己的网名画的图作收尾:

前部分介绍性文字来源于百度百科等网络资源


关于Python技术储备

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
在这里插入图片描述

二、Python基础学习视频

② 路线对应学习视频

还有很多适合0基础入门的学习视频,有了这些视频,轻轻松松上手Python~在这里插入图片描述
在这里插入图片描述

③练习题

每节视频课后,都有对应的练习题哦,可以检验学习成果哈哈!
在这里插入图片描述
因篇幅有限,仅展示部分资料

三、精品Python学习书籍

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
在这里插入图片描述

四、Python工具包+项目源码合集
①Python工具包

学习Python常用的开发软件都在这里了!每个都有详细的安装教程,保证你可以安装成功哦!
在这里插入图片描述

②Python实战案例

光学理论是没用的,要学会跟着一起敲代码,动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。100+实战案例源码等你来拿!
在这里插入图片描述

③Python小游戏源码

如果觉得上面的实战案例有点枯燥,可以试试自己用Python编写小游戏,让你的学习过程中增添一点趣味!
在这里插入图片描述

五、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
在这里插入图片描述
在这里插入图片描述

六、Python兼职渠道

而且学会Python以后,还可以在各大兼职平台接单赚钱,各种兼职渠道+兼职注意事项+如何和客户沟通,我都整理成文档了。
在这里插入图片描述
在这里插入图片描述
这份完整版的Python全套学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1247171.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】匿名管道+进程池

文章目录 前置知识一、管道的原理二、管道的特性三、管道的接口四、使用管道实现简单的进程池解决进程池的一个小问题 前置知识 一个进程在创建时&#xff0c;会默认打开三个文件&#xff0c;分别是&#xff1a;stdin&#xff0c;stdout&#xff0c;stderr 进程中有一个维护进…

社区物联网云服务架构设计

文章目录 1 摘要2 架构图2.1 社区物联网云服务网络拓扑图2.2 社区物联网云服务通讯流程图2.3 社区远程开锁功能流程图 3 应用场景 1 摘要 随着社区管理越来越智能化&#xff0c;社区物联网升级与改造的市场空间也越来越大。社区物联网包含楼宇对讲、门禁门锁、通道闸等等设备系…

浅谈国内智能制造现状和未来发展趋势

进人二十一世纪&#xff0c;互联网、新能源、大数据等技术的迅猛发展&#xff0c;从而使得社会发生巨大的改变&#xff0c;人类生产工业发生变革。为应对全球挑战&#xff0c;我国根据发展的实际情况&#xff0c;提出《中国制造2025》的国家战略规划。毋庸置疑的是&#xff0c;…

大数据题目的解题技巧

目录 大数据题目的技巧总括 实例精析 实例一 实例二 实例三 大数据题目的技巧总括 &#xff08;1&#xff09;哈希函数可以把数据按照种类均匀分流&#xff1b; &#xff08;2&#xff09;布隆过滤器用于集合的建立与查询&#xff0c;并可以节省大量空间&#xff1b; &…

Git永久或者限时保存用户名及密码,解决每次拉取或者提交代码时都需要手动输入验证信息

介绍 这里以我自身项目情况为例: 依据项目要求,这边使用了 TortoiseGit进行项目的统一管理,下载了 TortoiseGit克隆项目之后,每次拉取或者提交代码,都会弹出一个提示框,要求输入用户名及密码。 解决方式 单个仓库内设置,只作用于对当前仓库 在当前项目目录文件夹下,…

vue3之echarts渐变柱状图

vue3之echarts渐变柱状图 效果&#xff1a; 核心代码&#xff1a; <template><div class"abnormal"><div class"chart" ref"chartsRef"></div></div> </template><script setup> import * as echa…

【EI会议征稿】第三届电子信息技术国际学术会议(EIT 2024)

The 3rd International Conference on Electronic Information Technology 第三届电子信息技术国际学术会议&#xff08;EIT 2024&#xff09; 电子信息工程在我国信息化产业的发展过程中举足轻重&#xff0c;且随着现代社会的发展&#xff0c;航空航天领域、制造业领域和智能…

2024年度投资策略:AI大模型和半导体国产化加速

今天分享的是AI系列深度研究报告&#xff1a;《2024年度投资策略&#xff1a;AI大模型和半导体国产化加速》。 &#xff08;报告出品方&#xff1a;东方证券&#xff09; 报告共计&#xff1a;48页 前言: 行情回顾与未来展望 电子板块涨幅转正&#xff0c;信心逐渐回归。截至…

7000家门店的盈利增长,从导购的人效提升开始

管理是艺术&#xff0c;还是科学&#xff1f; 说管理是艺术&#xff0c;是因为管理面向的是人&#xff0c;而人是动态复杂的&#xff1b;说管理是科学&#xff0c;是因为我们可以研究动态的人背后的共性需求&#xff0c;并使管理的模型、策略、工具与之契合。 在绫致时装看来…

搭建Angular并引入NG-ZORRO组件库

作者&#xff1a;baekpcyyy&#x1f41f; 1.安装node.js 注&#xff1a;安装 16.0 或更高版本的 Node.js node官网&#xff1a;https://nodejs.org/en 2.进入angular官网 https://angular.cn/guide/setup-local 新建一个文件夹 vsc打开 打开终端 1.首先安装angular手脚架…

静电放电模型中的阻容参数

依据静电放电产生原因及其对集成电路放电方式的不同&#xff0c;静电放电模型可分成以下四类模型&#xff1a;1、人体放电模型(HBM, Human-Body Model)、2、机器放电模型(MM, Machine Model)、3、器件充电模型(CDM, Charged-Device Model)、4、电场感应模型(FIM, Field-Induced…

从设计上理解JDK动态代理

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 照理说&#xff0c;动态…

【Django-DRF】md笔记第6篇:Django-DRF的视图、认证、分页和其他功能详解

本文从分析现在流行的前后端分离Web应用模式说起&#xff0c;然后介绍如何设计REST API&#xff0c;通过使用Django来实现一个REST API为例&#xff0c;明确后端开发REST API要做的最核心工作&#xff0c;然后介绍Django REST framework能帮助我们简化开发REST API的工作。 DR…

win10 tensorrt源码编译onnx

直接利用官方源码&#xff0c;如下图&#xff0c;trtexec源码在TensorRT安装目录下&#xff0c;双击trtexec.sln文件&#xff0c;使用vs2019打开源码工程。 如下图&#xff0c;以yolov8为例子&#xff0c;编译成功项目之后&#xff0c;设置命令行参数&#xff1a; --onnxd:/yo…

表单邮箱密码登录 原生+Jquery实现

文章目录 效果代码邮箱验证正则表达式HTMLCSS JS 效果 正确密码为&#xff1a;123456 点击登录按钮校验。 代码 表单校验 - CodeSandbox 邮箱验证正则表达式 /(?:[a-z0-9!#$%&*/?^_{|}~-](?:\.[a-z0-9!#$%&*/?^_{|}~-])*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1…

实现HTTP服务监听,快来试试springboot服务端接口公网远程调试

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 二. 内网穿透2.1 安装…

AND/选品机制算法/用户表设计

3大步骤总结 大步骤总结&#xff1a; 第一大步骤&#xff1a; 生成AND算法机制所需要的8个表 AND musics Works Pool Table(音乐作品池表) 需要创建表 所需归类 AND算法池 AND videos Works Pool Table(视频作品池表) 需要创建表 所需归类 AND算法池 AND image…

基于Halcon的空间域图像滤波

任务描述&#xff1a; 图为HALCON中附带的例图“particle”。图中为某种液体&#xff0c;里面悬浮了微小颗粒&#xff0c;请分析出液体中的颗粒。 案例分析&#xff1a; 图中存在两种类型的对象&#xff1a;大的明亮物体和亮度较低的小物体&#xff08;颗粒&#xff09;。图像…

Rust UI开发(一):使用iced构建UI时,如何在界面显示中文字符

注&#xff1a;此文适合于对rust有一些了解的朋友 iced是一个跨平台的GUI库&#xff0c;用于为rust语言程序构建UI界面。 iced的基本逻辑是&#xff1a; UI交互产生消息message&#xff0c;message传递给后台的update&#xff0c;在这个函数中编写逻辑&#xff0c;然后通过…

经典的回溯算法题leetcode全排列问题思路代码详解

目录 全排列问题 leetcode46题.全排列 leetcode47题.全排列II 对回溯算法感兴趣的朋友也可以多多支持一下我的其他文章。 回溯算法详解-CSDN博客 经典的回溯算法题leetcode组合问题整理及思路代码详解-CSDN博客 经典的回溯算法题leetcode子集问题思路代码详解-CSDN博客 …