这是我今天的学习过程中看到的
代码来源:《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()
如果你觉得我的分享有点意思,或者能给你带来一些收获,那么给我点个赞叭!