如何用python写一个2048?

用python写一个2048?你也可以!

这是我今天的学习过程中看到的
代码来源:《Python游戏设计案例实战》
过程很复杂啦,我把源码放在这,具体程序放在GitHub上,想要的点击这里

from msilib.schema import Directory
from tkinter import *
from tkinter import messagebox as msgbox
import random
from tkinter import scrolledtext
from turtle import left
from unittest import result
v = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
def init(v):
    for i in range(4):
        v[i] = [random.choice([0,0,0,2,2,4])for x in v[i]]
def align(vList,direction):
    '''
    对齐非零的数字
    direction == 'left':向左对齐,如[8,0,0,2]左对齐后成为[8,2,0,0]
    direction == 'right':向右对齐,如[8,0,0,2]左对齐后成为[0,0,8,2]
    '''
    #移除列表中的0元素
    for i in range(vList.count(0)):
        vList.remove(0)
    #被移除的0元素
    zeros = [0 for x in range(4 - len(vList))]
    if direction == 'left':
        #在右侧补0元素
        vList.extend(zeros)
    else:
        #在左侧补0元素
        vList[:0] = zeros
def addSame(vList,direction):
    #将相同的元素相加,返回新增积分
    score = 0
    if direction == 'left':
        for i in [0,1,2]:
            if vList[i] == vList[i+1] != 0:
                vList[i] *= 2
                vList[i+1] = 0
                score += vList[i]
                return {'bool':True,'score':score}
    else:
        for i in [3,2,1]:
            if vList[i] == vList[i-1] != 0:
                vList[i] *= 2
                vList[i-1] = 0
                score += vList[i]
                return{'bool':True,'score':score}
    return{'bool':False,'score':score}
def handle(vList,direction):
    '''
    处理一行(列)中的数据,得到最终的该行(列)的数字状态值,返回得分
    vList:列表结构,存储了一行(列)中的数据
    direction:移动放向,向上和向左都使用方向'left',向右和向下都使用'right'
    '''
    increment = 0
    align(vList,direction)
    result = addSame(vList,direction)
    #合并的得分
    increment += result['score']
    align(vList,direction)
    return increment
def operation(v,op):
    totalScore = 0
    #计算本次得分
    gameOver = False
    direction = 'left'
    print(op)
    if op == 'Left':
        #向左移动
        direction = 'left'
        for row in range(4):
            totalScore += handle(v[row],direction)
    elif op == 'Right':
        #向右移动
        direction = 'right'
        for row in range(4):
            totalScore += handle(v[row],direction)
    elif op == 'Up':
        #向上移动
        direction = 'left'
        for col in range(4):
            #将矩阵中一列复制到一个列表中然后处理
            vList = [v[row][col]for row in range(4)]
            totalScore += handle(vList,direction)
            #将处理后的列表中的数字覆盖原来矩阵中的值
            for row in range(4):
                v[row][col] = vList[row]
    elif op == 'Down':
        #向下移动
        direction = 'right'
        for col in range(4):
            #将矩阵中一列复制到一个列表中然后处理
            vList = [v[row][col]for row in range(4)]
            totalScore += handle(vList,direction)
            #将处理后的列表中的数字覆盖原来矩阵中的值
            for row in range(4):
                v[row][col] = vList[row]
    #以下是在空白区域随机产生的新的数字
    N = 0
    for q in v:
        #统计0的个数
        N += q.count(0)
        #统计空白区域数目N
        #存在剩余的空白区域时,产生随机数2和4
        if N != 0:
            addElement(N)
        #判断游戏是否真正结束
        if isOver():
            gameOver = True
        return {'gameOver':gameOver,'score':totalScore}
def addElement(N):
    #按照数字2和数字4出现的比率为3:1来产生随机数2和4
    num = random.choice([2,2,2,4])
    #产生随机数K,上一步产生的2或4将被填到第k个空白区域
    k = random.randrange(1,N+1)
    n = 0
    for i in range(4):
        for j in range(4):
            if v[i][j] == 0:
                n += 1
                if n == k:
                    v[i][j] = num
                    break
def isOver():
    N = 0
    for q in v:
        #统计0的个数
        N += q.count(0)
    if N != 0:
        return False
    else:
        for row in range(4):
            #按行判断是否有相同元素
            flag = isListOver(v[row])
            if flag ==False:
                return False
        for col in range(4):
            #按列判断是否有相同元素
            #将矩阵中的一列复制到一个列表中然后处理
            vList = [v[row][col] for row in range(4)]
            flag = isListOver(vList)
            if flag == False:
                return False
    return True
def isListOver(vList):
    for i in [0,1,2]:
        if vList[i] == vList[i+1] and vList[i+1] != 0:
            return False
    return True
def drawGameImage():
    global x,y 
    for i in range(0,4):
        for j in range(0,4):
            #计算对应的图像索引号
            m = v[i][j]
            #二维列表中存储的是2,4,8,需要将其转换成图像索引号
            #print('m',m)
            n = 0
            while m > 1:
                n = n + 1
                m = m / 2
            #print('n',n)
            img1 = imgs[n]
            #从imgs列表获取对应的图像
            cv.create_image((j*120+70,i*120+70),image = img1)
            #显示到Canvas上
            cv.pack()
def callback(event):
    #按键处理
    global score 
    print('按下键:',event.char)
    KeyCode = event.keysym
    #获取用户按下的方向键
    result = operation(v,KeyCode)
    #根据移动方向重新计算矩阵值
    drawGameImage()
    #绘制游戏界面
    score += result['score']
    #从字典中获取'score'键值
    root.title('得分:'+str(score))
    if result['gameOver'] == True:
        #游戏结束
        print('Game Over, You failed!')
        msgbox.showinfo('Game Over','Your total score:'+str(score))
    else:
        if score >= 20480:
            print('Game Over, You win!!!')
            msgbox.showinfo('Game Over','You Win!!!')
init(v)
score = 0
root = Tk()
root.title('2048')
imgs = [PhotoImage(file=x) for x in ['0.png','2.png','4.png','8.png','16.png','32.png','64.png','128.png','256.png','512.png','1024.png','2048.png','4096.png']]
cv = Canvas(root,bg='green',width = 500,height = 500)
drawGameImage()
cv.bind('<KeyPress>',callback)
cv.pack()
cv.focus_set()
#将焦点设置到cv上
root.mainloop()

如果你觉得我的分享有点意思,或者能给你带来一些收获,那么给我点个赞叭!

上一篇:elementui多选框部分禁用


下一篇:JSON字符串控制台格式化输出 java