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

这篇具有很好参考价值的文章主要介绍了Python 一步一步教你用pyglet制作汉诺塔游戏(续)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Python 一步一步教你用pyglet制作汉诺塔游戏(续),Python,python,pyglet

目录

汉诺塔游戏

7. 汉诺塔类

8. 移动圆盘

9. 移动演示

10. 递归问题

11. 任意展示

12. 鼠标操作


汉诺塔游戏

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

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

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

本篇接着上期讲下去,这次争取把圆盘移动起来,前篇的链接地址:

Python 一步一步教你用pyglet制作汉诺塔游戏-CSDN博客

7. 汉诺塔类

前篇的最后已经初步把汉诺塔的架子搭好了,可以显示但移动的描述很复杂。所以得改造一下,把三个塔架设计到一个类中,方便圆盘的移动,运行后效果不变:

Python 一步一步教你用pyglet制作汉诺塔游戏(续),Python,python,pyglet

代码:

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)

class Hann:
    def __init__(self, x, y, order=2, space=250, thickness=20, width=200, height=300):
        assert(order>1)
        self.pole = [pyglet.shapes.Line(x-i*space, y, x-i*space, y+height, width=thickness, color=Color[0], batch=batch) for i in range(-1,2)]
        self.disk = [Disk(x+i*space, y, color=Color[0], width=width+thickness, height=thickness) for i in range(-1,2)]
        self.x, self.y = x, y
        self.order = order
        self.space = space
        self.thickness = thickness
        self.width = width
        self.height = (height-thickness*2)/order
        self.step = (width-thickness)/(order+1)
        coordinates = [(self.x-space, self.y+(i+1)*self.height-(self.height-thickness)/2) for i in range(order)]
        self.beads = [Disk(*xy, Color[i%8+1], width=self.width-i*self.step, height=self.height) for i,xy in enumerate(coordinates)]

@window.event
def on_draw():
    window.clear()
    batch.draw()

hann = Hann(window.width/2, 120, 8)

pyglet.app.run()

8. 移动圆盘

给圆盘类和汉诺塔类各设计一个.move()方法,主旨思想是圆盘的相对位置移动,不需要在调用时计算各种控件的具体坐标值。

Python 一步一步教你用pyglet制作汉诺塔游戏(续),Python,python,pyglet

代码:

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)
    def move(self, dx, dy):
        self.cir1.x += dx; self.cir1.y += dy
        self.cir2.x += dx; self.cir2.y += dy
        self.rect.x += dx; self.rect.y += dy

class Hann:
    def __init__(self, x, y, order=2, space=250, thickness=20, width=200, height=300):
        assert(order>1)
        self.pole = [pyglet.shapes.Line(x-i*space, y, x-i*space, y+height, width=thickness, color=Color[0], batch=batch) for i in range(-1,2)]
        self.disk = [Disk(x+i*space, y, color=Color[0], width=width+thickness, height=thickness) for i in range(-1,2)]
        self.x, self.y = x, y
        self.order = order
        self.space = space
        self.thickness = thickness
        self.width = width
        self.height = (height-thickness*2)/order
        self.step = (width-thickness)/(order+1)
        coordinates = [(self.x-space, self.y+(i+1)*self.height-(self.height-thickness)/2) for i in range(order)]
        self.beads = [Disk(*xy, Color[i%8+1], width=self.width-i*self.step, height=self.height) for i,xy in enumerate(coordinates)]
        self.array = [[*range(order)], [], []]
    def move(self, pole1, pole2):
        if self.array[pole1]:
            bead = self.array[pole1].pop()
            if self.array[pole2] and bead<self.array[pole2][-1]:
                print('大盘不能搬到小盘上')
                return False
        else:
            print('所选择的塔架为空!')
            return None
        self.beads[bead].move((pole2-pole1)*self.space, (len(self.array[pole2])-len(self.array[pole1]))*self.height)
        self.array[pole2].append(bead)
        return True

@window.event
def on_draw():
    window.clear()
    batch.draw()

hann = Hann(window.width/2, 100, 7)
hann.move(0,1)
hann.move(0,2)
hann.move(1,2)
hann.move(0,1)
hann.move(2,0)
hann.move(2,1)
hann.move(0,1)
hann.move(0,2)

pyglet.app.run()

9. 移动演示

pyglet.clock.schedule_interval(function,  seconds) 是 Pyglet 库中的一个函数调用,用于定期调度另一个函数function在指定的时间间隔seconds内执行。

pyglet.clock.unschedule(function) 任务完成后使用此函数来取消调度,以避免不必要的资源消耗。

以下展示一个四层汉诺塔的移动演示:

Python 一步一步教你用pyglet制作汉诺塔游戏(续),Python,python,pyglet

代码: 

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)
    def move(self, dx, dy):
        self.cir1.x += dx; self.cir1.y += dy
        self.cir2.x += dx; self.cir2.y += dy
        self.rect.x += dx; self.rect.y += dy

class Hann:
    def __init__(self, x, y, order=2, space=250, thickness=20, width=200, height=300):
        assert(order>1)
        self.pole = [pyglet.shapes.Line(x-i*space, y, x-i*space, y+height, width=thickness, color=Color[0], batch=batch) for i in range(-1,2)]
        self.disk = [Disk(x+i*space, y, color=Color[0], width=width+thickness, height=thickness) for i in range(-1,2)]
        self.x, self.y = x, y
        self.order = order
        self.space = space
        self.thickness = thickness
        self.width = width
        self.height = (height-thickness*2)/order
        self.step = (width-thickness)/(order+1)
        coordinates = [(self.x-space, self.y+(i+1)*self.height-(self.height-thickness)/2) for i in range(order)]
        self.beads = [Disk(*xy, Color[i%8+1], width=self.width-i*self.step, height=self.height) for i,xy in enumerate(coordinates)]
        self.array = [[*range(order)], [], []]
    def move(self, pole1, pole2):
        if self.array[pole1]:
            bead = self.array[pole1].pop()
            if self.array[pole2] and bead<self.array[pole2][-1]:
                print('大盘不能搬到小盘上')
                return False
        else:
            print('所选择的塔架为空!')
            return None
        self.beads[bead].move((pole2-pole1)*self.space, (len(self.array[pole2])-len(self.array[pole1]))*self.height)
        self.array[pole2].append(bead)
        return True

@window.event
def on_draw():
    window.clear()
    batch.draw()

def on_move(event):
    global moves
    if moves:
        x, y = moves.pop(0)
        hann.move(x, y)
        label.text = f'盘架{x+1}的圆盘移到盘架{y+1}上'
    else:
        label.text = '演示完毕!'
        pyglet.clock.unschedule(on_move)

hann = Hann(window.width/2, 120, 4)
moves = [(0,1), (0,2), (1,2), (0,1), (2,0), (2,1), (0,1), (0,2), (1,2), (1,0), (2,0), (1,2), (0,1), (0,2), (1,2)]
label = pyglet.text.Label('汉诺塔圆盘自动移动演示', font_size=24, color=(0,0,0,255), x=window.width/2, y=50, anchor_x='center', batch=batch)

pyglet.clock.schedule_interval(on_move, 1)
pyglet.app.run()

10. 递归问题

虽然解决了自动演示的功能,但继续增加层数怎么办?还是要自己解决这个问题,本篇前言里就说了汉诺塔问题就是一个递归问题,所以就用递归函数来解决,通常写法:

def hanoi(n, start, mid, end):
    if n == 1:
        print('Move disk 1 from', start, 'to', end)
    else:
        hanoi(n-1, start, end, mid)
        print('Move disk', n, 'from', start, 'to', end)
        hanoi(n-1, mid, start, end)

hanoi(4, 0, 1, 2)

运行的打印结果为: 

Move disk 1 from 0 to 1
Move disk 2 from 0 to 2
Move disk 1 from 1 to 2
Move disk 3 from 0 to 1
Move disk 1 from 2 to 0
Move disk 2 from 2 to 1
Move disk 1 from 0 to 1
Move disk 4 from 0 to 2
Move disk 1 from 1 to 2
Move disk 2 from 1 to 0
Move disk 1 from 2 to 0
Move disk 3 from 1 to 2
Move disk 1 from 0 to 1
Move disk 2 from 0 to 2
Move disk 1 from 1 to 2

移动的坐标刚好与上一步指定的相同,但要改造这个函数,我们需要的是坐标返回值不是打印信息,所以指定一列表用于存放这些坐标,改造后的函数:

def hanoi(n, start, mid, end, moves=None):
    if moves is None:
        moves = []
    if n == 1:
        moves.append((start, end))
    else:
        hanoi(n-1, start, end, mid, moves)
        moves.append((start, end))
        hanoi(n-1, mid, start, end, moves)
    return moves

for order in (4,7,8):
    moves = hanoi(order, 0, 1, 2)
    print(len(moves)==2**order-1)
    print(moves)

运行结果:

True
[(0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2)]
True
[(0, 2), (0, 1), (2, 1), (0, 2), (1, 0), (1, 2), (0, 2), (0, 1), (2, 1), (2, 0), (1, 0), (2, 1), (0, 2), (0, 1), (2, 1), (0, 2), (1, 0), (1, 2), (0, 2), (1, 0), (2, 1), (2, 0), (1, 0), (1, 2), (0, 2), (0, 1), (2, 1), (0, 2), (1, 0), (1, 2), (0, 2), (0, 1), (2, 1), (2, 0), (1, 0), (2, 1), (0, 2), (0, 1), (2, 1), (2, 0), (1, 0), (1, 2), (0, 2), (1, 0), (2, 1), (2, 0), (1, 0), (2, 1), (0, 2), (0, 1), (2, 1), (0, 2), (1, 0), (1, 2), (0, 2), (0, 1), (2, 1), (2, 0), (1, 0), (2, 1), (0, 2), (0, 1), (2, 1), (0, 2), (1, 0), (1, 2), (0, 2), (1, 0), (2, 1), (2, 0), (1, 0), (1, 2), (0, 2), (0, 1), (2, 1), (0, 2), (1, 0), (1, 2), (0, 2), (1, 0), (2, 1), (2, 0), (1, 0), (2, 1), (0, 2), (0, 1), (2, 1), (2, 0), (1, 0), (1, 2), (0, 2), (1, 0), (2, 1), (2, 0), (1, 0), (1, 2), (0, 2), (0, 1), (2, 1), (0, 2), (1, 0), (1, 2), (0, 2), (0, 1), (2, 1), (2, 0), (1, 0), (2, 1), (0, 2), (0, 1), (2, 1), (0, 2), (1, 0), (1, 2), (0, 2), (1, 0), (2, 1), (2, 0), (1, 0), (1, 2), (0, 2), (0, 1), (2, 1), (0, 2), (1, 0), (1, 2), (0, 2)]
True
[(0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (2, 0), (1, 2), (1, 0), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (2, 1), (0, 1), (2, 0), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (2, 0), (1, 2), (1, 0), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (2, 0), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (2, 1), (0, 1), (2, 0), (1, 2), (1, 0), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (2, 0), (1, 2), (1, 0), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (2, 1), (0, 1), (2, 0), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (2, 1), (0, 1), (2, 0), (1, 2), (1, 0), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (2, 0), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (2, 1), (0, 1), (2, 0), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (2, 0), (1, 2), (1, 0), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (2, 1), (0, 1), (2, 0), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2), (0, 1), (2, 0), (2, 1), (0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (1, 2), (0, 1), (0, 2), (1, 2)]

由此,也验证了总步骤数 steps = 2^n - 1,n为层数。

11. 任意展示

解决递归问题后,就可以展示任意层数的移动演示了,就用上一步得到的7层汉诺塔的移动坐标来展示一下它的移动过程:

Python 一步一步教你用pyglet制作汉诺塔游戏(续),Python,python,pyglet

完整代码:

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)
    def move(self, dx, dy):
        self.cir1.x += dx; self.cir1.y += dy
        self.cir2.x += dx; self.cir2.y += dy
        self.rect.x += dx; self.rect.y += dy

class Hann:
    def __init__(self, x, y, order=2, space=250, thickness=20, width=200, height=300):
        assert(order>1)
        self.pole = [pyglet.shapes.Line(x-i*space, y, x-i*space, y+height, width=thickness, color=Color[0], batch=batch) for i in range(-1,2)]
        self.disk = [Disk(x+i*space, y, color=Color[0], width=width+thickness, height=thickness) for i in range(-1,2)]
        self.x, self.y = x, y
        self.order = order
        self.space = space
        self.thickness = thickness
        self.width = width
        self.height = (height-thickness*2)/order
        self.step = (width-thickness)/(order+1)
        coordinates = [(self.x-space, self.y+(i+1)*self.height-(self.height-thickness)/2) for i in range(order)]
        self.beads = [Disk(*xy, Color[i%8+1], width=self.width-i*self.step, height=self.height) for i,xy in enumerate(coordinates)]
        self.array = [[*range(order)], [], []]
    def move(self, pole1, pole2):
        if self.array[pole1]:
            bead = self.array[pole1].pop()
            if self.array[pole2] and bead<self.array[pole2][-1]:
                self.array[pole1].append(bead)
                print('大盘不能搬到小盘上')
                return False
        else:
            print('所选择的塔架为空!')
            return None
        self.beads[bead].move((pole2-pole1)*self.space, (len(self.array[pole2])-len(self.array[pole1]))*self.height)
        self.array[pole2].append(bead)
        return True

@window.event
def on_draw():
    window.clear()
    batch.draw()

@window.event
def on_key_press(symbol, modifiers):
    global start
    if not start:
        start = True
        pyglet.clock.schedule_interval(on_move, 0.3)

@window.event
def on_mouse_press(x, y, button, modifier):
    global start
    if not start:
        start = True
        pyglet.clock.schedule_interval(on_move, 0.3)
    
def hanoi(n, start, mid, end, moves=None):
    if moves is None:
        moves = []
    if n == 1:
        moves.append((start, end))
    else:
        hanoi(n-1, start, end, mid, moves)
        moves.append((start, end))
        hanoi(n-1, mid, start, end, moves)
    return moves

def on_move(event):
    global moves,steps
    if moves:
        x, y = moves.pop(0)
        hanns.move(x, y)
        label.text = f'盘架{x+1}的圆盘移到盘架{y+1}上'
        message.text = f'总步骤数:{steps}\t当前步数:{steps-len(moves)}'
    else:
        label.text = '演示完毕!'
        pyglet.clock.unschedule(on_move)

order = 7
start = False
hanns = Hann(window.width/2, 120, order)
label = pyglet.text.Label('汉诺塔圆盘自动移动演示,任意按键开始......', font_size=24, color=(0,0,0,255), x=window.width/2, y=50, anchor_x='center', batch=batch)
moves = hanoi(order, 0, 1, 2)
steps = len(moves)
message = pyglet.text.Label(f'总步骤数:{steps}\t当前步数:{steps-len(moves)}', font_size=24, color=(0,0,0,255), x=100, y=450, batch=batch)

pyglet.app.run()

12. 鼠标操作

增加一个新的属性.poleheight,把原来的.height属性改为.beadheight以示区别;再给塔类增加两个方法判断鼠标点击和是否成功:

    def on_mouse_over(self, x, y):
        for i in range(-1,2):
            if hanns.x-hanns.width/2 < x-i*hanns.space < hanns.x+hanns.width/2 and hanns.y-hanns.thickness/2 < y < hanns.y+hanns.poleheight:
                return i+1
    def success(self):
        return len(self.array[2]) == self.order

最后配合鼠标点击事件,就能开始玩游戏了!

@window.event
def on_mouse_press(x, y, dx, dy):
    global moves
    if not hanns.success():
        pole = hanns.on_mouse_over(x, y)
        if pole is not None:
            print(pole)
            moves.append(pole)
        if len(moves)==2:
            hanns.move(*moves)
            moves.clear()
        if hanns.success():
            print('Success!')

Python 一步一步教你用pyglet制作汉诺塔游戏(续),Python,python,pyglet

完整代码: 

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)
    def move(self, dx, dy):
        self.cir1.x += dx; self.cir1.y += dy
        self.cir2.x += dx; self.cir2.y += dy
        self.rect.x += dx; self.rect.y += dy

class Hann:
    def __init__(self, x, y, order=2, space=250, thickness=20, width=200, height=300):
        assert(order>1)
        self.pole = [pyglet.shapes.Line(x-i*space, y, x-i*space, y+height, width=thickness, color=Color[0], batch=batch) for i in range(-1,2)]
        self.disk = [Disk(x+i*space, y, color=Color[0], width=width+thickness, height=thickness) for i in range(-1,2)]
        self.x, self.y = x, y
        self.order = order
        self.space = space
        self.thickness = thickness
        self.width = width
        self.poleheight = height
        self.beadheight = (height-thickness*2)/order
        self.step = (width-thickness)/(order+1)
        coordinates = [(self.x-space, self.y+(i+1)*self.beadheight-(self.beadheight-thickness)/2) for i in range(order)]
        self.beads = [Disk(*xy, Color[i%8+1], width=self.width-i*self.step, height=self.beadheight) for i,xy in enumerate(coordinates)]
        self.array = [[*range(order)], [], []]
    def move(self, pole1, pole2):
        if self.array[pole1]:
            bead = self.array[pole1].pop()
            if self.array[pole2] and bead<self.array[pole2][-1]:
                self.array[pole1].append(bead)
                print('大盘不能搬到小盘上')
                return False
        else:
            print('所选择的塔架为空!')
            return None
        self.beads[bead].move((pole2-pole1)*self.space, (len(self.array[pole2])-len(self.array[pole1]))*self.beadheight)
        self.array[pole2].append(bead)
        return True
    def on_mouse_over(self, x, y):
        for i in range(-1,2):
            if hanns.x-hanns.width/2 < x-i*hanns.space < hanns.x+hanns.width/2 and hanns.y-hanns.thickness/2 < y < hanns.y+hanns.poleheight:
                return i+1
    def success(self):
        return len(self.array[2]) == self.order

@window.event
def on_draw():
    window.clear()
    batch.draw()

@window.event
def on_mouse_press(x, y, dx, dy):
    global moves
    if not hanns.success():
        pole = hanns.on_mouse_over(x, y)
        if pole is not None:
            print(pole)
            moves.append(pole)
        if len(moves)==2:
            hanns.move(*moves)
            moves.clear()
        if hanns.success():
            print('Success!')

moves = []
hanns = Hann(window.width/2, 120, 4)

pyglet.app.run()

本篇至此暂时告一段落,下期会继续给游戏增加信息提示等等功能,敬请期待......文章来源地址https://www.toymoban.com/news/detail-839246.html

到了这里,关于Python 一步一步教你用pyglet制作汉诺塔游戏(续)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python 一步一步教你用pyglet制作可播放音乐的扬声器类

    目录 扬声器类 1. 绘制喇叭 2. 扬声器类 3. 禁音状态  4. 设置状态 5. 切换状态 6. 播放音乐 本篇将教你用pyglet画一个小喇叭,如上图。这里要用到pyglety库shapes模块中的圆弧Arc和多边形Pylygon画出这个扬声器的图片: Arc(x, y, radius, segments=None, angle=6.283185307179586, start_angle=0, closed=

    2024年03月10日
    浏览(60)
  • Python 一步一步教你用pyglet仿制鸿蒙系统里的时钟

    目录 鸿蒙时钟 1. 绘制圆盘 2. 创建表类 3. 绘制刻度 4. 刻度数值 5. 添加指针 6. 转动指针 7. 联动时间 8. 时钟走动 本篇将用python pyglet库复刻华为手机鸿蒙系统闹钟程序的时钟,先在上图中抓取出时分秒针及刻度、表盘的颜色RGB值: bHour = (42, 43, 48, 255) bMinute = (70, 71, 75, 255) rSe

    2024年03月12日
    浏览(68)
  • FastAPI + NGINX + Gunicorn:一步一步教你部署一个高性能的Python网页应用

    部署一个 FastAPI 应用到你的服务器是一项复杂的任务。如果你对 NGINX 、 Gunicorn 和 Uvicorn 这些技术不熟悉,可能会浪费大量的时间。如果你是刚接触 Python 语言不久或者希望利用 Python 构建自己的Web应用程序,本文的内容可能会让你第一次部署时更节省时间。 FastAPI 是用于开发

    2024年02月05日
    浏览(65)
  • Android一步一步教你实现Emoji表情键盘

    背景: 说到聊天,就离不开文字、表情和图片,表情和图片增加了聊天的趣味性,让原本无聊的文字瞬间用表情动了起来,今天给大家带来的是表情键盘,教你一步一步实现,先来看下效果图: 效果图 功能: 1、如何控制表情键盘与输入法的切换 2、如何解析表情 3、如何处

    2024年02月16日
    浏览(42)
  • GitHub入门指南:一步一步教你使用GitHub

    引言: GitHub是一个流行的代码托管平台,它提供了强大的版本控制和协作功能,对于开发者来说是一个不可或缺的工具。本文将一步一步地教你如何使用GitHub,从注册账号到代码同步,让你能够快速上手并充分利用这个平台。 打开GitHub官网(github.com)。 点击右上角的\\\"Sign

    2024年02月15日
    浏览(49)
  • Midjourney:一步一步教你如何使用 AI 绘画 MJ

    一步一步如何使用 Midjourney 教程:教学怎么用 MJ? 原文:如何使用 Midjourney 教程 https://bysocket.com/saas-digital-marketing-channel/ Midjourney是一款使用文字描述来生成高质量图像的AI绘画工具。这篇文章主要介绍了Midjourney及其用途,并针对Midjourney的使用提供了一些指南。该工具可以帮

    2023年04月21日
    浏览(82)
  • 文本转语音-微软Azure-一步一步教你从注册到使用

    牙叔教程 简单易懂 他们的中文也许还行, 但是英文我试了都不满意, 我再网上搜到的我认为最好的是 但是丫真贵 Best Free Text To Speech Voice Reader | Speechify 现在的汇率是 139 × 6.91 = 960.49 一年一千块, 好像还行哈, 但是没卡呀, 擦, 比来比去, 还是微软Azure性价比最高, 没有微软Azure的

    2024年02月07日
    浏览(44)
  • 一步一步教你如何使用 Visual Studio Code 编译一段 C# 代码

    以下是一步一步教你如何使用 Visual Studio Code 编写使用 C# 语言输出当前日期和时间的代码: 1、下载并安装 .NET SDK。您可以从 Microsoft 官网下载并安装它。 2、打开 Visual Studio Code,并安装 C# 扩展。您可以在 Visual Studio Code 中通过扩展菜单安装它。 3、打开 Visual Studio Code 中的文

    2024年02月11日
    浏览(51)
  • 一步一步教你如何白嫖谷歌云Google Cloud服务器$300美金羊毛

    我们都知道,Depay(现在改名为Dupay了)卡平常可以用于微信,支付宝,美团消费,直接用USDT做日常小额消费,还免收手续费,小额的话,这点还是很舒服的。 但其实,Depay卡的用途远不止此,平常可以多挖掘挖掘。今天教大家如何用Depay卡白嫖谷歌云服务器。申请成功后随即可

    2024年02月04日
    浏览(130)
  • 【沐风老师】一步一步教你在3dMax中进行UVW贴图和展开UVW的方法

    将简单或程序材质应用于对象并不难。但是当表面需要在其上显示某种纹理时,它会变得更加复杂。任何纹理贴图都放在材质的 Diffuse 插槽中,但渲染的结果可能无法预测。这就是为什么我们需要了解 3DMAX 如何将纹理应用于 3D 对象,什么是 UVW 贴图,以及为什么要“展开”它

    2024年02月04日
    浏览(64)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包