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!
-
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) ```
-
@Tonnoaw, very nice-looking and functional game, congratulations!
Unfortunately, the whole board does not fit on an iPhone screen.
-
@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.
-
@mikael Thanks for your suggestions . I'll apply your suggestions in my next projects and practices
-
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.
-
@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.