目录
1.我们可以把它看成4*4的二维矩阵+我们可以把二维矩阵初始化全为0+而为了确定是否发生滑动,也就是格子前后是否有变化,我们需要对前后进行比较
4.我们可以通过按键控制上下左右方向+我们可以理解为当发生滑动时,会随机把一个为0的格子随机成2或者4。
一、游戏简介
有16个格子,分布为4*4.初始时会有两个格子上安放了两个数字2或者4,每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方随即出现一个数字方块2或者4,相同数字的方块在靠拢、相撞时会相加。
二、思路
我们把游戏简介进行分开解读。
1.有16个格子,分布为4*4:我们可以把它看成4*4的二维矩阵。
2.初始时会有两个格子上安放了两个数字2或者4:我们可以把二维矩阵初始化全为0,再随机挑选两个格子的0随机变成2或者4。
3.每次可以选择上下左右其中一个方向去滑动:我们可以通过按键控制上下左右方向
4.每滑动一次,所有的数字方块都会往滑动的方向靠拢外:滑动。
5.系统也会在空白的地方随即出现一个数字方块2或者4:我们可以理解为当发生滑动时,会随机把一个为0的格子随机成2或者4。而为了确定是否发生滑动,也就是格子前后是否有变化,我们需要对前后进行比较。
6.相同数字的方块在靠拢、相撞时会相加:当滑动时,如果有相同的数字相撞,会进行相加。
三、思路分解成代码
根据思路中带颜色的文字进行代码分析。
1.我们可以把它看成4*4的二维矩阵+我们可以把二维矩阵初始化全为0+而为了确定是否发生滑动,也就是格子前后是否有变化,我们需要对前后进行比较
这三句话一起看可知,我们需要两个矩阵。因为前后进行比较,一个矩阵记录滑动后的矩阵(这个矩阵是变化后的矩阵,也就是我们在界面上看到的矩阵),另一个矩阵记录滑动前的矩阵(这个矩阵是变化前的矩阵,也就是我们没有看见的矩阵)。并且这两个矩阵初始化都是0,于是有了如下代码
before_matrix=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
after_matrix=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
def compare_matrix():
if before_matrix != after_matrix:
random_location()
random_location()函数在第2点
2.再随机挑选两个格子的0随机变成2或者4。
因为随机挑选的两个格子只能变成2或者4,我们需要一个元组保存2和4,再从中随机取值。
random_tuple=(2,4)
因为从这个元组中随机取值,所以我们需要获取这个元组的长度(假设为random_tuple_len),再通过元组下标随机取值。于是有random.randint(0,random_tuple_len-1)获取元组随机下标。
比如说,当前元组长度为2,也就是random_tuple_len=2。再通过
random.randint(0,random_tuple_len-1)随机取到0到1.
再结合元组,于是有了random_tuple[random.randint(0,random_tuple_len-1)],这样就能随机取到元组的值。
再在一个随机位置上把矩阵的0变成这个元组的随机值。有如下代码
def random_location():
random_tuple_len=len(random_tuple)
while True:
x = random.randint(0,3)
y = random.randint(0, 3)
if after_matrix[x][y]==0:
after_matrix[x][y]=random_tuple[random.randint(0,random_tuple_len-1)]
break
其中after_matrix是我们看到的矩阵.但是一次只能随机变化一个位置的矩阵值,所以需要循环两次,并打印出来。
def init():
for i in range(2):
random_location()
print_matrix()
def print_matrix():
for i in after_matrix:
print(i)
打印函数把二维数组的每行取出来,打印后换行。
3.滑动+当滑动时,如果有相同的数字相撞,会进行相加。
接下来讲解滑动操作,为了解释更清晰,我们举例说明。
1.左移
我们首先取出二维矩阵的一行(可以看作是一个列表),可以分为以下四种情况
0,0,0,2 0,0,2,2 2,0,0,0
都按照左移进行分析,这几种情况,左移后
2,0,0,0 4,0,0,0 2,0,0,0
先看第3种情况,我们发现它没有发生变化也就是没有发生滑动,也就不需要改变
再看第1种情况,我们发现非0数字往左移。我们可以从右往左检查,如果为0则删除,并且往这个列表后面补0。于是有
def zero_to_end(list_data):
for i in range(3,-1,-1):
if list_data[i]==0:
del list_data[i]
list_data.append(0)
其中参数list_data是二维矩阵的每一行。
再看第2种情况,我们发现经过第一步0往后移,它变成2,2,0,0。要变成4,0,0,0则发生碰撞。我们可以从左往右检查列表,如果前一位=后一位,则前一位*2,删除后一位,再往列表后面补0,但是为了防止0,0,0,0这种情况,我们可以进行判断这一行是否都为0
def merge_list(list_data):
zero_to_end(list_data)
for i in range(3):
if list_data[i]==0:
break
if list_data[i]==list_data[i+1]:
list_data[i]*=2
del list_data[i+1]
list_data.append(0)
因为需要把矩阵每行传过去,所以需要
def merge():
for i in range(4):
merge_list(after_matrix[i])
def left():
merge()
这样左移就完成了。
2.右移
同样举例,
0,2,0,0 0,2,4,0
看第1种情况,左移为2,0,0,0,右移为0,0,0,2。只需要把列表左移后再进行逆转
但是看第2种情况,左移为2,4,0,0,右移应该为0,0,2,4。但是把列表左移后再进行逆转,发现成为0,0,4,2。所以需要在左移前进行一次逆转。如下
0,2,4,0——0,4,2,0——4,2,0,0——0,0,2,4
def reverse():
for i in range(4):
after_matrix[i].reverse()
def right():
reverse()
merge()
reverse()
3.上移
对于把水平方向改为垂直方向,只需要把矩阵置换成水平方向,左移后,再转置回去
def transposition():
for x in range(4):
for y in range(x,4):
after_matrix[x][y],after_matrix[y][x]=after_matrix[y][x],after_matrix[x][y]
def up():
transposition()
merge()
transposition()
4.下移
def down():
transposition()
reverse()
merge()
reverse()
transposition()
需要先置换,再逆转,左移,再逆转,再置换。根据以上可以自行理解。
4.我们可以通过按键控制上下左右方向+我们可以理解为当发生滑动时,会随机把一个为0的格子随机成2或者4。
可以在主代码中实现。
def main():
init()
while True:
try:
global before_matrix
before_matrix=copy.deepcopy(after_matrix)
key=input("输入:")
if key=='a':left()
if key == 'd': right()
if key == 'w': up()
if key == 's': down()
compare_matrix()
print_matrix()
except KeyboardInterrupt:
break
global:全局变量
copy.deepcopy():深拷贝
浅拷贝:只复制地址,不复制对象。也就是新旧对象共享一个地址。如果after_matrix对象改变,before_matrix也会改变
深拷贝:会创造一个一模一样的对象,新旧对象不共享一个地址,修改after_matrix,不会改变before_matrix
最后调用主函数完成。
if __name__ == '__main__':
main()
四、整体代码
import copy
import random
before_matrix=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
after_matrix=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
random_tuple=(2,4)
def compare_matrix():
if before_matrix != after_matrix:
random_location()
def random_location():
random_tuple_len=len(random_tuple)
while True:
x = random.randint(0,3)
y = random.randint(0, 3)
if after_matrix[x][y]==0:
after_matrix[x][y]=random_tuple[random.randint(0,random_tuple_len-1)]
break
def init():
for i in range(2):
random_location()
print_matrix()
def print_matrix():
for i in after_matrix:
print(i)
def zero_to_end(list_data):
for i in range(3,-1,-1):
if list_data[i]==0:
del list_data[i]
list_data.append(0)
def merge_list(list_data):
zero_to_end(list_data)
for i in range(3):
if list_data[i]==0:
break
if list_data[i]==list_data[i+1]:
list_data[i]*=2
del list_data[i+1]
list_data.append(0)
def merge():
for i in range(4):
merge_list(after_matrix[i])
def left():
merge()
def reverse():
for i in range(4):
after_matrix[i].reverse()
def right():
reverse()
merge()
reverse()
def transposition():
for x in range(4):
for y in range(x,4):
after_matrix[x][y],after_matrix[y][x]=after_matrix[y][x],after_matrix[x][y]
def up():
transposition()
merge()
transposition()
def down():
transposition()
reverse()
merge()
reverse()
transposition()
def main():
init()
while True:
try:
global before_matrix
before_matrix=copy.deepcopy(after_matrix)
key=input("输入:")
if key=='a':left()
if key == 'd': right()
if key == 'w': up()
if key == 's': down()
compare_matrix()
print_matrix()
except KeyboardInterrupt:
break
if __name__ == '__main__':
main()