Earlier, we used python to implement games such as snake, tank battle, spaceship battle, gomoku, etc.
Today we use python to implement the minesweeper game
This game has a lot of code and source files
You can get it from my GitHub address
Construct a minefield
import random
fromenumimport Enum
BLOCK_WIDTH =30
BLOCK_HEIGHT =16
SIZE =20 #Block size
MINE_COUNT =99 #Number of mines
classBlockStatus(Enum):
normal =1 #Not clicked
opened =2 #Clicked
mine =3 #Landmine
flag =4 #Mark as a landmine
ask =5 #Mark as question mark
bomb =6 #Stepped on a landmine
hint =7 #Double clicked surrounding
double =8 #Being double-clicked by the left and right mouse buttons
classMine:
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):returnstr(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 =1else:
self._value =0
value =property(fget=get_value, fset=set_value, doc='0:Non-mine 1:mine')
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='Number of mines around')
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')classMineBlock:
def __init__(self):
self._block =[[Mine(i, j)for i inrange(BLOCK_WIDTH)]for j inrange(BLOCK_HEIGHT)]
# Mine mine
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):
# Stepped on thunder
if self._block[y][x].value:
self._block[y][x].status = BlockStatus.bomb
return False
# First change the status to opened
self._block[y][x].status = BlockStatus.opened
around =_get_around(x, y)
_ sum =0for i, j in around:if self._block[j][i].value:
_ sum +=1
self._block[y][x].around_mine_count = _sum
# If there is no thunder around, then recursively count the surrounding 8 misses
# This can achieve the effect of a large opening
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 #Number of marked mines around
for i, j in_get_around(x, y):if self._block[j][i].status == BlockStatus.flag:
sumflag +=1
# The surrounding mines have all been marked
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):"""return(x, y)The coordinates of the surrounding points"""
# Note here that the end of the range is an open range, so add 1 return[(i, j)for i inrange(max(0, x -1),min(BLOCK_WIDTH -1, x +1)+1)for j inrange(max(0, y -1),min(BLOCK_HEIGHT -1, y +1)+1)if i != x or j != y]
Main function
import sys
import time
fromenumimport Enum
import pygame
from pygame.locals import*from mineblock import*
# The width of the game screen
SCREEN_WIDTH = BLOCK_WIDTH * SIZE
# The height of the game screen
SCREEN_HEIGHT =(BLOCK_HEIGHT +2)* SIZE
classGameStatus(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('Mine clearing')
font1 = pygame.font.Font('resources/a.TTF', SIZE *2) #Score font
fwidth, fheight = font1.size('999')
red =(200,40,40)
# Load the resource image, because the resource file size is different, so a unified zoom process is done
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) #Background color
block =MineBlock()
game_status = GameStatus.readied
start_time = None #Starting time
elapsed_time =0 #time consuming
while True:
# Fill background color
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:
# Press the left and right buttons of the mouse at the same time, if all mines have been marked, open the surrounding circle
# If all the mines have not been marked, there will be an effect that the surrounding circle is pressed simultaneously
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 =0continueif game_status == GameStatus.readied:
game_status = GameStatus.started
start_time = time.time()
elapsed_time =0if game_status == GameStatus.started:
mine = block.getmine(x, y)if b1 and not b3: #Left mouse button
if mine.status == BlockStatus.normal:if not block.open_mine(x, y):
game_status = GameStatus.over
elif not b1 and b3: #Right click
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 =0for 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()
running result
More interesting classic mini game implementation topics, share with you:
C++ classic games summary
Python classic games summary
python tetris game collection
JavaScript classic games are constantly playing
Summary of classic java games
JavaScript classic games summary
The above is the whole content of this article, I hope it will be helpful to everyone's study.
Recommended Posts