python 汉诺塔

有个朋友在捣鼓汉诺塔,来了点兴趣,想自己来实现,看了网上博客,基本都是递归,感觉看的很懵,于是自己也折腾了一天,挺不聪明的,搞好了留个底

python3版本

# -*- coding: utf-8 -*-
"""
汉诺塔游戏
@author: lzh997
@create_time: 2021-09-19 16:29
@updater:
@update_time:
"""
import time


class Plate(object):
    """
    塔盘类
    """
    def __init__(self, name, value, pre_position=None):
        """

        :param name: 盘名称
        :param value: 盘的数值,用于比较大小
        :param pre_position: 上一个存放该盘的塔的名称
        """
        self.name = name
        self.value = value
        self.pre_position = pre_position

    def __repr__(self):
        """
        对象打印信息
        :return:
        """
        return f'({self.name}, {self.pre_position})'


class Tower(object):
    """
    汉诺塔的塔类
    """

    def __init__(self, name, empty_value):
        """
        plates存放盘的列表
        empty_value代表塔没有盘的值,盘的最大值 + 1
        :param name: 塔名称
        :param empty_value: 塔没有盘的时候的值
        """
        self.plates = []
        self.name = name
        self.empty_value = empty_value

    def remove(self):
        """
        移除最上面的盘
        :return:
        """
        return self.plates.pop()

    def add(self, plate):
        """
        在塔上添加盘
        :param plate:
        :return:
        """
        self.plates.append(plate)

    def first(self):
        """
        获取塔最上面盘的数值
        :return:
        """
        return self.plates[-1].value if self.plates else self.empty_value

    def __str__(self):
        """
        塔信息打印
        """
        return f'{[plate.name for plate in self.plates]}'


class TowerOfHanoi(object):
    """
    汉诺塔
    """
    def __init__(self, plate_number):
        """
        :param plate_number: 开始的盘数量
        """
        self.plate_number = plate_number
        self.tower_1 = None
        self.tower_2 = None
        self.tower_3 = None
        self.init_tower()

    def init_tower(self):
        """
        创建塔1/2/3对象,将所有盘按升序存放在塔1内
        :return:
        """
        empty_value = self.plate_number + 1
        self.tower_1 = Tower('t1', empty_value)
        for i in range(self.plate_number, 0, -1):
            self.tower_1.add(Plate('plate' + str(i), i, None))
        self.tower_2 = Tower('t2', empty_value)
        self.tower_3 = Tower('t3', empty_value)
        print(f'*'*80 + '\n' +
              f'create tower of Hanoi:' + '\n' +
              f'\ttower 1: {self.tower_1}, ' + '\n' +
              f'\ttower 2: {self.tower_2}, ' + '\n' +
              f'\ttower 3: {self.tower_3}' + '\n' +
              f'*'*80)

    def play(self):
        """
        启动游戏
        :return:
        """
        # 盘要移动到指定塔的优先级
        action_priority = {
            't1': [self.tower_3, self.tower_2],
            't2': [self.tower_1, self.tower_3],
            't3': [self.tower_2, self.tower_1]
        }

        # 完成状态信息
        completion_status = [plate.name for plate in self.tower_1.plates]
        while True:
            # 遍历塔
            for tower in [self.tower_1, self.tower_2, self.tower_3]:
                # 当前塔是否移动过盘
                plate_move = False

                # 从上到下遍历当前塔的存放的所有盘,因为塔存放盘是先进后出的
                # 所有需要反转盘顺序
                for plate in tower.plates[::-1]:
                    # 如果当前遍历的盘的值小于移动目标塔第一个盘的值
                    # 以及上一次不是从移动目标塔移动过来的,则将该盘子移动到这个塔上,
                    # 然后将该盘对象从当前遍历的塔中移除
                    action_towers = action_priority[tower.name]
                    move_tower_name = ''

                    if plate.value < action_towers[0].first() \
                            and plate.pre_position != action_towers[0].name:
                        plate.pre_position = tower.name
                        action_towers[0].add(plate)
                        tower.remove()
                        plate_move = True
                        move_tower_name = action_towers[0].name

                    elif plate.value < action_towers[1].first() \
                            and plate.pre_position != action_towers[1].name:
                        plate.pre_position = tower.name
                        action_towers[1].add(plate)
                        tower.remove()
                        plate_move = True
                        move_tower_name = action_towers[1].name

                    # 如果当前遍历盘没有被移动,代表当前塔没有可以继续移动的盘,
                    # 退出盘的遍历
                    if plate_move is False:
                        break

                    # 所有盘以及按顺序存放在塔3,完成游戏
                    if [plate.name for plate in self.tower_3.plates] \
                            == completion_status:
                        print(
                            f'done done! '
                            f't1: {self.tower_1}, '
                            f't2: {self.tower_2}, '
                            f't3: {self.tower_3}')
                        return
                    print(
                        f'{tower.name} {plate.name} move to '
                        f'{move_tower_name}:\n'
                        f'\tt1: {self.tower_1},\n'
                        f'\tt2: {self.tower_2},\n'
                        f'\tt3: {self.tower_3}.\n' +
                        f'*'*80
                    )
                    time.sleep(1)


if __name__ == '__main__':
    hanoi = TowerOfHanoi(3)
    hanoi.play()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值