omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    I created 2D minesweeper game, Try out!

    Pythonista
    game python 3 minesweeper scene
    3
    6
    3000
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Tonnoaw
      Tonnoaw last edited by ccc

      I created 2D minesweeper game
      I've learned Python for a month and I decided to create 2D minesweeper game using scene module in Pythonista. I want some recommendations from any experts to make my code more cleaner and remove some unnecessary steps.
      Also try out my game :)

      from scene import *
      import sound
      import random
      
      #randomly install the mines on the board
      def setTheMine(board):
              for i in range(int(len(board))):
                  board[random.randint(0,len(board) - 1)][random.randint(0,len(board) - 1)] = "#"
              return board
              
      class App(Scene):    
          def setup(self):
              self.x, self.y = 0, 0
              #turn cheat to True to see the mines while playing
              self.cheat = False
              #create 2d matrix board
              # '-' = empty space and '#' = mine
              self.board = [["-" for i in range(10)] for i in range(10)]
              self.background_color = '#828adb'
              #install the mine
              self.board = setTheMine(self.board)
              #assign tile coordinates  
              self.tileDict = {}
              for row in range(len(self.board)):
                  for block in range(len(self.board[0])):
                      posist = str(block)+str(row)
                      posX_value = int(self.size.w / 2) - int((len(self.board) * 48) / 2) + (48 * block)
                      posY_value = int(self.size.h / 2) + int((len(self.board) * 48) / 2) - (48 * row)
                      x = self.tileDict.setdefault(posist, (posX_value, posY_value))
              #tile color according values
              self.tileColor = {
                  "0": 'pzl:Green3',
                  "1": 'pzl:Blue3',
                  "2": 'pzl:Yellow3',
                  "3": 'pzl:Red3',
                  "4": 'pzl:Red3',
                  "5": 'pzl:Red3',
                  "6": 'pzl:Red3',
                  "7": 'pzl:Red3',
                  "-": 'pzl:Gray3',
                  "#": 'pzl:Gray3'
              }
              self.labelFont = ('Adidas Unity', 50)
              self.gameStart = True
              #display 2D graphic board
              self.displayBoard()
              
          def touch_began(self, touch):
              self.x, self.y = touch.location
              
          def displayBoard(self):
              grid = Node(parent=self)
              row1 = 0
              for row in self.board:
                  column = 0
                  for block in row:
                      posX , posY = self.tileDict.get(str(column)+str(row1))
                      tile = SpriteNode(Texture(self.tileColor.get(block)), position = (posX, posY), scale = 1.5)
                      grid.add_child(tile)
                      if self.cheat:
                          if block == '#':
                              self.mine = SpriteNode(Texture('emj:Bomb'), position = (posX, posY), scale = 0.5)
                              self.add_child(self.mine)
                      if block is not "-" and block is not "#":
                          self.mineLabel = LabelNode(self.board[row1][column], self.labelFont, position = (posX, posY), scale = 0.5)
                          self.add_child(self.mineLabel)
                      column += 1
                  row1 += 1
                               
          def update(self):
              #check for touch input. is touch input on the board 
              found = False
              for y in range(len(self.board)):
                  for x in range(len(self.board[0])):
                      testCase = str(x)+str(y)
                      #x and y coordinates for each tile
                      testPosX, testPosY = self.tileDict.get(testCase)
                      if testPosX - 24 < self.x < testPosX + 24 and testPosY - 24 < self.y < testPosY + 24: 
                          self.x, self.y = 0, 0
                          sound.play_effect('8ve:8ve-beep-shinymetal')
                          if self.gameStart:
                              found = True
                          #tile that user touched
                          tileSelected = testCase
                          break
                  if found:
                      break
              if found:
                  #check if user touched on the mine
                  if self.board[int(tileSelected[1])][int(tileSelected[0])] is "#":
                      self.gameStart = False
                      self.gameStatus = 'lose'
                  else:
                  #else reveal the number of mines that surround the tile
                      if self.board[int(tileSelected[1])][int(tileSelected[0])] is not "#":
                          self.board = zeroScanning(self.board, (int(tileSelected[0]), int(tileSelected[1])))
                  self.foundSpace = False
                  #check if all tiles are revealed
                  for row in self.board:
                      for tile in row:
                          if tile is '-':
                              self.foundSpace = True
                              break
                      if self.foundSpace:
                          break
                  #if there is no empty tile left = win!
                  if self.foundSpace == False:
                      self.gameStatus = 'win'
                      self.gameStart = False
                  if self.gameStart:
                      self.displayBoard()
                  #if game ends
                  else:
                      #reveals the mine
                      self.cheat = True
                      self.gameStart = False
                      self.displayBoard()
                      if self.gameStatus == 'lose':
                          self.statusLabel = LabelNode('LOSE!', ('Anantason', 25), position = (self.size.x / 2, 750), scale = 3, color = '#ff0000')
                      if self.gameStatus == 'win':
                          self.statusLabel = LabelNode('WIN!', ('Anantason', 25), position = (self.size.x / 2, 750), scale = 3, color = '#7aff13')
                      self.add_child(self.statusLabel)
              #reset the touch inout
              self.x, self.y = 0, 0
          
      def countMines(board, coor):
          tileX, tileY = coor
          mineCount = 0
          #check surrounding tiles
          for y in range(-1, 2):
              for x in range(-1, 2):
                  try:
                      #prevent of negative index
                      if int(tileX) + x != -1 and int(tileY) + y != -1:
                          if board[int(tileY) + y][int(tileX) + x] == "#":
                              mineCount += 1
                  except IndexError:
                      pass
          return str(mineCount)
                      
      def zeroScanning(board, coordinate):
          PosX, PosY = coordinate
          board[PosY][PosX] = countMines(board, (PosX, PosY))
          if countMines(board, (PosX, PosY)) == '0':
              for testX in range(-1, 2):
                  for testY in range(-1, 2):       
                      PosX1 = PosX + testX
                      PosY1 = PosY + testY
                      try:
                          if (PosX1 != -1 and PosY1 != -1):
                              if countMines(board, (PosX1, PosY1)) == "0" and board[PosY1][PosX1] != '0':
                                  zeroScanning(board, (PosX1, PosY1))
                              else:
                                  board[PosY1][PosX1] = countMines(board, (PosX1, PosY1))
                      except IndexError:
                          pass
          return board
              
      if __name__ == '__main__':
          run(App(), LANDSCAPE) ```
      mikael 2 Replies Last reply Reply Quote 1
      • mikael
        mikael @Tonnoaw last edited by

        @Tonnoaw, very nice-looking and functional game, congratulations!

        Unfortunately, the whole board does not fit on an iPhone screen.

        1 Reply Last reply Reply Quote 0
        • mikael
          mikael @Tonnoaw last edited by

          @Tonnoaw, some improvement auggestions, on a quick read through:

          • You can use self.size to fit the board to screen.
          • setTheMine and the functions at the bottom could be in the class, for consistency.
          • Using continuously-running update to wait for touches seems curious, instead of just triggering the update from the touch method.
          • Also, maybe I am not getting all the details here, but the string based coordinates, converting with ints etc. looks like it could be optimized, storing more directly what you need in the matrix.
          • For readability, I would recommend learning the Python conventions: variables, functions and methods are lower_case, while classes are immediately recognizable since only they are CamelCased.

          Besides the size thing, these are of course all just focused on efficiency and style.

          Tonnoaw 1 Reply Last reply Reply Quote 0
          • Tonnoaw
            Tonnoaw @mikael last edited by Tonnoaw

            @mikael Thanks for your suggestions . I'll apply your suggestions in my next projects and practices

            1 Reply Last reply Reply Quote 0
            • PinhoBD
              PinhoBD last edited by

              Very interesting game. For similar game idea for young children, I would change mines into coins (or even Easter eggs) and count how many touches it takes to collect how many coins.

              1 Reply Last reply Reply Quote 0
              • PinhoBD
                PinhoBD last edited by

                @Tonnoaw I would also try to import game_menu.py and build a menu with title and option selection buttons. So, rather than setting “cheat” mode in the script, define a mode button for a non-programmer to change mode of operation.

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post
                Powered by NodeBB Forums | Contributors