Привет
# Головоломка Ханойская башня
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()