import curses # python3.7可以直接导入函数模块
import random
from itertools import chain
class GameField(object):
def __init__(self,width=4,height=4):
self.width=width # 棋盘的宽
self.height=height # 棋盘的长
self.score=0 # 当前成绩
self.hightscore=0 # 最高分
self.ismove={} #存储,判断各个方向是否可移动 的函数
self.ismove["Left"]=self.is_move_left
self.ismove["Right"]=self.is_move_right
self.ismove["Up"]=self.is_move_up
self.ismove["Down"]=self.is_move_down
self.moves = {} # 存储 执行各个方向移动 的函数
self.moves['Left'] = self.move_left
self.moves['Right'] = self.move_right
self.moves['Up'] = self.move_up
self.moves['Down'] = self.move_down
# 重置棋盘,重新开始游戏执行的操作
def reset(self):
# 更新游戏的最高分数,将当前成绩更新为0
if self.score>self.hightscore:
self.hightscore=self.score
self.score=0
# 创建棋盘的数据,默认情况为4*4,数据全为0
self.field=[[0 for j in range(4)] for i in range(4)]
self.random_create()
self.random_create()
# 开始游戏,随机在棋盘上生成2个数字【2或者4】
def random_create(self):
# 防止数字在同一位置重复生成
while True:
firstIndex=random.choice(range(4))
secondIndex=random.choice(range(4))
if self.field[firstIndex][secondIndex]==0:
# 设置生成2或者4的概率
self.field[firstIndex][secondIndex]=random.choice([2,2,2,2,4])
break # 如果在没有数字的位置生成数字,跳出循环
# 绘制棋盘图形
def draw(self,stdstr):
def draw_sep():
stdstr.addstr("+-----" * 4 + "+\n")
def draw_one_row(row):
stdstr.addstr("".join(["| %d " % (item)
if item != 0 else "| " for item in row]) + "|\n")
stdstr.clear() #清空在屏幕上添加的字符,重新画游戏界面
# 绘制游戏图形
for row in self.field:
draw_sep()
draw_one_row(row)
draw_sep()
# 在curses这个显示屏幕上添加字符串
stdstr.addstr("\n当前分数:%d" %(self.score))
stdstr.addstr("\n当前最高分数:%d" %(self.hightscore))
stdstr.addstr("\n游戏帮助:上下左右健 (R)estart (Q)uit")
if self.is_win():
stdstr.addstr("\n游戏胜利")
if self.is_gameover():
stdstr.addstr("\n游戏是失败")
# 判断游戏是否胜利的函数
def is_win(self):
return max(chain(*self.field))>=2048 # 判断游戏中最大数是否大于2048
# 判断游戏是否失败的函数
def is_gameover(self):
return not any([
self.is_move_left(self.field),
self.is_move_right(self.field),
self.is_move_up(self.field),
self.is_move_down(self.field)
])
# 判断游戏中一行是否可以移动
@staticmethod
def is_row_left(row):
# 判断一行中相邻的两个元素是否可以移动
def is_change(index):
if row[index]==0 and row[index+1]!=0:
return True
if row[index]!=0 and row[index]==row[index+1]:
return True
return False
return any([is_change(index) for index in range(3)])
# 判断游戏是否可以向左移动
def is_move_left(self,field):
return any([self.is_row_left(row) for row in field])
def invert(self,field): # 反转
return [row[::-1] for row in field]
# 判断游戏是否可以向右移动
def is_move_right(self,field):
invertField=self.invert(field)
return self.is_move_left(invertField)
def transpose(self,field): #转置
return [list(row) for row in zip(*field)]
# 判断游戏是否可以向上移动
def is_move_up(self,field):
transposeField=self.transpose(field)
return self.is_move_left(transposeField)
# 判断游戏是否可以向下移动
def is_move_down(self,field):
transposeField=self.transpose(field)
return self.is_move_right(transposeField)
# 一行数字向左移动
def move_row_left(self,row):
tight=sorted(row,key=lambda x:1 if x==0 else 0)
for index in range(3):
if tight[index]==tight[index+1]:
tight[index]*=2
tight[index+1]=0
self.score+=tight[index]
return sorted(tight,key=lambda x:1 if x==0 else 0)
# 游戏数字向左移动
def move_left(self,field):
return [self.move_row_left(row) for row in field]
# 游戏数字向右移动
def move_right(self,field):
invertField=self.invert(field)
return self.invert(self.move_left(invertField))
# 游戏数字向上移动
def move_up(self,field):
transposeField=self.transpose(field)
return self.transpose(self.move_left(transposeField))
# 游戏数字向下移动
def move_down(self,field):
transposeField=self.transpose(field)
return self.transpose(self.move_right(transposeField))
# 2048游戏的移动
def move(self,direction):
if direction in self.ismove:
# 1). 判断这个方向是否可以移动
if self.ismove[direction](self.field):
# 2). 执行移动的操作
self.field=self.moves[direction](self.field)
# 3). 再随机生成一个2或4
self.random_create()
else:
return False
def get_user_action(stdstr):
# 获取用户键盘输入的内容
action=stdstr.getch()
if action==curses.KEY_UP:
return "Up"
if action==curses.KEY_DOWN:
return "Down"
if action==curses.KEY_LEFT:
return "Left"
if action==curses.KEY_RIGHT:
return "Right"
if action==ord("r"):
return "Restart"
if action==ord("q"):
return "Exit"
def main(stdstr):
def init():
game_field.reset()
game_field.draw(stdstr)
return "Game"
def game():
game_field.draw(stdstr)
action=get_user_action(stdstr)
if action=="Restart":
return "Init"
if action == 'Exit':
return 'Exit'
if game_field.move(action):
if game_field.is_win():
return 'Win'
if game_field.is_gameover():
return 'Gameover'
return 'Game'
return 'Game'
def not_game():
action = get_user_action(stdstr)
if action == 'Restart':
return 'Init'
if action == 'Exit':
return 'Exit'
game_field=GameField() # 调用2048游戏模块
state = 'Init'
state_dict = {
'Init': init, # 游戏初始化
'Game': game, # 开始游戏
'Win': not_game, # 游戏胜利
'Gameover': not_game, # 游戏失败
'Exit': exit # 退出游戏
}
while True:
state = state_dict[state]() # 调用主函数对应的游戏函数模块
curses.wrapper(main)
python3---2048小游戏
最新推荐文章于 2024-07-30 16:12:44 发布