Python实现四款经典小游戏合集

这篇文章主要介绍了利用Python编写一个经典小游戏的合集,包括:贪吃蛇,扫雷,俄罗斯方块,五子棋。感兴趣的小伙伴可以跟随小编一起学习一下

目录

  •  一、效果展示
  • 1、俄罗斯方块
  • 2、扫雷
  • 3、五子棋
  • 4、贪吃蛇
  • 二、代码展示
  • 1、俄罗斯方块
  • 2、扫雷
  • 3、五子棋
  • 4、贪吃蛇
  •  一、效果展示

    1、俄罗斯方块

    这个应该是玩起来最最简单的了…

    2、扫雷

    运气好,点了四下都没踩雷哈哈…

    3、五子棋

    我是菜鸡,玩不赢电脑人…

    4、

    4、贪吃蛇

    害,这个是最惊心动魄的,为了我的小心脏,不玩了不玩了…

    女朋友:你就是借机在玩游戏,逮到了

    啊这…

    那我不吹牛逼了,我们来敲代码吧~

    二、代码展示

    1、俄罗斯方块

    方块部分

    这部分代码单独保存py文件,这里我命名为 blocks.py

    方块形状的设计,一开始我是做成 4 × 4,长宽最长都是4的话旋转的时候就不考虑怎么转了,就是从一个图形替换成另一个。

    要实现这个功能,只要固定左上角的坐标就可以了。

    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

    import random

    from collections import namedtuple

    Point = namedtuple('Point', 'X Y')

    Shape = namedtuple('Shape', 'X Y Width Height')

    Block = namedtuple('Block', 'template start_pos end_pos name next')

    # S形方块

    S_BLOCK = [Block(['.OO',

                      'OO.',

                      '...'], Point(0, 0), Point(2, 1), 'S', 1),

               Block(['O..',

                      'OO.',

                      '.O.'], Point(0, 0), Point(1, 2), 'S', 0)]

    # Z形方块

    Z_BLOCK = [Block(['OO.',

                      '.OO',

                      '...'], Point(0, 0), Point(2, 1), 'Z', 1),

               Block(['.O.',

                      'OO.',

                      'O..'], Point(0, 0), Point(1, 2), 'Z', 0)]

    # I型方块

    I_BLOCK = [Block(['.O..',

                      '.O..',

                      '.O..',

                      '.O..'], Point(1, 0), Point(1, 3), 'I', 1),

               Block(['....',

                      '....',

                      'OOOO',

                      '....'], Point(0, 2), Point(3, 2), 'I', 0)]

    # O型方块

    O_BLOCK = [Block(['OO',

                      'OO'], Point(0, 0), Point(1, 1), 'O', 0)]

    # J型方块

    J_BLOCK = [Block(['O..',

                      'OOO',

                      '...'], Point(0, 0), Point(2, 1), 'J', 1),

               Block(['.OO',

                      '.O.',

                      '.O.'], Point(1, 0), Point(2, 2), 'J', 2),

               Block(['...',

                      'OOO',

                      '..O'], Point(0, 1), Point(2, 2), 'J', 3),

               Block(['.O.',

                      '.O.',

                      'OO.'], Point(0, 0), Point(1, 2), 'J', 0)]

    # L型方块

    L_BLOCK = [Block(['..O',

                      'OOO',

                      '...'], Point(0, 0), Point(2, 1), 'L', 1),

               Block(['.O.',

                      '.O.',

                      '.OO'], Point(1, 0), Point(2, 2), 'L', 2),

               Block(['...',

                      'OOO',

                      'O..'], Point(0, 1), Point(2, 2), 'L', 3),

               Block(['OO.',

                      '.O.',

                      '.O.'], Point(0, 0), Point(1, 2), 'L', 0)]

    # T型方块

    T_BLOCK = [Block(['.O.',

                      'OOO',

                      '...'], Point(0, 0), Point(2, 1), 'T', 1),

               Block(['.O.',

                      '.OO',

                      '.O.'], Point(1, 0), Point(2, 2), 'T', 2),

               Block(['...',

                      'OOO',

                      '.O.'], Point(0, 1), Point(2, 2), 'T', 3),

               Block(['.O.',

                      'OO.',

                      '.O.'], Point(0, 0), Point(1, 2), 'T', 0)]

    BLOCKS = {'O': O_BLOCK,

              'I': I_BLOCK,

              'Z': Z_BLOCK,

              'T': T_BLOCK,

              'L': L_BLOCK,

              'S': S_BLOCK,

              'J': J_BLOCK}

    def get_block():

        block_name = random.choice('OIZTLSJ')

        b = BLOCKS[block_name]

        idx = random.randint(0, len(b) - 1)

        return b[idx]

    def get_next_block(block):

        b = BLOCKS[block.name]

        return b[block.next]

    素材 

     

    游戏主代码

    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

    215

    216

    217

    218

    219

    220

    221

    222

    223

    224

    225

    226

    227

    228

    229

    230

    231

    232

    233

    234

    import sys

    import time

    import pygame

    from pygame.locals import *

    import blocks

    SIZE = 30  # 每个小方格大小

    BLOCK_HEIGHT = 25  # 游戏区高度

    BLOCK_WIDTH = 10   # 游戏区宽度

    BORDER_WIDTH = 4   # 游戏区边框宽度

    BORDER_COLOR = (40, 40, 200# 游戏区边框颜色

    SCREEN_WIDTH = SIZE * (BLOCK_WIDTH + 5# 游戏屏幕的宽

    SCREEN_HEIGHT = SIZE * BLOCK_HEIGHT      # 游戏屏幕的高

    BG_COLOR = (40, 40, 60# 背景色

    BLOCK_COLOR = (20, 128, 200#

    BLACK = (0, 0, 0)

    RED = (200, 30, 30)      # GAME OVER 的字体颜色

    def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):

        imgText = font.render(text, True, fcolor)

        screen.blit(imgText, (x, y))

    def main():

        pygame.init()

        screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

        pygame.display.set_caption('俄罗斯方块')

        font1 = pygame.font.SysFont('SimHei', 24# 黑体24

        font2 = pygame.font.Font(None, 72# GAME OVER 的字体

        font_pos_x = BLOCK_WIDTH * SIZE + BORDER_WIDTH + 10  # 右侧信息显示区域字体位置的X坐标

        gameover_size = font2.size('GAME OVER')

        font1_height = int(font1.size('得分')[1])

        cur_block = None   # 当前下落方块

        next_block = None  # 下一个方块

        cur_pos_x, cur_pos_y = 0, 0

        game_area = None    # 整个游戏区域

        game_over = True

        start = False       # 是否开始,当start = True,game_over = True 时,才显示 GAME OVER

        score = 0           # 得分

        orispeed = 0.5      # 原始速度

        speed = orispeed    # 当前速度

        pause = False       # 暂停

        last_drop_time = None   # 上次下落时间

        last_press_time = None  # 上次按键时间

        def _dock():

            nonlocal cur_block, next_block, game_area, cur_pos_x, cur_pos_y, game_over, score, speed

            for _i in range(cur_block.start_pos.Y, cur_block.end_pos.Y + 1):

                for _j in range(cur_block.start_pos.X, cur_block.end_pos.X + 1):

                    if cur_block.template[_i][_j] != '.':

                        game_area[cur_pos_y + _i][cur_pos_x + _j] = '0'

            if cur_pos_y + cur_block.start_pos.Y <= 0:

                game_over = True

            else:

                # 计算消除

                remove_idxs = []

                for _i in range(cur_block.start_pos.Y, cur_block.end_pos.Y + 1):

                    if all(_x == '0' for _x in game_area[cur_pos_y + _i]):

                        remove_idxs.append(cur_pos_y + _i)

                if remove_idxs:

                    # 计算得分

                    remove_count = len(remove_idxs)

                    if remove_count == 1:

                        score += 100

                    elif remove_count == 2:

                        score += 300

                    elif remove_count == 3:

                        score += 700

                    elif remove_count == 4:

                        score += 1500

                    speed = orispeed - 0.03 * (score // 10000)

                    # 消除

                    _i = _j = remove_idxs[-1]

                    while _i >= 0:

                        while _j in remove_idxs:

                            _j -= 1

                        if _j < 0:

                            game_area[_i] = ['.'] * BLOCK_WIDTH

                        else:

                            game_area[_i] = game_area[_j]

                        _i -= 1

                        _j -= 1

                cur_block = next_block

                next_block = blocks.get_block()

                cur_pos_x, cur_pos_y = (BLOCK_WIDTH - cur_block.end_pos.X - 1) // 2, -1 - cur_block.end_pos.Y

        def _judge(pos_x, pos_y, block):

            nonlocal game_area

            for _i in range(block.start_pos.Y, block.end_pos.Y + 1):

                if pos_y + block.end_pos.Y >= BLOCK_HEIGHT:

                    return False

                for _j in range(block.start_pos.X, block.end_pos.X + 1):

                    if pos_y + _i >= 0 and block.template[_i][_j] != '.' and game_area[pos_y + _i][pos_x + _j] != '.':

                        return False

            return True

        while True:

            for event in pygame.event.get():

                if event.type == QUIT:

                    sys.exit()

                elif event.type == KEYDOWN:

                    if event.key == K_RETURN:

                        if game_over:

                            start = True

                            game_over = False

                            score = 0

                            last_drop_time = time.time()

                            last_press_time = time.time()

                            game_area = [['.'] * BLOCK_WIDTH for _ in range(BLOCK_HEIGHT)]

                            cur_block = blocks.get_block()

                            next_block = blocks.get_block()

                            cur_pos_x, cur_pos_y = (BLOCK_WIDTH - cur_block.end_pos.X - 1) // 2, -1 - cur_block.end_pos.Y

                    elif event.key == K_SPACE:

                        if not game_over:

                            pause = not pause

                    elif event.key in (K_w, K_UP):

                        if 0 <= cur_pos_x <= BLOCK_WIDTH - len(cur_block.template[0]):

                            _next_block = blocks.get_next_block(cur_block)

                            if _judge(cur_pos_x, cur_pos_y, _next_block):

                                cur_block = _next_block

            if event.type == pygame.KEYDOWN:

                if event.key == pygame.K_LEFT:

                    if not game_over and not pause:

                        if time.time() - last_press_time > 0.1:

                            last_press_time = time.time()

                            if cur_pos_x > - cur_block.start_pos.X:

                                if _judge(cur_pos_x - 1, cur_pos_y, cur_block):

                                    cur_pos_x -= 1

                if event.key == pygame.K_RIGHT:

                    if not game_over and not pause:

                        if time.time() - last_press_time > 0.1:

                            last_press_time = time.time()

                            # 不能移除右边框

                            if cur_pos_x + cur_block.end_pos.X + 1 < BLOCK_WIDTH:

                                if _judge(cur_pos_x + 1, cur_pos_y, cur_block):

                                    cur_pos_x += 1

                if event.key == pygame.K_DOWN:

                    if not game_over and not pause:

                        if time.time() - last_press_time > 0.1:

                            last_press_time = time.time()

                            if not _judge(cur_pos_x, cur_pos_y + 1, cur_block):

                                _dock()

                            else:

                                last_drop_time = time.time()

                                cur_pos_y += 1

            _draw_background(screen)

            _draw_game_area(screen, game_area)

            _draw_gridlines(screen)

            _draw_info(screen, font1, font_pos_x, font1_height, score)

            # 画显示信息中的下一个方块

            _draw_block(screen, next_block, font_pos_x, 30 + (font1_height + 6) * 5, 0, 0)

            if not game_over:

                cur_drop_time = time.time()

                if cur_drop_time - last_drop_time > speed:

                    if not pause:

                        if not _judge(cur_pos_x, cur_pos_y + 1, cur_block):

                            _dock()

                        else:

                            last_drop_time = cur_drop_time

                            cur_pos_y += 1

            else:

                if start:

                    print_text(screen, font2,

                               (SCREEN_WIDTH - gameover_size[0]) // 2, (SCREEN_HEIGHT - gameover_size[1]) // 2,

                               'GAME OVER', RED)

            # 画当前下落方块

            _draw_block(screen, cur_block, 0, 0, cur_pos_x, cur_pos_y)

            pygame.display.flip()

    # 画背景

    def _draw_background(screen):

        # 填充背景色

        screen.fill(BG_COLOR)

        # 画游戏区域分隔线

        pygame.draw.line(screen, BORDER_COLOR,

                         (SIZE * BLOCK_WIDTH + BORDER_WIDTH // 2, 0),

                         (SIZE * BLOCK_WIDTH + BORDER_WIDTH // 2, SCREEN_HEIGHT), BORDER_WIDTH)

    # 画网格线

    def _draw_gridlines(screen):

        # 画网格线 竖线

        for x in range(BLOCK_WIDTH):

            pygame.draw.line(screen, BLACK, (x * SIZE, 0), (x * SIZE, SCREEN_HEIGHT), 1)

        # 画网格线 横线

        for y in range(BLOCK_HEIGHT):

            pygame.draw.line(screen, BLACK, (0, y * SIZE), (BLOCK_WIDTH * SIZE, y * SIZE), 1)

    # 画已经落下的方块

    def _draw_game_area(screen, game_area):

        if game_area:

            for i, row in enumerate(game_area):

                for j, cell in enumerate(row):

                    if cell != '.':

                        pygame.draw.rect(screen, BLOCK_COLOR, (j * SIZE, i * SIZE, SIZE, SIZE), 0)

    # 画单个方块

    def _draw_block(screen, block, offset_x, offset_y, pos_x, pos_y):

        if block:

            for i in range(block.start_pos.Y, block.end_pos.Y + 1):

                for j in range(block.start_pos.X, block.end_pos.X + 1):

                    if block.template[i][j] != '.':

                        pygame.draw.rect(screen, BLOCK_COLOR,

                                         (offset_x + (pos_x + j) * SIZE, offset_y + (pos_y + i) * SIZE, SIZE, SIZE), 0)

    # 画得分等信息

    def _draw_info(screen, font, pos_x, font_height, score):

        print_text(screen, font, pos_x, 10, f'得分: ')

        print_text(screen, font, pos_x, 10 + font_height + 6, f'{score}')

        print_text(screen, font, pos_x, 20 + (font_height + 6) * 2, f'速度: ')

        print_text(screen, font, pos_x, 20 + (font_height + 6) * 3, f'{score // 10000}')

        print_text(screen, font, pos_x, 30 + (font_height + 6) * 4, f'下一个:')

    if __name__ == '__main__':

        main()

    2、扫雷

    地雷部分

    一样的,单独保存py文件,mineblock.py

    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

    import random

    from enum import Enum

    BLOCK_WIDTH = 30

    BLOCK_HEIGHT = 16

    SIZE = 20           # 块大小

    MINE_COUNT = 99     # 地雷数

    class BlockStatus(Enum):

        normal = 1  # 未点击

        opened = 2  # 已点击

        mine = 3    # 地雷

        flag = 4    # 标记为地雷

        ask = 5     # 标记为问号

        bomb = 6    # 踩中地雷

        hint = 7    # 被双击的周围

        double = 8  # 正被鼠标左右键双击

    class Mine:

        def __init__(self, x, y, value=0):

            self._x = x

            self._y = y

            self._value = 0

            self._around_mine_count = -1

            self._status = BlockStatus.normal

            self.set_value(value)

        def __repr__(self):

            return str(self._value)

            # return f'({self._x},{self._y})={self._value}, status={self.status}'

        def get_x(self):

            return self._x

        def set_x(self, x):

            self._x = x

        x = property(fget=get_x, fset=set_x)

        def get_y(self):

            return self._y

        def set_y(self, y):

            self._y = y

        y = property(fget=get_y, fset=set_y)

        def get_value(self):

            return self._value

        def set_value(self, value):

            if value:

                self._value = 1

            else:

                self._value = 0

        value = property(fget=get_value, fset=set_value, doc='0:非地雷 1:雷')

        def get_around_mine_count(self):

            return self._around_mine_count

        def set_around_mine_count(self, around_mine_count):

            self._around_mine_count = around_mine_count

        around_mine_count = property(fget=get_around_mine_count, fset=set_around_mine_count, doc='四周地雷数量')

        def get_status(self):

            return self._status

        def set_status(self, value):

            self._status = value

        status = property(fget=get_status, fset=set_status, doc='BlockStatus')

    class MineBlock:

        def __init__(self):

            self._block = [[Mine(i, j) for i in range(BLOCK_WIDTH)] for j in range(BLOCK_HEIGHT)]

            # 埋雷

            for i in random.sample(range(BLOCK_WIDTH * BLOCK_HEIGHT), MINE_COUNT):

                self._block[i // BLOCK_WIDTH][i % BLOCK_WIDTH].value = 1

        def get_block(self):

            return self._block

        block = property(fget=get_block)

        def getmine(self, x, y):

            return self._block[y][x]

        def open_mine(self, x, y):

            # 踩到雷了

            if self._block[y][x].value:

                self._block[y][x].status = BlockStatus.bomb

                return False

            # 先把状态改为 opened

            self._block[y][x].status = BlockStatus.opened

            around = _get_around(x, y)

            _sum = 0

            for i, j in around:

                if self._block[j][i].value:

                    _sum += 1

            self._block[y][x].around_mine_count = _sum

            # 如果周围没有雷,那么将周围8个未中未点开的递归算一遍

            # 这就能实现一点出现一大片打开的效果了

            if _sum == 0:

                for i, j in around:

                    if self._block[j][i].around_mine_count == -1:

                        self.open_mine(i, j)

            return True

        def double_mouse_button_down(self, x, y):

            if self._block[y][x].around_mine_count == 0:

                return True

            self._block[y][x].status = BlockStatus.double

            around = _get_around(x, y)

            sumflag = 0     # 周围被标记的雷数量

            for i, j in _get_around(x, y):

                if self._block[j][i].status == BlockStatus.flag:

                    sumflag += 1

            # 周边的雷已经全部被标记

            result = True

            if sumflag == self._block[y][x].around_mine_count:

                for i, j in around:

                    if self._block[j][i].status == BlockStatus.normal:

                        if not self.open_mine(i, j):

                            result = False

            else:

                for i, j in around:

                    if self._block[j][i].status == BlockStatus.normal:

                        self._block[j][i].status = BlockStatus.hint

            return result

        def double_mouse_button_up(self, x, y):

            self._block[y][x].status = BlockStatus.opened

            for i, j in _get_around(x, y):

                if self._block[j][i].status == BlockStatus.hint:

                    self._block[j][i].status = BlockStatus.normal

    def _get_around(x, y):

        """返回(x, y)周围的点的坐标"""

        # 这里注意,range 末尾是开区间,所以要加 1

        return [(i, j) for i in range(max(0, x - 1), min(BLOCK_WIDTH - 1, x + 1) + 1)

                for j in range(max(0, y - 1), min(BLOCK_HEIGHT - 1, y + 1) + 1) if i != x or j != y]

    以上就是Python实现四个经典小游戏合集的详细内容

    在这里还是要推荐下我自己建的Python学习Q群:831804576,群里都是学Python的,如果你想学或者正在学习Python ,欢迎你加入,大家都是软件开发党,不定期分享干货(只有Python软件开发相关的),
    包括我自己整理的一份2021最新的Python进阶资料和零基础教学,欢迎进阶中和对Python感兴趣的小伙伴加入!

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python实现四款经典小游戏合集

    发表评论