import pygame
import random as r
import sys
import traceback
from pygame.locals import *
### py(3.9.5)
pygame.init()
screen_size = width, height = 400, 400
screen = pygame.display.set_mode(screen_size)
clock = pygame.time.Clock()
fps = 30
# 列表中是否有零
def not_zero_num(lista):
for i in range(len(lista)):
if lista[i] != 0:
return lista[i], i
# 清除列表前n个0 orient = False <---, orient = True --->
def clear_zero(listb, orient = False):
# 先清除中间部分
target_list = listb.copy()
for i in range(len(target_list) - 1):
if target_list[i] == 0:
target_list.pop(i)
target_list.insert(len(target_list), 0)
if not orient :
for i in range(len(target_list)):
if target_list[0] == 0:
target_list.pop(0)
target_list.append(0)
elif orient:
length = len(target_list)
for i in range(length):
if target_list[length - 1] == 0:
target_list.pop(length - 1)
target_list.insert(0, 0)
return target_list
# 主函数 移动矩阵
def move_box(listc, orient = False, high_dim = False): # <--- 移动方向 orient 默认方向
calc_list = listc[:] # 好像列表复制不好用
calc_list = clear_zero(calc_list, orient)
if orient:
for i in range(len(calc_list) - 1):
if calc_list[len(calc_list) - 1 - i] == calc_list[len(calc_list) - 2 - i]:
calc_list[len(calc_list) - 1 - i] = 2 * calc_list[len(calc_list) - 1 - i]
calc_list.pop(len(calc_list) - 2 - i)
calc_list.insert(0, 0)
elif not orient:
for i in range(len(calc_list) - 1):
if calc_list[i] == calc_list[i + 1]:
calc_list[i] = calc_list[i] * 2
calc_list.pop(i + 1)
calc_list.insert(len(calc_list), 0)
return calc_list
# 转置矩阵
def reverse_matrix(matrix):
result = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
for y in range(len(matrix)):
for x in range(len(matrix[0])):
result[y][x] = matrix[x][y]
return result
# 随机空白位置生成新数字
def new_num(matrix):
blank = []
for y in range(len(matrix)):
for x in range(len(matrix[0])):
if not matrix[y][x]:
blank.append((y, x))
if not blank:
return False
else:
select = r.choice(blank)
matrix[select[0]][select[1]] = r.choice([2,4])
return True
# 色库
BLACK = 0, 0, 0
GREEN = 0, 255, 0
# 字体
font = pygame.font.Font(None, 20)
# 初始化数据
main_list = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
font_list = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
font_pos = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
check = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]] # 检验矩阵
memorize = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]] # 记忆矩阵
running = True
row, col = 4, 4
rect_size = x, y = 96, 96
check_active = False
new_num(main_list) # 初始化游戏
def move_left(row, matrix):
for i in range(row):
matrix[i] = move_box(matrix[i], False)
return matrix
def move_right(row, matrix):
for i in range(row):
matrix[i] = move_box(matrix[i], True)
return matrix
def move_up(col, matrix):
matrix = reverse_matrix(matrix)
move_left(col, matrix)
matrix = reverse_matrix(matrix)
return matrix
def move_down(col, matrix):
matrix = reverse_matrix(matrix)
move_right(col, matrix)
matrix = reverse_matrix(matrix)
return matrix
# 记录文字位置初始数据
for i in range(screen_size[0] // x): # 行
for j in range(screen_size[1] // y): # 列
font_pos[i][j] = (pygame.draw.rect(screen, BLACK, [i * 100 + 2, j * 100 + 2, x, y]).center)
while running:
# 检测事件
screen.fill(GREEN)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
# 用户操作
key_pressed = pygame.key.get_pressed()
if key_pressed[K_LEFT] or key_pressed[K_RIGHT] or key_pressed[K_DOWN] or key_pressed[K_UP]:
memorize = main_list[:]
check_active = True
if key_pressed[K_LEFT]:
main_list = move_left(row, main_list)
if key_pressed[K_RIGHT]:
main_list = move_right(row, main_list)
if key_pressed[K_DOWN]:
main_list = move_down(col, main_list)
if key_pressed[K_UP]:
main_list = move_up(col, main_list)
check = main_list[:]
check = move_left(row, check)
if check == main_list:
check = move_right(row, check)
if check == main_list:
check = move_down(col, check)
if check == main_list:
move_up(col, check)
if check == main_list:
print("game over")
# 检验是否真的无法移动
ENDDING = True
# game over
while ENDDING:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_RETURN:
ENDDING = False
# reset
main_list = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
font_list = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
check = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
new_num(main_list)
running = True
row, col = 4, 4
rect_size = x, y = 96, 96
check_active = False
screen.fill(BLACK)
font_rect = font.render("Game Over. Press [Enter] to continue", True, (255,255,255)).get_rect()
font_rect.center = screen_size[0] // 2, screen_size[1] // 2
screen.blit(font.render("Game Over. Press [Enter] to continue", True, (255,255,255)),font_rect)
pygame.display.flip()
new_num(main_list)
# 恢复上一步
if event.type == KEYDOWN:
if event.key == K_SPACE:
if check_active:
main_list = memorize.copy()
check_active = False
# 绘制背景 及 数据
for i in range(screen_size[0] // x): # 列
for j in range(screen_size[1] // y): # 行
font_list[i][j] = font.render(str(main_list[j][i]), True, GREEN)
pygame.draw.rect(screen, BLACK, [i * 100 + 2, j * 100 + 2, x, y])
if main_list[j][i] != 0:
screen.blit(font_list[i][j], (font_pos[i][j][0] - font_list[i][j].get_rect().width // 2,\
font_pos[i][j][1] - font_list[i][j].get_rect().height // 2))
pygame.display.flip()
clock.tick(fps)