pygame—炸弹牌(可做课设)

游戏介绍

  1. 在5X5的数字宫格里翻牌,翻出所有的2和3即可获胜
  2. 每一格只能是0、1、2、3,
  3. 第六列和最第六行为 X | Y,X代表该列或该行的数字总和,Y代表该列或该行的0的个数
  4. 控制难度,每行每列的数字总和不超过9
  5. 该游戏需要一定运气及技巧

核心代码

生成二维数字列表

def createNumList() -> list:
    arr = []
    for i in range(6):
        row = []
        row_sum = 0
        col_sum = 0
        row_zeros = 0
        col_zeros = 0
        for j in range(5):
            # 从第二行开始计算每列当前和
            col_sum = sum([arr[s - 1][j] for s in range(i)]) if i > 0 else None
            if i < 5:
                num = random.randint(0, 3)
                if col_sum:
                    while row_sum + num > 9 or col_sum + num > 9: # 控制总和
                        num = random.randint(0, 3)
                else:
                    while row_sum + num > 9: # 控制总和
                        num = random.randint(0, 3)
                row.append(num)
                row_sum += num
                row_zeros = row_zeros + 1 if num == 0 else row_zeros
            else:
                # 第六行开始计算每列0的数量
                col_zeros = [arr[s][j] for s in range(5)].count(0)
                row.append((col_sum, col_zeros))
        row.append((row_sum, row_zeros))
        arr.append(row)
    return arr

绘制宫格

def makePalace(numList, window, screen, click_list=[]):
    """
    绘制宫格,根据是否被点击来更改样式
    :param click_list: 被点击的格子,默认没有
    :param numList: 数字列表
    :param window:  surface
    :param screen: screen
    :return: 宫格列表(一维)
    """
    palace_list = []
    for i in range(6):
        for j in range(6):
            # 特殊格子的内容
            if i == 5 or j == 5:
                text = f'{numList[i][j][0]} | {numList[i][j][1]}'
                if i == 5 and j == 5:
                    text = ' '
            else:
                text = numList[i][j]

            # 每一个的样式
            border = 2
            palace_color = color_dict['black']

            if (i, j) in click_list:
                if text == '0':
                    border = 0
                    palace_color = color_dict['red']
                    text_color = color_dict['white']
                else:
                    border = 1
                    text_color = color_dict['black']
            else:
                text_color = color_dict['white']

            if i == 5 or j == 5:
                text_color = color_dict['black']

            palace = makeAndDrawRect(surface=window,
                                     x=(screen.width - screen.height) / 2 + j * screen.height / 6,
                                     y=i * screen.height / 6,
                                     width=screen.height / 6,
                                     height=screen.height / 6,
                                     border=border,
                                     color=palace_color,
                                     text=text,
                                     text_color=text_color,
                                     font_size=70)
            palace_list.append({
                'rect': palace,
                'click': False,
                'index': (i, j),
                'data': text if len(text) == 1 else None
            })
    return palace_list

完整代码

import pygame
import screeninfo
import gameNum

from color import color_dict

pygame.init()


def makeText(surface, txt, x, y, text_color=color_dict['white'], size=40):
    """
    绘制以(x, y)为中心的文本
    :param size:
    :param surface:
    :param txt:
    :param x:
    :param y:
    :param text_color:
    :return:
    """
    font_name = pygame.font.match_font('Microsoft YaHei')
    font = pygame.font.Font(font_name, size)
    text = font.render(txt, True, text_color)
    text_rect = text.get_rect(center=(x, y))
    surface.blit(text, text_rect)


def makeAndDrawRect(surface, x, y, width, height, text=None, border=0, color=color_dict['white'],
                    text_color=color_dict['white'], font_size=40, border_radius=0):
    """
    生成按钮,生成以(x, y)为顶点,文本在中间的按钮
    :param border_radius:
    :param font_size:
    :param text_color:
    :param color:
    :param border:
    :param surface:
    :param x:
    :param y:
    :param width:
    :param height:
    :param text:
    :return: button
    """
    button = pygame.Rect(x, y, width, height)
    pygame.draw.rect(surface, color, rect=button, width=border, border_radius=border_radius)
    if text:
        makeText(surface, text, x + width / 2, y + height / 2, text_color, font_size)
    return button


def makePalace(numList, window, screen, click_list=[]):
    """
    绘制宫格,根据是否被点击来更改样式
    :param click_list: 被点击的格子,默认没有
    :param numList: 数字列表
    :param window:  surface
    :param screen: screen
    :return: 宫格列表(一维)
    """
    palace_list = []
    for i in range(6):
        for j in range(6):
            # 特殊格子的内容
            if i == 5 or j == 5:
                text = f'{numList[i][j][0]} | {numList[i][j][1]}'
                if i == 5 and j == 5:
                    text = ' '
            else:
                text = numList[i][j]

            # 每一个的样式
            border = 2
            palace_color = color_dict['black']

            if (i, j) in click_list:
                if text == '0':
                    border = 0
                    palace_color = color_dict['red']
                    text_color = color_dict['white']
                else:
                    border = 1
                    text_color = color_dict['black']
            else:
                text_color = color_dict['white']

            if i == 5 or j == 5:
                text_color = color_dict['black']

            palace = makeAndDrawRect(surface=window,
                                     x=(screen.width - screen.height) / 2 + j * screen.height / 6,
                                     y=i * screen.height / 6,
                                     width=screen.height / 6,
                                     height=screen.height / 6,
                                     border=border,
                                     color=palace_color,
                                     text=text,
                                     text_color=text_color,
                                     font_size=70)
            palace_list.append({
                'rect': palace,
                'click': False,
                'index': (i, j),
                'data': text if len(text) == 1 else None
            })
    return palace_list


def main():
    screen = screeninfo.get_monitors()[0]
    window = pygame.display.set_mode((screen.width, screen.height))
    pygame.display.set_caption('炸弹牌')

    Gameplay = "每一个格子的数字只能是1、2、3, \n" \
               "'X | Y' 代表了该行或该列的数字之和为X,炸弹数量为Y\n" \
               "找出所有的2和3即为胜利"
    numList = []  # 每一局的数字列表
    clickPalace_indexList = []  # 被点击的格子
    now_2_3_Count = 0
    bt_again = None

    sound_click = pygame.mixer.Sound('turn.wav')
    sound_over = pygame.mixer.Sound('dedede.wav')
    sound_win = pygame.mixer.Sound('win.mp3')

    running = True
    playing = False
    result = None  # True则赢,False则输
    while running:
        window.fill(color_dict['black'])
        # 开始界面
        if playing is False:
            bt_start = makeAndDrawRect(surface=window,
                                       x=(screen.width - 200) / 2,
                                       y=screen.height * 0.7,
                                       width=200,
                                       height=80,
                                       text='开始游戏',
                                       border=5,
                                       border_radius=5)
            bt_exit = makeAndDrawRect(surface=window,
                                      x=(screen.width - 200) / 2,
                                      y=screen.height * 0.7 + 120,
                                      width=200,
                                      height=80,
                                      text='退出游戏',
                                      border=5,
                                      border_radius=5)
            lines = Gameplay.split('\n')
            offset = -60
            for line in lines:
                makeText(window, line, screen.width / 2, screen.height / 2 + offset)
                offset += 60
        else:
            # 生成当局数字
            if numList:
                pass
            else:
                numList = gameNum.elementToStr()

            bt_exit = makeAndDrawRect(surface=window,
                                      x=50,
                                      y=screen.height * 0.7 + 120,
                                      width=200,
                                      height=80,
                                      text='退出游戏',
                                      border=5,
                                      border_radius=5)
            # 正方形白色背景
            makeAndDrawRect(surface=window,
                            x=(screen.width - screen.height) / 2,
                            y=0,
                            width=screen.height,
                            height=screen.height)
            # 根据是否被点击显示内容
            palace_list = makePalace(numList, window, screen, clickPalace_indexList if clickPalace_indexList else [])

            # 游戏结束所显示的内容
            if result is not None:
                bt_again = bt_start = makeAndDrawRect(surface=window,
                                                      x=50,
                                                      y=screen.height * 0.7,
                                                      width=200,
                                                      height=80,
                                                      text='再玩一局',
                                                      border=5,
                                                      border_radius=5)
                if result is True:
                    makeText(window, '你赢了!', screen.width * 0.1, screen.height * 0.5)
                else:
                    makeText(window, '翻到炸弹了!', screen.width * 0.1, screen.height * 0.5)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                if bt_exit.collidepoint(event.pos):
                    sound_click.play()
                    running = False
                if playing is False:
                    if bt_start.collidepoint(event.pos):
                        sound_click.play()
                        playing = True
                        del bt_start
                else:
                    # 点击宫格
                    count_2_3 = len([x for x in palace_list if x['data'] in ['2', '3']])
                    for palace in palace_list:
                        if palace['rect'].collidepoint(event.pos) and result is None:  # 被点击且游戏还没有结束
                            if palace['index'] not in clickPalace_indexList and palace['data']:  # 去重插入数字区数据
                                if palace['data'] == '0':
                                    sound_over.play()
                                    result = False
                                else:
                                    sound_click.play()
                                if palace['data'] != '1':
                                    now_2_3_Count += 1
                                clickPalace_indexList.append(palace['index'])
                    # 所有2和3被找出
                    if count_2_3 == now_2_3_Count and result is not True:
                        sound_win.play()
                        result = True

                # 游戏结束
                if result is not None and bt_again:
                    if bt_again.collidepoint(event.pos):
                        sound_click.play()
                        result = None
                        now_2_3_Count = 0
                        numList = []
                        clickPalace_indexList = []
                        bt_again = None

        pygame.display.flip()
    pygame.quit()


if __name__ == '__main__':
    main()

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ice冰山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值