目錄
漢諾塔游戲
1. 抓取顏色
2. 繪制圓盤
3. 九層漢塔
4. 繪制塔架
5. 疊加圓盤
6. 游戲框架
?
漢諾塔游戲
漢諾塔(Tower of Hanoi),是一個(gè)源于印度古老傳說的益智玩具。這個(gè)傳說講述了大梵天創(chuàng)造世界的時(shí)候,他做了三根金剛石柱子,并在其中一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門將這些圓盤從下面開始按大小順序重新擺放在另一根柱子上,并規(guī)定在小圓盤上不能放大圓盤,同時(shí)在三根柱子之間一次只能移動(dòng)一個(gè)圓盤。當(dāng)盤子的數(shù)量增加時(shí),移動(dòng)步驟的數(shù)量會(huì)呈指數(shù)級(jí)增長(zhǎng),圓盤數(shù)為n時(shí),總步驟數(shù)steps為2^n - 1。
n = 64, steps = 2^64 - 1 = 18446744073709551616 ≈ 1.845 x 10^19
漢諾塔問題是一個(gè)遞歸問題,也可以使用非遞歸法來解決,例如使用棧來模擬遞歸過程。這個(gè)問題不僅是一個(gè)數(shù)學(xué)和邏輯問題,也是一個(gè)很好的教學(xué)工具,可以用來教授遞歸、算法和邏輯思考等概念。同時(shí),漢諾塔游戲也具有一定的娛樂性,人們可以通過解決不同規(guī)模的漢諾塔問題來挑戰(zhàn)自己的智力和耐心。
1. 抓取顏色
本篇將展示如何用python pyglet庫(kù)制作這個(gè)小游戲,首先在上圖中抓取出需要用到的顏色RGB值,每種顏色畫一個(gè)矩形塊:
Rectangle(x, y, width, height, color=color)
代碼:
import pyglet
window = 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個(gè)半圓表示,半圓用扇形控件繪制:
Sector(x,?y, radius=R, angle=pi, start_angle=-pi/2, color=color)
注意圓盤類中的矩形的寬度和坐標(biāo)需要調(diào)整,整個(gè)圓盤類的寬度是矩形寬度加2倍扇形半徑,圓盤的中心是矩形的中心而不是矩形左下角。
import pyglet
window = 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. 九層漢塔
疊加多個(gè)圓盤,繪制出漢諾塔的樣子:
代碼:
import pyglet
window = 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 pyglet
window = 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. 疊加圓盤
把多個(gè)圓盤疊加磊在塔架上,圓盤數(shù)至少為2。 注意Color顏色列表共有9種顏色,Color[i%8+1]只取后8種顏色,Color[0]僅用于塔架的涂色。
Hann類中各控件的坐標(biāo)計(jì)算有點(diǎn)復(fù)雜,以下方案可以解決問題但未必是最佳方案:
? ? ? ? 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 pyglet
window = 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, 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])
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. 游戲框架
畫三個(gè)相同的塔架,左邊的磊放好圓盤。另外用兩個(gè)圓代替兩個(gè)扇形,效果一樣卻省了pi常量。
Circle(x+width/2-height/2, y, radius=height/2, color=color)
代碼:?文章來源:http://www.zghlxwxcb.cn/news/detail-838906.html
import pyglet
window = 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, 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])
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, y
self.space = space
self.order = order
self.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()
接下來就要添加鼠標(biāo)和鍵盤事件,用于操作在塔架上移動(dòng)圓盤。本篇完,下期繼續(xù)......文章來源地址http://www.zghlxwxcb.cn/news/detail-838906.html
到了這里,關(guān)于Python 一步一步教你用pyglet制作漢諾塔游戲的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!