pygame10 扫雷游戏3

上一节课我们完成了扫雷游戏地图中雷数量的显示,今天我们将把雷的生成做出来

一、地雷的生成

地图中有20*20共400个格子,我们可以设定一共可以生成40个地雷,为了使得每次生成的地图都不一样,可以使用随机数randint,每次x的索引和y的索引分别从0至19中取随机数,当发现maps[x][y]不为0,我们就往里面放一个雷,放雷的逻辑很简单,通过masp[x][y] = 'X'完成

代码如下:

def _born(self):
    for i in range(40):
        x = randint(0, 19)
        y = randint(0, 19)
        while self.maps[x][y] != 0:
            x = randint(0, 19)
            y = randint(0, 19)
        self.maps[x][y] = 'X'
    return

雷放上去了,接下来需要计算地图上各个格子上雷的数量。根据第一课所述逻辑,每个格子周围8个格子如果有1个雷,那么此格子的数字是1,如果是2个雷,则是2,依此类推,最极端的情况是这个格子的周围8个格子全是雷,数字则为8.

换一种思路,也就是说每放下一个雷,则此雷周边8个格子如果不是雷的,就应该将数字增加1,这样只需要在产生雷时把周围相应的格子都增加一个数字1即可,计算雷周边的数字时需要注意的是如果在地图边沿时通过上下左右的移动超过地图边界时就不计算,代码如下:

    def _calc_thunder_num(self, x, y):
        for m in self.moves:
            i = m[0] + x
            j = m[1] + y
            if i >= 0 and i < 20 and j >= 0 and j < 20 and self.maps[i][j] != 'X':
                self.maps[i][j] += 1
        return

由于计算是根据每一个雷来算的,因此可以在生成雷时直接算出雷的数量,

    def _born(self):
        for i in range(40):
            # 略
            self._calc_thunder_num(x, y)
        return

贴出一个随机生成的地雷图:

 二、隐藏地雷,只在点击时显示数字或是雷

地雷生成好了,对应的数字也生成好了,只是游戏启动后,这些东西是不应该显示的,只有当鼠标点击对应格子才应该显示出来。我们可以用一个show_maps来记录需要显示的地图内容,每次点击地图,只将对应的地图索引存于show_maps中,然后显示出来,将原来直接显示的maps改为只显示show_maps

则原先的地图显示的代码更改为:

    def show(self):
        for item in self.show_maps:
            i = item[0]
            j = item[1]
            msg = "{}".format(self.maps[i][j])
            font = pygame.font.SysFont(None, 45)
            font_image = font.render(msg, True, [60, 0, 0], None)
            rect = font_image.get_rect()
            rect.top = j * 25
            rect.left = i * 25
            rect.width = 24
            rect.height = 24
            self.screen.blit(font_image, rect)

首先通过show_maps获取地图格子的索引,然后显示索引中对应的数字或是雷

点击格子时,将点击的位置转换为索引值存储于self.show_maps中即可

    def add(self, xpos, ypos):
        x = xpos // 25
        y = ypos // 25
        if x >= 0 and x < 20 and y >= 0 and y < 20:
            if [x, y] not in self.show_maps:
                self.show_maps.append([x, y])

简单的游戏界面:

现在的问题是,我们玩游戏时,点击到0时应该将0周围的一片区域都显示出来。

首先我们看一下逻辑,当点击的为0时,先将此格显示出来,然后查找周围的记录,若不为0且不是雷的,直接显示,若是0,查找此格周围8格,按同样的方式处理。

代码如下

    def _connect(self, x, y):
        tmp = list()
        if self.maps[x][y] == 0:
            tmp.append([x, y])
        while tmp:
            cur = tmp[-1]
            del tmp[-1]
            for m in self.moves:
                i = cur[0] + m[0]
                j = cur[1] + m[1]
                if i >= 0 and i < 20 and j >= 0 and j < 20 and self.maps[i][j] != 'X' and [i, j] not in self.show_maps:
                    self.show_maps.append([i, j])
                    self.cover.delete(i * 25, j * 25)
                    if self.maps[i][j] == 0:
                        tmp.append([i, j])

 效果图:

现在的问题是一般为0时,最好不要显示,这个只需在显示的时候判定maps[i][j]是否为0即可

代码如下:

    def show(self):
        for item in self.show_maps:
            i = item[0]
            j = item[1]
            if self.maps[i][j] == 0:
                continue
            # 略

 效果图:

 

当然可以使用Pygame来编写扫雷游戏!以下是一个简单的示例代码: ```python import pygame import random # 游戏窗口大小 WINDOW_WIDTH, WINDOW_HEIGHT = 400, 400 # 方块大小和行列数 BLOCK_SIZE = 20 ROWS, COLS = WINDOW_HEIGHT // BLOCK_SIZE, WINDOW_WIDTH // BLOCK_SIZE # 的数量 NUM_MINES = 40 # 初始化Pygame pygame.init() # 创建游戏窗口 window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) # 设置窗口标题 pygame.display.set_caption("扫雷游戏") # 定义颜色 BLACK = (0, 0, 0) GRAY = (128, 128, 128) WHITE = (255, 255, 255) # 游戏结束标志 game_over = False # 创建方块类 class Block: def __init__(self, row, col): self.row = row self.col = col self.x = col * BLOCK_SIZE self.y = row * BLOCK_SIZE self.is_mine = False self.is_revealed = False def draw(self): if self.is_revealed: pygame.draw.rect(window, GRAY, (self.x, self.y, BLOCK_SIZE, BLOCK_SIZE)) if self.is_mine: pygame.draw.circle(window, BLACK, (self.x + BLOCK_SIZE // 2, self.y + BLOCK_SIZE // 2), BLOCK_SIZE // 4) else: pygame.draw.rect(window, WHITE, (self.x, self.y, BLOCK_SIZE, BLOCK_SIZE)) pygame.draw.rect(window, GRAY, (self.x, self.y, BLOCK_SIZE, BLOCK_SIZE), 1) def reveal(self): self.is_revealed = True # 创建方块列表 blocks = [[Block(row, col) for col in range(COLS)] for row in range(ROWS)] # 随机生成的位置 mines = random.sample(range(ROWS * COLS), NUM_MINES) for mine in mines: row = mine // COLS col = mine % COLS blocks[row][col].is_mine = True # 游戏主循环 while not game_over: # 处理事件 for event in pygame.event.get(): if event.type == pygame.QUIT: game_over = True if event.type == pygame.MOUSEBUTTONDOWN: if pygame.mouse.get_pressed()[0]: # 左键点击 x, y = pygame.mouse.get_pos() row = y // BLOCK_SIZE col = x // BLOCK_SIZE blocks[row][col].reveal() # 绘制方块 for row in blocks: for block in row: block.draw() # 更新屏幕 pygame.display.update() # 退出游戏 pygame.quit() ``` 这只是一个简单的示例,并没有包括计算周围数、判断游戏胜利条件、点击时的游戏失败等功能。你可以根据自己的需求进行扩展和修改。希望对你有帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

永远的麦田

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

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

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

打赏作者

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

抵扣说明:

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

余额充值