Python 一步一步教你用pyglet制作汉诺塔游戏

目录

汉诺塔游戏

1. 抓取颜色

2. 绘制圆盘

3. 九层汉塔

4. 绘制塔架

5. 叠加圆盘

6. 游戏框架


 

汉诺塔游戏

汉诺塔(Tower of Hanoi),是一个源于印度古老传说的益智玩具。这个传说讲述了大梵天创造世界的时候,他做了三根金刚石柱子,并在其中一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门将这些圆盘从下面开始按大小顺序重新摆放在另一根柱子上,并规定在小圆盘上不能放大圆盘,同时在三根柱子之间一次只能移动一个圆盘。当盘子的数量增加时,移动步骤的数量会呈指数级增长,圆盘数为n时,总步骤数steps为2^n - 1。

n = 64, steps = 2^64 - 1 = 18446744073709551616 ≈ 1.845 x 10^19

汉诺塔问题是一个递归问题,也可以使用非递归法来解决,例如使用栈来模拟递归过程。这个问题不仅是一个数学和逻辑问题,也是一个很好的教学工具,可以用来教授递归、算法和逻辑思考等概念。同时,汉诺塔游戏也具有一定的娱乐性,人们可以通过解决不同规模的汉诺塔问题来挑战自己的智力和耐心。

1. 抓取颜色

本篇将展示如何用python pyglet库制作这个小游戏,首先在上图中抓取出需要用到的颜色RGB值,每种颜色画一个矩形块:

Rectangle(x, y, width, height, color=color)

代码:

import pygletwindow = pyglet.window.Window(800, 500, caption='汉诺塔')
pyglet.gl.glClearColor(1, 1, 1, 1)
batch = pyglet.graphics.Batch()Color = (182,128,18),(25,65,160),(56,170,210),(16,188,78),(20,240,20),(240,240,20),(255,128,20),(240,20,20),(245,60,138)class Rect:def __init__(self, x, y, color=(0,0,0), width=180, height=60):self.rect = pyglet.shapes.Rectangle(x, y, width, height, color=color, batch=batch)@window.event
def on_draw():window.clear()batch.draw()rectangle = [None]*9
for i,color in enumerate(Color):rectangle[i] = Rect(110+i//3*200, 120+i%3*100, color)pyglet.app.run()

2. 绘制圆盘

圆盘用矩形加2个半圆表示,半圆用扇形控件绘制:

Sector(x, y, radius=R, angle=pi, start_angle=-pi/2, color=color)

注意圆盘类中的矩形的宽度和坐标需要调整,整个圆盘类的宽度是矩形宽度加2倍扇形半径,圆盘的中心是矩形的中心而不是矩形左下角。

import pygletwindow = pyglet.window.Window(800, 500, caption='汉诺塔')
pyglet.gl.glClearColor(1, 1, 1, 1)
batch = pyglet.graphics.Batch()pi = 3.141592653589793
Color = (182,128,18),(25,65,160),(56,170,210),(16,188,78),(20,240,20),(240,240,20),(255,128,20),(240,20,20),(245,60,138)class Bead:def __init__(self, x, y, width=180, height=60):self.sec1 = pyglet.shapes.Sector(x+width/2-height/2, y, radius=height/2, angle=pi, start_angle=-pi/2, color=Color[5], batch=batch)self.sec2 = pyglet.shapes.Sector(x-width/2+height/2, y, radius=height/2, angle=pi, start_angle=pi/2, color=Color[5], batch=batch)self.rect = pyglet.shapes.Rectangle(x-width/2+height/2, y-height/2, width-height, height, color=Color[1], batch=batch)@window.event
def on_draw():window.clear()batch.draw()ead1 = Bead(window.width/2, window.height/2)pyglet.app.run()

3. 九层汉塔

叠加多个圆盘,绘制出汉诺塔的样子:

代码:

import pygletwindow = pyglet.window.Window(800, 500, caption='汉诺塔')
pyglet.gl.glClearColor(1, 1, 1, 1)
batch = pyglet.graphics.Batch()pi = 3.141592653589793
Color = (182,128,18),(25,65,160),(56,170,210),(16,188,78),(20,240,20),(240,240,20),(255,128,20),(240,20,20),(245,60,138)class Disk:def __init__(self, x, y, color=(0,0,0), width=200, height=20):self.sec1 = pyglet.shapes.Sector(x+width/2-height/2, y, radius=height/2, angle=pi, start_angle=-pi/2, color=color, batch=batch)self.sec2 = pyglet.shapes.Sector(x-width/2+height/2, y, radius=height/2, angle=pi, start_angle=pi/2, color=color, batch=batch)self.rect = pyglet.shapes.Rectangle(x-width/2+height/2, y-height/2, width-height, height, color=color, batch=batch)assert(width>height and x-width/2+height/2>0)@window.event
def on_draw():window.clear()batch.draw()x, y = window.width/2, window.height/2
width, height = 200, 40
disk = []
for i in range(9):disk.append(Disk(x, y+height*(i-4), Color[i], width=width-20*(i-1), height=height))pyglet.app.run()

4. 绘制塔架

把圆盘变簿(高度换成厚度),再加一条粗直线(直线的宽度等于圆盘的厚度)表示出“竖杆”,就画出叠放的架子来:

        self.pole = pyglet.shapes.Line(x, y, x, y+height, width=thickness, color=color)
        self.disk = Disk(x, y, color=color, width=width, height=thickness)

代码:

import pygletwindow = pyglet.window.Window(800, 500, caption='汉诺塔')
pyglet.gl.glClearColor(1, 1, 1, 1)
batch = pyglet.graphics.Batch()pi = 3.141592653589793
Color = (182,128,18),(25,65,160),(56,170,210),(16,188,78),(20,240,20),(240,240,20),(255,128,20),(240,20,20),(245,60,138)class Disk:def __init__(self, x, y, color=(0,0,0), width=200, height=20):self.sec1 = pyglet.shapes.Sector(x+width/2-height/2, y, radius=height/2, angle=pi, start_angle=-pi/2, color=color, batch=batch)self.sec2 = pyglet.shapes.Sector(x-width/2+height/2, y, radius=height/2, angle=pi, start_angle=pi/2, color=color, batch=batch)self.rect = pyglet.shapes.Rectangle(x-width/2+height/2, y-height/2, width-height, height, color=color, batch=batch)assert(width>height and x-width/2+height/2>0)class Hann:def __init__(self, x, y, color=(0,0,0), width=220, height=300, thickness=20):self.pole = pyglet.shapes.Line(x, y, x, y+height, width=thickness, color=color, batch=batch)self.disk = Disk(x, y, color=color, width=width, height=thickness)@window.event
def on_draw():window.clear()batch.draw()pole1 = Hann(window.width/2-250, 100)
pole2 = Hann(window.width/2, 100, color=Color[0])
pole3 = Hann(window.width/2+250, 100, color=Color[1])pyglet.app.run()

5. 叠加圆盘

把多个圆盘叠加磊在塔架上,圆盘数至少为2。 注意Color颜色列表共有9种颜色,Color[i%8+1]只取后8种颜色,Color[0]仅用于塔架的涂色。

Hann类中各控件的坐标计算有点复杂,以下方案可以解决问题但未必是最佳方案:

        self.x, self.y = x, y
        self.width = width
        self.height = (height-thickness*2)/order
        self.step = (width-thickness)/(order+1)
        self.beads = []
        self.coordinates = []
        for i in range(order):
            self.coordinates.append([self.x, self.y+(i+1)*self.height-(self.height-thickness)/2])

 代码:

import pygletwindow = pyglet.window.Window(800, 500, caption='汉诺塔')
pyglet.gl.glClearColor(1, 1, 1, 1)
batch = pyglet.graphics.Batch()pi = 3.141592653589793
Color = (182,128,18),(25,65,160),(56,170,210),(16,188,78),(20,240,20),(240,240,20),(255,128,20),(240,20,20),(245,60,138)class Disk:def __init__(self, x, y, color=(0,0,0), width=200, height=20):self.sec1 = pyglet.shapes.Sector(x+width/2-height/2, y, radius=height/2, angle=pi, start_angle=-pi/2, color=color, batch=batch)self.sec2 = pyglet.shapes.Sector(x-width/2+height/2, y, radius=height/2, angle=pi, start_angle=pi/2, color=color, batch=batch)self.rect = pyglet.shapes.Rectangle(x-width/2+height/2, y-height/2, width-height, height, color=color, batch=batch)assert(width>height and x-width/2+height/2>0)class Hann:def __init__(self, x, y, order=2, thickness=20, width=220, height=300):assert(order>1)self.pole = pyglet.shapes.Line(x, y, x, y+height, width=thickness, color=Color[0], batch=batch)self.disk = Disk(x, y, color=Color[0], width=width+thickness, height=thickness)self.x, self.y = x, yself.width = widthself.height = (height-thickness*2)/orderself.step = (width-thickness)/(order+1)self.beads = []self.coordinates = []for i in range(order):self.coordinates.append([self.x, self.y+(i+1)*self.height-(self.height-thickness)/2])self.fillup()def fillup(self):for i,xy in enumerate(self.coordinates):self.beads.append(Disk(*xy, Color[i%8+1], width=self.width-i*self.step, height=self.height))@window.event
def on_draw():window.clear()batch.draw()hann1 = Hann(window.width/2-260, 100, 2)
hann2 = Hann(window.width/2-22, 180, 5, 25)
hann3 = Hann(window.width/2+230, 80, 10, 15, 300, 380)pyglet.app.run()

6. 游戏框架

画三个相同的塔架,左边的磊放好圆盘。另外用两个圆代替两个扇形,效果一样却省了pi常量。

Circle(x+width/2-height/2, y, radius=height/2, color=color)

代码: 

import pygletwindow = pyglet.window.Window(800, 500, caption='汉诺塔')
pyglet.gl.glClearColor(1, 1, 1, 1)
batch = pyglet.graphics.Batch()Color = (182,128,18),(25,65,160),(56,170,210),(16,188,78),(20,240,20),(240,240,20),(255,128,20),(240,20,20),(245,60,138)class Disk:def __init__(self, x, y, color=(0,0,0), width=200, height=20):self.cir1 = pyglet.shapes.Circle(x+width/2-height/2, y, radius=height/2, color=color, batch=batch)self.cir2 = pyglet.shapes.Circle(x-width/2+height/2, y, radius=height/2, color=color, batch=batch)self.rect = pyglet.shapes.Rectangle(x-width/2+height/2, y-height/2, width-height, height, color=color, batch=batch)assert(width>height and x-width/2+height/2>0)class Hann:def __init__(self, x, y, order=2, thickness=20, width=200, height=300):assert(order>1)self.pole = pyglet.shapes.Line(x, y, x, y+height, width=thickness, color=Color[0], batch=batch)self.disk = Disk(x, y, color=Color[0], width=width+thickness, height=thickness)self.x, self.y = x, yself.width = widthself.height = (height-thickness*2)/orderself.step = (width-thickness)/(order+1)self.beads = []self.coordinates = []for i in range(order):self.coordinates.append([self.x, self.y+(i+1)*self.height-(self.height-thickness)/2])def fillup(self):for i,xy in enumerate(self.coordinates):self.beads.append(Disk(*xy, Color[i%8+1], width=self.width-i*self.step, height=self.height))class Game:def __init__(self, x, y, order=2, space=250):self.x, self.y = x, yself.space = spaceself.order = orderself.hanns = Hann(x-space, y, order), Hann(x, y, order), Hann(x+space, y, order)self.hanns[0].fillup()@window.event
def on_draw():window.clear()batch.draw()hann = Game(window.width/2, 100, 8)pyglet.app.run()

接下来就要添加鼠标和键盘事件,用于操作在塔架上移动圆盘。本篇完,下期继续......

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python错题集-8:AttributeError(找不到对应的对象的属性)

1问题描述 AttributeError: AxesSubplot object has no attribute arc 2代码详情 import matplotlib.pyplot as plt# 创建一个新的图形和坐标轴 fig, ax plt.subplots()# 定义弧线的参数 center (0.5, 0.5) # 圆心坐标 (x, y) width 1.0 # 半径 height 0.5 # 半径 ang…

使用阿里云服务器搭建网站简单吗?超简单教程

使用阿里云服务器快速搭建网站教程,先为云服务器安装宝塔面板,然后在宝塔面板上新建站点,阿里云服务器网aliyunfuwuqi.com以搭建WordPress网站博客为例,来详细说下从阿里云服务器CPU内存配置选择、Web环境、域名解析到网站上线全流…

AI领域再出“王炸“----Claude3是否会成为下一个“神“

目录 一.Claude3最新发布 二.Claude3支持20万token 三.Claude3在未公开算法上取得重大突破 1.Claude 3读懂博士论文 2.量子跃迁集成: Claude 3智商:101 测试方法 测试细节 通过Karpathy挑战 Claude 3自画像,突破本我 从洛杉矶排到…

MySQl基础入门⑦

上一章知识内容 分析数据且区分数据类型 看下表分析数据的特征,根据其特征确定相应的数据类型。 分析以上表格特征,确定数据类型,并对数据进行分类。分析数据后按固定长度字符串、可变长度字符串、整数、固定精度小数和日期时间数据类型对数…

VS Code引入ECharts

Charts是一个使用 JavaScript 实现的开源可视化库,涵盖各行业图表,提供了丰富的图表类型和交互能力。(摘自菜鸟教程) 下面我们来介绍一下VS Code引入ECharts的相关操作 检查电脑是否已经安装了Java语言的软件开发工具包 ECharts…

WebMagic框架

1.webmagic框架 webmagic框架是一个Java实现的爬虫框架,底层依然是HttpClient和jsoup 组件: downloader:下载器组件PageProcessor:页面解析组件(必须自定义)scheculer:访问队列组件pipeline&am…

kafka查看消息两种方式(命令行和软件)+另附发送消息方式

1、命令行方式 ①找到kafka安装文件夹 ②执行命令 #指定offset为指定时间作为消息起始位置 kafka-consumer-groups.sh \ --bootstrap-server 20.2.246.116:9092 \ --group group_1 \ --topic lanxin_qiao \ --reset-offsets \ --to-datetime 2023-07-19T01:00:00.000 \ -exe…

Linux--基础命令

一.pwd(Print Working Directory) (1)pwd:显示当前位置的绝对路径; 二.cd (Change Directory) (2)cd:切换目录,cd的参数表示要切换的位置,可以使用绝对路径或者相对路径; 三.ls (3)ls:显示目录中的文件 (l a i) ls补充: 理解使用: -A 显现除 “.”和“…

20-Java备忘录模式 ( Memento Pattern )

Java备忘录模式 摘要实现范例 备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象 备忘录模式属于行为型模式 摘要 1. 意图 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对…

mockjs学习

1.前言 最近面试发现之前团队协同合作的项目没有mock数据难以向面试官直接展示,所以迟到得来速学一下mockjs。 参考视频:mockJs 妈妈再也不用担心我没有后端接口啦_哔哩哔哩_bilibili 一开始查阅了一些资料,先是看了下EasyMock&#xff0c…

利用websocket +定时器简易的实现一个网络聊天室

其实原理非常简单,就是客户端用户通过websoket来连接websocket服务端。然后服务端,收集每个用户发出的消息, 进而将每条用户的消息通过广播的形式推送到每个连接到服务端的客户端。从而实现用户的实时聊天。 // TODO : 我主要是讲一下实现思路。并未完善其功能。 1.后端 依赖 …

Spring MVC 全局异常处理器

如果不加以异常处理,错误信息肯定会抛在浏览器页面上,这样很不友好,所以必须进行异常处理。 1.异常处理思路 系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异…

Tensorflow2.0+部署(tensorflow/serving)过程备忘记录Windows+Linux

Tensorflow2.0部署(tensorflow/serving)过程备忘记录 部署思路:采用Tensorflow自带的serving进模型部署,采用容器docker 1.首先安装docker 下载地址(下载windows版本):https://desktop.docke…

Jmeter之Ramp-up Period(in seconds)

1、Ramp-up Period概念 (in seconds)–并发用户启动周期,告知JMeter 要在多长时间内启动全部Vuser用户。 2、为什么需要有“ramp-up period”,立即启动所有的并发用户数不是更好? 对于绝大多数的网址或应用&#xf…

【Prometheus】DataModel

数据模型 DataModel 指标 Metric metric 包含 metric name 和 metric label 格式&#xff1a; <metric name>{<label name><label value>, ...}例如&#xff1a;服务器 HTTP 接口 /messages 的总请求数 api_http_requests_total{method"POST",…

Jmeter(三) - 从入门到精通 - 测试计划(Test Plan)的元件(详解教程)

1.简介 上一篇中已经教你如何通过JMeter来创建一个测试计划&#xff08;Test Plan&#xff09;&#xff0c;那么这一篇我们就将JMeter启动起来&#xff0c;创建一个测试计划&#xff08;Test plan&#xff09;&#xff0c;然后给大家介绍一下测试计划&#xff08;Test Plan&am…

二,几何相交---4,BO算法---(1)接近性和可分离性

提了三个观点 1&#xff0c;如果一条直线&#xff08;比如竖直&#xff09;可以分开两个线段&#xff0c;则这两个线段不相交 2&#xff0c;只需要观察与隔离线相交的几个线段 3&#xff0c;从左向右扫描线只需要观察每个线段的两个端点和一些可能的相交点。

力扣18:三数之和

15. 三数之和 - 力扣&#xff08;LeetCode&#xff09; 题意&#xff1a;给你一个包含 n 个整数的数组 nums&#xff0c;判断 nums 中是否存在三个元素 a&#xff0c;b&#xff0c;c &#xff0c;使得 a b c 0 &#xff1f;请你找出所有满足条件且不重复的三元组。 注意&a…

目标检测5:采用yolov8, RK3568上推理实时视频流

上一个效果图&#xff0c;海康球机对着电脑屏幕拍&#xff0c;清晰度不好。 RK3568接取RTSP视频流&#xff0c;通过解码&#xff0c;推理&#xff0c;编码&#xff0c;最终并把结果推出RTSP视频流。 RK3568 推理 数据集采用coco的80个种类集&#xff0c;通过从yovo8.pt&#x…

2024年AI辅助研发趋势:探索未来研发工作的AI应用

引言&#xff1a; 随着科技的不断发展&#xff0c;人工智能&#xff08;AI&#xff09;技术已经深入到了各个行业&#xff0c;其中包括研发领域。在2024年&#xff0c;AI辅助研发将继续成为关注的焦点&#xff0c;因为它为研发工作带来了许多新的机遇和挑战。本文将探讨2024年…