python实现扫雷小游戏-kb88凯时官网登录

时间:2020-04-24
阅读:
免费资源网 - https://freexyz.cn/

今天我们用python来实现一下扫雷游戏

本游戏代码量和源文件较多

可以从我的中获取

构建地雷区

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]

主函数

import sys
import time
from enum import enum
import pygame
from pygame.locals import *
from mineblock import *
# 游戏屏幕的宽
screen_width = block_width * size
# 游戏屏幕的高
screen_height = (block_height   2) * size
class gamestatus(enum):
 readied = 1,
 started = 2,
 over = 3,
 win = 4
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.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()

运行效果

python实现扫雷小游戏

免费资源网 - https://freexyz.cn/
返回顶部
顶部
网站地图