示例#1
0
    def test_clear_letters(self):
        grid = Grid(squares)

        grid = optimize._clear_letters((0, 2), (0, 2), grid)
        self.assertEqual(grid.get_square((0, 0)), '.')
        self.assertEqual(grid.get_square((0, 1)), '.')
        self.assertEqual(grid.get_square((1, 0)), '')
        self.assertEqual(grid.get_square((1, 1)), '')
示例#2
0
    def test_get_all_words(self):
        squares = [
            ['.', '', '', '', ''],
            ['', '', '', '', ''],
            ['', '', '.', '', ''],
            ['', '', '', '', ''],
            ['', '', '', '', '.']
        ]
        grid = Grid(squares, 5)
        words = grid.get_all_words()

        across = [w[0] for w in words if w[1] == Mode.ACROSS]
        self.assertEqual(across, [(0, 1), (1, 0), (2, 0), (2, 3), (3, 0), (4, 0)])

        down = [w[0] for w in words if w[1] == Mode.DOWN]
        self.assertEqual(down, [(0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (3, 2)])
示例#3
0
 def test_finish_two_step_puzzle(self):
     squares = [
         ['.', '.', ' ', ' ', ' '],
         ['B', 'E', 'E', ' ', 'H'],
         ['A', 'S', 'A', 'H', 'I'],
         ['T', 'A', 'C', ' ', 'S'],
         ['H', 'U', 'H', '.', '.']
     ]
     grid = Grid(squares)
     result, score = self.generator.optimize(grid)
     self.assertEqual(score, 475)
 def test_get_next_target(self):
     squares = [['X', 'X', 'X'], ['', 'X', ''], ['X', '', '']]
     grid = Grid(squares)
     info = SearchInfo(unfilled_words=[((1, 0), Mode.ACROSS),
                                       ((2, 0), Mode.ACROSS),
                                       ((0, 0), Mode.DOWN),
                                       ((0, 1), Mode.DOWN),
                                       ((0, 2), Mode.DOWN)],
                       used_words=[])
     target, direction = self.generator.get_next_target(grid, info)
     self.assertEqual(target, (0, 0))
     self.assertEqual(direction, Mode.DOWN)
示例#5
0
    def test_copy(self):
        grid = Grid(squares)
        copy = grid.copy()

        grid.set_square((2, 2), 'X')
        self.assertEqual(grid.get_square((2, 2)), 'X')
        self.assertEqual(copy.get_square((2, 2)), '')
示例#6
0
 def __init__(self, squares=None, filename=None, size=15, dictionary_path="dictionaries/"):
     if squares:
         self.grid = Grid(squares, size)
     elif filename and path.exists(filename):
         squares = storage.load(filename)
         self.grid = Grid(squares)
     else:
         self.grid = Grid(size=size)
     self.size = self.grid.size
     self.focus = (0, 0)
     self.highlight = []
     self.mode = Mode.ACROSS
     self.dictionary = Dictionary(dictionary_path)
示例#7
0
class Model:
    """
    A class that holds all of the UI state for a crossword puzzle.
    """

    def __init__(self, squares=None, filename=None, size=15, dictionary_path="dictionaries/"):
        if squares:
            self.grid = Grid(squares, size)
        elif filename and path.exists(filename):
            squares = storage.load(filename)
            self.grid = Grid(squares)
        else:
            self.grid = Grid(size=size)
        self.size = self.grid.size
        self.focus = (0, 0)
        self.highlight = []
        self.mode = Mode.ACROSS
        self.dictionary = Dictionary(dictionary_path)

    def toggle_orientation(self):
        self.mode = self.mode.opposite()
        self.update_highlighted_squares()

    def update_focus(self, row, col):
        self.focus = (row, col)
        self.update_highlighted_squares()

    def save(self, filename):
        storage.save(self.grid.squares, filename)

    def update_square(self, row, col, text):
        # maintain block symmetry
        if text == BLOCK:
            # add corresponding block
            self.grid.set_square((self.size - 1 - row, self.size - 1 - col), BLOCK)
        elif self.grid.get_square((row, col)) == BLOCK and text != BLOCK:
            # remove corresponding block if this square used to be a block
            self.grid.set_square((self.size - 1 - row, self.size - 1 - col), '')
        self.grid.set_square((row, col), text)
        self.get_next_focus(text)
        self.update_highlighted_squares()

    def get_square(self, row, col):
        text = self.grid.get_square((row, col))
        background = Background.WHITE
        if text == BLOCK:
            background = Background.BLACK
        elif (row, col) in self.highlight:
            background = Background.YELLOW
        focused = (row, col) == self.focus
        return Square(text, background, focused)

    def update_highlighted_squares(self):
        self.highlight = self.grid.get_word_squares(self.focus, self.mode)

    def get_next_focus(self, text):
        """
        Get the coordinates of the square that should be focused after the given square
        """
        if text == '':
            # text was deleted, go backwards
            if self.mode is Mode.ACROSS:
                self.move_left()
            else:
                self.move_up()
        else:
            # text was added
            if self.mode is Mode.ACROSS:
                self.move_right()
            else:
                self.move_down()

    def move_up(self):
        self.focus = (max(0, self.focus[0] - 1), self.focus[1])

    def move_down(self):
        self.focus = (min(self.size - 1, self.focus[0] + 1), self.focus[1])

    def move_left(self):
        self.focus = (self.focus[0], max(0, self.focus[1] - 1))

    def move_right(self):
        self.focus = (self.focus[0], min(self.size - 1, self.focus[1] + 1))

    def get_suggestions(self):
        # returns suggestions for the focused square
        # prioritizes words that use a letter compatible with crossing words
        # (across, down), each is a list of tuples (word, score)

        if self.grid.get_square(self.focus) == BLOCK:
            return [], []

        across = self._get_suggestions(self.focus, Mode.ACROSS)
        down = self._get_suggestions(self.focus, Mode.DOWN)

        return across, down

    def _get_suggestions(self, square, mode):
        word = self.grid.get_word(square, mode)
        squares = self.grid.get_word_squares(square, mode)

        # copy to avoid modifying cached lists
        words = self.dictionary.search(word).copy()
        compatible_words = words.copy()

        # loop through empty letter index and remove words that don't fit crossing words
        for i, s in enumerate(squares):
            if not self.grid.is_empty(s):
                # skip squares that are already filled in
                continue

            cross_index = self.grid.get_word_squares(s, mode.opposite()).index(s)
            cross_word = self.grid.get_word(s, mode.opposite())
            available_letters = self.dictionary.get_allowed_letters(cross_word, cross_index)
            compatible_words = [w for w in compatible_words if w[0][i] in available_letters]

        # add bonus to compatible words
        for i, w in enumerate(words):
            if w in compatible_words:
                words[i] = w[0], str(int(w[1]) + 100)

        words.sort(key=lambda w: int(w[1]), reverse=True)
        return words

    def fill(self):
        """ Fill the blank squares using a Generator """
        filled_grid, _ = optimize(self.grid, self.dictionary)
        self.grid = filled_grid

    def print(self):
        self.grid.print()
示例#8
0
 def test_get_word_squares(self, square, mode, expected):
     grid = Grid(squares, 5)
     actual = grid.get_word_squares(square, mode)
     self.assertEqual(actual, expected)
示例#9
0
    def test_is_complete(self):
        grid = Grid(squares)
        self.assertFalse(grid.is_complete())

        grid.set_square((2, 2), 'A')
        self.assertTrue(grid.is_complete())
示例#10
0
 def test_is_block(self):
     grid = Grid(squares, 5)
     self.assertTrue(grid.is_block((2, 1)))
     self.assertFalse(grid.is_block((3, 3)))
示例#11
0
 def test_is_empty(self):
     grid = Grid(squares, 5)
     self.assertTrue(grid.is_empty((2, 2)))
     self.assertFalse(grid.is_empty((0, 2)))
示例#12
0
 def test_get_square(self, square, expected):
     grid = Grid(squares, 5)
     self.assertEqual(grid.get_square(square), expected)
示例#13
0
 def test_create_empty_grid(self):
     grid = Grid(None, 2)
     self.assertEqual(grid.squares, [['', ''], ['', '']])
     self.assertEqual(grid.size, 2)
示例#14
0
 def test_raise_error_if_not_square(self):
     with self.assertRaises(AssertionError):
         Grid([[''], ['', '']], 3)
 def test_get_possible_words_down(self):
     squares = [['', '', '', ''], ['', '', '', ''], ['', 'O', 'T', 'E'],
                ['', '', '', '']]
     grid = Grid(squares)
     words = self.generator.get_possible_words(grid, (0, 0), Mode.DOWN)
     self.assertEqual(words, [("bind", 50)])
示例#16
0
 def test_set_square(self, square, text, expected):
     grid = Grid(squares, 5)
     grid.set_square(square, text)
     self.assertEqual(grid.get_square(square), expected)
 def test_set_word(self):
     grid = Grid()
     word = "ABCDEFGHIJKLMNO"
     self.generator.set_word(grid, (1, 2), Mode.ACROSS, word)
     self.assertEqual(grid.get_word((1, 2), Mode.ACROSS), word)