Пример #1
0
    def test_select(self):
        game = Game(GameConfig(3, 3, 2))
        board = self.flip([[False, True, False], [False, False, False],
                           [False, False, True]])
        self.reinit_game(game, board)

        #expose only same square
        result = game.select(1, 1)
        self.assertFalse(result.explosion)
        self.assertEqual(1, len(result.new_squares))
        self.assertEqual(result.new_squares[0], Position(1, 1, 2))

        #expose neighbors
        result = game.select(0, 2)
        self.assertFalse(result.explosion)
        self.assertEqual(3, len(result.new_squares))
        self.assertTrue(Position(0, 2, 0) in result.new_squares)
        self.assertTrue(Position(0, 1, 1) in result.new_squares)
        self.assertTrue(Position(1, 2, 1) in result.new_squares)

        #select square already selected or exposed
        self.assertIsNone(game.select(0, 2))
        self.assertIsNone(game.select(1, 2))

        #select outside the board
        with self.assertRaises(ValueError):
            game.select(2, 3)

        #boom
        result = game.select(1, 0)
        self.assertTrue(result.explosion)

        #select after game over
        with self.assertRaises(ValueError):
            game.select(2, 0)
Пример #2
0
 def test_reveal_mine(self):
     game = Game(self.mines, self.flags)
     self.assertEqual(False, game.reveal(1, 1))
     self.assertEqual(self.flags, Table.from_nested_list([
         [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown],
         [Flags.Unknown, Flags.Revealed, Flags.Unknown, Flags.Unknown],
         [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown],
         [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown],
     ]))
Пример #3
0
 def test_reveal_empty(self):
     game = Game(self.mines, self.flags)
     self.assertEqual(True, game.reveal(3, 3))
     self.assertEqual(self.flags, Table.from_nested_list([
         [Flags.Unknown, Flags.Unknown, Flags.Revealed, Flags.Revealed],
         [Flags.Unknown, Flags.Unknown, Flags.Revealed, Flags.Revealed],
         [Flags.Revealed, Flags.Revealed, Flags.Revealed, Flags.Revealed],
         [Flags.Revealed, Flags.Revealed, Flags.Revealed, Flags.Revealed],
     ]))
Пример #4
0
class TUITest(TestCase):
    def setUp(self):
        self.screen = FakeScreen()
        curses_module = FakeCurses(screen=self.screen)
        self.subject = TUI(curses_module=curses_module)

    def test_initial_board_state(self):
        self.simulate_game([])

        expected_snapshot = ['.....',
                             '.....',
                             '.....',
                             '.....',
                             '.....']

        self.assertEqual(self.screen.get_snapshot(), expected_snapshot)

    def test_reveal_single_numbered_cell(self):
        self.simulate_game([curses.KEY_RIGHT, ' '])
        expected_snapshot = ['.2...',
                             '.....',
                             '.....',
                             '.....',
                             '.....']
        self.assert_equal_snapshots(self.screen.get_snapshot(), expected_snapshot)

    def test_reveal_expanding_zero_cell(self):
        self.simulate_game([curses.KEY_RIGHT, curses.KEY_RIGHT, curses.KEY_RIGHT, curses.KEY_RIGHT, ' '])
        expected_snapshot = ['..1  ',
                             '..21 ',
                             '...21',
                             '.....',
                             '.....']
        self.assert_equal_snapshots(self.screen.get_snapshot(), expected_snapshot)

    # Private
    def assert_equal_snapshots(self, snapshot, expected_snapshot):
        self.assertEqual(self.screen.get_snapshot(),
                         expected_snapshot,
                         "\n\nExpected: \n\n{}\n\nBut got this instead:\n\n{}".format("\n".join(expected_snapshot),
                                                                                      "\n".join(snapshot)))

    def simulate_game(self, commands):
        self.screen.simulate_commands(commands)

        minefield_repository = InMemoryMinefieldRepository()
        turn_repository = InMemoryTurnRepository()
        mine_planter = LazyBeeMinePlanter()
        self.game = Game(minefield_repository=minefield_repository,
                         turn_repository=turn_repository,
                         mine_planter=mine_planter)

        self.game.start_new_game(row_count=5,
                                 column_count=5,
                                 observer=self.subject)
Пример #5
0
    def test_get_state(self):
        game = Game(GameConfig(3, 3, 3))
        board = self.flip([[False, False, True], [False, False, False],
                           [True, False, True]])
        self.reinit_game(game, board)

        game.select(0, 0)
        expected = self.flip([[0, 1, None], [1, 3, None], [None, None, None]])

        state = game.get_state()
        for x in [0, 1, 2]:
            for y in [0, 1, 2]:
                self.assertEqual(expected[x][y], state[x][y])
Пример #6
0
 def test_reveal_revealed_hint(self):
     self.flags = Table.from_nested_list([
         [Flags.Revealed, Flags.Unknown, Flags.Unknown, Flags.Unknown],
         [Flags.Unknown, Flags.Marked, Flags.Unknown, Flags.Unknown],
         [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown],
         [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown],
     ])
     game = Game(self.mines, self.flags)
     self.assertEqual(True, game.reveal(0, 0))
     self.assertEqual(self.flags, Table.from_nested_list([
         [Flags.Revealed, Flags.Revealed, Flags.Unknown, Flags.Unknown],
         [Flags.Revealed, Flags.Marked, Flags.Unknown, Flags.Unknown],
         [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown],
         [Flags.Unknown, Flags.Unknown, Flags.Unknown, Flags.Unknown],
     ]))
Пример #7
0
def restart():
    req = request.get_json()
    col = req['col']
    row = req['row']
    mines = req['mines']
    session['game'] = Game(row, col, mines)
    game_obj = session['game']
    return get_game_obj_response(game_obj)
Пример #8
0
def mark():
    req = request.get_json()
    col = req['col']
    row = req['row']
    if 'game' not in session:
        session['game'] = Game(*default_game)
    game_obj = session['game']
    game_obj.mark(row, col)
    session['game'] = game_obj
    return get_game_obj_response(game_obj)
Пример #9
0
 def test_init_counts(self):
     game = Game(GameConfig(5, 4, 4))
     board = self.flip([[True, False, False, False, False],
                        [False, False, False, True, False],
                        [False, False, False, True, False],
                        [False, False, True, False, False]])
     counts = self.flip([[0, 1, 1, 1, 1], [1, 1, 2, 1, 2], [0, 1, 3, 2, 2],
                         [0, 1, 1, 2, 1]])
     self.reinit_game(game, board)
     self.assertEqual(counts, game.counts)
Пример #10
0
    def test_get_state(self):
        game = Game(GameConfig(3, 3, 3))
        board = self.flip([
            [False, False, True],
            [False, False, False],
            [True,  False, True]
        ])
        self.reinit_game(game, board)

        game.select(0, 0)
        expected = self.flip([
          [0,    1,    None],
          [1,    3,    None],
          [None, None, None]
        ])

        state = game.get_state()
        for x in [0, 1, 2]:
            for y in [0, 1, 2]:
                self.assertEqual(expected[x][y], state[x][y])
Пример #11
0
    def simulate_game(self, commands):
        self.screen.simulate_commands(commands)

        minefield_repository = InMemoryMinefieldRepository()
        turn_repository = InMemoryTurnRepository()
        mine_planter = LazyBeeMinePlanter()
        self.game = Game(minefield_repository=minefield_repository,
                         turn_repository=turn_repository,
                         mine_planter=mine_planter)

        self.game.start_new_game(row_count=5,
                                 column_count=5,
                                 observer=self.subject)
Пример #12
0
    def test_select(self):
        game = Game(GameConfig(3, 3, 2))
        board = self.flip([
            [False, True,  False],
            [False, False, False],
            [False, False, True]
        ])
        self.reinit_game(game, board)

        #expose only same square
        result = game.select(1, 1)
        self.assertFalse(result.explosion)
        self.assertEqual(1, len(result.new_squares))
        self.assertEqual(result.new_squares[0], Position(1, 1, 2))

        #expose neighbors
        result = game.select(0, 2)
        self.assertFalse(result.explosion)
        self.assertEqual(3, len(result.new_squares))
        self.assertTrue(Position(0, 2, 0) in result.new_squares)
        self.assertTrue(Position(0, 1, 1) in result.new_squares)
        self.assertTrue(Position(1, 2, 1) in result.new_squares)

        #select square already selected or exposed
        self.assertIsNone(game.select(0, 2))
        self.assertIsNone(game.select(1, 2))

        #select outside the board
        with self.assertRaises(ValueError):
            game.select(2, 3)

        #boom
        result = game.select(1, 0)
        self.assertTrue(result.explosion)

        #select after game over
        with self.assertRaises(ValueError):
            game.select(2, 0)
Пример #13
0
    def test_is_game_over(self):
        game = Game(GameConfig(3, 3, 1))
        board = self.flip([[False, False, True], [False, False, False],
                           [False, False, False]])
        self.reinit_game(game, board)

        #not over before we start
        self.assertFalse(game.is_game_over())

        #over after explosion
        result = game.select(2, 0)
        self.assertTrue(result.explosion)
        self.assertTrue(game.is_game_over())

        #over when all the squares have been revealed
        self.reinit_game(game, board)
        result = game.select(0, 0)
        self.assertFalse(result.explosion)
        self.assertEqual(8, len(result.new_squares))
        self.assertTrue(game.is_game_over())
Пример #14
0
    def test_is_game_over(self):
        game = Game(GameConfig(3, 3, 1))
        board = self.flip([
            [False, False, True],
            [False, False, False],
            [False, False, False]
        ])
        self.reinit_game(game, board)

        #not over before we start
        self.assertFalse(game.is_game_over())

        #over after explosion
        result = game.select(2, 0)
        self.assertTrue(result.explosion)
        self.assertTrue(game.is_game_over())

        #over when all the squares have been revealed
        self.reinit_game(game, board)
        result = game.select(0, 0)
        self.assertFalse(result.explosion)
        self.assertEqual(8, len(result.new_squares))
        self.assertTrue(game.is_game_over())
Пример #15
0
 def setUp(self):
     minefield_repository = InMemoryMinefieldRepository()
     turn_repository = InMemoryTurnRepository()
     self.subject = Game(minefield_repository=minefield_repository,
                         turn_repository=turn_repository,
                         mine_planter=LazyBeeMinePlanter())
Пример #16
0
# Make a path for our model to be saved in.
if not os.path.exists(path):
    os.makedirs(path)

print("Start training.")
with tf.Session() as sess:
    sess.run(init)
    if load_model:
        print('Loading Model...')
        ckpt = tf.train.get_checkpoint_state(path)
        saver.restore(sess, ckpt.model_checkpoint_path)
    for i in range(num_episodes):
        episodeBuffer = qnetwork.ExperienceBuffer()
        # Reset environment and get first new observation
        game = Game(field_size, field_size, mines)
        s = game.state()
        d = False
        rAll = 0
        j = 0
        actions = []
        # The Q-Network
        while j < max_epLength:  # If the network takes more moves than needed for the field, cancel episode
            j += 1
            # Choose an action by greedily (with e chance of random action) from the Q-network
            if np.random.rand(1) < e or total_steps < pre_train_steps:
                a = np.random.randint(0, num_actions)
            else:
                a = sess.run(mainQN.predict,
                             feed_dict={
                                 mainQN.input:
Пример #17
0
 def test_place_mines(self):
     game = Game(GameConfig(100, 100, 800))
     self.assertEqual(800, sum([row.count(True) for row in game.board]))
Пример #18
0
def main(argv=None):
    available_directors = get_directors()

    parser = argparse.ArgumentParser(
        description='Minesweeper with an AI interface')

    parser.add_argument('-s', '--scenario',
                        type=argparse.FileType('r'),
                        help='Scenario/saved game to load')
    parser.add_argument('--state',
                        help='Game state to load')
    parser.add_argument('-u', '--scenario-unrevealed',
                        type=bool,
                        default=False,
                        help='Load scenario completely unrevealed')
    parser.add_argument('-r', '--repeat',
                        default=False,
                        action='store_true',
                        help='Repeat loaded scenario')

    parser.add_argument('-d', '--director',
                        choices=['none'] + list(available_directors),
                        default='attempt2',
                        help='AI director to use (none to disable)')
    parser.add_argument('--director-skip-frames',
                        type=int,
                        default=1,
                        help='Number of frames to skip between director steps')

    parser.add_argument('-m', '--mode',
                        choices=['winxp', 'win7'],
                        default='win7',
                        help='Which minesweeper mode to emulate '
                             '(winxp=clear first clicked cell,'
                             ' win7=clear neighbours of first clicked cell)')

    parser.add_argument("-v", "--verbose", help="increase output verbosity",
                        action="store_true")

    args = parser.parse_args(argv)
    if args.verbose:
        logging.basicConfig(level=logging.DEBUG)

    game = Game()

    game.director_skip_frames = args.director_skip_frames
    if args.director:
        director = available_directors.get(args.director)()
        if director:
            game.set_director(director)

    if args.scenario and args.state:
        raise RuntimeError("Cannot load both game state (--state) and scenario (-s/--scenario)")

    if args.scenario or args.state:
        if args.scenario:
            # We want to manage opening the file ourselves
            args.scenario.close()

            def load_scenario():
                game.load(args.scenario.name, unrevealed=args.scenario_unrevealed)

        elif args.state:
            serialized = args.state.replace('\\n', '\n')

            def load_scenario():
                game.deserialize(serialized)
        else:
            assert False, 'THIS SHOULD NOT HAPPEN'

        if args.repeat:
            def on_margin_clicked():
                game.init_game()
                load_scenario()
            game.on_margin_clicked = on_margin_clicked

        load_scenario()

    game.clear_neighbors_of_first_click = args.mode == 'win7'

    game.run()
Пример #19
0
class TestGame(TestCase):
    def setUp(self):
        minefield_repository = InMemoryMinefieldRepository()
        turn_repository = InMemoryTurnRepository()
        self.subject = Game(minefield_repository=minefield_repository,
                            turn_repository=turn_repository,
                            mine_planter=LazyBeeMinePlanter())

    def test_play_with_invalid_row_count(self):
        assert_invalid_board_parameters_should_raise_exception(create_board=self.subject.start_new_game,
                                                               row_count=4,
                                                               column_count=5,
                                                               expected_minimum_row_count=5,
                                                               expected_minimum_column_count=5,
                                                               test_case=self)

    def test_play_with_invalid_column_count(self):
        assert_invalid_board_parameters_should_raise_exception(create_board=self.subject.start_new_game,
                                                               row_count=5,
                                                               column_count=4,
                                                               expected_minimum_row_count=5,
                                                               expected_minimum_column_count=5,
                                                               test_case=self)

    def test_play_with_valid_dimensions_should_notify_observer_with_board(self):
        spy = Mock(GameObserver)
        self.subject.start_new_game(row_count=5, column_count=5, observer=spy)

        board = spy.game_did_create_board.call_args[1]['board']
        expected_board = Board(row_count=5, column_count=5)

        assert_boards_equal(board=board, expected_board=expected_board, test_case=self)

    def test_play_with_valid_dimensions_should_notify_observer_with_board_snapshot(self):
        spy = Mock(GameObserver)
        self.subject.start_new_game(row_count=5, column_count=5, observer=spy)

        board_snapshot = spy.game_did_create_board.call_args[1]['board_snapshot']

        expected_board_snapshot = [
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown],
        ]

        assert_board_snapshots_equal(board_snapshot=board_snapshot,
                                     expected_board_snapshot=expected_board_snapshot,
                                     test_case=self)

    def test_play_with_valid_dimensions_should_notify_observer_with_create_minefield(self):
        spy = Mock(GameObserver)
        self.subject.start_new_game(row_count=5, column_count=5, observer=spy)

        create_minefield = spy.game_did_create_board.call_args[1]['create_minefield']

        create_minefield(row_index=0, column_index=4)

        call_args = spy.game_did_create_minefield.call_args[1]
        board_snapshot = call_args['board_snapshot']

        expected_board_snapshot = [
            [CellType.Unknown, CellType.Unknown, CellType.One, CellType.Zero, CellType.Zero],
            [CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One, CellType.Zero],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown],
        ]
        assert_board_snapshots_equal(board_snapshot=board_snapshot,
                                     expected_board_snapshot=expected_board_snapshot,
                                     test_case=self)

    def test_play_with_valid_dimensions_should_notify_observer_with_game_state(self):
        spy = Mock(GameObserver)
        self.subject.start_new_game(row_count=5, column_count=5, observer=spy)

        create_minefield = spy.game_did_create_board.call_args[1]['create_minefield']

        create_minefield(row_index=0, column_index=4)

        call_args = spy.game_did_create_minefield.call_args[1]
        game_state = call_args['game_state']
        self.assertEqual(game_state, GameState.Started)

    def test_play_with_valid_dimensions_should_notify_observer_with_board_snapshot_after_minefield_creation(self):
        first_turn = RawTurn(action=TurnAction.RevealCell, coordinate=Coordinate(row_index=0, column_index=4))

        board_snapshot = self.simulate_start_game(row_count=5, column_count=5, turns=[first_turn])

        expected_board_snapshot = [
            [CellType.Unknown, CellType.Unknown, CellType.One, CellType.Zero, CellType.Zero],
            [CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One, CellType.Zero],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown],
        ]
        assert_board_snapshots_equal(board_snapshot=board_snapshot,
                                     expected_board_snapshot=expected_board_snapshot,
                                     test_case=self)

    def test_play_with_valid_dimensions_should_notify_observer_with_game_state_started_after_second_turn(self):
        spy = Mock(GameObserver)
        self.subject.start_new_game(row_count=5, column_count=5, observer=spy)

        create_minefield = spy.game_did_create_board.call_args[1]['create_minefield']

        create_minefield(row_index=0, column_index=4)

        call_args = spy.game_did_create_minefield.call_args[1]

        reveal_cell = call_args['reveal_cell']
        reveal_cell(row_index=0, column_index=1)

        call_args = spy.game_did_take_turn.call_args[1]
        game_state = call_args['game_state']

        self.assertEqual(game_state, GameState.Started)

    def test_play_with_valid_dimensions_should_notify_observer_with_game_state_started_after_second_turn_reveals_mine(
            self):
        spy = Mock(GameObserver)
        self.subject.start_new_game(row_count=5, column_count=5, observer=spy)

        create_minefield = spy.game_did_create_board.call_args[1]['create_minefield']

        create_minefield(row_index=0, column_index=4)

        call_args = spy.game_did_create_minefield.call_args[1]

        reveal_cell = call_args['reveal_cell']
        reveal_cell(row_index=0, column_index=0)

        call_args = spy.game_did_take_turn.call_args[1]
        game_state = call_args['game_state']

        self.assertEqual(game_state, GameState.Lost)

    def test_play_with_valid_dimensions_should_notify_observer_with_board_snapshot_after_second_turn(self):
        spy = Mock(GameObserver)
        self.subject.start_new_game(row_count=5, column_count=5, observer=spy)

        create_minefield = spy.game_did_create_board.call_args[1]['create_minefield']

        create_minefield(row_index=0, column_index=4)

        call_args = spy.game_did_create_minefield.call_args[1]

        reveal_cell = call_args['reveal_cell']
        reveal_cell(row_index=0, column_index=1)

        call_args = spy.game_did_take_turn.call_args[1]
        board_snapshot = call_args['board_snapshot']

        expected_board_snapshot = [
            [CellType.Unknown, CellType.Two, CellType.One, CellType.Zero, CellType.Zero],
            [CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One, CellType.Zero],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown],
            [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown],
        ]
        assert_board_snapshots_equal(board_snapshot=board_snapshot,
                                     expected_board_snapshot=expected_board_snapshot,
                                     test_case=self)

    def test_present_start_menu_with_no_minefields_should_notify_observer_with_correct_start_menu_options(self):
        spy = Mock(GameObserver)
        self.subject.present_start_menu(observer=spy)

        keyword_arguments = spy.game_did_present_start_menu.call_args[1]
        menu_options = keyword_arguments['menu_options']
        expected_menu_options = MenuOptions(options=[StartMenuOptionType.StartNewGame, StartMenuOptionType.Quit],
                                            initially_selected_option=StartMenuOptionType.StartNewGame)
        self.assertEqual(menu_options, expected_menu_options)

    def test_present_start_menu_with_no_minefields_should_notify_observer_with_present_create_board_options(self):
        spy = Mock(GameObserver)
        self.subject.present_start_menu(observer=spy)

        keyword_arguments = spy.game_did_present_start_menu.call_args[1]
        present_create_board_options = keyword_arguments['present_create_board_options']
        present_create_board_options()
        keyword_arguments = spy.game_did_present_create_board_options.call_args[1]
        minimum_row_count = keyword_arguments['minimum_row_count']
        minimum_column_count = keyword_arguments['minimum_column_count']

        self.assertEqual(minimum_row_count, 5)
        self.assertEqual(minimum_column_count, 5)

        create_board = keyword_arguments['create_board']
        create_board(row_count=minimum_row_count, column_count=minimum_column_count)

        keyword_arguments = spy.game_did_create_board.call_args[1]

        board = keyword_arguments['board']
        expected_board = Board(row_count=5, column_count=5)

        assert_boards_equal(board=board, expected_board=expected_board, test_case=self)

    # "Private"

    def simulate_start_game(self, row_count: int, column_count: int, turns: [RawTurn]) -> [[CellType]]:
        spy = Mock(GameObserver)
        self.subject.start_new_game(row_count=row_count, column_count=column_count, observer=spy)

        first_turn = turns.pop(0)
        create_minefield = spy.game_did_create_board.call_args[1]['create_minefield']
        create_minefield(row_index=first_turn.coordinate.row_index, column_index=first_turn.coordinate.column_index)
        call_args = spy.game_did_create_minefield.call_args[1]

        for turn in turns:
            reveal_cell = call_args['reveal_cell']
            toggle_flag = call_args['toggle_flag']

            if turn.action == TurnAction.RevealCell:
                reveal_cell(row_index=turn.coordinate.row_index, column_index=turn.coordinate.column_index)
            elif turn.action == TurnAction.ToggleFlag:
                toggle_flag(row_index=turn.coordinate.row_index, column_index=turn.coordinate.column_index)

            call_args = spy.did_take_turn.call_args[1]

        return call_args['board_snapshot']
Пример #20
0
from string import ascii_lowercase

from minesweeper import Game


if __name__ == '__main__':
    size_x = 8
    size_y = 8
    mines = 10
    letters = {letter: index for index, letter in enumerate(ascii_lowercase)}
    game = Game(size_y, size_x, mines)

    print('Minesweper ({},{}) with {} mines.'.format(size_y, size_x, mines))
    print('Input your moves in row column format, e.g. a 4.')
    print('If you want to add a flag, add f after the position, e.g. b 6 f.')
    print('Flags are {} and unopened fields are {}.'.format(Game._FLAG, Game._UNOPENED))

    while game.won() == 0:
        game.show_field()
        print()
        move = input('Your input: ')
        move = move.split()
        try:
            y = letters[move[0]]
            x = int(move[1])
            if len(move) == 2:
                game.open(y, x)
            else:
                game.flag(y, x)
        except Exception:
            print('Invalid move. Please try again.')
#!/usr/bin/env python3

import argparse

from minesweeper import Game
from minesweeper.common.persistence import InMemoryMinefieldRepository, InMemoryTurnRepository
from tui.game_observer import TUI

if __name__ == '__main__':
    parser = argparse.ArgumentParser()

    parser.add_argument('-r', '--row-count', type=int, default=5)
    parser.add_argument('-c', '--column-count', type=int, default=10)

    args = parser.parse_args()
    tui = TUI()

    minefield_repository = InMemoryMinefieldRepository()
    turn_repository = InMemoryTurnRepository()
    game = Game(minefield_repository=minefield_repository,
                turn_repository=turn_repository)

    game.present_start_menu(observer=tui)