56807cdc36696f22e750b3f6ae45bc3ef0f2df38
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 def __init__ (self
, rows
, cols
):
50 # define number of rows and columns
54 # initialize the list to hold the grid
57 # initial state of the grid is unfrozen
58 self
.frozen_grid
= False
60 # create the grid data
61 for i
in range (rows
):
63 for j
in range (cols
):
64 self
.data
[i
].append (GridItem ())
67 def set_word_down (self
, row
, col
, word
):
68 # if the grid is frozen the abort
69 if self
.frozen_grid
is True:
70 raise FrozenGridException
72 # if the word length greater than totalrows - startrow
73 if len(word
) > self
.rows
- row
:
74 raise TooLongWordException (word
, len(word
))
76 # is the word intersecting any other word?
77 for i
in range (len(word
)):
79 if self
.data
[row
+i
][col
].occupied_down
is True:
80 raise IntersectWordException (word
, len(word
))
81 # on the previous column except first column
83 # except the first and last col
84 if i
> 0 and i
< len(word
) - 1:
85 if self
.data
[row
+i
][col
-1].occupied_down
is True:
86 raise IntersectWordException (word
, len(word
))
87 # on the next column except last column
88 if col
< len(word
) - 1:
89 # except the first and last row check if there is any
90 # down word in previous column
91 if i
> 0 and i
< len(word
) - 1:
92 if self
.data
[row
+i
][col
+1].occupied_down
is True:
93 raise IntersectWordException (word
, len(word
))
94 # check if there is any across word starting in the
96 if self
.data
[row
+i
][col
+1].across_start
is True:
97 raise IntersectWordException (word
, len(word
))
99 # also check the character before and after
100 if (row
> 0 and self
.data
[row
-1][col
].occupied_down
is True
101 and self
.data
[row
-1][col
].occupied_across
is True):
102 raise IntersectWordException (word
, len(word
))
103 if (row
+ len(word
) < self
.rows
and
104 self
.data
[row
+len(word
)][col
].occupied_across
is True and
105 self
.data
[row
+len(word
)][col
].occupied_down
is True):
106 raise IntersectWordException (word
, len(word
))
108 # set the down start to true
109 self
.data
[row
][col
].down_start
= True
111 for i
in range (len(word
)):
112 self
.data
[row
+i
][col
].occupied_down
= True
113 self
.data
[row
+i
][col
].char
= word
[i
].upper ()
116 # setting an across word
117 def set_word_across (self
, row
, col
, word
):
118 # if the grid is frozen the abort
119 if self
.frozen_grid
is True:
120 raise FrozenGridException
122 # is the word length greater than totalcols - startcol?
123 if len(word
) > self
.cols
- col
:
124 raise TooLongWordException (word
, len(word
))
126 # is the word intersecting any other word?
127 for i
in range (len(word
)):
129 if self
.data
[row
][col
+i
].occupied_across
is True:
130 raise IntersectWordException (word
, len(word
))
131 # on a previous row except first row
133 # if not the first or last col
134 if i
> 0 and i
< len(word
) - 1:
135 if self
.data
[row
-1][col
+i
].occupied_across
is True:
136 raise IntersectWordException (word
, len(word
))
138 if (row
< (self
.rows
- 1)):
139 # except the first and last letter check if there is
140 # any across intersection
141 if i
> 0 and i
< len (word
) - 1:
142 if self
.data
[row
+1][col
+i
].occupied_across
is True:
143 raise IntersectWordException (word
, len(word
))
144 # if a down word is starting at any column below the
146 if self
.data
[row
+1][col
+i
].down_start
is True:
147 raise IntersectWordException (word
, len(word
))
149 # also check the character beyond and before and after
150 if (col
> 0 and (self
.data
[row
][col
-1].occupied_across
is True or
151 self
.data
[row
][col
-1].occupied_down
is True)):
152 raise IntersectWordException (word
, len(word
))
153 if (col
+ len(word
) < self
.cols
and
154 (self
.data
[row
][col
+len(word
)].occupied_across
is True or
155 self
.data
[row
][col
+len(word
)].occupied_down
is True)):
156 raise IntersectWordException (word
, len(word
))
158 # set across start to true
159 self
.data
[row
][col
].across_start
= True
162 for i
in range (len(word
)):
163 self
.data
[row
][col
+i
].char
= word
[i
].upper ()
164 self
.data
[row
][col
+i
].occupied_across
= True
166 # freeze the grid numbers etc.
167 def freeze_grid (self
):
170 # run through the grid
171 for row
in range (self
.rows
):
172 for col
in range (self
.cols
):
173 # if grid is blank set the character to #
174 if (self
.data
[row
][col
].occupied_across
is False
175 and self
.data
[row
][col
].occupied_down
is False):
176 self
.data
[row
][col
].char
= "#"
177 elif (self
.data
[row
][col
].across_start
is True or
178 self
.data
[row
][col
].down_start
is True):
179 self
.data
[row
][col
].numbered
= numbering
182 self
.frozen_grid
= True
184 # unfreeze the grid numbers etc.
185 def unfreeze_grid (self
):
186 # run through the grid
187 for row
in range (self
.rows
):
188 for col
in range (self
.cols
):
189 self
.data
[row
][col
].numbered
= 0
190 if (self
.data
[row
][col
].occupied_across
is False and
191 self
.data
[row
][col
].occupied_down
is False):
192 self
.data
[row
][col
].char
= '.'
194 self
.frozen_grid
= False