游戏规律:
先将起点所有模块(k)分为两部分
最大(最下面)的一块为一部分(1)、其余为一部分(k-1)
然后将(k-1)部分移动到缓冲区
接着将(1)部分移动到终点
最后将(k-1)部分移动到终点
最简方式:
当模块的个数为k时,移动的次数应等于2^k – 1
当k为偶数时、模块顺时针移动
当k为偶数时、模块逆时针移动
起点->缓冲区->终点、为顺时针方向
终点->缓冲区->起点、为逆时针方向
'''
*递归游戏----汉诺塔*
*2019-01-07*
*Vk*
'''
print("游戏规则:\n")
print(" 游戏中共有三根柱子,柱子数量不可更改\n")
print(" 第一根柱子上有从小到大放置的模块,模块数量由用户输入\n")
print(" 将模块全部移动到第三根柱子上即可获得游戏胜利\n")
print(" 模块越多难度越大、且每次只能移动一个模块\n")
print(" 另外需要遵循大模块不能覆盖小模块的原则\n")
print(" 移动次数越少越好\n")
def hnt(k,A='1',B='2',C='3'): #定义函数、k为层数形参、ABC为柱子形参、123为柱子实参
if k < 1: #控制输入
print('请输入正确层数') #输入纠错
elif k == 1: #当层数为1时
print(A,'---->',C) #每次调用直到模块数为1时才输出
else: #当层数不为1时
hnt(k-1,A,C,B) #将(k-1)部分从起点A放到终点B
hnt(1,A,B,C) #将(1)部分从起点A放到终点C
hnt(k-1,B,A,C) #将(k-1)部分从起点B放到终点C
k = int(input('请输入游戏层数:\n')) #引导用户输入且强转数字字符串
number = hnt(k) #把函数值赋给变量number
number #输出值
else部分的形参与实参转换比较频繁、注意别搞混了、我研究了一上午才搞懂一点
重点:每次递归都会继承上一层实参并重新赋给形参
代码执行过程如下:
'''
*递归游戏----汉诺塔*
*2019-01-08*
*Vk*
'''
def hnt(k=3,A='1',B='2',C='3'): 此时实参为hnt(3,'1','2','3')
if k == 1: 条件不成立、不执行
print(A,' ----> ',C)
else:
hnt(k-1,A,C,B) 首次调用、实参为hnt(2,'1','3','2')
|
从头调用
|
V
hnt(k, A, B, C) 此时实参为hnt(2,'1','3','2')
if k == 1: 条件不成立、不执行
print(A,' ----> ',C)
else :
hnt(k-1,A,C,B) 二次调用、实参为hnt(1,'1','2','3')
|
从头调用
|
V
hnt(k, A, B, C) 此时实参为hnt(1,'1','2','3')
if k == 1: 条件成立、执行
print(A,' ----> ',C) 第一次输出、回退
<--回退完毕-----<-----
| else:
| hnt(k-1,A,C,B)
向下执行 hnt(1,A,B,C)
| hnt(k-1,B,A,C)
V
hnt(1,A,B,C) 二次调用、实参为hnt(1,'1','3','2')
|
从头调用
|
V
hnt(k,A,B,C) 实参为 hnt(1,'1','3','2')
if k == 1: 条件成立、执行
print(A,' ----> ',C) 第二次输出,回退
<--回退完毕-----<-----
| else:
| hnt(k-1,A,C,B)
向下执行 hnt(1,A,B,C)
| hnt(k-1,B,A,C)
V
hnt(k-1,B,A,C) 二次调用、实参为 hnt(2,'3','1','2')
|
从头调用
|
V
hnt(k,A,B,C) 实参为 hnt(1,'3','1','2')
if k == 1: 条件成立、执行
print(A,' ----> ',C) 第三次输出,回退
<--回退完毕-----<-----<-----<-----
| else:
| hnt(k-1,A,C,B)
向下执行 hnt(1,A,B,C)
| hnt(k-1,B,A,C)
V
hnt(1,A,B,C) 首次调用、此时实参为hnt(1,'1','2','3')
|
从头调用
|
V
hnt(k, A, B, C) 此时实参为hnt(1,'1','2','3')
if k == 1: 条件成立、执行
print(A,' ----> ',C) 第四次输出,回退
<--回退完毕-----<-----
| else:
| hnt(k-1,A,C,B)
向下执行 hnt(1,A,B,C)
| hnt(k-1,B,A,C)
V
hnt(k-1,B,A,C) 首次调用、实参hnt(2,'2','1','3')
|
从头调用
|
V
hnt(k, A, B, C) 此时实参为hnt(2,'2','1','3')
if k == 1: 条件不成立、不执行
print(A,' ----> ',C)
else :
hnt(k-1,A,C,B) 二次调用、实参为hnt(1,'2','3','1')
|
从头调用
|
V
hnt(k, A, B, C) 此时实参为hnt(1,'2','3','1')
if k == 1: 条件成立、执行
print(A,' ----> ',C) 第五次输出、回退
<--回退完毕-----<-----
| else:
| hnt(k-1,A,C,B)
向下执行 hnt(1,A,B,C)
| hnt(k-1,B,A,C)
V
hnt(1,A,B,C) 二次调用、实参为hnt(1,'2','1','3')
|
从头调用
|
V
hnt(k,A,B,C) 实参为hnt(1,'2','1','3')
if k == 1: 条件成立、执行
print(A,' ----> ',C) 第六次输出,回退
<--回退完毕-----<-----
| else:
| hnt(k-1,A,C,B)
向下执行 hnt(1,A,B,C)
| hnt(k-1,B,A,C)
V
hnt(k-1,B,A,C) 二次调用、实参为 hnt(1,'1','2','3')
|
从头调用
|
V
hnt(k,A,B,C) 实参为 hnt(1,'1','2','3')
if k == 1: 条件成立、执行
print(A,' ----> ',C) 第七次输出,回退
程序结束<--回退完毕-----<-----<-----<-----
'''
脑图展示形参与实参的转换应该会比较直观一点
框外的形参实参与框内上层的一一对应
框内上层的实参将直接赋给下层的形参