fb9ada55dad410a3e0182d3f076be0db8d6b8cc4
1 # Get A Clue (C) 2010 V. Harishankar
2 # Crossword puzzle maker program
3 # Licensed under the GNU GPL v3
5 # Class for the puzzle data representation
9 def __init__ (self
, item_char
='.', across_start
= False, down_start
= False,
10 occupied_across
= False, occupied_down
= False, num
= 0,
11 clue_across
= None, clue_down
= None, revealed
= False):
12 # character in the cell
14 # is the cell the start of an across word?
15 self
.across_start
= across_start
16 # is the cell the start of a down word?
17 self
.down_start
= down_start
18 # is the cell occupied by a letter in an across word?
19 self
.occupied_across
= occupied_across
20 # is the cell occupied by a letter in a down word?
21 self
.occupied_down
= occupied_down
22 # numbering of the cell if it is the start of a word
24 # clue across if the cell is the start of an across word
25 self
.clue_across
= clue_across
26 # clue down if the cell is the start of a down word
27 self
.clue_down
= clue_down
28 # is the letter revealed or hidden?
29 self
.revealed
= revealed
31 # exception for too long words
32 class TooLongWordException (Exception):
33 def __init__ (self
, word
, length
):
37 # exception for intersecting words
38 class IntersectWordException (Exception):
39 def __init__ (self
, word
, length
):
43 # exception when grid is sought to be changed when frozen
44 class FrozenGridException (Exception):
46 self
.msg
= "Grid is frozen and cannot be edited"
48 class CrosswordPuzzle
:
49 # ansi color codes for grid display
50 BRICKRED
= '\033[44;1;31m'
60 def __init__ (self
, rows
, cols
):
61 # define number of rows and columns
65 # initialize the list to hold the grid
68 # initial state of the grid is unfrozen
69 self
.frozen_grid
= False
71 # create the grid data
72 for i
in range (rows
):
74 for j
in range (cols
):
75 self
.data
[i
].append (GridItem ())
78 def set_word_down (self
, row
, col
, word
):
79 # if the grid is frozen the abort
80 if self
.frozen_grid
is True:
81 raise FrozenGridException
83 # if the word length greater than totalrows - startrow
84 if len(word
) > self
.rows
- row
:
85 raise TooLongWordException (word
, len(word
))
87 # is the word intersecting any other word?
88 for i
in range (len(word
)):
90 if self
.data
[row
+i
][col
].occupied_down
is True:
91 raise IntersectWordException (word
, len(word
))
92 # on the previous column
93 if col
> 0 and self
.data
[row
+i
][col
-1].occupied_down
is True:
94 raise IntersectWordException (word
, len(word
))
96 if (col
< (len(word
) - 1) and
97 (self
.data
[row
+i
][col
+1].occupied_down
is True or
98 self
.data
[row
+i
][col
+1].across_start
is True)):
99 raise IntersectWordException (word
, len(word
))
101 # also check the character before and after
102 if (row
> 0 and self
.data
[row
-1][col
].occupied_down
is True
103 and self
.data
[row
-1][col
].occupied_across
is True):
104 raise IntersectWordException (word
, len(word
))
105 if (row
+ len(word
) < self
.rows
and
106 self
.data
[row
+len(word
)][col
].occupied_across
is True and
107 self
.data
[row
+len(word
)][col
].occupied_down
is True):
108 raise IntersectWordException (word
, len(word
))
110 # set the down start to true
111 self
.data
[row
][col
].down_start
= True
113 for i
in range (len(word
)):
114 self
.data
[row
+i
][col
].occupied_down
= True
115 self
.data
[row
+i
][col
].char
= word
[i
].upper ()
118 # setting an across word
119 def set_word_across (self
, row
, col
, word
):
120 # if the grid is frozen the abort
121 if self
.frozen_grid
is True:
122 raise FrozenGridException
124 # is the word length greater than totalcols - startcol?
125 if len(word
) > self
.cols
- col
:
126 raise TooLongWordException (word
, len(word
))
128 # is the word intersecting any other word?
129 for i
in range (len(word
)):
131 if self
.data
[row
][col
+i
].occupied_across
is True:
132 raise IntersectWordException (word
, len(word
))
133 # on a previous line except the last column
134 if row
> 0 and self
.data
[row
-1][col
+i
].occupied_across
is True:
135 raise IntersectWordException (word
, len(word
))
136 # on a next line except the last column
137 if (row
< (self
.rows
- 1) and
138 (self
.data
[row
+1][col
+i
].down_start
is True
139 or self
.data
[row
+1][col
+i
].occupied_across
is True)):
140 raise IntersectWordException (word
, len(word
))
142 # also check the character beyond and before and after
143 if (col
> 0 and (self
.data
[row
][col
-1].occupied_across
is True or
144 self
.data
[row
][col
-1].occupied_down
is True)):
145 raise IntersectWordException (word
, len(word
))
146 if (col
+ len(word
) < self
.cols
and
147 (self
.data
[row
][col
+len(word
)].occupied_across
is True or
148 self
.data
[row
][col
+len(word
)].occupied_down
is True)):
149 raise IntersectWordException (word
, len(word
))
151 # set across start to true
152 self
.data
[row
][col
].across_start
= True
155 for i
in range (len(word
)):
156 self
.data
[row
][col
+i
].char
= word
[i
].upper ()
157 self
.data
[row
][col
+i
].occupied_across
= True
159 # freeze the grid numbers etc.
160 def freeze_grid (self
):
163 # run through the grid
164 for row
in range (self
.rows
):
165 for col
in range (self
.cols
):
166 # if grid is blank set the character to #
167 if (self
.data
[row
][col
].occupied_across
is False
168 and self
.data
[row
][col
].occupied_down
is False):
169 self
.data
[row
][col
].char
= "#"
170 elif (self
.data
[row
][col
].across_start
is True or
171 self
.data
[row
][col
].down_start
is True):
172 self
.data
[row
][col
].numbered
= numbering
175 self
.frozen_grid
= True
177 # unfreeze the grid numbers etc.
178 def unfreeze_grid (self
):
179 # run through the grid
180 for row
in range (self
.rows
):
181 for col
in range (self
.cols
):
182 self
.data
[row
][col
].numbered
= 0
183 if (self
.data
[row
][col
].occupied_across
is False and
184 self
.data
[row
][col
].occupied_down
is False):
185 self
.data
[row
][col
].char
= '.'