From c2031a5fe0f3aa317c011a2f221ea6efc69c0c3d Mon Sep 17 00:00:00 2001 From: Harishankar Date: Sun, 5 Dec 2010 15:58:40 +0530 Subject: [PATCH] Save and restore functionality implemented Puzzle can now be saved and loaded from disk. Also implemented displaying across and down clues for the puzzle. --- .gitignore | 1 + crosswordpuzzle.py | 37 +++++++++++++++++ crosswordpuzzlecreator.py | 86 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 119 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 0d20b64..dc58cc7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.pyc +sample* diff --git a/crosswordpuzzle.py b/crosswordpuzzle.py index 9617897..8091d3d 100644 --- a/crosswordpuzzle.py +++ b/crosswordpuzzle.py @@ -50,6 +50,11 @@ class NoWordException (Exception): def __init__ (self, row, col): self.pos = (row, col) +# exception when no words are present in the grid +class NoWordsException (Exception): + def __init__ (self): + self.msg = "No words in grid" + class CrosswordPuzzle: def __init__ (self, rows, cols): # define number of rows and columns @@ -68,6 +73,38 @@ class CrosswordPuzzle: for j in range (cols): self.data[i].append (GridItem ()) + # get all the clues for across + def get_clues_across (self): + clues = [] + # traverse the grid + for row in range (self.rows): + for col in range (self.cols): + if (self.data[row][col].occupied_across is True and + self.data[row][col].across_start is True): + word_across = self.get_word_across (row, col) + clues.append ((word_across, self.data[row][col].clue_across)) + # if no across words are found at all + if not clues: + raise NoWordsException + + return clues + + # get all the clues for down + def get_clues_down (self): + clues = [] + # traverse the grid + for row in range (self.rows): + for col in range (self.cols): + if (self.data[row][col].occupied_down is True and + self.data[row][col].down_start is True): + word_down = self.get_word_down (row, col) + clues.append ((word_down, self.data[row][col].clue_down)) + # if no down words are found at all + if not clues: + raise NoWordsException + + return clues + # getting a down word at a position def get_word_down (self, row, col): # if index is out of bounds diff --git a/crosswordpuzzlecreator.py b/crosswordpuzzlecreator.py index ed7e1d8..cdd233f 100644 --- a/crosswordpuzzlecreator.py +++ b/crosswordpuzzlecreator.py @@ -4,6 +4,8 @@ # Cross puzzle creator class import sys +import cPickle +import readline import crosswordpuzzle @@ -30,6 +32,20 @@ class CrosswordPuzzleCreator: self.current_file = None self.puzzle = None + # save the puzzle + def save_puzzle (self): + if self.current_file: + fpuzzle = open (self.current_file, "wb") + cPickle.dump (self.puzzle, fpuzzle, cPickle.HIGHEST_PROTOCOL) + sys.stdout.write (self.BLUE + "Puzzle saved to: " + + self.current_file + "\n" + self.ENDCOL) + + # load the puzzle + def load_puzzle (self): + if self.current_file: + fpuzzle = open (self.current_file, "rb") + self.puzzle = cPickle.load (fpuzzle) + # display the grid with words def print_puzzle (self, no_words=False): # if self.puzzle is not none @@ -77,6 +93,40 @@ class CrosswordPuzzleCreator: sys.stdout.write (' ' + self.BLUE + "%2d" % row + self.ENDCOL + "\n") raw_input (self.BRICKRED + "Press to continue" + self.ENDCOL) + # display existing clues + def display_clues (self): + try: + aclues = self.puzzle.get_clues_across () + sys.stdout.write (self.BOLD + "\n------------\n") + sys.stdout.write ("Across words\n") + sys.stdout.write ("------------\n" + self.ENDCOL) + + for word, clue in aclues: + sys.stdout.write (self.BOLD + word[0] + ": " + self.ENDCOL) + if clue: + sys.stdout.write (self.BLUE + clue + "\n" + self.ENDCOL) + else: + sys.stdout.write (self.BLUE + "(No clue yet)\n" + self.ENDCOL) + except crosswordpuzzle.NoWordsException: + sys.stderr.write ("No words across\n") + + try: + dclues = self.puzzle.get_clues_down () + sys.stdout.write (self.BOLD + "\n----------\n") + sys.stdout.write ("Down words\n") + sys.stdout.write ("----------\n" + self.ENDCOL) + + for word, clue in dclues: + sys.stdout.write (self.BOLD + word[0] + ": " + self.ENDCOL) + if clue: + sys.stdout.write (self.BLUE + clue + "\n" + self.ENDCOL) + else: + sys.stdout.write (self.BLUE + "(No clue yet)\n" + self.ENDCOL) + except crosswordpuzzle.NoWordsException: + sys.stderr.write ("No words down\n") + + raw_input (self.BRICKRED + "Press to continue" + self.ENDCOL) + # set a clue to a word def set_clue (self): self.print_puzzle () @@ -92,14 +142,26 @@ class CrosswordPuzzleCreator: return try: + # across word set the clue if found aword, arow, acol, alen = self.puzzle.get_word_across (row, col) - sys.stdout.write (self.BLUE + "Word at position: " + aword + "\n" + self.ENDCOL) - clue = raw_input (self.BRICKRED + "Clue for word: " + self.ENDCOL) + sys.stdout.write (self.BLUE + "Across word at position: " + aword + "\n" + self.ENDCOL) + clue = raw_input (self.BRICKRED + "Clue for across word: " + self.ENDCOL) if clue: self.puzzle.data[arow][acol].clue_across = clue sys.stdout.write (self.BLUE + "Set clue: \n" + self.puzzle.data[arow][acol].clue_across) except crosswordpuzzle.NoWordException: - sys.stderr.write ("No across word found at that position") + sys.stderr.write ("No across word found at that position\n") + + try: + # down word set the clue if found + dword, drow, dcol, dlen = self.puzzle.get_word_down (row, col) + sys.stdout.write (self.BLUE + "Down word at position: " + dword + "\n" + self.ENDCOL) + clue = raw_input (self.BRICKRED + "Clue for down word: " + self.ENDCOL) + if clue: + self.puzzle.data[drow][dcol].clue_down = clue + sys.stdout.write (self.BLUE + "Set clue: \n" + self.puzzle.data[drow][dcol].clue_down) + except crosswordpuzzle.NoWordException: + sys.stderr.write ("No down word found at that position\n") # add a word to the puzzle def add_word (self, across=True): @@ -134,8 +196,8 @@ class CrosswordPuzzleCreator: # Puzzle loop def do_puzzle_loop (self): # there is a current file - while True: - if self.current_file and self.puzzle: + if self.current_file and self.puzzle: + while True: sys.stdout.write (self.BOLD + "\n-----------------------------------\n") sys.stdout.write ("Puzzle: " + self.current_file + "\n") sys.stdout.write ("-----------------------------------" + self.ENDCOL + "\n") @@ -147,6 +209,7 @@ class CrosswordPuzzleCreator: sys.stdout.write ("6. Freeze grid\n") sys.stdout.write ("7. Unfreeze grid\n") sys.stdout.write ("8. Set clue for word\n") + sys.stdout.write ("9. Display clues\n") sys.stdout.write ("S. Save puzzle\n") sys.stdout.write ("X. Exit to main menu\n" + self.ENDCOL) ch = raw_input (self.BRICKRED + "Your choice: " + self.ENDCOL) @@ -162,6 +225,10 @@ class CrosswordPuzzleCreator: self.puzzle.unfreeze_grid () elif ch == "8": self.set_clue () + elif ch == "9": + self.display_clues () + elif ch == "S" or ch == "s": + self.save_puzzle () elif ch == "X" or ch == "x": break @@ -180,6 +247,13 @@ class CrosswordPuzzleCreator: self.puzzle = crosswordpuzzle.CrosswordPuzzle (rows, cols) self.do_puzzle_loop () + # when user chooses to load puzzle + def on_load_puzzle (self): + self.current_file = raw_input (self.BRICKRED + "Puzzle to load: " + + self.ENDCOL) + self.load_puzzle () + self.do_puzzle_loop () + # Main application loop def do_main_loop (self): # display the menu @@ -193,5 +267,7 @@ class CrosswordPuzzleCreator: ch = raw_input (self.BRICKRED + "Your choice: " + self.ENDCOL) if ch == '1': self.on_new_puzzle () + if ch == '2': + self.on_load_puzzle () if ch == 'x' or ch == 'X': break -- 2.20.1