2048小游戏也算是一款好玩的益智休闲小游戏,下面本博主用 python 语言将该游戏复现,感兴趣的小伙伴点击 关注 哦!
同时博主还用 java 语言复现了该游戏,可点击以下链接浏览博主的另一篇文章:JAVA实现2048小游戏 !
目录
一、效果
二、教程
1、文件结构
2、configs.py
3、main.py
4、Game2048.py
三、代码
1、configs.py
2、main.py
3、Game2048.py
2048小游戏是一款比较流行的数字游戏,游戏规则如下:
每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方乱数出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。不断的叠加最终拼凑出2048这个数字就算成功。
ps: 博主就没有添加成功的图片了,实在是因为技术不行,试完了几次均没有凑成 2048 ...因此放上了凑成256成功的图片
常用参数:
(1) 窗口设置
A. screen_width:游戏窗口的宽
B. screen_height:游戏窗口的高
(2) 方块设置
A. block_gap:方块与方块之间的间隙
B. block_size:方块的大小
C. block_arc:方块四角的弧度
(1) 调用Game2048类,创建2048游戏示例game
game = Game2048(screen_width, screen_height, block_gap, block_size, block_arc)
(2) 开始游戏
game.Form()
(1) 导入包
import os
import sys
import numpy
import random
import pygame
(2) 类的创建
类名:Game2048
class Game2048(object):
(3) 类的初始化
A. 变量
a. screen_width: 窗口的宽 400
b. screen_height:窗口的高 500
c. block_gap: 方块间隙 10
d. block_size:方块大小 86
e. block_arc:方块的弧度
f. size:矩阵的大小 4 * 4
g. martix:初始化矩阵 4 * 4
h. form:窗体
i. is_over:游戏是否结束
j. is_success:游戏是否成功
k. score:分数
l. isadd:是否添加数字
m. block_color:方块颜色
n. nums_color:数字颜色
o. title_font:窗口标题字体类型及大小
p. score_font:分数字体类型及大小
q. tips_font:说明字体类型及大小
r. font:数字字体类型及大小
B. 代码
def __init__(self, screen_width, screen_height, block_gap, block_size, block_arc):
""" 窗口 """
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 # 游戏是否结束
self.is_success = False # 游戏是否成功
self.score = 0 # 分数
self.isadd = True # 是否添加数字
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: (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 = '' # 窗口标题字体类型及大小: 2048
self.score_font = '' # 分数字体类型及大小
self.tips_font = '' # 说明字体类型及大小
self.font = '' # 数字字体
(4) 窗体的设置
- init(): 初始化所有导入的 pygame 模块
- display.set_caption(title): 设置窗口的标题
- display.set_mode(): 初始化一个准备显示的窗口或屏幕
- display.update(): 使绘制的显示到窗口上
def Form(self):
pygame.init() # 初始化所有导入的 pygame 模块
pygame.display.set_caption("Game2048") # 窗口标题
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() # 用户行为: 按键/鼠标
self.Paint() # 表格绘制
pygame.display.update() # 使绘制的显示到窗口上
(5) 用户行为:按键/鼠标
- pygame.event.get(): 获取所有消息并将其从队列中删除
- pygame.QUIT: 窗口右上角的红 ×
- sys.exit()函数是通过抛出异常的方式来终止进程的
- pygame.KEYDOWN 按下键盘时
- pygame.KEYUP 释放键盘时
- K_ESCAPE: ESC
- K_UP: ↑
- K_DOWN: ↓
- K_LEFT: ←
- K_RIGHT: →
def Action(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
""" 重新开始游戏 """
if event.key == pygame.K_ESCAPE:
self.InitGame() # 游戏初始化
""" ↑ """
if event.key == pygame.K_UP and self.is_over == False:
self.MoveUp()
""" ↓ """
if event.key == pygame.K_DOWN and self.is_over == False:
self.MoveDown()
""" ← """
if event.key == pygame.K_LEFT and self.is_over == False:
self.MoveLeft()
""" → """
if event.key == pygame.K_RIGHT and self.is_over == False:
self.MoveRight()
(6) 游戏初始化
def InitGame(self):
self.score = 0
self.is_over = False
self.is_success = False
self.martix = numpy.zeros([self.size, self.size])
# 随机生成两个数
for i in range(2):
self.isadd = True
self.CreatNum()
(7) 随机在一个位置生成一个数字
- 2, 4出现概率3:1
- random.randint(m, n): 随机生成[m, n]
def CreatNum(self):
list = self.GetEmpty() # 获取空白方格下标
if list and self.isadd:
""" 随机生成的数字 """
value = 4 if random.randint(0, 3) % 3 == 0 else 2
""" 获取随机位置下标 """
x, y = random.sample(list, 1)[0]
""" 在随机位置上生成随机数字 """
self.martix[x][y] = value
self.isadd = False
(8) 获取空白方格
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
(9) 向上移动
def MoveUp(self):
""" Move Up """
"""
向上移动,只需考虑第二行到第四行
共分为两种情况:
1、当前数字上边无空格,即上边值不为 0
a. 当前数字与上边数字相等,合并
b. 当前数字与上边数字不相等,continue
2、当前数字上边有空格,即上边值为 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]:
# 当前数字 == 上边数字
""" 分数: 当前数字 + 上边数字
数值: 上边数字 = 上边数字 + 当前数字, 当前数字 = 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
# 当前数字与上边数字不相等,continue 可以省略不写
elif self.martix[index][j] == 0:
# 当前数字上边有0
""" 分数: 不变
数值: 上边数字 = 当前数字, 当前数字 = 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相当于慢指针,j相当于快指针
# 也就是说快指针和慢指针中间可能存在一个以上的空格,或者index和j并未相邻
# 上边数字 = 0
""" 分数: 不变
数值: 上边数字 = 当前数字, 当前数字 = 0 """
self.martix[index][j] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
(10) 向下移动
def MoveDown(self):
""" Move Down """
"""
向下移动,只需考虑第一列到第三列
共分为两种情况:
1、当前数字下边无空格,即下边值不为 0
a. 当前数字与下边数字相等,合并
b. 当前数字与下边数字不相等,continue
2、当前数字下边有空格,即下边值为 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]:
# 当前数字 == 下边数字
""" 分数: 当前数字 + 下边数字
数值: 下边数字 = 下边数字 + 当前数字, 当前数字 = 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
# 当前数字与下边数字不相等,continue 可以省略不写
elif self.martix[index][j] == 0:
# 当前数字下边有0
""" 分数: 不变
数值: 下边数字 = 当前数字, 当前数字 = 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相当于慢指针,j相当于快指针
# 也就是说快指针和慢指针中间可能存在一个以上的空格,或者index和j并未相邻
# 下边数字 = 0
""" 分数: 不变
数值: 下边数字 = 当前数字, 当前数字 = 0 """
self.martix[index][j] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
(11) 向左移动
def MoveLeft(self):
"""
Move Left
"""
"""
向左移动,只需考虑第二列到第四列
共分为两种情况:
1、当前数字左边无空格,即左边值不为 0
a. 当前数字与左边数字相等,合并
b. 当前数字与左边数字不相等,continue
2、当前数字左边有空格,即左边值为 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]:
# 当前数字 == 左边数字
""" 分数: 当前数字 + 左边数字
数值: 左边数字 = 左边数字 + 当前数字, 当前数字 = 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
# 当前数字与左边数字不相等,continue 可以省略不写
elif self.martix[i][index] == 0:
# 当前数字左边有0
""" 分数: 不变
数值: 左边数字 = 当前数字, 当前数字 = 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相当于慢指针,j相当于快指针
# 也就是说快指针和慢指针中间可能存在一个以上的空格,或者index和j并未相邻
# 左边数字 = 0
""" 分数: 不变
数值: 左边数字 = 当前数字, 当前数字 = 0 """
self.martix[i][index] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
(12) 向右移动
def MoveRight(self):
"""
Move Right
"""
"""
向右移动,只需考虑第一列到第三列
共分为两种情况:
1、当前数字右边无空格,即右边值不为 0
a. 当前数字与右边数字相等,合并
b. 当前数字与右边数字不相等,continue
2、当前数字右边有空格,即右边值为 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]:
# 当前数字 == 右边数字
""" 分数: 当前数字 + 右边数字
数值: 右边数字 = 右边数字 + 当前数字, 当前数字 = 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
# 当前数字与左边数字不相等,continue 可以省略不写
elif self.martix[i][index] == 0:
# 当前数字右边有0
""" 分数: 不变
数值: 右边数字 = 当前数字, 当前数字 = 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相当于慢指针,j相当于快指针
# 也就是说快指针和慢指针中间可能存在一个以上的空格,或者index和j并未相邻
# 右边数字 = 0
""" 分数: 不变
数值: 右边数字 = 当前数字, 当前数字 = 0 """
self.martix[i][index] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
(13) 判断游戏是否结束
def JudgeGameOver(self):
# 当空白空格不为空时,即游戏未结束
zerolist = self.GetEmpty()
if zerolist:
return False
# 当空白方格为空时,判断是否存在可合并的方格
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
# 若不满足以上两种情况,则游戏结束
return True
(14) 判断游戏是否成功
def JudgeGameSuccess(self):
# 检查是否有2048
if self.martix.max() == 2048:
return True
return False
(15) 绘制表格
A. 游戏背景
- fill(color): 填充某一种颜色
self.form.fill((220, 220, 220))
B. 初始化字体
pygame.font.init()
C. 添加标题
- pygame.font.Font.render(): 在一个新 Surface 对象上绘制文本
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))
D. 添加分数:得分: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))
E. 添加游戏说明
self.tips_font = pygame.font.SysFont('simsunnsimsun', 20)
tips_text = self.tips_font.render('操作: ↑ ↓ ← →, 按esc键重新开始', True, (0, 0, 0))
self.form.blit(tips_text, (25, 70))
F. 绘制方格
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])
pygame.draw.rect(self.form, self.block_color[value], (x + 5, y + 100, self.block_size, self.block_size),
border_radius=self.block_arc)
# 数字字体即大小
if value < 10:
self.font = pygame.font.SysFont('simsunnsimsun', 46, True) # 数字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) # 数字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) # 数字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) # 数字1024, 2048
value_text = self.font.render(str(value), True, self.nums_color[value])
self.form.blit(value_text, (x + 5, y + 120))
# 新增数字
self.CreatNum()
G. 如果游戏结束
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))
H. 如果游戏成功
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))
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()
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)
import os
import sys
import numpy
import random
import pygame
"""
Form(): 窗口的设置
Action(): 用户行为: 按键/鼠标
InitGame(): 游戏初始化
CreatNum(): 随机在一个位置生成一个数
GetEmpty(): 获取空白方格
MoveUp(): 向上移动
MoveDown(): 向下移动
MoveLeft(): 向左移动
MoveRight(): 向右移动
JudgeGameOver(): 判断游戏是否结束
JudgeGameSuccess(): 判断游戏是否成功
Paint(): 绘制表格
"""
class Game2048(object):
# 初始化函数
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 # 游戏是否结束
self.is_success = False # 游戏是否成功
self.score = 0 # 分数
self.isadd = True # 是否添加数字
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 = '' # 窗口标题字体类型及大小: 2048
self.score_font = '' # 分数字体类型及大小
self.tips_font = '' # 说明字体类型及大小
self.font = '' # 数字字体
# 窗口的设置
def Form(self):
"""
init(): 初始化所有导入的 pygame 模块
display.set_caption(title): 设置窗口的标题
display.set_mode(): 初始化一个准备显示的窗口或屏幕
display.update(): 使绘制的显示到窗口上
"""
pygame.init() # 初始化所有导入的 pygame 模块
pygame.display.set_caption("Game2048") # 窗口标题
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() # 用户行为: 按键/鼠标
self.Paint() # 表格绘制
pygame.display.update() # 使绘制的显示到窗口上
# 用户行为: 按键/鼠标
def Action(self):
for event in pygame.event.get(): # pygame.event.get(): 获取所有消息并将其从队列中删除
if event.type == pygame.QUIT: # pygame.QUIT: 窗口右上角的红 ×
sys.exit() # sys.exit()函数是通过抛出异常的方式来终止进程的
elif event.type == pygame.KEYDOWN:
"""
pygame.KEYDOWN 按下键盘时
pygame.KEYUP 释放键盘时
"""
"""
K_ESCAPE: ESC
K_UP: ↑
K_DOWN: ↓
K_LEFT: ←
K_RIGHT: →
"""
""" 重新开始游戏 """
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])
# 随机生成两个数
for i in range(2):
self.isadd = True
self.CreatNum()
# 随机在一个位置生成一个数
def CreatNum(self):
list = self.GetEmpty() # 获取空白方格下标
if list and self.isadd:
""" 随机生成的数字 """
# 2, 4出现概率3:1
# random.randint(m, n): 随机生成[m, n]
value = 4 if random.randint(0, 3) % 3 == 0 else 2
""" 获取随机位置下标 """
x, y = random.sample(list, 1)[0]
""" 在随机位置上生成随机数字 """
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
# 向上移动
def MoveUp(self):
# print('up')
""" Move Up """
"""
向上移动,只需考虑第二行到第四行
共分为两种情况:
1、当前数字上边无空格,即上边值不为 0
a. 当前数字与上边数字相等,合并
b. 当前数字与上边数字不相等,continue
2、当前数字上边有空格,即上边值为 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]:
# 当前数字 == 上边数字
""" 分数: 当前数字 + 上边数字
数值: 上边数字 = 上边数字 + 当前数字, 当前数字 = 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
# 当前数字与上边数字不相等,continue 可以省略不写
elif self.martix[index][j] == 0:
# 当前数字上边有0
""" 分数: 不变
数值: 上边数字 = 当前数字, 当前数字 = 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相当于慢指针,j相当于快指针
# 也就是说快指针和慢指针中间可能存在一个以上的空格,或者index和j并未相邻
# 上边数字 = 0
""" 分数: 不变
数值: 上边数字 = 当前数字, 当前数字 = 0 """
self.martix[index][j] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
# print('up')
# print(self.martix)
# 向下移动
def MoveDown(self):
# print('down')
""" Move Down """
"""
向下移动,只需考虑第一列到第三列
共分为两种情况:
1、当前数字下边无空格,即下边值不为 0
a. 当前数字与下边数字相等,合并
b. 当前数字与下边数字不相等,continue
2、当前数字下边有空格,即下边值为 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]:
# 当前数字 == 下边数字
""" 分数: 当前数字 + 下边数字
数值: 下边数字 = 下边数字 + 当前数字, 当前数字 = 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
# 当前数字与下边数字不相等,continue 可以省略不写
elif self.martix[index][j] == 0:
# 当前数字下边有0
""" 分数: 不变
数值: 下边数字 = 当前数字, 当前数字 = 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相当于慢指针,j相当于快指针
# 也就是说快指针和慢指针中间可能存在一个以上的空格,或者index和j并未相邻
# 下边数字 = 0
""" 分数: 不变
数值: 下边数字 = 当前数字, 当前数字 = 0 """
self.martix[index][j] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
# print('down')
# print(self.martix)
# 向左移动
def MoveLeft(self):
# print('left')
"""
Move Left
"""
"""
向左移动,只需考虑第二列到第四列
共分为两种情况:
1、当前数字左边无空格,即左边值不为 0
a. 当前数字与左边数字相等,合并
b. 当前数字与左边数字不相等,continue
2、当前数字左边有空格,即左边值为 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]:
# 当前数字 == 左边数字
""" 分数: 当前数字 + 左边数字
数值: 左边数字 = 左边数字 + 当前数字, 当前数字 = 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
# 当前数字与左边数字不相等,continue 可以省略不写
elif self.martix[i][index] == 0:
# 当前数字左边有0
""" 分数: 不变
数值: 左边数字 = 当前数字, 当前数字 = 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相当于慢指针,j相当于快指针
# 也就是说快指针和慢指针中间可能存在一个以上的空格,或者index和j并未相邻
# 左边数字 = 0
""" 分数: 不变
数值: 左边数字 = 当前数字, 当前数字 = 0 """
self.martix[i][index] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
# print('left')
# print(self.martix)
# 向右移动
def MoveRight(self):
# print('right')
"""
Move Right
"""
"""
向右移动,只需考虑第一列到第三列
共分为两种情况:
1、当前数字右边无空格,即右边值不为 0
a. 当前数字与右边数字相等,合并
b. 当前数字与右边数字不相等,continue
2、当前数字右边有空格,即右边值为 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]:
# 当前数字 == 右边数字
""" 分数: 当前数字 + 右边数字
数值: 右边数字 = 右边数字 + 当前数字, 当前数字 = 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
# 当前数字与左边数字不相等,continue 可以省略不写
elif self.martix[i][index] == 0:
# 当前数字右边有0
""" 分数: 不变
数值: 右边数字 = 当前数字, 当前数字 = 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相当于慢指针,j相当于快指针
# 也就是说快指针和慢指针中间可能存在一个以上的空格,或者index和j并未相邻
# 右边数字 = 0
""" 分数: 不变
数值: 右边数字 = 当前数字, 当前数字 = 0 """
self.martix[i][index] = self.martix[i][j]
self.martix[i][j] = 0
self.isadd = True
# print('right')
# print(self.martix)
# 判断游戏是否结束
def JudgeGameOver(self):
# 当空白空格不为空时,即游戏未结束
zerolist = self.GetEmpty()
if zerolist:
return False
# 当空白方格为空时,判断是否存在可合并的方格
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
# 若不满足以上两种情况,则游戏结束
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))
""" 字体设置 """
# 初始化字体
pygame.font.init()
# 添加标题
# f = pygame.font.get_fonts() #: 获取字体样式
# pygame.font.Font.render(): 在一个新 Surface 对象上绘制文本
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))
# 添加分数: 得分: 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))
# 添加游戏说明
self.tips_font = pygame.font.SysFont('simsunnsimsun', 20)
tips_text = self.tips_font.render('操作: ↑ ↓ ← →, 按esc键重新开始', 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)
# 数字字体即大小
if value < 10:
self.font = pygame.font.SysFont('simsunnsimsun', 46, True) # 数字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) # 数字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) # 数字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) # 数字1024, 2048
value_text = self.font.render(str(value), True, self.nums_color[value])
self.form.blit(value_text, (x + 5, y + 120))
# 新增数字
self.CreatNum()
""" 如果游戏结束 """
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))