python3---2048小游戏

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)

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值