Python Terminal Mine Sweeper

Hello everyone!

I’m pretty new to the forums, and I can already see by the “your topic is similar to…” that I am far from the first person to create a minesweeper game for the portfolio project. I tried to make make mine a little bit different by adding in some flare, but overall it’s probably pretty close to what you expect.

Just some helpful tips, I realized early on that there’s only two moves you can do on any given turn. SO to prevent myself from having to do multiple steps, instead of entering “Select” to select a cell, you can use s:(row),(column) to quickly pick out the cell. Same thing can be done with flags as well ( f:(row),(column) ). Don’t worry if you add spaces or capitalize letters. I also programmed the game to auto-open surrounding cells when the number of flags match the number in the selected cell (if you picked the wrong cell to flag for a mine, it will still cause a game over scenario).

Any feedback you have would be wonderful.

Thanks!

MineSweeper

I’m confused by having this static value:

class Game:
    # Game number shows total games, wins, losses, and cells cleared
    game_num = [0, 0, 0, 0]

    def __init__(self):
        Game.game_num[0] += 1
        self.game_num = Game.game_num[0]

I understand you’re storing those values across instances, but why? If you want to reset your game instance to play again, why not do that?

There’s probably a number of places where you could separate the game engine from all the UI.

The main option is… interesting:

elif "main" in selection:
    Game.game_num[2] += 1
    # this gamelist is in global space?!?
    gamelist.append(Game())
    # why are you saving in a game list?
    gamelist[-1].start_game()

It also seems to just pop you out, so those static totals don’t get adjusted? Your quit, which might have gathered that stack, I suppose, just does a hard exit(). Never call exit(); seriously, don’t. Your logic should be able to find its way out of your game state without it.

This is what I’d like to see:

class Game:
    def __init__(self):
        self.done = False
        self.played, self.wins = 0, 0
        # losses can be derived, (self.played - self.wins)

# a basic game loop
game = Game()
while not game.done:
    game.play()

If the user chooses “main”, you return from play. If the user chooses “quit”, you return from play after setting self.done = True.

Calling play(), course, does all the setup for a new game and then, well, does all the stuff you’re doing in start_game(). So just start_game() with some of that setup from your constructor.

Hope this makes sense and works for you.

Thanks for the feedback!

I agree, creating another instance of the game class in the gamelist is a bad idea as this chews-up valuable resources on something that’s already been completed. Originally the intent was to create a print function that could then print all the games you had played in that session to a text file, but that could be more easily achieved by saving the final state of the tiles to the list rather than opening a new instance of the game.

The only advantage is that if I changed the return to main menu into a paused-game feature… well then you could quickly resume any of the games in the session instead of starting a new one. Again, not exactly a great use of system resources though. (I’ll be thinking about all of this if I continue updating)

Speaking of the “main” UI:
Main is meant to function like a return to main menu. If you use main before the first cell is selected, it’s not meant to incur a loss because that’s a free one (ie maybe you didn’t intend to start a new game yet). I also had plans for other main menu features but… maybe I’ll work on this more in a bit.

Quit is meant to terminate the script. It’s also separated out because ideally in the future quit would run a small script that saves stats to a text file for stat tracking… but I never got to that so for the time being its just exit. If I removed the hard exit logic, it still finds its way out. However, my original intent for “quit” was to push the player back to the terminal and end the script, not to keep them in Python.