背景
最近在学Python,我觉得学习一个新语言最好的方式就是写一个简单的项目,所以就打算写一个简单的俄罗斯方块游戏。那么在写的过程中遇到了一个小问题。
1
2
3
|
def __init__( self , width = 10 , height = 30 ):
self .width, self .height = width, height
self .board_size = [width, height]
|
我用一个二维List来记录游戏空间的状态,game_boardx代表一个格子,0代表这格子是空的,1代表不是。很显然,初始化的时候应该将所有的格子都赋值为0。查询了一下List的相关文档,发现可以用[0] * n这样的方式来快速创建特定长度的List,因此很自然的写出了下面这行代码。
1
|
self .game_board = [[ 0 ] * height] * width
|
查看一下结果,确实创建了长宽符合预期、值全部都是0的一个二维List,感觉没什么问题,就接着往下写了。
问题
但这两天在写消除方法的时候,使用最下面3排全是1,第四排中间是1其他全是0,这样消除完成之后应该还剩1个1掉落到第一排。但测试过程中发现无论如何都会导致所有的1都被消除了,一开始我还以为是消除的算法有问题,但后来在每一步过程中都监控整个game_board的状态时才发现,当一横排有一个值为1的时候,这一横排所有值都自动变成1了。
解决
很自然的就想到,这是由于List对象的引用产生的。[0] * height产生了长度为height并且内容全是0的List,由于0是个int,是基础数据类型,因此这样使用是正确的。但用这个List去进行* width操作时,产生的都是这个List的引用,而不是新建了width个List,所以修改其中任意一个就全部都修改了。
经过查阅Python文档,将代码修改为:
1
|
self .game_board = [([ 0 ] * height) for i in range (width)]
|
测试发现问题解决。
创建二维数组的办法
直接创建法
1
|
test = [ 0 , 0 , 0 ], [ 0 , 0 , 0 ], [ 0 , 0 , 0 ]]
|
简单粗暴,不过太麻烦,一般不用。
列表生成式法
1
|
test = [[ 0 for i in range (m)] for j in range (n)]
|
学会使用列表生成式,终生受益。
使用模块numpy创建
1
2
|
import numpy as np
test = np.zeros((m, n), dtype = np. int )
|
总结
其实是很基础的问题,对于Python *这个运算符不够了解,因此想当然觉得代表了对对象进行深拷贝。而且可能前端做多了,对数据结构这种基础不太敏感了吧,还是要多做练习啊。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://segmentfault.com/a/1190000017939526