First commit
authorHarishankar <v.harishankar@gmail.com>
Sat, 4 Dec 2010 09:12:43 +0000 (14:42 +0530)
committerHarishankar <v.harishankar@gmail.com>
Sat, 4 Dec 2010 09:12:43 +0000 (14:42 +0530)
This is the first commit. Beginning of the menus and
functionality

.gitignore [new file with mode: 0644]
crosswordpuzzle.py [new file with mode: 0644]
crosswordpuzzlecreator.py [new file with mode: 0644]
getaclue [new file with mode: 0755]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..0d20b64
--- /dev/null
@@ -0,0 +1 @@
+*.pyc
diff --git a/crosswordpuzzle.py b/crosswordpuzzle.py
new file mode 100644 (file)
index 0000000..c1f822b
--- /dev/null
@@ -0,0 +1,210 @@
+# Get A Clue (C) 2010 V. Harishankar
+# Crossword puzzle maker program
+# Licensed under the GNU GPL v3
+
+# Class for the puzzle data representation
+
+class GridItem:
+       # initialize the item
+       def __init__ (self, item_char='.', across_start = False, down_start = False,
+                                       occupied_across = False, occupied_down = False, num = 0,
+                                       clue_across = None, clue_down = None, revealed = False):
+               # character in the cell
+               self.char = item_char
+               # is the cell the start of an across word?
+               self.across_start = across_start
+               # is the cell the start of a down word?
+               self.down_start = down_start
+               # is the cell occupied by a letter in an across word?
+               self.occupied_across = occupied_across
+               # is the cell occupied by a letter in a down word?
+               self.occupied_down = occupied_down
+               # numbering of the cell if it is the start of a word
+               self.numbered = num
+               # clue across if the cell is the start of an across word
+               self.clue_across = clue_across
+               # clue down if the cell is the start of a down word
+               self.clue_down = clue_down
+               # is the letter revealed or hidden?
+               self.revealed = revealed
+
+# exception for too long words
+class TooLongWordException (Exception):
+       def __init__ (self, word, length):
+               self.word = word
+               self.length = length
+
+# exception for intersecting words
+class IntersectWordException (Exception):
+       def __init__ (self, word, length):
+               self.word = word
+               self.length = length
+
+# exception when grid is sought to be changed when frozen
+class FrozenGridException (Exception):
+       def __init__ (self):
+               self.msg = "Grid is frozen and cannot be edited"
+
+class CrosswordPuzzle:
+       # ansi color codes for grid display
+       BRICKRED = '\033[44;1;31m'
+       # bold
+       BOLD = '\033[33m'
+       # blue
+       BLUE = '\033[34m'
+       # grey
+       GREY = '\033[30m'
+       # disable colors
+       ENDCOL = '\033[0m'
+
+       def __init__ (self, rows, cols):
+               # define number of rows and columns
+               self.rows = rows
+               self.cols = cols
+
+               # initialize the list to hold the grid
+               self.data = []
+
+               # initial state of the grid is unfrozen
+               self.frozen_grid = False
+
+               # create the grid data
+               for i in range (rows):
+                       self.data.append ([])
+                       for j in range (cols):
+                               self.data[i].append (GridItem ())
+
+       # setting a down word
+       def set_word_down (self, row, col, word):
+               # if the grid is frozen the abort
+               if self.frozen_grid is True:
+                       raise FrozenGridException
+
+               # if the word length greater than totalrows - startrow
+               if len(word) > self.rows - row:
+                       raise TooLongWordException (word, len(word))
+
+               # is the word intersecting any other word?
+               for i in range (len(word)):
+                       # on the same column
+                       if self.data[row+i][col].occupied_down is True:
+                               raise IntersectWordException (word, len(word))
+                       # on the previous column
+                       if col > 0 and self.data[row+i][col-1].occupied_down is True:
+                               raise IntersectWordException (word, len(word))
+                       # on the next column
+                       if (col < (len(word) - 1) and
+                               (self.data[row+i][col+1].occupied_down is True or
+                               self.data[row+i][col+1].across_start is True)):
+                               raise IntersectWordException (word, len(word))
+
+               # also check the character before and after
+               if (row > 0 and self.data[row-1][col].occupied_down is True
+                       and self.data[row-1][col].occupied_across is True):
+                       raise IntersectWordException (word, len(word))
+               if (row + len(word) < self.rows and
+                       self.data[row+len(word)][col].occupied_across is True and
+                       self.data[row+len(word)][col].occupied_down is True):
+                       raise IntersectWordException (word, len(word))
+
+               # set the down start to true
+               self.data[row][col].down_start = True
+               # set the word
+               for i in range (len(word)):
+                       self.data[row+i][col].occupied_down = True
+                       self.data[row+i][col].char = word[i].upper ()
+
+
+       # setting an across word
+       def set_word_across (self, row, col, word):
+               # if the grid is frozen the abort
+               if self.frozen_grid is True:
+                       raise FrozenGridException
+
+               # is the word length greater than totalcols - startcol?
+               if len(word) > self.cols - col:
+                       raise TooLongWordException (word, len(word))
+
+               # is the word intersecting any other word?
+               for i in range (len(word)):
+                       # on the same line
+                       if self.data[row][col+i].occupied_across is True:
+                               raise IntersectWordException (word, len(word))
+                       # on a previous line except the last column
+                       if row > 0 and self.data[row-1][col+i].occupied_across is True:
+                               raise IntersectWordException (word, len(word))
+                       # on a next line except the last column
+                       if (row < (self.rows - 1) and
+                        (self.data[row+1][col+i].down_start is True
+                       or self.data[row+1][col+i].occupied_across is True)):
+                               raise IntersectWordException (word, len(word))
+
+               # also check the character beyond and before and after
+               if (col > 0 and (self.data[row][col-1].occupied_across is True or
+                                       self.data[row][col-1].occupied_down is True)):
+                       raise IntersectWordException (word, len(word))
+               if (col + len(word) < self.cols and
+                               (self.data[row][col+len(word)].occupied_across is True or
+                               self.data[row][col+len(word)].occupied_down is True)):
+                       raise IntersectWordException (word, len(word))
+
+               # set across start to true
+               self.data[row][col].across_start = True
+
+               # set the word
+               for i in range (len(word)):
+                       self.data[row][col+i].char = word[i].upper ()
+                       self.data[row][col+i].occupied_across = True
+
+       # display the grid with words
+       def print_grid (self, no_words=False):
+               # get row, col and print them (with grid number if set)
+               for col in range (self.cols):
+                       # print the first row as column headers
+                       print self.BLUE + '  ' + str (col) + self.ENDCOL,
+               print
+
+               for row in range (self.rows):
+                       for col in range (self.cols):
+                               # print the data
+                               # if the cell is numbered i.e. start of a word
+                               if self.data[row][col].numbered != 0:
+                                       print self.BRICKRED + str(self.data[row][col].numbered) + self.ENDCOL,
+                               # print a space
+                               else:
+                                       print ' ',
+                               # if the character is not a blank or a block
+                               if self.data[row][col].char <> "." and self.data[row][col].char <> "#":
+                                       # if words are to be shown regardless of hidden/revealed state
+                                       if no_words is False:
+                                               print self.BOLD + self.data[row][col].char + self.ENDCOL,
+                                       else:
+                                               # display only revealed
+                                               if self.data[row][col].revealed is True:
+                                                       print self.BOLD + self.data[row][col].char + self.ENDCOL,
+                                               # else print a block
+                                               else:
+                                                       print self.GREY + '.' + self.ENDCOL,
+                               else:
+                                       print self.GREY + self.data[row][col].char + self.ENDCOL,
+
+                       print ' ' + self.BLUE + str(row) + self.ENDCOL
+
+       # freeze the grid numbers etc.
+       def freeze_grid (self):
+               # numbering
+               numbering = 1
+               # run through the grid
+               for row in range (self.rows):
+                       for col in range (self.cols):
+                               # if grid is blank set the character to #
+                               if (self.data[row][col].occupied_across is False
+                                       and self.data[row][col].occupied_down is False):
+                                       self.data[row][col].char = "#"
+                               elif (self.data[row][col].across_start is True or
+                                       self.data[row][col].down_start is True):
+                                       self.data[row][col].numbered = numbering
+                                       numbering += 1
+
+               self.frozen_grid = True
+
diff --git a/crosswordpuzzlecreator.py b/crosswordpuzzlecreator.py
new file mode 100644 (file)
index 0000000..ae1f8ca
--- /dev/null
@@ -0,0 +1,113 @@
+# Get A Clue (C) 2010 V. Harishankar
+# Crossword puzzle maker program
+# Licensed under the GNU GPL v3
+
+# Cross puzzle creator class
+
+import crosswordpuzzle
+
+class CrosswordPuzzleCreator:
+       # ansi color codes for grid display
+       BRICKRED = '\033[31m'
+       # bold
+       BOLD = '\033[33m'
+       # blue
+       BLUE = '\033[34m'
+       # grey
+       GREY = '\033[30m'
+       # disable colors
+       ENDCOL = '\033[0m'
+
+       def __init__ (self):
+               self.do_main_loop ()
+               self.current_file = None
+               self.puzzle = None
+
+       # display the grid with words
+       def print_puzzle (self, no_words=False):
+               # if self.puzzle is not none
+               if self.puzzle:
+                       # get row, col and print them (with grid number if set)
+                       for col in range (self.puzzle.cols):
+                               # print the first row as column headers
+                               print self.BLUE + '  ' + str (col) + self.ENDCOL,
+                       print
+
+                       for row in range (self.puzzle.rows):
+                               for col in range (self.puzzle.cols):
+                                       # print the data
+                                       # if the cell is numbered i.e. start of a word
+                                       if self.puzzle.data[row][col].numbered != 0:
+                                               print self.BRICKRED + str(self.puzzle.data[row][col].numbered) + self.ENDCOL,
+                                       # print a space
+                                       else:
+                                               print ' ',
+                                       # if the character is not a blank or a block
+                                       if self.puzzle.data[row][col].char <> "." and self.puzzle.data[row][col].char <> "#":
+                                               # if words are to be shown regardless of hidden/revealed state
+                                               if no_words is False:
+                                                       print self.BOLD + self.puzzle.data[row][col].char + self.ENDCOL,
+                                               else:
+                                                       # display only revealed
+                                                       if self.puzzle.data[row][col].revealed is True:
+                                                               print self.BOLD + self.puzzle.data[row][col].char + self.ENDCOL,
+                                                       # else print a block
+                                                       else:
+                                                               print self.GREY + '.' + self.ENDCOL,
+                                       else:
+                                               print self.GREY + self.puzzle.data[row][col].char + self.ENDCOL,
+
+                               print ' ' + self.BLUE + str(row) + self.ENDCOL
+                       raw_input (self.GREY + "Press <return> to continue" + self.ENDCOL)
+
+       # Puzzle loop
+       def do_puzzle_loop (self):
+               # there is a current file
+               while True:
+                       if self.current_file and self.puzzle:
+                               print self.BOLD + "-----------------------------------"
+                               print "Puzzle: " + self.current_file
+                               print "-----------------------------------" + self.ENDCOL
+                               print self.BLUE + "1. Display grid"
+                               print "2. Add across word"
+                               print "3. Add down word"
+                               print "4. Freeze grid"
+                               print "5. Unfreeze grid"
+                               print "6. Save puzzle"
+                               print "X. Exit to main menu" + self.ENDCOL
+                               ch = raw_input (self.BRICKRED + "Your choice: " + self.ENDCOL)
+                               if ch == "1":
+                                       self.print_puzzle ()
+                               elif ch == "X" or ch == "x":
+                                       break
+
+       # when user chooses new puzzle
+       def on_new_puzzle (self):
+               self.current_file = raw_input ("New puzzle file name: ")
+               srows = raw_input ("Number of rows: ")
+               scols = raw_input ("Number of cols: ")
+               try:
+                       rows = int (srows)
+                       cols = int (scols)
+               except ValueError:
+                       print "Invalid number of rows/columns"
+                       return
+               self.puzzle = crosswordpuzzle.CrosswordPuzzle (rows, cols)
+               self.do_puzzle_loop ()
+
+       # Main application loop
+       def do_main_loop (self):
+               # display the menu
+               while True:
+                       print
+                       print self.BOLD + "-----------------------------------"
+                       print "Get A Clue - Crossword Puzzle Maker"
+                       print "-----------------------------------" + self.ENDCOL
+                       print self.BLUE + "1. Start a new puzzle"
+                       print "2. Open an existing puzzle"
+                       print "X. Exit" + self.ENDCOL
+                       ch = raw_input (self.BRICKRED + "Your choice: " + self.ENDCOL)
+                       if ch == '1':
+                               self.on_new_puzzle ()
+                       if ch == 'x' or ch == 'X':
+                               break
diff --git a/getaclue b/getaclue
new file mode 100755 (executable)
index 0000000..f950a89
--- /dev/null
+++ b/getaclue
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+# Get A Clue (C) 2010 V. Harishankar
+# Crossword puzzle maker program
+# Licensed under the GNU GPL v3
+
+# Main script
+
+import crosswordpuzzlecreator
+
+def main ():
+       app = crosswordpuzzlecreator.CrosswordPuzzleCreator ()
+
+if __name__=="__main__":
+       main ()