|
|
50鱼币
本帖最后由 l0stparadise 于 2020-3-2 00:21 编辑
未解决,手欠手机上点错了,再次求助,如下图,利用数字和一个空格模拟九宫格拼图
但是运行后发现,上图第2次移动可以完成,第3次失败,第4次又成功,自查一直找不到bug,代码如下,请高手解决,多谢~~~
- import random
- def print_chestable(foo): #定义打印格式,输出九宫格
- num=0
- for i in foo:
- num+=1
- if num%3==0:
- print(i)
- else:
- print(i, end=" ")
- def move(): #定义移动步骤
- global list1 #list1为产生九宫格的1-8,以及一个空格组成,格式如[6, ' ', 7, 8, 4, 3, 1, 5, 2]
- dict1={0:[1,3], 1:[0,2,4],2:[1,5],3:[0,4,6],4:[1,3,5,7],5:[2,4,8],6:[3,7],7:[4,6,8],8:[5,7]}
- #对空格位置周围出现的其他可移动位置的列表索引号进行编号
- chocie = int(input("请输入要移动的数字:")) #用户输入要移动的数字
- '''
- 判断用户输入要移动的数字是不是在空格周围可移动的的数字中,如果在:
- 交换空格位置和用户输入位置数字的值
- 返回新的列表
- 如果用户输入要移动的数字不在空格周围可移动的的数字中:
- 重新运行这个移动步骤
- '''
- if list1.index(chocie) in dict1[list1.index(" ")]:
- list1[list1.index(" ")], list1[list1.index(chocie)] = list1[list1.index(chocie)],list1[list1.index(" ")]
- return list1
- else:
- move()
- '''
- 定义游戏开始
- 进入循环
- 执行移动步骤并输出九宫格
- 如果排序正确
- 输出赢了
- 结束循环
- '''
- def game_bengin(bar):
- while True:
- print_chestable(move())
- if bar ==[1,2,3,4,5,6,7,8," "]:
- print("你赢了,牛逼")
- break
- list1=[i for i in range(1,9)] #产生[1,2,3,4,5,6,7,8]的列表
- list1.append(" ") #产生[1,2,3,4,5,6,7,8," "]的列表
- random.shuffle(list1) #产生[1,2,3,4,5,6,7,8," "]的洗牌后列表
- print_chestable(list1) #初始化
- game_bengin(list1) #运行游戏
复制代码
本帖最后由 在东边 于 2020-3-2 13:05 编辑
显然,bug 是由下面这行代码产生的
- list1[list1.index(" ")], list1[list1.index(chocie)] = list1[list1.index(chocie)], list1[list1.index(" ")]
复制代码
为了方便讨论,我们简化一下问题,考虑下面这个情况
- ls = [1, 2]
- ls[ls.index(1)], ls[ls.index(2)] = 2, 1 # 试图交换 1、2,使 ls 变为 [2, 1]
- print(ls)
复制代码
上面这段代码的运行结果为
可以看到,ls 并未改变
这个问题与楼主遇到的问题本质上是一样的,即在修改列表过程中,调用列表的 index 方法,列表却并未能如预期那样改变
实际上,这种现象出现的原因主要是因为 index 方法调用与修改列表之间存在先后顺序的问题
- ls[ls.index(1)], ls[ls.index(2)] = 2, 1
复制代码
上面这行代码进行了如下几个操作
1. 计算 ls.index(1),结果为 0
2. 将 2 赋值给 ls[0],此时 ls 的值为 [2, 2]
3. 计算 ls.index(2)(注意此时 ls 已经不是原来的 [1, 2],而是 [2, 2]),结果为 0
4. 将 1 赋值给 ls[0],ls 的值为 [1, 2]
也就是说 ls 的值经过了这样一个变化:[1, 2] --> [2, 2] --> [1, 2]
下面通过一些代码验证上述想法
- class NList(list):
- def index(self, val):
- print(f"当前列表的值为:{self}")
- res = super().index(val)
- print(f"返回值为:{res}")
- return res
- nls = NList([1, 2])
- nls[nls.index(1)], nls[nls.index(2)] = 2, 1
- print(nls)
复制代码
运行结果如下
- 当前列表的值为:[1, 2]
- 返回值为:0
- 当前列表的值为:[2, 2]
- 返回值为:0
- [1, 2]
复制代码
代码中,定义了一个继承了 list 的类 NList,并重写了 index 方法,使其在调用 index 方法时,打印一些信息
从运行结果中,我们可以看到
在执行 nls.index(2) 这个操作的时候,列表 nls 的值已经变为 [2, 2]
那么 nls.index(2) 就将返回 0,然后再将 1 赋值给 nls[0],最终 nls 的值就为 [1, 2]
所以,看起来 nls 好像 ”从未改变“,实际上,它是经历了一个变化过程,又变回了原来的样子
最后,回到最初的问题
- list1[list1.index(" ")], list1[list1.index(chocie)] = list1[list1.index(chocie)], list1[list1.index(" ")]
- list1[list1.index(" ")], list1[list1.index(chocie)] = chocie, " "
复制代码
上面这两行代码是等价的,都是试图交换 chocie 和 " " 在 list1 中的位置
但由于 list1.index(chocie) 这一步是发生在 list1[list1.index(" ")] = chocie 之后,所以就可能会发生问题
为什么说是可能,而不是一定呢
看下面的代码
- >>> ls = [1, 2]
- >>> # ls[ls.index(1)], ls[ls.index(2)] = 2, 1 # 不能交换 ls 中 1 和 2 的位置,上面已解释
- >>> # 交换一下赋值顺序
- >>> ls[ls.index(2)], ls[ls.index(1)] = 1, 2
- >>> ls
- [2, 1] # 1 和 2 成功交换位置
- >>> ls[ls.index(2)], ls[ls.index(1)] = 1, 2
- >>> ls
- [2, 1] # 1、2 位置不变
复制代码
可以看到在利用 ls[ls.index(2)], ls[ls.index(1)] = 1, 2 成功交换一次之后
再尝试利用 ls[ls.index(2)], ls[ls.index(1)] = 1, 2 交换的时候,并未成功
第一次交换的过程如下:
1. 计算 ls.index(2),结果为 1
2. 将 1 赋值给 ls[1],此时 ls 的值为 [1, 1]
3. 计算 ls.index(1)(注意此时 ls 已经不是原来的 [1, 2],而是 [1, 1]),结果为 0
4. 将 2 赋值给 ls[0],ls 的值为 [2, 1]
也就是说 ls 的值经过了这样一个变化:[1, 2] --> [1, 1] --> [2, 1]
第二次交换的过程如下:
1. 计算 ls.index(2),结果为 0
2. 将 1 赋值给 ls[0],此时 ls 的值为 [1, 1]
3. 计算 ls.index(1)(注意此时 ls 已经不是原来的 [2, 1],而是 [1, 1]),结果为 0
4. 将 2 赋值给 ls[0],ls 的值为 [2, 1]
也就是说 ls 的值经过了这样一个变化:[2, 1] --> [1, 1] --> [2, 1]
上述过程表明
- list1[list1.index(" ")], list1[list1.index(chocie)] = chocie, " "
复制代码
如果你不停地输入同样的数字(即 chocie 每次都一样),那么上面这行代码至多只在第一次产生效果
所以,就出现了楼主的图中,第一次输入 5,正常交换,后面再输入 5 无法交换的问题
|
|