千家信息网

Python实现四个经典小游戏的示例分析

发表于:2024-10-24 作者:千家信息网编辑
千家信息网最后更新 2024年10月24日,本篇文章给大家分享的是有关Python实现四个经典小游戏的示例分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。一、效果展示1、俄罗斯方
千家信息网最后更新 2024年10月24日Python实现四个经典小游戏的示例分析

本篇文章给大家分享的是有关Python实现四个经典小游戏的示例分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

一、效果展示

1、俄罗斯方块

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

2、扫雷

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

3、五子棋

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

4、贪吃蛇

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

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

啊这…

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

二、代码展示

1、俄罗斯方块

方块部分

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

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

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

import randomfrom collections import namedtuplePoint = 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]

游戏主代码

import sysimport timeimport pygamefrom pygame.locals import *import blocksSIZE = 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

import randomfrom enum import EnumBLOCK_WIDTH = 30BLOCK_HEIGHT = 16SIZE = 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.normaldef _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]

素材

主代码

import sysimport timefrom enum import Enumimport pygamefrom pygame.locals import *from mineblock import *# 游戏屏幕的宽SCREEN_WIDTH = BLOCK_WIDTH * SIZE# 游戏屏幕的高SCREEN_HEIGHT = (BLOCK_HEIGHT + 2) * SIZEclass GameStatus(Enum):    readied = 1,    started = 2,    over = 3,    win = 4def 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.Font('resources/a.TTF', SIZE * 2)  # 得分的字体    fwidth, fheight = font1.size('999')    red = (200, 40, 40)    # 加载资源图片,因为资源文件大小不一,所以做了统一的缩放处理    img0 = pygame.image.load('resources/0.bmp').convert()    img0 = pygame.transform.smoothscale(img0, (SIZE, SIZE))    img1 = pygame.image.load('resources/1.bmp').convert()    img1 = pygame.transform.smoothscale(img1, (SIZE, SIZE))    img2 = pygame.image.load('resources/2.bmp').convert()    img2 = pygame.transform.smoothscale(img2, (SIZE, SIZE))    img3 = pygame.image.load('resources/3.bmp').convert()    img3 = pygame.transform.smoothscale(img3, (SIZE, SIZE))    img4 = pygame.image.load('resources/4.bmp').convert()    img4 = pygame.transform.smoothscale(img4, (SIZE, SIZE))    img5 = pygame.image.load('resources/5.bmp').convert()    img5 = pygame.transform.smoothscale(img5, (SIZE, SIZE))    img6 = pygame.image.load('resources/6.bmp').convert()    img6 = pygame.transform.smoothscale(img6, (SIZE, SIZE))    img7 = pygame.image.load('resources/7.bmp').convert()    img7 = pygame.transform.smoothscale(img7, (SIZE, SIZE))    img8 = pygame.image.load('resources/8.bmp').convert()    img8 = pygame.transform.smoothscale(img8, (SIZE, SIZE))    img_blank = pygame.image.load('resources/blank.bmp').convert()    img_blank = pygame.transform.smoothscale(img_blank, (SIZE, SIZE))    img_flag = pygame.image.load('resources/flag.bmp').convert()    img_flag = pygame.transform.smoothscale(img_flag, (SIZE, SIZE))    img_ask = pygame.image.load('resources/ask.bmp').convert()    img_ask = pygame.transform.smoothscale(img_ask, (SIZE, SIZE))    img_mine = pygame.image.load('resources/mine.bmp').convert()    img_mine = pygame.transform.smoothscale(img_mine, (SIZE, SIZE))    img_blood = pygame.image.load('resources/blood.bmp').convert()    img_blood = pygame.transform.smoothscale(img_blood, (SIZE, SIZE))    img_error = pygame.image.load('resources/error.bmp').convert()    img_error = pygame.transform.smoothscale(img_error, (SIZE, SIZE))    face_size = int(SIZE * 1.25)    img_face_fail = pygame.image.load('resources/face_fail.bmp').convert()    img_face_fail = pygame.transform.smoothscale(img_face_fail, (face_size, face_size))    img_face_normal = pygame.image.load('resources/face_normal.bmp').convert()    img_face_normal = pygame.transform.smoothscale(img_face_normal, (face_size, face_size))    img_face_success = pygame.image.load('resources/face_success.bmp').convert()    img_face_success = pygame.transform.smoothscale(img_face_success, (face_size, face_size))    face_pos_x = (SCREEN_WIDTH - face_size) // 2    face_pos_y = (SIZE * 2 - face_size) // 2    img_dict = {        0: img0,        1: img1,        2: img2,        3: img3,        4: img4,        5: img5,        6: img6,        7: img7,        8: img8    }    bgcolor = (225, 225, 225)   # 背景色    block = MineBlock()    game_status = GameStatus.readied    start_time = None   # 开始时间    elapsed_time = 0    # 耗时    while True:        # 填充背景色        screen.fill(bgcolor)        for event in pygame.event.get():            if event.type == QUIT:                sys.exit()            elif event.type == MOUSEBUTTONDOWN:                mouse_x, mouse_y = event.pos                x = mouse_x // SIZE                y = mouse_y // SIZE - 2                b1, b2, b3 = pygame.mouse.get_pressed()                if game_status == GameStatus.started:                    # 鼠标左右键同时按下,如果已经标记了所有雷,则打开周围一圈                    # 如果还未标记完所有雷,则有一个周围一圈被同时按下的效果                    if b1 and b3:                        mine = block.getmine(x, y)                        if mine.status == BlockStatus.opened:                            if not block.double_mouse_button_down(x, y):                                game_status = GameStatus.over            elif event.type == MOUSEBUTTONUP:                if y < 0:                    if face_pos_x <= mouse_x <= face_pos_x + face_size \                            and face_pos_y <= mouse_y <= face_pos_y + face_size:                        game_status = GameStatus.readied                        block = MineBlock()                        start_time = time.time()                        elapsed_time = 0                        continue                if game_status == GameStatus.readied:                    game_status = GameStatus.started                    start_time = time.time()                    elapsed_time = 0                if game_status == GameStatus.started:                    mine = block.getmine(x, y)                    if b1 and not b3:       # 按鼠标左键                        if mine.status == BlockStatus.normal:                            if not block.open_mine(x, y):                                game_status = GameStatus.over                    elif not b1 and b3:     # 按鼠标右键                        if mine.status == BlockStatus.normal:                            mine.status = BlockStatus.flag                        elif mine.status == BlockStatus.flag:                            mine.status = BlockStatus.ask                        elif mine.status == BlockStatus.ask:                            mine.status = BlockStatus.normal                    elif b1 and b3:                        if mine.status == BlockStatus.double:                            block.double_mouse_button_up(x, y)        flag_count = 0        opened_count = 0        for row in block.block:            for mine in row:                pos = (mine.x * SIZE, (mine.y + 2) * SIZE)                if mine.status == BlockStatus.opened:                    screen.blit(img_dict[mine.around_mine_count], pos)                    opened_count += 1                elif mine.status == BlockStatus.double:                    screen.blit(img_dict[mine.around_mine_count], pos)                elif mine.status == BlockStatus.bomb:                    screen.blit(img_blood, pos)                elif mine.status == BlockStatus.flag:                    screen.blit(img_flag, pos)                    flag_count += 1                elif mine.status == BlockStatus.ask:                    screen.blit(img_ask, pos)                elif mine.status == BlockStatus.hint:                    screen.blit(img0, pos)                elif game_status == GameStatus.over and mine.value:                    screen.blit(img_mine, pos)                elif mine.value == 0 and mine.status == BlockStatus.flag:                    screen.blit(img_error, pos)                elif mine.status == BlockStatus.normal:                    screen.blit(img_blank, pos)        print_text(screen, font1, 30, (SIZE * 2 - fheight) // 2 - 2, 'd' % (MINE_COUNT - flag_count), red)        if game_status == GameStatus.started:            elapsed_time = int(time.time() - start_time)        print_text(screen, font1, SCREEN_WIDTH - fwidth - 30, (SIZE * 2 - fheight) // 2 - 2, 'd' % elapsed_time, red)        if flag_count + opened_count == BLOCK_WIDTH * BLOCK_HEIGHT:            game_status = GameStatus.win        if game_status == GameStatus.over:            screen.blit(img_face_fail, (face_pos_x, face_pos_y))        elif game_status == GameStatus.win:            screen.blit(img_face_success, (face_pos_x, face_pos_y))        else:            screen.blit(img_face_normal, (face_pos_x, face_pos_y))        pygame.display.update()if __name__ == '__main__':    main()

3、五子棋

五子棋就没那么多七七八八的素材和其它代码了

import sysimport randomimport pygamefrom pygame.locals import *import pygame.gfxdrawfrom collections import namedtupleChessman = namedtuple('Chessman', 'Name Value Color')Point = namedtuple('Point', 'X Y')BLACK_CHESSMAN = Chessman('黑子', 1, (45, 45, 45))WHITE_CHESSMAN = Chessman('白子', 2, (219, 219, 219))offset = [(1, 0), (0, 1), (1, 1), (1, -1)]class Checkerboard:    def __init__(self, line_points):        self._line_points = line_points        self._checkerboard = [[0] * line_points for _ in range(line_points)]    def _get_checkerboard(self):        return self._checkerboard    checkerboard = property(_get_checkerboard)    # 判断是否可落子    def can_drop(self, point):        return self._checkerboard[point.Y][point.X] == 0    def drop(self, chessman, point):        """        落子        :param chessman:        :param point:落子位置        :return:若该子落下之后即可获胜,则返回获胜方,否则返回 None        """        print(f'{chessman.Name} ({point.X}, {point.Y})')        self._checkerboard[point.Y][point.X] = chessman.Value        if self._win(point):            print(f'{chessman.Name}获胜')            return chessman    # 判断是否赢了    def _win(self, point):        cur_value = self._checkerboard[point.Y][point.X]        for os in offset:            if self._get_count_on_direction(point, cur_value, os[0], os[1]):                return True    def _get_count_on_direction(self, point, value, x_offset, y_offset):        count = 1        for step in range(1, 5):            x = point.X + step * x_offset            y = point.Y + step * y_offset            if 0 <= x < self._line_points and 0 <= y < self._line_points and self._checkerboard[y][x] == value:                count += 1            else:                break        for step in range(1, 5):            x = point.X - step * x_offset            y = point.Y - step * y_offset            if 0 <= x < self._line_points and 0 <= y < self._line_points and self._checkerboard[y][x] == value:                count += 1            else:                break        return count >= 5SIZE = 30  # 棋盘每个点时间的间隔Line_Points = 19  # 棋盘每行/每列点数Outer_Width = 20  # 棋盘外宽度Border_Width = 4  # 边框宽度Inside_Width = 4  # 边框跟实际的棋盘之间的间隔Border_Length = SIZE * (Line_Points - 1) + Inside_Width * 2 + Border_Width  # 边框线的长度Start_X = Start_Y = Outer_Width + int(Border_Width / 2) + Inside_Width  # 网格线起点(左上角)坐标SCREEN_HEIGHT = SIZE * (Line_Points - 1) + Outer_Width * 2 + Border_Width + Inside_Width * 2  # 游戏屏幕的高SCREEN_WIDTH = SCREEN_HEIGHT + 200  # 游戏屏幕的宽Stone_Radius = SIZE // 2 - 3  # 棋子半径Stone_Radius2 = SIZE // 2 + 3Checkerboard_Color = (0xE3, 0x92, 0x65)  # 棋盘颜色BLACK_COLOR = (0, 0, 0)WHITE_COLOR = (255, 255, 255)RED_COLOR = (200, 30, 30)BLUE_COLOR = (30, 30, 200)RIGHT_INFO_POS_X = SCREEN_HEIGHT + Stone_Radius2 * 2 + 10def 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', 32)    font2 = pygame.font.SysFont('SimHei', 72)    fwidth, fheight = font2.size('黑方获胜')    checkerboard = Checkerboard(Line_Points)    cur_runner = BLACK_CHESSMAN    winner = None    computer = AI(Line_Points, WHITE_CHESSMAN)    black_win_count = 0    white_win_count = 0    while True:        for event in pygame.event.get():            if event.type == QUIT:                sys.exit()            elif event.type == KEYDOWN:                if event.key == K_RETURN:                    if winner is not None:                        winner = None                        cur_runner = BLACK_CHESSMAN                        checkerboard = Checkerboard(Line_Points)                        computer = AI(Line_Points, WHITE_CHESSMAN)            elif event.type == MOUSEBUTTONDOWN:                if winner is None:                    pressed_array = pygame.mouse.get_pressed()                    if pressed_array[0]:                        mouse_pos = pygame.mouse.get_pos()                        click_point = _get_clickpoint(mouse_pos)                        if click_point is not None:                            if checkerboard.can_drop(click_point):                                winner = checkerboard.drop(cur_runner, click_point)                                if winner is None:                                    cur_runner = _get_next(cur_runner)                                    computer.get_opponent_drop(click_point)                                    AI_point = computer.AI_drop()                                    winner = checkerboard.drop(cur_runner, AI_point)                                    if winner is not None:                                        white_win_count += 1                                    cur_runner = _get_next(cur_runner)                                else:                                    black_win_count += 1                        else:                            print('超出棋盘区域')        # 画棋盘        _draw_checkerboard(screen)        # 画棋盘上已有的棋子        for i, row in enumerate(checkerboard.checkerboard):            for j, cell in enumerate(row):                if cell == BLACK_CHESSMAN.Value:                    _draw_chessman(screen, Point(j, i), BLACK_CHESSMAN.Color)                elif cell == WHITE_CHESSMAN.Value:                    _draw_chessman(screen, Point(j, i), WHITE_CHESSMAN.Color)        _draw_left_info(screen, font1, cur_runner, black_win_count, white_win_count)        if winner:            print_text(screen, font2, (SCREEN_WIDTH - fwidth)//2, (SCREEN_HEIGHT - fheight)//2, winner.Name + '获胜', RED_COLOR)        pygame.display.flip()def _get_next(cur_runner):    if cur_runner == BLACK_CHESSMAN:        return WHITE_CHESSMAN    else:        return BLACK_CHESSMAN# 画棋盘def _draw_checkerboard(screen):    # 填充棋盘背景色    screen.fill(Checkerboard_Color)    # 画棋盘网格线外的边框    pygame.draw.rect(screen, BLACK_COLOR, (Outer_Width, Outer_Width, Border_Length, Border_Length), Border_Width)    # 画网格线    for i in range(Line_Points):        pygame.draw.line(screen, BLACK_COLOR,                         (Start_Y, Start_Y + SIZE * i),                         (Start_Y + SIZE * (Line_Points - 1), Start_Y + SIZE * i),                         1)    for j in range(Line_Points):        pygame.draw.line(screen, BLACK_COLOR,                         (Start_X + SIZE * j, Start_X),                         (Start_X + SIZE * j, Start_X + SIZE * (Line_Points - 1)),                         1)    # 画星位和天元    for i in (3, 9, 15):        for j in (3, 9, 15):            if i == j == 9:                radius = 5            else:                radius = 3            # pygame.draw.circle(screen, BLACK, (Start_X + SIZE * i, Start_Y + SIZE * j), radius)            pygame.gfxdraw.aacircle(screen, Start_X + SIZE * i, Start_Y + SIZE * j, radius, BLACK_COLOR)            pygame.gfxdraw.filled_circle(screen, Start_X + SIZE * i, Start_Y + SIZE * j, radius, BLACK_COLOR)# 画棋子def _draw_chessman(screen, point, stone_color):    # pygame.draw.circle(screen, stone_color, (Start_X + SIZE * point.X, Start_Y + SIZE * point.Y), Stone_Radius)    pygame.gfxdraw.aacircle(screen, Start_X + SIZE * point.X, Start_Y + SIZE * point.Y, Stone_Radius, stone_color)    pygame.gfxdraw.filled_circle(screen, Start_X + SIZE * point.X, Start_Y + SIZE * point.Y, Stone_Radius, stone_color)# 画左侧信息显示def _draw_left_info(screen, font, cur_runner, black_win_count, white_win_count):    _draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, Start_X + Stone_Radius2), BLACK_CHESSMAN.Color)    _draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, Start_X + Stone_Radius2 * 4), WHITE_CHESSMAN.Color)    print_text(screen, font, RIGHT_INFO_POS_X, Start_X + 3, '玩家', BLUE_COLOR)    print_text(screen, font, RIGHT_INFO_POS_X, Start_X + Stone_Radius2 * 3 + 3, '电脑', BLUE_COLOR)    print_text(screen, font, SCREEN_HEIGHT, SCREEN_HEIGHT - Stone_Radius2 * 8, '战况:', BLUE_COLOR)    _draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, SCREEN_HEIGHT - int(Stone_Radius2 * 4.5)), BLACK_CHESSMAN.Color)    _draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, SCREEN_HEIGHT - Stone_Radius2 * 2), WHITE_CHESSMAN.Color)    print_text(screen, font, RIGHT_INFO_POS_X, SCREEN_HEIGHT - int(Stone_Radius2 * 5.5) + 3, f'{black_win_count} 胜', BLUE_COLOR)    print_text(screen, font, RIGHT_INFO_POS_X, SCREEN_HEIGHT - Stone_Radius2 * 3 + 3, f'{white_win_count} 胜', BLUE_COLOR)def _draw_chessman_pos(screen, pos, stone_color):    pygame.gfxdraw.aacircle(screen, pos[0], pos[1], Stone_Radius2, stone_color)    pygame.gfxdraw.filled_circle(screen, pos[0], pos[1], Stone_Radius2, stone_color)# 根据鼠标点击位置,返回游戏区坐标def _get_clickpoint(click_pos):    pos_x = click_pos[0] - Start_X    pos_y = click_pos[1] - Start_Y    if pos_x < -Inside_Width or pos_y < -Inside_Width:        return None    x = pos_x // SIZE    y = pos_y // SIZE    if pos_x % SIZE > Stone_Radius:        x += 1    if pos_y % SIZE > Stone_Radius:        y += 1    if x >= Line_Points or y >= Line_Points:        return None    return Point(x, y)class AI:    def __init__(self, line_points, chessman):        self._line_points = line_points        self._my = chessman        self._opponent = BLACK_CHESSMAN if chessman == WHITE_CHESSMAN else WHITE_CHESSMAN        self._checkerboard = [[0] * line_points for _ in range(line_points)]    def get_opponent_drop(self, point):        self._checkerboard[point.Y][point.X] = self._opponent.Value    def AI_drop(self):        point = None        score = 0        for i in range(self._line_points):            for j in range(self._line_points):                if self._checkerboard[j][i] == 0:                    _score = self._get_point_score(Point(i, j))                    if _score > score:                        score = _score                        point = Point(i, j)                    elif _score == score and _score > 0:                        r = random.randint(0, 100)                        if r % 2 == 0:                            point = Point(i, j)        self._checkerboard[point.Y][point.X] = self._my.Value        return point    def _get_point_score(self, point):        score = 0        for os in offset:            score += self._get_direction_score(point, os[0], os[1])        return score    def _get_direction_score(self, point, x_offset, y_offset):        count = 0   # 落子处我方连续子数        _count = 0  # 落子处对方连续子数        space = None   # 我方连续子中有无空格        _space = None  # 对方连续子中有无空格        both = 0    # 我方连续子两端有无阻挡        _both = 0   # 对方连续子两端有无阻挡        # 如果是 1 表示是边上是我方子,2 表示敌方子        flag = self._get_stone_color(point, x_offset, y_offset, True)        if flag != 0:            for step in range(1, 6):                x = point.X + step * x_offset                y = point.Y + step * y_offset                if 0 <= x < self._line_points and 0 <= y < self._line_points:                    if flag == 1:                        if self._checkerboard[y][x] == self._my.Value:                            count += 1                            if space is False:                                space = True                        elif self._checkerboard[y][x] == self._opponent.Value:                            _both += 1                            break                        else:                            if space is None:                                space = False                            else:                                break   # 遇到第二个空格退出                    elif flag == 2:                        if self._checkerboard[y][x] == self._my.Value:                            _both += 1                            break                        elif self._checkerboard[y][x] == self._opponent.Value:                            _count += 1                            if _space is False:                                _space = True                        else:                            if _space is None:                                _space = False                            else:                                break                else:                    # 遇到边也就是阻挡                    if flag == 1:                        both += 1                    elif flag == 2:                        _both += 1        if space is False:            space = None        if _space is False:            _space = None        _flag = self._get_stone_color(point, -x_offset, -y_offset, True)        if _flag != 0:            for step in range(1, 6):                x = point.X - step * x_offset                y = point.Y - step * y_offset                if 0 <= x < self._line_points and 0 <= y < self._line_points:                    if _flag == 1:                        if self._checkerboard[y][x] == self._my.Value:                            count += 1                            if space is False:                                space = True                        elif self._checkerboard[y][x] == self._opponent.Value:                            _both += 1                            break                        else:                            if space is None:                                space = False                            else:                                break   # 遇到第二个空格退出                    elif _flag == 2:                        if self._checkerboard[y][x] == self._my.Value:                            _both += 1                            break                        elif self._checkerboard[y][x] == self._opponent.Value:                            _count += 1                            if _space is False:                                _space = True                        else:                            if _space is None:                                _space = False                            else:                                break                else:                    # 遇到边也就是阻挡                    if _flag == 1:                        both += 1                    elif _flag == 2:                        _both += 1        score = 0        if count == 4:            score = 10000        elif _count == 4:            score = 9000        elif count == 3:            if both == 0:                score = 1000            elif both == 1:                score = 100            else:                score = 0        elif _count == 3:            if _both == 0:                score = 900            elif _both == 1:                score = 90            else:                score = 0        elif count == 2:            if both == 0:                score = 100            elif both == 1:                score = 10            else:                score = 0        elif _count == 2:            if _both == 0:                score = 90            elif _both == 1:                score = 9            else:                score = 0        elif count == 1:            score = 10        elif _count == 1:            score = 9        else:            score = 0        if space or _space:            score /= 2        return score    # 判断指定位置处在指定方向上是我方子、对方子、空    def _get_stone_color(self, point, x_offset, y_offset, next):        x = point.X + x_offset        y = point.Y + y_offset        if 0 <= x < self._line_points and 0 <= y < self._line_points:            if self._checkerboard[y][x] == self._my.Value:                return 1            elif self._checkerboard[y][x] == self._opponent.Value:                return 2            else:                if next:                    return self._get_stone_color(Point(x, y), x_offset, y_offset, False)                else:                    return 0        else:            return 0if __name__ == '__main__':    main()

4、贪吃蛇

import randomimport sysimport timeimport pygamefrom pygame.locals import *from collections import dequeSCREEN_WIDTH = 600      # 屏幕宽度SCREEN_HEIGHT = 480     # 屏幕高度SIZE = 20               # 小方格大小LINE_WIDTH = 1          # 网格线宽度# 游戏区域的坐标范围SCOPE_X = (0, SCREEN_WIDTH // SIZE - 1)SCOPE_Y = (2, SCREEN_HEIGHT // SIZE - 1)# 食物的分值及颜色FOOD_STYLE_LIST = [(10, (255, 100, 100)), (20, (100, 255, 100)), (30, (100, 100, 255))]LIGHT = (100, 100, 100)DARK = (200, 200, 200)      # 蛇的颜色BLACK = (0, 0, 0)           # 网格线颜色RED = (200, 30, 30)         # 红色,GAME OVER 的字体颜色BGCOLOR = (40, 40, 60)      # 背景色def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):    imgText = font.render(text, True, fcolor)    screen.blit(imgText, (x, y))# 初始化蛇def init_snake():    snake = deque()    snake.append((2, SCOPE_Y[0]))    snake.append((1, SCOPE_Y[0]))    snake.append((0, SCOPE_Y[0]))    return snakedef create_food(snake):    food_x = random.randint(SCOPE_X[0], SCOPE_X[1])    food_y = random.randint(SCOPE_Y[0], SCOPE_Y[1])    while (food_x, food_y) in snake:        # 如果食物出现在蛇身上,则重来        food_x = random.randint(SCOPE_X[0], SCOPE_X[1])        food_y = random.randint(SCOPE_Y[0], SCOPE_Y[1])    return food_x, food_ydef get_food_style():    return FOOD_STYLE_LIST[random.randint(0, 2)]def main():    pygame.init()    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))    pygame.display.set_caption('贪吃蛇')    font1 = pygame.font.SysFont('SimHei', 24)  # 得分的字体    font2 = pygame.font.Font(None, 72)  # GAME OVER 的字体    fwidth, fheight = font2.size('GAME OVER')    # 如果蛇正在向右移动,那么快速点击向下向左,由于程序刷新没那么快,向下事件会被向左覆盖掉,导致蛇后退,直接GAME OVER    # b 变量就是用于防止这种情况的发生    b = True    # 蛇    snake = init_snake()    # 食物    food = create_food(snake)    food_style = get_food_style()    # 方向    pos = (1, 0)    game_over = True    start = False       # 是否开始,当start = True,game_over = True 时,才显示 GAME OVER    score = 0           # 得分    orispeed = 0.5      # 原始速度    speed = orispeed    last_move_time = None    pause = False       # 暂停    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                        b = True                        snake = init_snake()                        food = create_food(snake)                        food_style = get_food_style()                        pos = (1, 0)                        # 得分                        score = 0                        last_move_time = time.time()                elif event.key == K_SPACE:                    if not game_over:                        pause = not pause                elif event.key in (K_w, K_UP):                    # 这个判断是为了防止蛇向上移时按了向下键,导致直接 GAME OVER                    if b and not pos[1]:                        pos = (0, -1)                        b = False                elif event.key in (K_s, K_DOWN):                    if b and not pos[1]:                        pos = (0, 1)                        b = False                elif event.key in (K_a, K_LEFT):                    if b and not pos[0]:                        pos = (-1, 0)                        b = False                elif event.key in (K_d, K_RIGHT):                    if b and not pos[0]:                        pos = (1, 0)                        b = False        # 填充背景色        screen.fill(BGCOLOR)        # 画网格线 竖线        for x in range(SIZE, SCREEN_WIDTH, SIZE):            pygame.draw.line(screen, BLACK, (x, SCOPE_Y[0] * SIZE), (x, SCREEN_HEIGHT), LINE_WIDTH)        # 画网格线 横线        for y in range(SCOPE_Y[0] * SIZE, SCREEN_HEIGHT, SIZE):            pygame.draw.line(screen, BLACK, (0, y), (SCREEN_WIDTH, y), LINE_WIDTH)        if not game_over:            curTime = time.time()            if curTime - last_move_time > speed:                if not pause:                    b = True                    last_move_time = curTime                    next_s = (snake[0][0] + pos[0], snake[0][1] + pos[1])                    if next_s == food:                        # 吃到了食物                        snake.appendleft(next_s)                        score += food_style[0]                        speed = orispeed - 0.03 * (score // 100)                        food = create_food(snake)                        food_style = get_food_style()                    else:                        if SCOPE_X[0] <= next_s[0] <= SCOPE_X[1] and SCOPE_Y[0] <= next_s[1] <= SCOPE_Y[1] \                                and next_s not in snake:                            snake.appendleft(next_s)                            snake.pop()                        else:                            game_over = True        # 画食物        if not game_over:            # 避免 GAME OVER 的时候把 GAME OVER 的字给遮住了            pygame.draw.rect(screen, food_style[1], (food[0] * SIZE, food[1] * SIZE, SIZE, SIZE), 0)        # 画蛇        for s in snake:            pygame.draw.rect(screen, DARK, (s[0] * SIZE + LINE_WIDTH, s[1] * SIZE + LINE_WIDTH,                                            SIZE - LINE_WIDTH * 2, SIZE - LINE_WIDTH * 2), 0)        print_text(screen, font1, 30, 7, f'速度: {score//100}')        print_text(screen, font1, 450, 7, f'得分: {score}')        if game_over:            if start:                print_text(screen, font2, (SCREEN_WIDTH - fwidth) // 2, (SCREEN_HEIGHT - fheight) // 2, 'GAME OVER', RED)        pygame.display.update()if __name__ == '__main__':    main()

以上就是Python实现四个经典小游戏的示例分析,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

0