X-Git-Url: https://harishankar.org/repos/?p=getaclue.git;a=blobdiff_plain;f=crosswordpuzzle.py;h=e6608008c667fec891f40618ea1c9d66327f193d;hp=9617897fddada51883187489cdb2153e268ab6f6;hb=8169cbe268942c829ff7db563b9bcb1ed4f51e1b;hpb=8e802b4a6d2d5af14810a2b6603fd53b2697c039 diff --git a/crosswordpuzzle.py b/crosswordpuzzle.py index 9617897..e660800 100644 --- a/crosswordpuzzle.py +++ b/crosswordpuzzle.py @@ -4,6 +4,8 @@ # Class for the puzzle data representation +import cairo + class GridItem: # initialize the item def __init__ (self, item_char='.', across_start = False, down_start = False, @@ -50,6 +52,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 +75,132 @@ class CrosswordPuzzle: for j in range (cols): self.data[i].append (GridItem ()) + # export to an image + def export_image (self, filename, solution=False): + # don't export if grid is not frozen + if self.frozen_grid is False: + raise FrozenGridException + + # create cairo image surface and context + px = 30 + surf = cairo.ImageSurface (cairo.FORMAT_RGB24, self.cols*px, self.rows*px) + ctx = cairo.Context (surf) + + ctx.set_source_rgb (1, 1, 1) + ctx.rectangle (0, 0, self.cols*px, self.rows*px) + ctx.fill () + + # traverse through the grid + for row in range (self.rows): + for col in range (self.cols): + # if grid is un-occupied + if (self.data[row][col].occupied_across is False and + self.data[row][col].occupied_down is False): + ctx.set_source_rgb (0, 0, 0) + ctx.rectangle (col*px, row*px, px, px) + ctx.fill () + # grid is occupied + else: + ctx.set_source_rgb (1, 1, 1) + ctx.rectangle (col*px, row*px, px, px) + ctx.fill () + ctx.set_source_rgb (0, 0, 0) + ctx.rectangle (col*px, row*px, px, px) + ctx.stroke () + # if solution is not to be provided, number the grid + if solution is False: + if self.data[row][col].numbered <> 0: + ctx.select_font_face ("Serif") + ctx.set_font_size (10) + ctx.move_to (col*px+5, row*px+10) + ctx.show_text (str(self.data[row][col].numbered)) + # display the words + else: + ctx.select_font_face ("Serif") + ctx.set_font_size (16) + ctx.move_to (col*px+10, row*px+20) + ctx.show_text (self.data[row][col].char) + + surf.write_to_png (open (filename, "wb")) + + # get the AcrossLite(TM) data for exporting + def export_acrosslite (self, title, author, copyright): + # don't export if grid is not frozen + if self.frozen_grid is False: + raise FrozenGridException + + across_data = [] + across_data.append ("\r\n") + across_data.append ("\r\n") + across_data.append (title + "\r\n") + across_data.append ("<AUTHOR>\r\n") + across_data.append (author + "\r\n") + across_data.append ("<COPYRIGHT>\r\n") + across_data.append (copyright + "\r\n") + across_data.append ("<SIZE>\r\n") + str_size = str (self.cols) + "x" + str (self.rows) + across_data.append (str_size + "\r\n") + across_data.append ("<GRID>\r\n") + for row in range (self.rows): + for col in range (self.cols): + if (self.data[row][col].occupied_across is True or + self.data[row][col].occupied_down is True): + across_data.append (self.data[row][col].char) + else: + across_data.append (".") + across_data.append ("\r\n") + + across_data.append ("<ACROSS>\r\n") + clues_across = self.get_clues_across () + for word, clue in clues_across: + if clue: + across_data.append (clue + "\r\n") + else: + across_data.append ("(No clue yet)\r\n") + + across_data.append ("<DOWN>\r\n") + clues_down = self.get_clues_down () + for word, clue in clues_down: + if clue: + across_data.append (clue + "\r\n") + else: + across_data.append ("(No clue yet\r\n") + + acrosslite_str = "".join (across_data) + return acrosslite_str + + # 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 @@ -136,7 +269,7 @@ class CrosswordPuzzle: word = "".join (word_chars) # return the word, starting column, row and length as a tuple - return (word, start_col, row, len(word)) + return (word, row, start_col, len(word)) # setting a down word def set_word_down (self, row, col, word):