• 技术文章 >Python技术 >Python基础教程

    如何用python写2048

    爱喝马黛茶的安东尼爱喝马黛茶的安东尼2019-10-11 14:01:04原创6364

    2048游戏规则:简单的移动方向键让数字叠加,并且获得这些数字每次叠加后的得分,当出现2048这个数字时游戏胜利。同时每次移动方向键时,都会在这个4*4的方格矩阵的空白区域随机产生一个数字2或者4,如果方格被数字填满了,那么就GameOver了。

    来一步步的进行剖析:

    (1)生成4*4的棋盘, 其中数据结构为列表嵌套列表

    field = [[0 for j in range(4)] for i in range(4)]

    (2)创建函数random_create, 在棋盘的一个随机位置插入一个数字2或者4,其中2的几率大

    import random
    def random_create():
        i = random.choice(range(4))
        j = random.choice(range(4))
        value = random.choice([2,2,2,4])
        field[i][j] = value

    (3)如果随机插入数字的位置已经有内容, 如何解决覆盖原有数字的问题

    def random_creat():
        while True:
            i = random.choice(range(4))
            j = random.choice(range(4))
            if li[i][j] == 0:
                li[i][j] = 4 if random.randint(1, 100) > 80 else 2
                break
    random_creat()
    random_creat()

    (4)将生成的数据, 通过图像画出来

    def draw_sep():
        print('+-----' * 4 + '+')
    def draw_num(row):
        print(''.join('|{:^5}'.format(num) if num != 0 else '|     ' for num in row) + '|')
    for row in li:
        draw_sep()
        draw_num(row)
    draw_sep()

    (5)矩阵的反转

    def invert(field):
        return [row[::-1] for row in field]

    (6)矩阵的转秩

    def transpose(field):
        return [list(row) for row in zip(*field)]

    (7)判断棋盘是否可移动

    def is_row_change(row):
        # row
        # 判断一行内容是否可以移动
        def is_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
            else:
                return False
        return any([is_change(index) for index in range(len(row) - 1)])

    (8)判断这个棋盘是否可左右上下移动

    def is_move_left(field):
        return any([is_row_change(row) for row in field])
    def is_move_right(field):
        #  对于列表元素进行反转
        field = invert(field)
        print(field)
        return is_move_left(field)
    def is_move_up(field):
        # 对于列表元素进行转置
        field = transpose(field)
        return is_move_left(field)
    def is_move_down(field):
        # 反转+ 转置
        field = transpose(field)
        return is_move_right(field)

    棋盘的移动,相加

    def tight(row):   # [2, 0, 2, 0]
    # 最快的方式, 通过排序实现...........
        return sorted(row, key=lambda x: if  x == 0 )
    score = 0
    # 相加
    def merge(row): # [2,2,0,0]
        # [0,1,2]
        for i in range(len(row)-1):
    # 如果两个值相等, 前一个元素*2, 后一个元素改为0。
            if row[i] == row[i+1]:
                row[i] *= 2
                row[i+1] = 0
    # 如果覆盖成功, 就给得分
                global score
                score += row[i]
        return row

    棋盘左右上下移动相加

    def move_row_left(self, row):
        return self.tight(self.merge(self.tight(row)))
    def move_left(self, field):
        return [self.move_row_left(row) for row in field]
    def move_right(self, field):
        field = self.invert(field)
        return self.invert([self.move_row_left(row) for row in field])
    def move_up(self, field):
        return self.transpose([self.move_row_left(row) for row in self.transpose(field)])
    def move_down(self, field):
        return self.invert(self.transpose([self.move_row_left(row)
            for row in self.invert(self.transpose(field))]))

    (9)判断游戏的胜利与结束

    #判断游戏何时胜利:当棋盘中出现2048时,就代表着游戏胜利
    def victory(field):
        li = [y for row in li for y in row]
        if max(li) >= 2048:
            print('Victory')
    def game_over(filed):
        if all((is_move_left(filed), is_move_right(filed), is_move_up(filed), is_move_down(filed))) == False:
            print('Game Over')

    这样程序的各个部分就写好了,将各个部分封装到一个类里面,再导入curses模块来控制游戏,就可以了。

    相关推荐:《Python教程

    下面是完整的代码:

    import curses
    from itertools import chain
    from random import choice
    class GameField(object):
        # 初始化信息
        def __init__(self, width=4, height=4, win_value=8):
            self.width = width
            self.height = height
            self.win_value = win_value
            self.score = 0  # 当前得分
            self.highscore = 0  # 最高分
            self.moves = {}
            self.moves['Left'] = self.is_move_left
            self.moves['Right'] = self.is_move_right
            self.moves['Down'] = self.is_move_down
            self.moves['Up'] = self.is_move_up
            self.movesDict = {}
            self.movesDict['Left'] = self.move_left
            self.movesDict['Right'] = self.move_right
            self.movesDict['Down'] = self.move_down
            self.movesDict['Up'] = self.move_up
        def reset(self):  # 重置棋盘
            if self.score > self.highscore:
                self.highscore = self.score  # 更新最高分
            self.score = 0
            # 需求1: 生成4*4的棋盘, 其中数据结构选择列表嵌套列表;
            self.field = [[0 for j in range(self.width)]
                          for i in range(self.height)]
            # 在棋盘的一个随机位置插入一个数字2或者4
            self.random_create()
            self.random_create()
        def random_create(self):
            # 在棋盘的一个随机位置插入一个数字2或者4
            # field[0][3] = 2
            while True:
                i, j = choice(range(self.height)), choice(range(self.width))
                if self.field[i][j] == 0:
                    self.field[i][j] = choice([2, 2, 2, 4])
                    break
        def draw(self, stdscr):
            def draw_sep():
                stdscr.addstr('+' + "-----+" * self.width + '\n')
            def draw_one_row(row):
                stdscr.addstr("".join('|{:^5}'.format(num) if num != 0 else "|   " for num in row) + '|' + '\n')
            # 清屏
            stdscr.clear()
            stdscr.addstr("2048".center(50, '-') + '\n')
            stdscr.addstr("当前分数:" + str(self.score) + '\n')
            if self.highscore != 0:
                stdscr.addstr("最高分:" + str(self.highscore) + '\n')
            for row in self.field:
                draw_sep()
                draw_one_row(row)
            draw_sep()
            # 判断是否赢或者输
            if self.is_win():
                stdscr.addstr("胜利!!!!" + '\n')
            if self.is_gameover():
                stdscr.addstr("游戏结束!!!!" + '\n')
            stdscr.addstr(" 游戏帮助: 上下左右键  (R)Restart     Q(Quit)")
        def is_win(self):
            return max(chain(*self.field)) >= self.win_value
        def is_gameover(self):
            # 任何方向都不能移动的时候, 游戏结束
            return not any([self.move_is_possible(direction)
                            for direction in self.moves])
        @staticmethod
        def invert(field):
            # 矩阵进行反转
            return [row[::-1] for row in field]
            # print(invert(li))
        @staticmethod
        # 矩阵的转置
        def transpose(field):
            return [list(row) for row in zip(*field)]
        @staticmethod
        def is_row_change(row):
            # row
            # 需求3. 判断一行内容是否可移动。
            def is_change(i):  # 0
                # 判断每两个元素之间是否可移动
                if row[i] == 0 and row[i + 1] != 0:
                    return True
                if row[i] != 0 and row[i] == row[i + 1]:
                    return True
                return False
            return any([is_change(index) for index in range(len(row) - 1)])
        # 判断这个棋盘是否可向左移动
        def is_move_left(self, field):
            return any([self.is_row_change(row) for row in field])
        def is_move_right(self, field):
            #  对于列表元素进行反转
            field = self.invert(field)
            print(field)
            return self.is_move_left(field)
        def is_move_up(self, field):
            # 对于列表元素进行转置
            field = self.transpose(field)
            return self.is_move_left(field)
        def is_move_down(self, field):
            # 反转+ 转置
            field = self.transpose(field)
            return self.is_move_right(field)
        def move_is_possible(self, direction):  # 'left'
            # 判断用户选择的方向是否可移动
            if direction in self.moves:
                return self.moves[direction](self.field)
            else:
                return False
        # 将棋盘每一行的非0数向前移动, 0向后移动;
        @staticmethod
        def tight(row):  # [2, 0, 2, 0]
            # 最快的方式, 通过排序实现...........
            return sorted(row, key=lambda x: 1 if x == 0 else 0)
        def merge(self, row):  # [2,2,0,0]
            # [0,1,2]
            for i in range(len(row) - 1):
                # 如果两个值相等, 前一个元素*2, 后一个元素改为0。
                if row[i] == row[i + 1]:
                    row[i] *= 2
                    row[i + 1] = 0
                    # 如果覆盖成功, 就给得分
                    self.score += row[i]
            return row  # [4, 0, 0, 0]
        def move_row_left(self, row):
            return self.tight(self.merge(self.tight(row)))
        def move_left(self, field):
            return [self.move_row_left(row) for row in field]
        def move_right(self, field):
            field = self.invert(field)
            return self.invert([self.move_row_left(row) for row in field])
        def move_up(self, field):
            return self.transpose([self.move_row_left(row) for row in self.transpose(field)])
        def move_down(self, field):
            return self.invert(self.transpose([self.move_row_left(row)
                for row in self.invert(self.transpose(field))]))
        def move(self, direction):  # 'left'
            # 判断用户选择的方向是否可移动
            if direction in self.movesDict:
                # 判断是否可移动
                if self.move_is_possible(direction):
                    self.field = self.movesDict[direction](self.field)
                    self.random_create()
                    return True
            else:
                return False
    def get_user_action(stdscr):
        action = stdscr.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(stdscr):
        action = stdscr.getch()
        def init():
            # 初始化棋盘的操作
            game_field.reset()
            game_field.draw(stdscr)
            return 'Game'
        def game():
            game_field.draw(stdscr)
            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'
        def not_game():
            game_field.draw(stdscr)
            while True:
                action = get_user_action(stdscr)
                if action == 'Restart':
                    return 'Init'
                if action == 'Exit':
                    return 'Exit'
        state_actions = {
            'Init': init,
            'Game': game,
            'Win': not_game,
            'GameOver': not_game,
        }
        game_field = GameField()
        state = 'Init'
        # 如果当前状态不是退出, 那么一直执行
        while state != 'Exit':
            # 执行当前状态需要操作的内容, 并返回, 下一次的状态为什么.
            state = state_actions[state]()
    curses.wrapper(main)

    实现双人版的2048游戏

    import curses
    import random
    from itertools import chain
    class GameField(object):
        def __init__(self, width=4, height=4, win_value=2048):
            self.width = width
            self.height = height
            self.win_value = win_value
            self.score1 = 0
            self.score2 = 0
            self.highscore = 0
            self.moves = {}
            self.moves['Left1'] = self.is_left_move
            self.moves['Right1'] = self.is_right_move
            self.moves['Up1'] = self.is_up_move
            self.moves['Down1'] = self.is_down_move
            self.moves['Left2'] = self.is_left_move
            self.moves['Right2'] = self.is_right_move
            self.moves['Up2'] = self.is_up_move
            self.moves['Down2'] = self.is_down_move
            self.movesDict1 = {}
            self.movesDict2 = {}
            self.movesDict1['Left1'] = self.left_move
            self.movesDict1['Right1'] = self.right_move
            self.movesDict1['Up1'] = self.up_move
            self.movesDict1['Down1'] = self.down_move
            self.movesDict2['Left2'] = self.left_move
            self.movesDict2['Right2'] = self.right_move
            self.movesDict2['Up2'] = self.up_move
            self.movesDict2['Down2'] = self.down_move
        def random_create1(self):
            while True:
                i, j = random.randint(0, self.height - 1), random.randint(0, self.width - 1)
                if self.field1[i][j] == 0:
                    self.field1[i][j] = random.choice([2, 2, 2, 4])
                    break
        def random_create2(self):
            while True:
                i, j = random.randint(0, self.height - 1), random.randint(0, self.width - 1)
                if self.field2[i][j] == 0:
                    self.field2[i][j] = random.choice([2, 2, 2, 4])
                    break
        def reset(self):
            self.field1 = [[0 for j in range(self.width)] for i in range(self.height)]
            self.score1 = 0
            self.field2 = [[0 for j in range(self.width)] for i in range(self.height)]
            self.score2 = 0
            self.random_create1()
            self.random_create1()
            self.random_create2()
            self.random_create2()
        def draw(self, stdscr):
            stdscr.clear()
            self.score1 = sum(chain(*self.field1))
            self.score2 = sum(chain(*self.field2))
            if max(self.score1, self.score2) > self.highscore:
                self.highscore = max(self.score1, self.score2)
            stdscr.addstr('最高分:' + str(self.highscore) + ' ')
            stdscr.addstr('玩家1分数:' + str(self.score1) + ' ')
            stdscr.addstr('玩家2分数:' + str(self.score2) + '\n')
            for row in self.field1:
                stdscr.addstr('+' + '-----+' * self.width + '\n')
                stdscr.addstr("".join('|{:^5}'.format(num) if num != 0 else "|    " for num in row) + '|' + '\n')
            stdscr.addstr('+' + '-----+' * self.width + '\n')
            if self.is_win1():
                stdscr.addstr('胜利\n')
            if self.is_gameover1():
                stdscr.addstr('游戏结束\n')
            for row in self.field2:
                stdscr.addstr('+' + '-----+' * self.width + '\n')
                stdscr.addstr("".join('|{:^5}'.format(num) if num != 0 else "|    " for num in row) + '|' + '\n')
            stdscr.addstr('+' + '-----+' * self.width + '\n')
            if self.is_win2():
                stdscr.addstr('胜利\n')
            if self.is_gameover2():
                stdscr.addstr('游戏结束\n')
            stdscr.addstr("玩家1:上下左右键 玩家2:wasd键(R)重置(Q)退出")
        def is_win1(self):
            return max(chain(*self.field1)) >= self.win_value
        def is_win2(self):
            return max(chain(*self.field2)) >= self.win_value
        def is_gameover1(self):
            return not any([self.is_move_possible1(direction) for direction in self.moves])
        def is_gameover2(self):
            return not any([self.is_move_possible2(direction) for direction in self.moves])
        @staticmethod
        def invert(field):
            return [row[::-1] for row in field]
        @staticmethod
        def transpose(field):
            return [list(row) for row in zip(*field)]
        @staticmethod
        def is_row_change(row):
            for i in range(len(row) - 1):
                if row[i] == 0 and row[i + 1] != 0:
                    return True
                elif row[i] != 0 and row[i] == row[i + 1]:
                    return True
            else:
                return False
        def is_left_move(self, field):
            return any([self.is_row_change(i) for i in field])
        def is_right_move(self, field):
            return any([self.is_row_change(i) for i in self.invert(field)])
        def is_up_move(self, field):
            return any([self.is_row_change(i) for i in self.transpose(field)])
        def is_down_move(self, field):
            return any([self.is_row_change(i) for i in self.invert(self.transpose(field))])
        def is_move_possible1(self, direction):
            if direction in self.moves:
                return self.moves[direction](self.field1)
            else:
                return False
        def is_move_possible2(self, direction):
            if direction in self.moves:
                return self.moves[direction](self.field2)
            else:
                return False
        @staticmethod
        def row_move(row):
            row = sorted(row, key=lambda x: 1 if x == 0 else 0)
            for i in range(len(row) - 1):
                if row[i] == row[i + 1]:
                    row[i] *= 2
                    row[i + 1] = 0
            return sorted(row, key=lambda x: 1 if x == 0 else 0)
        def left_move(self, field):
            return [self.row_move(i) for i in field]
        def right_move(self, field):
            return self.invert([self.row_move(i) for i in self.invert(field)])
        def up_move(self, field):
            return self.transpose([self.row_move(i) for i in self.transpose(field)])
        def down_move(self, field):
            return self.transpose(self.invert([self.row_move(i) for i in self.invert(self.transpose(field))]))
        def move1(self, direction):
            if direction in self.movesDict1 and self.is_move_possible1(direction):
                self.field1 = self.movesDict1[direction](self.field1)
                self.random_create1()
                return True
            else:
                return False
        def move2(self, direction):
            if direction in self.movesDict2 and self.is_move_possible2(direction):
                self.field2 = self.movesDict2[direction](self.field2)
                self.random_create2()
                return True
            else:
                return False
    def get_user_action(stdscr):
        action = stdscr.getch()
        if action == curses.KEY_UP:
            return 'Up1'
        elif action == curses.KEY_DOWN:
            return 'Down1'
        elif action == curses.KEY_LEFT:
            return 'Left1'
        elif action == curses.KEY_RIGHT:
            return 'Right1'
        elif action == ord('r'):
            return 'Restart'
        elif action == ord('q'):
            return 'Exit'
        elif action == ord('w'):
            return 'Up2'
        elif action == ord('s'):
            return 'Down2'
        elif action == ord('a'):
            return 'Left2'
        elif action == ord('d'):
            return 'Right2'
    def main(stdscr):
        def init():
            game_field.reset()
            game_field.draw(stdscr)
            return 'Game'
        def game():
            game_field.draw(stdscr)
            action = get_user_action(stdscr)
            if action == 'Restart':
                return 'Init'
            if action == 'Exit':
                return 'Exit'
            if action in ('Up1', 'Down1', 'Left1', 'Right1'):
                if game_field.move1(action):
                    if game_field.is_win1():
                        return 'Win'
                    if game_field.is_gameover1():
                        return 'GameOver'
            if action in ('Up2', 'Down2', 'Left2', 'Right2'):
                if game_field.move2(action):
                    if game_field.is_win2():
                        return 'Win'
                    if game_field.is_gameover2():
                        return 'GameOver'
            return 'Game'
        def not_game():
            game_field.draw(stdscr)
            while True:
                action = get_user_action(stdscr)
                if action == 'Restart':
                    return 'Init'
                if action == 'Exit':
                    return 'Exit'
        game_field = GameField()
        state = 'Init'
        state_actions = {
            'Init': init,
            'Game': game,
            'Win': not_game,
            'GameOver': not_game
        }
        while state != 'Exit':
            state = state_actions[state]()
    curses.wrapper(main)
    专题推荐:python 2048
    上一篇:有哪些python写的游戏 下一篇:如何用Python求素数之和

    相关文章推荐

    • 什么是网络协议• python中的去除重复项的操作• python中少见的函数map()和partial()• python的sort()排序方法• Python中的文件读写-理论知识

    全部评论我要评论

    © 2021 Python学习网 苏ICP备2021003149号-1

  • 取消发布评论
  • 

    Python学习网