用 ASCII 说明汉内塔

Illustrate Tower of Hanoi with ASCII

我熟悉河内塔的递归函数。

现在我需要可视化运动,用星号表示圆盘(我猜圆盘数 = 星号数是有道理的)。

有没有人有关于如何仅使用

逐步绘制圆盘运动的提示或示例
        *                           
       ***                        ***
      *****                      *****            *
     --------------------       -----------------------     ...    

或类似?

这是我的教授提供的示例代码,我确实了解递归的工作原理。但是在 Python 的一次讲座之后,我必须说我对可视化任务有些不知所措。

def hanoi(n, p1, p2, p3):
    if n==1:
        print("move from %d to %d" %(p1, p3))
    else:
        hanoi(n-1, p1, p3, p2)
        print("move from %d to %d " %(p1, p3))
        hanoi(n-1, p2, p1, p3)

    return

if __name__=='__main__':
    j=int(input('Input the number of disk to be moved:\n'))
    print('Number of disk to be move is %d \n'%j)
    hanoi(j, 1, 2, 3)

不胜感激!

正如 Phi Lipp 提到的,您需要了解状态。

状态可以用多种方式表示,但最终目标是打印到屏幕上的 X 乘 Y 字符网格。

例如,如果我们想打印

  *
 ***
*****

我们可以在代码中将其存储为 3x5 数组。

[
  [' ', ' ', '*', ' ', ' '],
  [' ', '*', '*', '*', ' '],
  ['*', '*', '*', '*', '*'],
]

然后你可以遍历它并打印它。

for row in state:
    for character in row:
        print(character, end='')

一个丑陋的捷径是

print('\n'.join(''.join(y) for y in x))

现在,如果您将其想象成电影,那么动画的每一帧都是这个 X 乘 Y 数组。每一帧也是代码中的打印语句之一。困难在于转换动作,例如"Move from 1 to 3",转化为状态表示。

如果我们使用 X x Y 数组作为状态,则很难从 space1 移动到 space2,因为字符数组不会告诉您任何有关 space1 中有多少个环以及环有多大的信息.这表明我们需要一个更好的状态。

这是非常开放的,但一个解决方案是,如果我们应用面向对象的编程,我们可以定义 Ring 和 Tower 对象,其中塔是环的集合。因此,一个动作在塔之间移动环,并且 Rings 和 Tower 对象的状态用于创建 X by Y 数组。

我会偷懒,将环表示为整数,塔是 3 deques 的数组。初始状态可能类似于

from collections import deque
towers = [deque([1,2,3]), deque(), deque()]

现在你需要一个从U塔移动到V塔的函数:

def move_ring(from, to):
    top_ring = from.popleft()
    to.append(top_right)

最后,您需要从 towers/rings 状态转到可打印的 X 乘 Y 数组。一次渲染每个塔会更容易,每个环都在:

def render_ring(ring):
    result = '*' * ring  # the character * repeated ring times.
    return result.center(user_input) # add the spaces required

def render_tower(tower):
    result = []
    for ring in tower:
        result.append(render_ring(ring))
    return result

最后,我们要将这些塔组合成一个可打印的阵列。您可以为此使用 zip

def render_final(塔): tower_results = [] 对于塔中塔: tower_results.append(render_tower(塔)) 结果 = [] 对于 zip 中的 all_rows(结果): result.append(''.join(all_rows)) return 结果

现在您应该可以打印出结果并查看动画的帧了。

这应该可以帮助您走上正轨。请将上面的代码视为伪代码,因为它没有经过测试。我也不建议使用整数和双端队列列表作为您的状态,因为这无助于代码清洁。

还有一件事,如果您打印出结果,它不会很漂亮,因为文本将被打印并向下滚动。但是,如果您使用内置的 curses 库,您可以获得漂亮的输出。