Article \ | wild guest
Source: Python Technology “ID: pythonall”
Minesweeper is a puzzle game that was first released by Microsoft on Windows in 1992. The game is suitable for all ages. The rules are simple: find all the non-lightning grids in the shortest time and do not step on the mines in the process.
In this article we use Python to implement minesweeper games, the main Python library is PyGame.
implementation
The game is composed of relatively simple, mainly including: small squares, timers, mines and so on.
First, we initialize some constants, such as the number of vertical and horizontal squares, the number of mines, mouse clicks, etc., as shown below:
BLOCK_WIDTH = 30
BLOCK_HEIGHT = 16# block SIZE SIZE =20# Number of mines MINE_COUNT =66# no click normal =1# Opened =2# mine =3# Flag mine =4# mark with question mark ask =5# Step on a landmine bomb =6# double click around hint =7# double-click double = by mouse button8
readied = 1,
started = 2,
over = 3,
win = 4
Copy the code
Then define a mine class, which defines some basic attributes (such as coordinates, states, etc.) and get, set methods, the code implementation is as follows:
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 = normal
self.set_value(value)
def __repr__(self):
return str(self._value)
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: 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')
Copy the code
We then define a MineBlock class that handles the basic minesweeping logic as follows:
class MineBlock:
def __init__(self):
self._block = [[Mine(i, j) for i in range(BLOCK_WIDTH)] for j in range(BLOCK_HEIGHT)] # minefor 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):
returnSelf._block[y][x] def open_mine(self, x, y)if self._block[y][x].value:
self._block[y][x].status = bomb
return_block[y][x]. Status = Opened around = _get_around(x, y) _sum =0
for i, j in around:
if self._block[j][i].value:
_sum += 1Self._block[y][x]. Around_mine_count = _sum #8I'm going to recurse over all of themif _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:
returnTrue self._block[y][x]. Status = double around = _get_around(x, y) #0
for i, j in _get_around(x, y):
if self._block[j][i].status == flag:
sumflag += 1# all surrounding mines have been marked result = Trueif sumflag == self._block[y][x].around_mine_count:
for i, j in around:
if self._block[j][i].status == normal:
if not self.open_mine(i, j):
result = False
else:
for i, j in around:
if self._block[j][i].status == normal:
self._block[j][i].status = hint
return result
def double_mouse_button_up(self, x, y):
self._block[y][x].status = opened
for i, j in _get_around(x, y):
if self._block[j][i].status == hint:
self._block[j][i].status = normal
Copy the code
Next, we initialize the interface. First, a panel composed of small squares is generated. The main code is as follows:
for row in block.block:
for mine in row:
pos = (mine.x * SIZE, (mine.y + 2) * SIZE)
if mine.status == opened:
screen.blit(img_dict[mine.around_mine_count], pos)
opened_count += 1
elif mine.status == double:
screen.blit(img_dict[mine.around_mine_count], pos)
elif mine.status == bomb:
screen.blit(img_blood, pos)
elif mine.status == flag:
screen.blit(img_flag, pos)
flag_count += 1
elif mine.status == ask:
screen.blit(img_ask, pos)
elif mine.status == hint:
screen.blit(img0, pos)
elif game_status == over and mine.value:
screen.blit(img_mine, pos)
elif mine.value == 0 and mine.status == flag:
screen.blit(img_error, pos)
elif mine.status == normal:
screen.blit(img_blank, pos)
Copy the code
Take a look at the results:
Then add the head part of the panel, including: display the number of thunder, restart button (smiling face), display time, the main code implementation is as follows:
print_text(screen, font1, 30, (SIZE * 2 - fheight) // 2 - 2, '%02d' % (MINE_COUNT - flag_count), red)
if game_status == 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 = win
if game_status == over:
screen.blit(img_face_fail, (face_pos_x, face_pos_y))
elif game_status == win:
screen.blit(img_face_success, (face_pos_x, face_pos_y))
else:
screen.blit(img_face_normal, (face_pos_x, face_pos_y))
Copy the code
Take a look at the results:
Then add various click events, the code implementation is as follows:
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()
ifGame_status == started: # Hold down the left and right mouse keys at the same time, if all mines have been marked, then open a circle around them; If not all mines have been marked, there will be an effect where all around are pressed simultaneouslyif b1 and b3:
mine = block.getmine(x, y)
if mine.status == opened:
if not block.double_mouse_button_down(x, y):
game_status = 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 = readied
block = MineBlock()
start_time = time.time()
elapsed_time = 0
continue
if game_status == readied:
game_status = started
start_time = time.time()
elapsed_time = 0
ifGame_status == started: mine = block.getmine(x, y) #if b1 and not b3:
if mine.status == normal:
ifNot block.open_mine(x, y): game_status = over #if mine.status == normal:
mine.status = flag
elif mine.status == flag:
mine.status = ask
elif mine.status == ask:
mine.status = normal
elif b1 and b3:
if mine.status == double:
block.double_mouse_button_up(x, y)
Copy the code
Let’s take a look at the final implementation:
conclusion
In this article, we have implemented a simple minesweeper game in Python. If you are interested, you can put it into practice and see if you can remove all mines.
PS: Reply “Python” within the public number to enter the Python novice learning exchange group, together with the 100-day plan!
Old rules, brothers still remember, the lower right corner of the “watching” click, if you feel the content of the article is good, remember to share moments to let more people know!
[Code access ****]
Identify the qr code at the end of the article, reply: 201021