python implementation of "minesweeping" small game

Children and old people are not deceived. The main program is definitely less than 60 lines (and it is still the kind of blank line)!!!

Don't say much nonsense, just talk about the process.

1. Draw a horizontal line and a vertical line to separate the grid (please, Xiaobian. This is known to everyone. OK, can't you pick the key points to talk about!)

2. Create a 20 * 20 array, all initialized to 0, indicating a blank game map.

3. 40 mines are randomly generated in the map (X is used in the code implementation). Each time a mine is generated, the number of the square around it (not the square of the mine) should be added by 1.

4. Create a class to manage the grids that have not been clicked. Use the list to store the coordinates of all the grids that have not been clicked. After the mouse clicks a grid, judge the legitimacy of the location of the single machine. If it is legal, remove the coordinates of the grid clicked by the mouse from the list, representing that the grid has been clicked. Each time the screen is updated, the corresponding grid cover is drawn according to the elements in the list.

5. Create a class to manage the clicked grid, use a list to store the coordinates of all the clicked grids, and draw the corresponding pattern according to the array in 2 (if the corresponding number is 0, then don't draw anything, just display the background color).

6. Every time a grid is opened, if the number is 0, use the width search to display all the grids directly connected to it with the number of 0

Well, I don't want to say anything superfluous. More detailed explanations are presented in the form of comments in the corresponding code.

Code server.

If you don't believe your own numbers, plus all the blank lines, the main program (the life-saving guy can't lose it!) The last line is also line 59 (this wave is actually licking blood on the blade tip!!!)

import sys   #Call the exit() function to end the game

import pygame

from covers import Cover    #Cover on the surface when the square is not clicked
from map_of_game import Map   #Map inside the game box
from settings import setting  #Game parameter settings


class Game:
        """Manage the main program of the game"""

        def __init__(self):
                pygame.init()
                self.setting = setting()

                #Create the game main interface
                self.screen = pygame.display.set_mode(self.setting.screen_size)
                self.screen_rect = self.screen.get_rect()
                pygame.display.set_caption('mine clearance')

                self.covers = Cover(self.setting, self.screen)  #Surface covering
                self.maps = Map(self.setting, self.covers, self.screen)  # internal map



        def run_game(self):
                while True:
                        self._event_check_()  #Detection event
                        self._update_screen_()  #Update screen

        def _event_check_(self):
                for event in pygame.event.get():
                        if event.type == pygame.QUIT:  #End the game
                                sys.exit()
                        elif event.type == pygame.MOUSEBUTTONDOWN:
                                x, y = pygame.mouse.get_pos()  #A mouse click event is detected, and the mouse position is passed in
                                self.covers.delete(x, y) #Delete the cover on the corresponding box
                                self.maps.add(x, y)  #Add the game map under the cover of this position to the team to be displayed

        def _update_screen_(self):

                self.screen.fill(self.setting.background_color) #Fill background color

                for i in range(25): #Draw squares
                        pygame.draw.line(self.screen, self.setting.line_color, [0, i * 25], [500, i * 25],
                                         self.setting.line_width) #Horizontal line
                        pygame.draw.line(self.screen, self.setting.line_color, [i * 25, 0], [i * 25, 500],
                                         self.setting.line_width) #Vertical line

                self.maps.show()   #Show the numbers under all the clicked squares
                self.covers.show() #Show the numbers that have not been clicked

                pygame.display.update()  #Update the screen display and show the above work on the game interface


if __name__ == '__main__':
        my_game = Game()
        my_game.run_game()

class setting:
        """A class that manages parameters in a game"""

        def __init__(self):
                self.screen_size = (500, 500)  # Screen size:
                self.background_color = (255, 255, 255)  # Background color
                self.line_width = 1  # Line thickness
                self.line_color = (120, 120,120)  # line color
                self.block_width = 24 #Width of each square
                self.screen_color = (150, 150, 150)  # Display interface color

import pygame


class Cover:
        """Classes that manage game coverings"""
        def __init__(self, setting, screen):  #Game parameter setting and game main interface
                self.setting = setting
                self.screen = screen

                self.covers = []  # Stores the location of the cover of the square that has not been clicked
                for i in range(20):
                        for j in range(20):
                                self.covers.append([i, j])  #At the beginning, the entire interface was covered

        def delete(self, x, y):  #Pass in the position of the stand-alone mouse to determine whether it is legal. If yes, delete the current box
                x = x // 25
                y = y // 25
                if [x, y] in self.covers:
                        self.covers.remove([x, y])

        def show(self):  #Show all the squares that have not been clicked
                for cur in self.covers:
                        pygame.draw.rect(self.screen, self.setting.screen_color, ((cur[0] * 25, cur[1] * 25), (24, 24)))

from random import randint

import pygame

from game_over import Over


class Map:
        """Manage thunder and numbers in the game"""

        def __init__(self, setting, covers, screen): #Game parameters, game coverage, game interface
                self.setting = setting
                self.bg_color = self.setting.background_color
                self.screen = screen
                self.covers = covers

                #All initial values are 0 at the beginning, indicating that there is nothing in the current box
                self.maps = [[0 for _ in range(20)] for _ in range(20)]

                #In the state transition array, all (x+moves[i][0], y+moves[i][1]) represent the other 8 blocks surrounding the (x, y) block,
                #It is used to update the number on the square around the mine after it is randomly generated
                self.moves = [[-1, -1], [0, -1], [1, -1], [-1, 0], [1, 0], [-1, 1], [0, 1], [1, 1]]

                #What is stored is the subscript in the corresponding moves array of the upper, left, right and lower state transitions of (x,y)
                self.move_to = [1, 3, 4, 6]

                #Stores the current number box that needs to be displayed
                self.now_show = []

                #Click on the mine to end the game
                self.over = Over(self.screen)

                #Randomly generate game map
                self._born_map()

        def _born_map(self):
                """Randomly generated map"""
                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'
                        self._connect_(x, y) #Update figures around mines

        def _connect_(self, x, y):
                """Function to update numbers around mines"""
                for cur in self.moves:
                        i = x + cur[0]
                        j = y + cur[1]
                        if i >= 0 and i < 20 and j >= 0 and j < 20 and self.maps[i][j] != 'X':
                                self.maps[i][j] += 1

        def add(self, x, y):  #Pass in the position of the current mouse click to judge the validity. If it is legal, pass the left side of the corresponding box into the list to be displayed
                i = x // 25
                j = y // 25
                if i >= 0 and i < 20 and j >= 0 and j < 20:
                        self.now_show.append([i, j])
                        if self.maps[i][j] == 0:
                                self._add_connect_(i, j)

                #If a landmine is currently clicked, mark the landmine as a red square and display it. Pause the game for 3 seconds and automatically exit the game
                if self.maps[i][j] == 'X':
                        pygame.draw.rect(self.screen, (255, 0, 0), ((i * 25, j * 25), (25, 25)))
                        self.over.show()

        # The blank squares directly connected to (x,y) are also displayed
        def _add_connect_(self, x, y):
                que = []
                que.append([x, y])
                while que:
                        cur = que[-1]
                        del (que[-1])
                        for k in self.move_to:
                                i, j = cur[0] + self.moves[k][0], cur[1] + self.moves[k][1]
                                if i >= 0 and i < 20 and j >= 0 and j < 20 and self.maps[i][j] == 0 and [i,
                                                                                                         j] not in self.now_show:
                                        self.now_show.append([i, j])
                                        self.covers.delete(i * 25, j * 25)
                                        que.append([i, j])

        def show(self):
                """Display the generated map on the screen"""
                for cur in self.now_show:
                        i = cur[0]
                        j = cur[1]
                        if self.maps[i][j] == 0:
                                continue
                        else:
                                self.msg = str(self.maps[i][j])
                                self.font = pygame.font.SysFont(None, 45)
                                self.font_image = self.font.render(self.msg, True, (60, 0, 0), None)
                                self.image_ract = self.font_image.get_rect()
                                self.image_ract.x = i * 25
                                self.image_ract.y = j * 25
                                self.image_ract.width = 24
                                self.image_ract.height = 24
                                self.screen.blit(self.font_image, self.image_ract)

import sys  #End the game
from time import sleep  #Pause the game

import pygame


class Over:
        """Class that controls the end of the game"""
        def __init__(self, screen): #Game main interface
                self.is_over = False
                self.screen = screen
                self.screen_rect = self.screen.get_rect()

                self.msg = 'GAME OVER'
                #Render the text 'GAME OVER' to the game main interface
                self.font = pygame.font.SysFont(None, 48)
                self.image = self.font.render(self.msg, True, (100, 0, 0), (0, 0, 60))
                self.rect = self.image.get_rect()
                self.rect.center = self.screen_rect.center  #Place text in the center of the interface

        def show(self):  #When you encounter a bomb, the game ends. Before the end, mark the bomb that the player encounters with a red square and draw it before the end
                self.screen.blit(self.image, self.rect)
                pygame.display.update()
                sleep(3)
                sys.exit()

 

 

See here, don't want to praise!!! (sobbing)

 

 

Tags: Python pygame

Posted by Jorge on Tue, 23 Aug 2022 13:20:44 +0930