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

    如何用python写2048

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

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

    来一步步的进行剖析:

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

    1

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

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

    1

    2

    3

    4

    5

    6

    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)如果随机插入数字的位置已经有内容, 如何解决覆盖原有数字的问题

    1

    2

    3

    4

    5

    6

    7

    8

    9

    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)将生成的数据, 通过图像画出来

    1

    2

    3

    4

    5

    6

    7

    8

    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)矩阵的反转

    1

    2

    def invert(field):

        return [row[::-1] for row in field]

    (6)矩阵的转秩

    1

    2

    def transpose(field):

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

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

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    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)判断这个棋盘是否可左右上下移动

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    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)

    棋盘的移动,相加

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    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

    棋盘左右上下移动相加

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    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)判断游戏的胜利与结束

    1

    2

    3

    4

    5

    6

    7

    8

    #判断游戏何时胜利:当棋盘中出现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教程

    下面是完整的代码:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84

    85

    86

    87

    88

    89

    90

    91

    92

    93

    94

    95

    96

    97

    98

    99

    100

    101

    102

    103

    104

    105

    106

    107

    108

    109

    110

    111

    112

    113

    114

    115

    116

    117

    118

    119

    120

    121

    122

    123

    124

    125

    126

    127

    128

    129

    130

    131

    132

    133

    134

    135

    136

    137

    138

    139

    140

    141

    142

    143

    144

    145

    146

    147

    148

    149

    150

    151

    152

    153

    154

    155

    156

    157

    158

    159

    160

    161

    162

    163

    164

    165

    166

    167

    168

    169

    170

    171

    172

    173

    174

    175

    176

    177

    178

    179

    180

    181

    182

    183

    184

    185

    186

    187

    188

    189

    190

    191

    192

    193

    194

    195

    196

    197

    198

    199

    200

    201

    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游戏

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84

    85

    86

    87

    88

    89

    90

    91

    92

    93

    94

    95

    96

    97

    98

    99

    100

    101

    102

    103

    104

    105

    106

    107

    108

    109

    110

    111

    112

    113

    114

    115

    116

    117

    118

    119

    120

    121

    122

    123

    124

    125

    126

    127

    128

    129

    130

    131

    132

    133

    134

    135

    136

    137

    138

    139

    140

    141

    142

    143

    144

    145

    146

    147

    148

    149

    150

    151

    152

    153

    154

    155

    156

    157

    158

    159

    160

    161

    162

    163

    164

    165

    166

    167

    168

    169

    170

    171

    172

    173

    174

    175

    176

    177

    178

    179

    180

    181

    182

    183

    184

    185

    186

    187

    188

    189

    190

    191

    192

    193

    194

    195

    196

    197

    198

    199

    200

    201

    202

    203

    204

    205

    206

    207

    208

    209

    210

    211

    212

    213

    214

    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学习网