记录下今天写的2048小游戏代码~
路漫漫其修远兮,仍需自我修炼。
目录
bill.py
"""
游戏逻辑控制器,负责处理游戏的核心算法
"""
from model import DirectionModel
from model import Location
import random
class GameCoreController:
def __init__(self):
self.__list_merge = None
self.__list_empty_location = []
self.__map = [
[2, 0, 0, 2],
[4, 4, 2, 2],
[2, 4, 0, 4],
[0, 0, 2, 2],
]
@property
def map(self):
return self.__map
def __zero_to_end(self):
# 从后向前,如果发现0元素就删除并追加
for i in range(len(self.__list_merge) - 1, -1, -1):
if self.__list_merge[i] == 0:
del self.__list_merge[i]
self.__list_merge.append(0)
def __merge(self):
# 将中间的0元素后移
self.__zero_to_end()
for i in range(len(self.__list_merge) - 1):
# 将相邻2个相同的元素进行相加合并
if self.__list_merge[i] == self.__list_merge[i + 1]:
self.__list_merge[i] += self.__list_merge[i + 1]
del self.__list_merge[i + 1]
self.__list_merge.append(0)
def __move_left(self):
for line in self.__map:
# 将map的每一行,交给成员变量list_merge进行处理
self.__list_merge = line
self.__merge()
self.generate_new_number()
def __move_right(self):
# 将map中的每行(从右向左)交给merge函数进行处理
for line in self.__map:
# 切片,从右向左取出数据,形成新列表
self.__list_merge = line[::-1]
self.__merge()
# 从右向左接受合并后的数据
line[::-1] = self.__list_merge
self.generate_new_number()
def __move_down(self):
self.__square_matrix_transpose()
self.__move_left()
self.__square_matrix_transpose()
self.generate_new_number()
def __move_up(self):
self.__square_matrix_transpose()
self.__move_right()
self.__square_matrix_transpose()
self.generate_new_number()
def __square_matrix_transpose(self):
# 矩阵转置
for c in range(1, len(self.__map)):
for r in range(c, len(self.__map)):
self.__map[r][c - 1], self.__map[c - 1][r] = self.__map[c - 1][r], self.__map[r][c - 1]
def move(self, direction):
"""
移动方法
:param directon: 移动的方向,DirectionModel模型
"""
if direction == DirectionModel.UP:
self.__move_left()
elif direction == DirectionModel.DOWN:
self.__move_down()
elif direction == DirectionModel.LEFT:
self.__move_left()
elif direction == DirectionModel.RIGHT:
self.__move_right()
def __get_empty_location(self):
"""
获取空白位置
:return: 所有的空白位置,列表
"""
# 每次统计空位置之前,先清空之前的数据
self.__list_empty_location.clear()
# 选出所有空白位置,再随机挑选一个
for r in range(len(self.__map)):
for c in range(len(self.__map[r])):
if self.__map[r][c] == 0:
# 记录r和c--元组
self.__list_empty_location.append((Location(r, c)))
def __select_random_number(self):
"""
获取需要在空白处添加的随机数字
:return: 4 或者 2
"""
return 4 if random.randint(1, 11) == 1 else 2
def generate_new_number(self):
"""
在空白位置生成随机数字 2 或者 4
"""
self.__get_empty_location()
if len(self.__list_empty_location) == 0:
return
# 从list_empty_location中随机挑选一个空白位置
loc = random.choice(self.__list_empty_location)
self.__map[loc.r_index][loc.c_index] = self.__select_random_number()
# 只剩下一个空位置的时候,生成了新数字,所以该位置就不再是空位置,所以应该从__list_empty_location列表中移除
self.__list_empty_location.remove(loc)
def is_game_over(self):
"""
判断游戏是否结束
:return: True:结束,False:没有结束
"""
# 判断是否存在空位置
if len(self.__list_empty_location) > 0:
return False
for r in range(len(self.__map)): # 0 1 2 3
for c in range(len(self.__map[r]) - 1): # 0 1 2 3
# 判断横向、或者竖向是否存在相同元素
if self.__map[r][c] == self.__map[r][c + 1] or self.__map[c][r] == self.__map[c + 1][r]:
return False
# for r in range(len(self.__map)): # 0 1 2 3
# for c in range(len(self.__map[r]) - 1): # 0 1 2 3
# # 竖向是否存在相同元素
# if self.__map[c][r] == self.__map[c + 1][r]:
# return False
return True
# ------------------测试代码------------------
if __name__ == '__main__':
con = GameCoreController()
con.move(DirectionModel.RIGHT)
print(con.map)
# print(con.rand_number)
# while not con.is_game_over():
# con.move(DirectionModel.LEFT)
# print(con.map)
# print(con.is_game_over())
model.py
class DirectionModel:
"""
方向数据模型
枚举
"""
UP = 0,
DOWN = 1,
LEFT = 2,
RIGHT = 3,
class Location:
def __init__(self,r ,c):
self.r_index = r
self.c_index = c
ui.py
"""
2048控制台界面
"""
from bll import GameCoreController
from model import DirectionModel
import os
class GameConsoleView:
def __init__(self):
self.__controller = GameCoreController()
def main(self):
self.__start()
self.__update()
def __start(self):
# 产生2个数字
self.__controller.generate_new_number()
self.__controller.generate_new_number()
# 绘制界面
self.__draw_map()
pass
def __draw_map(self):
# 清空控制台
# os.system("cls")
for line in self.__controller.map:
for item in line:
print(item, end=" ")
print()
def __update(self):
while True:
# 判断玩家的输入,根据玩家的输入进行移动
self.__move_map_for_input()
# 产生新数字
self.__controller.generate_new_number()
# 绘制界面
self.__draw_map()
# 游戏结束判定 --> 提示是否结束
if self.__controller.is_game_over():
print("游戏结束")
break
def __move_map_for_input(self):
direction = input("请输入移动方向(wsad):")
direction_dir = {
"w": DirectionModel.UP,
"s": DirectionModel.DOWN,
"a": DirectionModel.LEFT,
"d": DirectionModel.RIGHT,
}
if direction.lower() in direction_dir:
self.__controller.move(direction_dir[direction.lower()])
else:
print("输入有误,请重新输入!")
if __name__ == '__main__':
view = GameConsoleView()
view.main()
main.py
from ui import GameConsoleView
if __name__ == '__main__':
GameConsoleView().main()