• 【python】2048


    来源:https://www.shiyanlou.com/courses/368

     实验楼的2048程序,在linux下可实现通过终端游戏。

    主要学习的知识点:

    1.状态机函数实现,用字典将状态和函数相对应,返回状态再通过字典调用相关函数

    2.字典的值可以是函数名,也可以是lambda匿名函数。 lambda:25  这种是没有输入的匿名函数

    3.defaultdict可以指定字典默认类型

    4.hasattr可以查找是否有指定属性

    5.函数可以定义在函数中,如果一个函数A只在函数B中使用,可以在B中定义A

    6. 注意如下写法

    choice([(i,j) for i in range(self.width) for j in range(self.height) if self.field[i][j] == 0])

    7. zip, any函数的使用

    8. 如果有函数A,则可以定义A.var这样的变量。在代码中可以实现类似C的静态变量的效果。

    import curses  #?
    from random import randrange, choice
    from collections import defaultdict
    
    
    letter_codes = [ord(ch) for ch in 'WASDRQwasdrq']
    actions = ['Up','Left','Down','Right','Restart','Exit']
    actions_dict = dict(zip(letter_codes, actions * 2))  #?
    
    def get_user_action(keyboard):
        char = "N"
        while char not in actions_dict:
            char = keyboard.getch()
        return actions_dict[char]
        
    def transpose(field):
        return [list(row) for row in zip(*field)]
    
    def invert(field):
        return [row[::-1] for row in field]
    
    class GameField(object):
        def __init__(self, height=4, width=4, win=2048):
            self.height = height
            self.width = width
            self.win_value = 2048
            self.score = 0
            self.highscore = 0
            self.reset()
        
    
        
        def reset(self):
            if self.score > self.highscore:
                self.highscore = self.score
            self.score = 0
            self.field = [[0 for i in range(self.width)] for j in range(self.height)]
            self.spawn()
            self.spawn()
        
        def move(self, direction):
            def move_row_left(row):
                def tighten(row): #把零散的非零单元挤到一块
                    new_row = [i for i in row if i != 0]
                    new_row += [0 for i in range(len(row) - len(new_row))]
                    return new_row
                
                def merge(row): #对邻近元素进行合并
                    pair = False
                    new_row = []
                    for i in range(len(row)):
                        if pair:
                            new_row.append(2 * row[i])
                            self.score += 2 * row[i]
                            pair = False
                        else:
                            if i + 1 < len(row) and row[i] == row[i + 1]:
                                pair = True
                                new_row.append(0)
                            else:
                                new_row.append(row[i])
                    assert len(new_row) == len(row)
                    return new_row
                
                #先挤到一块再合并再挤到一块
                return tighten(merge(tighten(row)))
            
            moves = {}
            moves['Left'] = lambda field: [move_row_left(row) for row in field]
            moves['Right'] = lambda field: invert(moves['Left'](invert(field)))
            moves['Up'] = lambda field: transpose(moves['Left'](transpose(field)))
            moves['Down'] = lambda field: transpose(moves['Right'](transpose(field)))
            
            if direction in moves:
                if self.move_is_possible(direction):
                    self.field = moves[direction](self.field)
                    self.spawn()
                    return True
                else:
                    return False
        
        def is_win(self):
            return any(any(i >= self.win_value for i in row) for row in self.field)
        
        def is_gameover(self):
            return not any(self.move_is_possible(move) for move in actions)
        
    
        
        def draw(self, screen):
            help_string1 = '(W)Up (S)Down (A)Left (D)Right'
            help_string2 = '      (R)Restart (Q)Exit'
            gameover_string = '            GAME OVER'
            win_string = '             YOU WIN!'
            
            def cast(string):
                screen.addstr(string + '
    ')
            
            #绘制水平分割线
            def draw_hor_separator():
                line = '+' + ('+------' * self.width + '+')[1:]
                separator = defaultdict(lambda: line)
                if not hasattr(draw_hor_separator, "counter"):
                    draw_hor_separator.counter = 0
                cast(separator[draw_hor_separator.counter])
                draw_hor_separator.counter += 1
            
            def draw_row(row):
                cast(''.join('|{: ^5} '.format(num) if num > 0 else '|      ' for num in row) + '|')
            
            screen.clear()
            cast('SCORE: ' + str(self.score))
            if 0 != self.highscore:
                cast('HIGHSCORE: ' + str(self.highscore))
            
            for row in self.field:
                draw_hor_separator()
                draw_row(row)
            
            draw_hor_separator()
            
            if self.is_win():
                cast(win_string)
            else:
                if self.is_gameover():
                    cast(gameover_string)
                else:
                    cast(help_string1)
            cast(help_string2)
        def spawn(self): #随机生成一个2或者4
            new_element = 4 if randrange(100) > 89 else 2
            (i,j) = choice([(i,j) for i in range(self.width) for j in range(self.height) if self.field[i][j] == 0])
            self.field[i][j] = new_element
    
        def move_is_possible(self, direction):
            def row_is_left_movable(row):
                def change(i):
                    if row[i] == 0 and row[i + 1] != 0: #可以移动
                        return True
                    if row[i] != 0 and row[i + 1] == row[i]: #可以合并
                        return True
                    return False
                return any(change(i) for i in range(len(row) - 1))
            
            check = {}
            check['Left'] = lambda field: any(row_is_left_movable(row) for row in field)
            check['Right'] = lambda field: check['Left'](invert(field))
            check['Up'] = lambda field: check['Left'](transpose(field))
            check['Down'] = lambda field: check['Right'](transpose(field))
            
            if direction in check:
                return check[direction](self.field)
            else:
                return False
    def main(stdscr):
        
        def init():
            #重置游戏
            game_field.reset()
            return 'Game'
        
        def not_game(state):
            #画出GameOver或者Win的界面
            game_field.draw(stdscr)
            #读取用户输入得到action,判断是重启还是结束游戏
            action = get_user_action(stdscr)
            responses = defaultdict(lambda: state)   #? 默认是当前状态,没有行为就会一直在当前界面循环
            responses['Restart'], responses['Exit'] = 'Init', 'Exit'
            return responses[action]
        
        def game():
            #画出当前棋盘状态
            game_field.draw(stdscr)
            #读取用户输入得到action
            action = get_user_action(stdscr)
            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'
        
        state_actions = {
                'Init': init,
                'Win': lambda: not_game('Win'),
                'Gameover': lambda: not_game('Gameover'),
                'Game': game
            }
        
        curses.use_default_colors()
        game_field = GameField(win=32)
        
        state = 'Init'
        
        #状态机开始循环
        while state != 'Exit':
            state = state_actions[state]()
        
    curses.wrapper(main)
  • 相关阅读:
    session一致性架构设计实践.
    从"嘿,今晚..."谈消息安全传输中的技术点
    跨公网调用的大坑与架构优化方案
    “配置”也有架构演进?看完深有痛感
    TCP接入层的负载均衡、高可用、扩展性架构
    究竟啥才是互联网架构“高并发”
    12.Nodes
    11.Layers, Containers and Interfaces
    10.Nodes and Bindings
    9.Hierarchy Editor
  • 原文地址:https://www.cnblogs.com/dplearning/p/5702063.html
Copyright © 2020-2023  润新知