900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > python玩扫雷_python实现扫雷小游戏

python玩扫雷_python实现扫雷小游戏

时间:2018-12-12 08:52:21

相关推荐

python玩扫雷_python实现扫雷小游戏

前面我们用python实现了贪吃蛇、坦克大战、飞船大战、五子棋等游戏

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

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

可以从我的GitHub地址中获取

构建地雷区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, '%02d' % (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, '%03d' % 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()

运行效果

更多有趣的经典小游戏实现专题,分享给大家:

C++经典小游戏汇总

python经典小游戏汇总

python俄罗斯方块游戏集合

JavaScript经典游戏 玩不停

java经典小游戏汇总

javascript经典小游戏汇总

以上就是本文的全部内容,希望对大家的学习有所帮助。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。