Advertisement
Tony041010

MineSweeper_Python_Version

Jun 23rd, 2022
857
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.26 KB | None | 0 0
  1. import random
  2. import re
  3. import time
  4.  
  5. # Board object to represent the minesweeper game
  6. class Board:
  7.     def __init__(self, dim_size, num_bombs):
  8.         # keep track of these parameters
  9.         self.dim_size = dim_size
  10.         self.num_bombs = num_bombs
  11.  
  12.         # create the board using helper function
  13.         self.board = self.make_new_board() # plant the bombs
  14.         self.assign_values_to_board()
  15.         # initialize a set to keep track of which locations we've uncovered
  16.         # we'll save (row, col) tuples into this set
  17.         self.dug = set() # if we dig at 0, 0, then self.dug = {(0,0)}
  18.    
  19.     def make_new_board(self):
  20.         # construct a new board based on the dim size and num bombs
  21.         # using a two-dimentions list (lists in lists)
  22.  
  23.         # generate a new board
  24.         board = [[None for _ in range(self.dim_size)] for _ in range(self.dim_size)]
  25.         # like this :
  26.         # [[None, None,......, None],
  27.         # [None, None,......, None],
  28.         # [None, None,......, None],
  29.         # [None, None,......, None]]
  30.  
  31.         # plant the bombs
  32.         bombs_planted = 0
  33.         while bombs_planted < self.num_bombs:
  34.             loc = random.randint(0, self.dim_size**2 -1)
  35.             row = loc // self.dim_size
  36.             col = loc % self.dim_size
  37.  
  38.             if board[row][col] == '*':
  39.                 # this means we've actually planted a bomb there already
  40.                 continue
  41.                
  42.             board[row][col] = '*'
  43.             bombs_planted += 1
  44.        
  45.         return board
  46.  
  47.  
  48.     def assign_values_to_board(self):
  49.         # assign a number 0-8 for all the empty spaces, which represents how many neighboring bombs there are.
  50.         # We can precompute these and it'll save us some effort checking what's around the board later on
  51.  
  52.         for r in range(self.dim_size):
  53.             for c in range(self.dim_size):
  54.                 if self.board[r][c] == '*':
  55.                     continue
  56.                 self.board[r][c] = self.get_num_neighboring_bombs(r, c)
  57.    
  58.     def get_num_neighboring_bombs(self, row, col):
  59.         # iterate through eac of the neighboring positions and sum number of bombs
  60.         # top left : (row-1, col-1)
  61.         # top middle : (row-1, col)
  62.         # top right : (row-1, col+1)
  63.         # left : (row, col-1)
  64.         # middle : (row, col)
  65.         # right : (row, col+1)
  66.         # bottom left : (row+1, col-1)
  67.         # bottom middle : (row+1, col)
  68.         # bottom right : (row+1, col+1)
  69.  
  70.         # make sure to not go out of bounds!
  71.  
  72.         num_neighboring_bombs = 0
  73.         for r in range(max(0, row-1), min(self.dim_size-1, row+1) + 1):
  74.             for c in range(max(0, col-1), min(self.dim_size-1, col+1) + 1):
  75.                 if r == row and c == col:
  76.                     continue
  77.                 if self.board[r][c] == '*':
  78.                     num_neighboring_bombs += 1
  79.        
  80.         return num_neighboring_bombs
  81.  
  82.     def dig(self, row, col):
  83.         # dig at the certain location
  84.         # return True if  it's a successful dig, False if a bomb has been dug
  85.  
  86.         # a few scenarios:
  87.         # it a bomb -> game over
  88.         # dig at location with neighborin bombs -> finish dig
  89.         # dig at location with no neighboring bombs -> recursively dig neighbors
  90.  
  91.         self.dug.add((row, col)) # keep track of where we've dug
  92.  
  93.         if self.board[row][col] == '*':
  94.             return False
  95.         elif self.board[row][col] > 0:
  96.             return True
  97.        
  98.         # self.board[row][col] == 0
  99.         for r in range(max(0, row-1), min(self.dim_size-1, row+1) + 1):
  100.             for c in range(max(0, col-1), min(self.dim_size, col+1) + 1):
  101.                 if (r, c) in self.dug:
  102.                     continue # don't dig where you've already dug
  103.                 self.dig(r, c)
  104.        
  105.         return True
  106.  
  107.     def __str__(self):
  108.         # this is a magic function where if you call print on this object,
  109.         # it'll print out what this functions returns
  110.         # we'remusing it to return a string that shows the board to the player
  111.  
  112.         visible_board = [[None for _ in range(self.dim_size)] for _ in range(self.dim_size)]
  113.         for row in range(self.dim_size):
  114.             for col in range(self.dim_size):
  115.                 if (row, col) in self.dug:
  116.                     visible_board[row][col] = str(self.board[row][col])
  117.                 else:
  118.                     visible_board[row][col] = ' '
  119.         # put this together in a string
  120.         string_rep = ''
  121.         # get max column widths for printing
  122.         widths = []
  123.         for idx in range(self.dim_size):
  124.             columns = map(lambda x: x[idx], visible_board)
  125.             widths.append(
  126.                 len(
  127.                     max(columns, key = len)
  128.                 )
  129.             )
  130.  
  131.         # print the csv strings
  132.         indices = [i for i in range(self.dim_size)]
  133.         indices_row = '   '
  134.         cells = []
  135.         for idx, col in enumerate(indices):
  136.             format = '%-' + str(widths[idx]) + "s"
  137.             cells.append(format % (col))
  138.         indices_row += '  '.join(cells)
  139.         indices_row += '  \n'
  140.        
  141.         for i in range(len(visible_board)):
  142.             row = visible_board[i]
  143.             string_rep += f'{i} |'
  144.             cells = []
  145.             for idx, col in enumerate(row):
  146.                 format = '%-' + str(widths[idx]) + "s"
  147.                 cells.append(format % (col))
  148.             string_rep += ' |'.join(cells)
  149.             string_rep += ' |\n'
  150.  
  151.         str_len = int(len(string_rep) / self.dim_size)
  152.         string_rep = indices_row + '-'*str_len + '\n' + string_rep + '-'*str_len
  153.  
  154.         return string_rep
  155.  
  156.  
  157.  
  158. # play the game
  159. def play(dim_size=10, num_bombs=10):
  160.     # Step 1 : Create the board and plant the bombs
  161.     board = Board(dim_size, num_bombs)
  162.  
  163.     # Step 2 : Show the user the board and ask for where they want to dig
  164.     # Step 3(a) : If the location is a bomb, show "game over" message
  165.     # Step 3(b) : If the location is not a bomb, dig recursively until each square is at least next to the bomb
  166.     # Step 4 : Repeat steps 2 and 3(a)/(b) until there are no more places to dig -> VICTORY!
  167.     safe = True
  168.     while len(board.dug) < board.dim_size**2 - board.num_bombs:
  169.         print(board)
  170.         print('')
  171.         user_input = re.split(',(\\s)*', input("Where would you like to dig? Input as row,col:")) # '0, 3
  172.         row, col = int(user_input[0]), int(user_input[-1])
  173.         if row < 0 or row >= board.dim_size or col <0 or col >= board.dim_size:
  174.             print("Invalid location. Try again.")
  175.             continue
  176.  
  177.         #if it's valid we dig
  178.         safe = board.dig(row, col)
  179.         if not safe:
  180.             # dug a bomb
  181.             break #(game over. RIP)
  182.         time.sleep(0.5)
  183.    
  184.     time.sleep(1)
  185.    
  186.     # 2 ways to end loop, lets check which one
  187.     if safe:
  188.         print("CONGRATULATIONS! YOU ARE VICTORIOUS")
  189.         time.sleep(5)
  190.     else:
  191.         print("SORRY, GAME OVER :(")
  192.         # reveal the whole board
  193.         board.dug = [(r,c) for r in range(board.dim_size) for c in range(board.dim_size)]
  194.         print(board)
  195.  
  196.         time.sleep(5)
  197.        
  198.  
  199.  
  200.  
  201. if __name__ == '__main__': # even the content of it is only one line code, it's still a good practice
  202.     play()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement