python命令行版2048小游戏

基本设计

本文是1小时入门Python的“课后习题”。完整代码请移步Python实现命令行版2048

按理说看到这里,并写到这里,就应该算是完成了入门,那么接下来就要用入门学会的知识,写一个命令行版的2048小游戏。

2048的逻辑无非是操作 4 × 4 4\times4 4×4的方格,每个方格中有一个数,我们可以操作这些数字进行移动,如果两个相同的数字在我们的操作下相撞了,那么它们就可以合并了。

而这个 4 × 4 4\times4 4×4的方格,其实就是一个矩阵。

我们的操作可以理解为输入字符,用wsad代表上下左右,y代表确定,n代表取消。

python接收字符的函数是input,例如

>>> x = input("input a number")
input a number5
>>> x
'5'

而创建矩阵,可以用np.zeros([4,4]).astype(int),表示创建一个 4 × 4 4\times4 4×4的全0矩阵,并化为整形。

矩阵中只有16个元素,尽管循环效率低下,但足以满足人的操作速度了。

操作逻辑

2048只有四个手势动作,即上下左右,这四个动作所引发的结果都可以归结为对单行或者单列的操作,进而归结为对一个列表的操作。

例如对于 [ 0 , 2 , 2 , 0 ] [0,2,2,0] [0,2,2,0],如果向右合并,则输出为 [ 0 , 0 , 0 , 4 ] [0,0,0,4] [0,0,0,4],向左合并则输出为 [ 4 , 0 , 0 , 0 ] [4,0,0,0] [4,0,0,0]

其实现方法如下

def addZeros(lst:list,flag:bool=True):
    zeros = [0]*(4-len(lst))
    return zeros+lst if flag else lst+zeros

# flat为Ture时把0补在左边;否则补右边
def rmZero(lst, flag=True):
    lst = [x for x in lst if x]
    end = len(lst)-1
    if end < 1:
        return addZeros(lst,flag)
    index = range(end) if flag else range(end,-1,-1)
    iter = 1 if flag else -1
    for i in index:
        if lst[i] == lst[i+iter]:
            lst[i] *= 2
            lst[i+iter] = 0
    lst = [x for x in lst if x]
    return addZeros(lst,flag)

然后,针对行和列均需遍历执行rmZero。其中,wsad分别表示上下左右

# w,s,a,d分别为上下左右
def updateMat(mat,op):
    flag = op in "sd"
    if op in "ws":
        for i in range(4):
            mat[:,i] = rmZero(mat[:,i],flag)
    else:
        for i  in range(4):
            mat[i,:] = rmZero(mat[i,:],flag)
    return mat

这三个函数已经完成了2048的交互逻辑,接下来就是将updateMat这个函数嵌入到游戏的流程之中。

初始化

2048游戏在开始之前,需要初始化一个 4 × 4 4\times4 4×4的矩阵,然后每次操作之前,需要在矩阵中为0的位置随机生成一个数。随机生成的数的取值范围决定了游戏的难度,所以生成方式也比较灵活,下面给出一种普通的生成方法

def addNew(mat):
    i,j = randint(4),randint(4)
    while(mat[i,j]!=0):
        i,j = randint(4),randint(4)
    else:
        x = randint(1,100)
        x = 7 - np.floor(np.log2(x))
        mat[i,j] = int(2**x)
    print(mat)

交互操作

然后是交互操作,asdw表示操作,q表示退出。

def InputNew(mat):
    op = input("input operator:")
    if op in "asdw":
        newMat = updateMat(mat*1,op)
        if np.max(np.abs(mat-newMat))==0:
            print("Invalid operation")
            return mat,"Error"
        else:
            return newMat,"True"
    if op == 'q':
        return mat, "Exit"
    print("Invalid Input")
    return mat, "Error"

main函数

if __name__ == "__main__":
    while(1):
        addNew(mat)
        newMat,flag = InputNew(mat)
        while flag=="Error":
            newMat,flag = InputNew(mat)
        if flag == "Exit":
            break
        mat = newMat
        print(mat)
        print('-'*30)

        if np.max(mat)==2048: flag == "win"
        if np.min(mat)!=0: flag == "lose"
        if flag in ["win","lose"]:
            if input(f"you {flag}, play again? ")=="y":
                mat *= 0
            else: break
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微小冷

请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值