Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 18, 2019 22:29:56

anickone
Зарегистрирован: 2018-07-17
Сообщения: 9
Репутация: +  1  -
Профиль   Отправить e-mail  

Головоломка Ханойская башня

Привет

 # Головоломка Ханойская башня
class Disk:
    def __init__(self, number, color):
        self.number = number
        self.view = self.get_disk(number, color)
 
    def get_disk(self, number, color):
        disk = '\u2588' * (number*2+1)
        shift = ' ' * ((13-len(disk))//2)
        disk_line = f'{shift}{disk}{shift}'
        return f'\033[{color}m{disk_line}\033[0m'
 
def get_pole(pyramid):
    pole, j = [], 1
    height = len(pyramid)
    free = 6 - height
    for i in range(6):
        if i < free:
            pole.append('      \u2551      ')
        else:
            disk = pyramid[height - j]
            pole.append(disk.view)
            j += 1
    return pole
 
def show(poles):
    show_time = []
    for i in list('123'):
        show_time.append(get_pole(poles[i]))
    fmt = '{:^13}'*3
    print(fmt.format(1, 2, 3))
    for a, b, c in zip(*show_time):
        print(f'{a}{b}{c}')
 
def check_moves(move, poles):
    from_pole, to_pole = move.split()
    if from_pole == to_pole or \
            not from_pole in poles or\
            not to_pole in poles:
        return False
    fp = poles[from_pole]
    if len(fp) > 0:
        move_disk = fp[-1]
    else:
        return False
    tp = poles[to_pole]
    if len(tp) > 0:
        top_disk = tp[-1]
    else:
        return True
    if move_disk.number < top_disk.number:
        return True
    return False
 
def move(from_pole, to_pole, poles):
    fp, tp = poles[from_pole], poles[to_pole]
    tp.append(fp.pop())
 
def choice_n_disks():
    n_disks = 3
    s = input('Введите число дисков[1..5](по умолчанию 3):\n>> ').strip()
    if s in list('12345'):
        n_disks = int(s)
    low_steps = 2**n_disks-1
    print(f'Дисков в башне: {n_disks}.\nМинимальное число ходов,'
        f' за которые возможно перемещение: {low_steps}.')
    return n_disks, low_steps
 
def introduce():
    print('Головоломка "Ханойская башня".\n'
    'Правила:\n'
    '    башня состоит из дисков;\n'
    '    нужно переместить башню на вторую позицию;\n'
    '    перемещение происходит по одному диску за ход;\n'
    '    для перемещения доступны только верхние диски;\n'
    '    разрешается перемещать:\n'
    '        меньший диск на больший,\n'
    '        любой диск на позицию без дисков;\n'
    '    пример первого хода: 1 2\n'
    '        верхний диск с позиции 1 переместится на позицию 2;\n'
    )
 
def run_game(poles, win):
    show(poles)
    steps = 1
    while True:
        s = input(f'Ход {steps}, введите перемещение или exit:\n>> ')
        if s == 'exit':
            exit()
        elif len(s.split()) == 2 and check_moves(s, poles):
            move(*s.split(), poles)
            show(poles)
            if win == poles['2']:
                return steps
            steps += 1
        else:
            print(f'Ошибка ввода, не допустимое перемещение: "{s}".')
 
def get_poles(n_disks):
    colors = [91, 92, 94, 95, 96]
    poles = {
        '1': [],
        '2': [],
        '3': [],
    }
    pole = poles['1']
    for i in range(n_disks, 0, -1):
        pole.append(Disk(i, colors[i-1]))
    return poles, pole.copy()
 
def main():
    win_msg = 'Поздравляю! Башня перемещена! Ходов: '
    introduce()
    while True:
        n_disks, low_steps = choice_n_disks()
        poles, win = get_poles(n_disks)
        steps = run_game(poles, win)
        if steps == low_steps:
            print(f'{win_msg}{steps}. Отлично!!!')
        else:
            print(f'{win_msg}{steps}. Вы можете лучше!!!')
        s = input('Сыграем еще?([y]/n)\n>> ')
        if s == 'n':
            return
 
if __name__ == '__main__':
    main()

Отредактировано anickone (Ноя. 18, 2019 22:30:34)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version