python——2048游戏实现

目录

一、游戏简介

二、思路

三、思路分解成代码

1.我们可以把它看成4*4的二维矩阵+我们可以把二维矩阵初始化全为0+而为了确定是否发生滑动,也就是格子前后是否有变化,我们需要对前后进行比较

2.再随机挑选两个格子的0随机变成2或者4。

3.滑动+当滑动时,如果有相同的数字相撞,会进行相加。

1.左移

2.右移

3.上移

4.下移

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()