上一节课我们完成了扫雷游戏地图中雷数量的显示,今天我们将把雷的生成做出来
地图中有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
# 略
效果图: