Python實(shí)現(xiàn)簡(jiǎn)單的2048小游戲
本文實(shí)例為大家分享了Python實(shí)現(xiàn)簡(jiǎn)單的2048小游戲的具體代碼,供大家參考,具體內(nèi)容如下
運(yùn)行效果:

1.項(xiàng)目結(jié)構(gòu)

2.代碼
configs.py
import argparse
def parse_args():
parser = argparse.ArgumentParser(description='Game 2048')
# Form
"""
screen_width: Width of the form
screen_height: Height of the form
"""
parser.add_argument('--screen_width', default=400)
parser.add_argument('--screen_height', default=500)
# Block
"""
block_gap: Gap between two blocks
block_size: Size of a block
block_arc: Arc of a block
"""
parser.add_argument('--block_gap', default=10)
parser.add_argument('--block_size', default=86)
parser.add_argument('--block_arc', default=10)
return parser.parse_args()
main.py
import configs from Game2048 import Game2048 def main(args): """ screen_width: Width of the form screen_height: Height of the form block_gap: Gap between two blocks block_size: Size of a block """ screen_width = args.screen_width screen_height = args.screen_height block_gap = args.block_gap block_size = args.block_size block_arc = args.block_arc game = Game2048(screen_width, screen_height, block_gap, block_size, block_arc) game.Form() if __name__ == '__main__': args = configs.parse_args() main(args)
Game2048.py
import os
import sys
import numpy
import random
import pygame
"""
Form(): 窗口的設(shè)置
Action(): 用戶行為: 按鍵/鼠標(biāo)
InitGame(): 游戲初始化
CreatNum(): 隨機(jī)在一個(gè)位置生成一個(gè)數(shù)
GetEmpty(): 獲取空白方格
MoveUp(): 向上移動(dòng)
MoveDown(): 向下移動(dòng)
MoveLeft(): 向左移動(dòng)
MoveRight(): 向右移動(dòng)
JudgeGameOver(): 判斷游戲是否結(jié)束
JudgeGameSuccess(): 判斷游戲是否成功
Paint(): 繪制表格
"""
class Game2048(object):
# 初始化函數(shù)
def __init__(self, screen_width, screen_height, block_gap, block_size, block_arc):
"""
:param screen_width: Width of the form
:param screen_height: Height of the form
:param block_gap: Gap between two blocks
:param block_size: Size of a block
:param size: Dimension of matrix
:param martix: Zero matrix
:param is_over: Sign of the end of the game
:param is_success: Sign of the success of the game
:param form: The form
:param score: score
:param title_font: Title type and size of form
:param score_font: Scores type and size
:param tips_font: Tips type and type
:param font: The numberes
:param isadd: Add number or not
"""
""" 窗口 """
self.screen_width = screen_width # 窗口的寬 400
self.screen_height = screen_height # 窗口的高 500
self.block_gap = block_gap # 方塊間隙 10
self.block_size = block_size # 方塊大小 86
self.block_arc = block_arc # 方塊的弧度
self.size = 4 # 矩陣 4 * 4
self.martix = [] # 初始化矩陣 4 * 4 的 0 矩陣
self.form = ''
""" 其他 """
self.is_over = False # 游戲是否結(jié)束
self.is_success = False # 游戲是否成功
self.score = 0 # 分?jǐn)?shù)
self.isadd = True # 是否添加數(shù)字
self.block_color = { # 方塊顏色
0: (205, 193, 180),
2: (238, 228, 218),
4: (237, 224, 200),
8: (242, 177, 121),
16: (245, 149, 99),
32: (246, 124, 95),
64: (246, 94, 59),
128: (237, 207, 114),
256: (237, 204, 97),
512: (237, 200, 80),
1024: (237, 197, 63),
2048: (237, 194, 46)
}
self.nums_color = {
# 0: (0, 0, 0),
0: (205, 193, 180),
2: (0, 0, 0),
4: (0, 0, 0),
8: (255, 255, 255),
16: (255, 255, 255),
32: (255, 255, 255),
64: (255, 255, 255),
128: (255, 255, 255),
256: (255, 255, 255),
512: (255, 255, 255),
1024: (255, 255, 255),
2048: (255, 255, 255)
}
""" 字體 """
self.title_font = '' # 窗口標(biāo)題字體類型及大小: 2048
self.score_font = '' # 分?jǐn)?shù)字體類型及大小
self.tips_font = '' # 說(shuō)明字體類型及大小
self.font = '' # 數(shù)字字體
# 窗口的設(shè)置
def Form(self):
"""
init(): 初始化所有導(dǎo)入的 pygame 模塊
display.set_caption(title): 設(shè)置窗口的標(biāo)題
display.set_mode(): 初始化一個(gè)準(zhǔn)備顯示的窗口或屏幕
display.update(): 使繪制的顯示到窗口上
"""
pygame.init() # 初始化所有導(dǎo)入的 pygame 模塊
pygame.display.set_caption("Game2048") # 窗口標(biāo)題
os.environ['SDL_VIDEO_CENTERED'] = '1' # 窗口居中顯示
self.form = pygame.display.set_mode([self.screen_width, self.screen_height], 0, 0) # 窗口大小
self.InitGame() # 矩陣的初始化
while True:
self.Action() # 用戶行為: 按鍵/鼠標(biāo)
self.Paint() # 表格繪制
pygame.display.update() # 使繪制的顯示到窗口上
# 用戶行為: 按鍵/鼠標(biāo)
def Action(self):
for event in pygame.event.get(): # pygame.event.get(): 獲取所有消息并將其從隊(duì)列中刪除
if event.type == pygame.QUIT: # pygame.QUIT: 窗口右上角的紅 ×
sys.exit() # sys.exit()函數(shù)是通過(guò)拋出異常的方式來(lái)終止進(jìn)程的
elif event.type == pygame.KEYDOWN:
"""
pygame.KEYDOWN 按下鍵盤(pán)時(shí)
pygame.KEYUP 釋放鍵盤(pán)時(shí)
"""
"""
K_ESCAPE: ESC
K_UP: ↑
K_DOWN: ↓
K_LEFT: ←
K_RIGHT: →
"""
""" 重新開(kāi)始游戲 """
if event.key == pygame.K_ESCAPE:
# print('ESC')
self.InitGame() # 游戲初始化
""" ↑ """
if event.key == pygame.K_UP and self.is_over == False:
# print('UP')
self.MoveUp()
# self.CreatNum()
""" ↓ """
if event.key == pygame.K_DOWN and self.is_over == False:
# print('DOWN')
self.MoveDown()
# self.CreatNum()
""" ← """
if event.key == pygame.K_LEFT and self.is_over == False:
# print('LEFT')
self.MoveLeft()
# self.CreatNum()
""" → """
if event.key == pygame.K_RIGHT and self.is_over == False:
# print('RIGHT')
self.MoveRight()
# self.CreatNum()
# 游戲初始化
def InitGame(self):
self.score = 0
self.is_over = False
self.is_success = False
self.martix = numpy.zeros([self.size, self.size])
# 隨機(jī)生成兩個(gè)數(shù)
for i in range(2):
self.isadd = True
self.CreatNum()
# 隨機(jī)在一個(gè)位置生成一個(gè)數(shù)
def CreatNum(self):
list = self.GetEmpty() # 獲取空白方格下標(biāo)
if list and self.isadd:
""" 隨機(jī)生成的數(shù)字 """
# 2, 4出現(xiàn)概率3:1
# random.randint(m, n): 隨機(jī)生成[m, n]
value = 4 if random.randint(0, 3) % 3 == 0 else 2
""" 獲取隨機(jī)位置下標(biāo) """
x, y = random.sample(list, 1)[0]
""" 在隨機(jī)位置上生成隨機(jī)數(shù)字 """
self.martix[x][y] = value
self.isadd = False
# print('CreatNum: {}'.format(value), (x, y))
# print(self.martix)
# 獲取空白方格
def GetEmpty(self):
list = []
for i in range(4):
for j in range(4):
if self.martix[i][j] == 0:
list.append([i, j])
return list
# 向上移動(dòng)
def MoveUp(self):
# print('up')
""" Move Up """
"""
向上移動(dòng),只需考慮第二行到第四行
共分為兩種情況:
1、當(dāng)前數(shù)字上邊無(wú)空格,即上邊值不為 0
a. 當(dāng)前數(shù)字與上邊數(shù)字相等,合并
b. 當(dāng)前數(shù)字與上邊數(shù)字不相等,continue
2、當(dāng)前數(shù)字上邊有空格,即上邊值為 0, 上移
"""
for j in range(4):
index = 0
for i in range(1, 4):
if self.martix[i][j] > 0:
if self.martix[i][j] == self.martix[index][j]:
# 當(dāng)前數(shù)字 == 上邊數(shù)字
""" 分?jǐn)?shù): 當(dāng)前數(shù)字 + 上邊數(shù)字
數(shù)值: 上邊數(shù)字 = 上邊數(shù)字 + 當(dāng)前數(shù)字, 當(dāng)前數(shù)字 = 0 """
self.score += self.martix[i][j] + self.martix[index][j]
self.martix[index][j] = self.martix[i][j] + self.martix[index][j]
self.martix[i][j] = 0
index += 1
self.isadd = True
# 當(dāng)前數(shù)字與上邊數(shù)字不相等,continue 可以省略不寫(xiě)
elif self.martix[index][j] == 0:
# 當(dāng)前數(shù)字上邊有0
""" 分?jǐn)?shù): 不變
數(shù)值: 上邊數(shù)字 = 當(dāng)前數(shù)字, 當(dāng)前數(shù)字 = 0 """
self.martix[index][j] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
else:
index += 1
if self.martix[index][j] == 0:
# index相當(dāng)于慢指針,j相當(dāng)于快指針
# 也就是說(shuō)快指針和慢指針中間可能存在一個(gè)以上的空格,或者index和j并未相鄰
# 上邊數(shù)字 = 0
""" 分?jǐn)?shù): 不變
數(shù)值: 上邊數(shù)字 = 當(dāng)前數(shù)字, 當(dāng)前數(shù)字 = 0 """
self.martix[index][j] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
# print('up')
# print(self.martix)
# 向下移動(dòng)
def MoveDown(self):
# print('down')
""" Move Down """
"""
向下移動(dòng),只需考慮第一列到第三列
共分為兩種情況:
1、當(dāng)前數(shù)字下邊無(wú)空格,即下邊值不為 0
a. 當(dāng)前數(shù)字與下邊數(shù)字相等,合并
b. 當(dāng)前數(shù)字與下邊數(shù)字不相等,continue
2、當(dāng)前數(shù)字下邊有空格,即下邊值為 0, 下移
"""
for j in range(4):
index = 3
for i in range(2, -1, -1):
if self.martix[i][j] > 0:
if self.martix[i][j] == self.martix[index][j]:
# 當(dāng)前數(shù)字 == 下邊數(shù)字
""" 分?jǐn)?shù): 當(dāng)前數(shù)字 + 下邊數(shù)字
數(shù)值: 下邊數(shù)字 = 下邊數(shù)字 + 當(dāng)前數(shù)字, 當(dāng)前數(shù)字 = 0 """
self.score += self.martix[i][j] + self.martix[index][j]
self.martix[index][j] = self.martix[i][j] + self.martix[index][j]
self.martix[i][j] = 0
index -= 1
self.isadd = True
# 當(dāng)前數(shù)字與下邊數(shù)字不相等,continue 可以省略不寫(xiě)
elif self.martix[index][j] == 0:
# 當(dāng)前數(shù)字下邊有0
""" 分?jǐn)?shù): 不變
數(shù)值: 下邊數(shù)字 = 當(dāng)前數(shù)字, 當(dāng)前數(shù)字 = 0 """
self.martix[index][j] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
else:
index -= 1
if self.martix[index][j] == 0:
# index相當(dāng)于慢指針,j相當(dāng)于快指針
# 也就是說(shuō)快指針和慢指針中間可能存在一個(gè)以上的空格,或者index和j并未相鄰
# 下邊數(shù)字 = 0
""" 分?jǐn)?shù): 不變
數(shù)值: 下邊數(shù)字 = 當(dāng)前數(shù)字, 當(dāng)前數(shù)字 = 0 """
self.martix[index][j] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
# print('down')
# print(self.martix)
# 向左移動(dòng)
def MoveLeft(self):
# print('left')
"""
Move Left
"""
"""
向左移動(dòng),只需考慮第二列到第四列
共分為兩種情況:
1、當(dāng)前數(shù)字左邊無(wú)空格,即左邊值不為 0
a. 當(dāng)前數(shù)字與左邊數(shù)字相等,合并
b. 當(dāng)前數(shù)字與左邊數(shù)字不相等,continue
2、當(dāng)前數(shù)字左邊有空格,即左邊值為 0, 左移
"""
for i in range(4):
index = 0
for j in range(1, 4):
if self.martix[i][j] > 0:
if self.martix[i][j] == self.martix[i][index]:
# 當(dāng)前數(shù)字 == 左邊數(shù)字
""" 分?jǐn)?shù): 當(dāng)前數(shù)字 + 左邊數(shù)字
數(shù)值: 左邊數(shù)字 = 左邊數(shù)字 + 當(dāng)前數(shù)字, 當(dāng)前數(shù)字 = 0 """
self.score += self.martix[i][j] == self.martix[i][index]
self.martix[i][index] = self.martix[i][j] + self.martix[i][index]
self.martix[i][j] = 0
index += 1
self.isadd = True
# 當(dāng)前數(shù)字與左邊數(shù)字不相等,continue 可以省略不寫(xiě)
elif self.martix[i][index] == 0:
# 當(dāng)前數(shù)字左邊有0
""" 分?jǐn)?shù): 不變
數(shù)值: 左邊數(shù)字 = 當(dāng)前數(shù)字, 當(dāng)前數(shù)字 = 0 """
self.martix[i][index] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
else:
index += 1
if self.martix[i][index] == 0:
# index相當(dāng)于慢指針,j相當(dāng)于快指針
# 也就是說(shuō)快指針和慢指針中間可能存在一個(gè)以上的空格,或者index和j并未相鄰
# 左邊數(shù)字 = 0
""" 分?jǐn)?shù): 不變
數(shù)值: 左邊數(shù)字 = 當(dāng)前數(shù)字, 當(dāng)前數(shù)字 = 0 """
self.martix[i][index] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
# print('left')
# print(self.martix)
# 向右移動(dòng)
def MoveRight(self):
# print('right')
"""
Move Right
"""
"""
向右移動(dòng),只需考慮第一列到第三列
共分為兩種情況:
1、當(dāng)前數(shù)字右邊無(wú)空格,即右邊值不為 0
a. 當(dāng)前數(shù)字與右邊數(shù)字相等,合并
b. 當(dāng)前數(shù)字與右邊數(shù)字不相等,continue
2、當(dāng)前數(shù)字右邊有空格,即右邊值為 0, 右移
"""
for i in range(4):
index = 3
for j in range(2, -1, -1):
if self.martix[i][j] > 0:
if self.martix[i][j] == self.martix[i][index]:
# 當(dāng)前數(shù)字 == 右邊數(shù)字
""" 分?jǐn)?shù): 當(dāng)前數(shù)字 + 右邊數(shù)字
數(shù)值: 右邊數(shù)字 = 右邊數(shù)字 + 當(dāng)前數(shù)字, 當(dāng)前數(shù)字 = 0 """
self.score += self.martix[i][j] + self.martix[i][index]
self.martix[i][index] = self.martix[i][j] + self.martix[i][index]
self.martix[i][j] = 0
index -= 1
self.isadd = True
# 當(dāng)前數(shù)字與左邊數(shù)字不相等,continue 可以省略不寫(xiě)
elif self.martix[i][index] == 0:
# 當(dāng)前數(shù)字右邊有0
""" 分?jǐn)?shù): 不變
數(shù)值: 右邊數(shù)字 = 當(dāng)前數(shù)字, 當(dāng)前數(shù)字 = 0 """
self.martix[i][index] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
else:
index -= 1
if self.martix[i][index] == 0:
# index相當(dāng)于慢指針,j相當(dāng)于快指針
# 也就是說(shuō)快指針和慢指針中間可能存在一個(gè)以上的空格,或者index和j并未相鄰
# 右邊數(shù)字 = 0
""" 分?jǐn)?shù): 不變
數(shù)值: 右邊數(shù)字 = 當(dāng)前數(shù)字, 當(dāng)前數(shù)字 = 0 """
self.martix[i][index] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
# print('right')
# print(self.martix)
# 判斷游戲是否結(jié)束
def JudgeGameOver(self):
# 當(dāng)空白空格不為空時(shí),即游戲未結(jié)束
zerolist = self.GetEmpty()
if zerolist:
return False
# 當(dāng)空白方格為空時(shí),判斷是否存在可合并的方格
for i in range(3):
for j in range(3):
if self.martix[i][j] == self.martix[i][j + 1]:
return False
if self.martix[i][j] == self.martix[i + 1][j]:
return False
# 若不滿足以上兩種情況,則游戲結(jié)束
return True
# 判斷游戲是否成功
def JudgeGameSuccess(self):
# 檢查是否有2048
if self.martix.max() == 2048:
return True
return False
# 繪制表格
def Paint(self):
""" 游戲背景 """
# fill(color): 填充某一種顏色
self.form.fill((220, 220, 220))
""" 字體設(shè)置 """
# 初始化字體
pygame.font.init()
# 添加標(biāo)題
# f = pygame.font.get_fonts() #: 獲取字體樣式
# pygame.font.Font.render(): 在一個(gè)新 Surface 對(duì)象上繪制文本
self.title_font = pygame.font.SysFont('幼圓', 50, True)
title_text = self.title_font.render('2048', True, (0, 0, 0))
self.form.blit(title_text, (50, 10))
# 添加分?jǐn)?shù): 得分: 0
pygame.draw.rect(self.form, (128, 128, 128), (250, 0, 120, 60))
self.score_font = pygame.font.SysFont('幼圓', 28, True)
score_text = self.score_font.render('得 分', True, (0, 0, 0))
self.form.blit(score_text, (275, 0))
digtial_score = self.score_font.render(str(int(self.score)), True, (255, 250, 250))
self.form.blit(digtial_score, (280, 30))
# 添加游戲說(shuō)明
self.tips_font = pygame.font.SysFont('simsunnsimsun', 20)
tips_text = self.tips_font.render('操作: ↑ ↓ ← →, 按esc鍵重新開(kāi)始', True, (0, 0, 0))
self.form.blit(tips_text, (25, 70))
""" 繪制方格 """
for i in range(4):
for j in range(4):
# (x, y) 方塊的初始位置
x = j * self.block_size + (j + 1) * self.block_gap
y = i * self.block_size + (i + 1) * self.block_gap
# 繪制方塊
value = int(self.martix[i][j])
# print(value)
pygame.draw.rect(self.form, self.block_color[value], (x + 5, y + 100, self.block_size, self.block_size),
border_radius=self.block_arc)
# 數(shù)字字體即大小
if value < 10:
self.font = pygame.font.SysFont('simsunnsimsun', 46, True) # 數(shù)字2、4、8
value_text = self.font.render(str(value), True, self.nums_color[value])
self.form.blit(value_text, (x + 35, y + 120))
elif value < 100:
self.font = pygame.font.SysFont('simsunnsimsun', 40, True) # 數(shù)字16, 32, 64
value_text = self.font.render(str(value), True, self.nums_color[value])
self.form.blit(value_text, (x + 25, y + 120))
elif value < 1000:
self.font = pygame.font.SysFont('simsunnsimsun', 34, True) # 數(shù)字128, 256, 512
value_text = self.font.render(str(value), True, self.nums_color[value])
self.form.blit(value_text, (x + 15, y + 120))
else:
self.font = pygame.font.SysFont('simsunnsimsun', 28, True) # 數(shù)字1024, 2048
value_text = self.font.render(str(value), True, self.nums_color[value])
self.form.blit(value_text, (x + 5, y + 120))
# 新增數(shù)字
self.CreatNum()
""" 如果游戲結(jié)束 """
self.is_over = self.JudgeGameOver()
if self.is_over:
over_font = pygame.font.SysFont("simsunnsimsun", 60, True)
str_text = over_font.render('Game Over!', True, (255, 255, 255))
self.form.blit(str_text, (30, 220))
""" 如果游戲成功 """
self.is_success = self.JudgeGameSuccess()
if self.is_success:
success_font = pygame.font.SysFont("simsunnsimsun", 60, True)
str_text = success_font.render('Successful!', True, (178, 34, 34))
self.form.blit(str_text, (10, 220))
注意這里需要導(dǎo)入兩個(gè)包(numpy,pygame),然后運(yùn)行main文件即可。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
python基于win32api實(shí)現(xiàn)鍵盤(pán)輸入
這篇文章主要介紹了python基于win32api實(shí)現(xiàn)鍵盤(pán)輸入,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2020-12-12
tensorflow 報(bào)錯(cuò)unitialized value的解決方法
今天小編就為大家分享一篇tensorflow 報(bào)錯(cuò)unitialized value的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-02-02
Python使用for生成列表實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了Python使用for生成列表實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
Python3+Requests+Excel完整接口自動(dòng)化測(cè)試框架的實(shí)現(xiàn)
這篇文章主要介紹了Python3+Requests+Excel完整接口自動(dòng)化測(cè)試框架的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
python編程開(kāi)發(fā)之日期操作實(shí)例分析
這篇文章主要介紹了python編程開(kāi)發(fā)之日期操作,以實(shí)例形式較為詳細(xì)的分析了Python中datetime與time庫(kù)的相關(guān)使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
Python可執(zhí)行文件反編譯教程(exe轉(zhuǎn)py)
python的便利性,使得如今許多軟件開(kāi)發(fā)者、黑客都開(kāi)始使用python打包成exe的方式進(jìn)行程序的發(fā)布,那么Python如何反編譯可執(zhí)行文件,本文就來(lái)介紹一下,感興趣的可以了解一下2021-12-12
python dict.get()和dict[''key'']的區(qū)別詳解
下面小編就為大家?guī)?lái)一篇python dict.get()和dict['key']的區(qū)別詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06

