# gcompris - sudoku # # Copyright (C) 2005, 2008 Bruno Coudoin # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # import goocanvas import gcompris import gcompris.utils import gcompris.skin import gcompris.bonus import gcompris.score import gobject import gtk import gtk.gdk import random from gcompris import gcompris_gettext as _ class Gcompris_sudoku: """Sudoku game""" def __init__(self, gcomprisBoard): self.gcomprisBoard = gcomprisBoard self.gcomprisBoard.disable_im_context = True # These are used to let us restart only after the bonus is displayed. # When the bonus is displayed, it call us first with pause(1) and then with pause(0) self.board_paused = 0; self.gamewon = 0; # It holds the canvas items for each square self.sudo_square = [] # The square Rect Item self.sudo_number = [] # The square Text Item self.sudo_symbol = [] # The square Symbol Item self.valid_chars = [] # The valid chars for the sudoku are calculated from the dataset # Holds the coordinate of the current square self.cursqre = None self.normal_square_color = 0x33CCFFffL self.highl_square_color = 0xFFCC33ffL self.focus_square_color = 0xFF6633ffL self.fixed_square_color = 0x3366FFffL self.error_square_color = 0xFF3366ffL self.lines_color = 0xFF3366ffL self.fixed_number_color = 0xFFFFFFFFL self.user_number_color = 0xFFFFFFFFL self.root_sudo = None self.sudoku = None # The current sudoku data self.sudo_size = 0 # the size of the current sudoku self.sudo_region = None # the modulo region in the current sudoku self.timer = 0 # The timer that highlights errors self.symbolize_level_max = 8 # Last level in which we set symbols self.symbols = [ (gcompris.utils.load_pixmap("sudoku/rectangle.png"), gcompris.utils.load_pixmap("sudoku/rectangle_grey.png")), (gcompris.utils.load_pixmap("sudoku/circle.png"), gcompris.utils.load_pixmap("sudoku/circle_grey.png")), (gcompris.utils.load_pixmap("sudoku/rhombus.png"), gcompris.utils.load_pixmap("sudoku/rhombus_grey.png")), (gcompris.utils.load_pixmap("sudoku/triangle.png"), gcompris.utils.load_pixmap("sudoku/triangle_grey.png")), (gcompris.utils.load_pixmap("sudoku/star.png"), gcompris.utils.load_pixmap("sudoku/star_grey.png")) ] def start(self): # Init the sudoku dataset self.sudoku = self.init_item_list() self.gcomprisBoard.level=1 self.gcomprisBoard.maxlevel=len(self.sudoku) self.gcomprisBoard.sublevel=1 gcompris.bar_set(gcompris.BAR_LEVEL|gcompris.BAR_REPEAT) gcompris.set_default_background(self.gcomprisBoard.canvas.get_root_item()) gcompris.bar_set_level(self.gcomprisBoard) # Create our rootitem. We put each canvas item in it so at the end we # only have to kill it. The canvas deletes all the items it contains automaticaly. self.rootitem = goocanvas.Group(parent = self.gcomprisBoard.canvas.get_root_item()) self.next_level() self.pause(0); def end(self): # Remove the root item removes all the others inside it self.rootitem.remove() self.rootitem = None gcompris.score.end() def ok(self): print("Gcompris_sudoku ok.") def repeat(self): self.display_sudoku(self.sudoku[self.gcomprisBoard.level-1][self.gcomprisBoard.sublevel-1]) def config(self): print("Gcompris_sudoku config.") def key_press(self, keyval, commit_str, preedit_str): if(self.cursqre == None): return False utf8char = gtk.gdk.keyval_to_unicode(keyval) strn = u'%c' % utf8char if(strn in self.valid_chars): if self.is_legal(strn): self.sudo_number[self.cursqre[0]][self.cursqre[1]].props.text = \ strn.encode('UTF-8') # Maybe it's all done if self.is_solved(): self.cursqre = None self.gamewon = 1 gcompris.bonus.display(gcompris.bonus.WIN, gcompris.bonus.FLOWER) else: # Erase the old number there if ((keyval == gtk.keysyms.BackSpace) or (keyval == gtk.keysyms.Delete) or (keyval == gtk.keysyms.space)): self.sudo_number[self.cursqre[0]][self.cursqre[1]].props.text = "" else: # No key processing done return False # Return True if you did process a key # Return False if you did not processed a key # (gtk need to send it to next widget) return True def pause(self, pause): self.board_paused = pause # When the bonus is displayed, it call us first # with pause(1) and then with pause(0) # the game is won if(self.gamewon == 1 and pause == 0): self.gamewon = 0 if(self.increment_level()): self.next_level() return def set_level(self, level): self.gcomprisBoard.level = level; self.gcomprisBoard.sublevel = 1; gcompris.bar_set_level(self.gcomprisBoard) self.next_level() # ---- End of Initialisation # Code that increments the sublevel and level # And bail out if no more levels are available # return True if continue, False if bail out def next_level(self): # Randomize symbols for j in range(0, len(self.symbols)): # Select a random new position to set the J symbol old_symbol = self.symbols[j] new_pos = random.randint(0,len(self.symbols)-1) self.symbols[j] = self.symbols[new_pos] self.symbols[new_pos] = old_symbol self.display_sudoku(self.sudoku[self.gcomprisBoard.level-1][self.gcomprisBoard.sublevel-1]) gcompris.score.start(gcompris.score.STYLE_NOTE, 610, 485, len(self.sudoku[self.gcomprisBoard.level-1])) gcompris.score.set(self.gcomprisBoard.sublevel) return True # Code that increments the sublevel and level # And bail out if no more levels are available # return True if continue, False if bail out def increment_level(self): self.gcomprisBoard.sublevel += 1 if(self.gcomprisBoard.sublevel > len(self.sudoku[self.gcomprisBoard.level-1])): # Try the next level self.gcomprisBoard.sublevel=1 self.gcomprisBoard.level += 1 # Set the level in the control bar gcompris.bar_set_level(self.gcomprisBoard); if(self.gcomprisBoard.level > self.gcomprisBoard.maxlevel): self.gcomprisBoard.level = self.gcomprisBoard.maxlevel return True # # Set a symbol in the sudoku # def set_sudoku_symbol(self, text, x, y): (pixmap, pixmap_grey) = self.get_pixmap_symbol(self.valid_chars, text) self.sudo_symbol[x][y].props.pixbuf = pixmap self.sudo_symbol[x][y].props.visibility = goocanvas.ITEM_VISIBLE self.sudo_number[x][y].props.text = text # # Event on a placed symbol. Means that we remove it # def hide_symbol_event(self, item, target, event, data): if(self.gamewon): return False if event.type == gtk.gdk.BUTTON_PRESS: item.props.visibility = goocanvas.ITEM_INVISIBLE self.sudo_number[data[0]][data[1]].props.text = "" # # This function is being called uppon a click on a symbol on the left # If a square has the focus, then the clicked square is assigned there # def symbol_item_event(self, item, target, event, text): if(self.gamewon): return False if self.selected_item == item: return False item.props.pixbuf = item.get_data("pixmap") if self.selected_item: self.selected_item.props.pixbuf = self.selected_item.get_data("pixmap_grey") self.selected_item = item return False # # This function is being called uppon a click on any little square # def square_item_event(self, widget, target, event, square): if(self.gamewon): return False # At level change this may be undefined try: self.sudo_square[square[0]][square[1]] except: return False if event.type == gtk.gdk.ENTER_NOTIFY: if self.cursqre != square: self.sudo_square[square[0]][square[1]].props.fill_color_rgba = \ self.highl_square_color elif event.type == gtk.gdk.LEAVE_NOTIFY: if ((self.gcomprisBoard.level >= self.symbolize_level_max) and (self.cursqre == square)): self.sudo_square[square[0]][square[1]].props.fill_color_rgba = \ self.focus_square_color else: self.sudo_square[square[0]][square[1]].props.fill_color_rgba = \ self.normal_square_color elif event.type == gtk.gdk.BUTTON_PRESS: # For low levels, we mark the selected item if(self.gcomprisBoard.level < self.symbolize_level_max): self.cursqre = (square[0], square[1]) text = self.selected_item.get_data("text") if self.is_legal(text): self.set_sudoku_symbol(text, square[0], square[1]) # Maybe it's all done if self.is_solved(): self.gamewon = 1 gcompris.bonus.display(gcompris.bonus.WIN, gcompris.bonus.FLOWER) else: if(self.cursqre): self.sudo_square[self.cursqre[0]][self.cursqre[1]].props.fill_color_rgba = \ self.normal_square_color self.cursqre = square self.sudo_square[square[0]][square[1]].props.fill_color_rgba = \ self.focus_square_color return True return False # Highlight the given item to show it's the one that causes the refusal # to place a number def unset_on_error(self, items): if(self.rootitem): for item in items: item.props.fill_color_rgba = self.fixed_square_color def set_on_error(self, items): for item in items: item.props.fill_color_rgba = self.error_square_color self.timer = gobject.timeout_add(3000, self.unset_on_error, items) # Return True or False if the given number is possible # def is_legal(self, number): if((self.cursqre[0] == None) or (self.cursqre[1] == None)): return possible = True bad_square = [] if(self.cursqre == None): return possible # Check this number is not already in a row for x in range(0, self.sudo_size): if x == self.cursqre[0]: continue item = self.sudo_number[x][self.cursqre[1]] othernumber = item.get_property('text').decode('UTF-8') if(number == othernumber): bad_square.append(self.sudo_square[x][self.cursqre[1]]) possible = False # Check this number is not already in a column for y in range(0, self.sudo_size): if y == self.cursqre[1]: continue item = self.sudo_number[self.cursqre[0]][y] othernumber = item.get_property('text').decode('UTF-8') if(number == othernumber): bad_square.append(self.sudo_square[self.cursqre[0]][y]) possible = False # # Check this number is in a region # # Region is the modulo place to set region if defined region = None if(self.sudo_region.has_key(self.sudo_size)): region=self.sudo_region[self.sudo_size] if(region): # First, find the top-left square of the region top_left=[self.cursqre[0]/region*region, self.cursqre[1]/region*region] for x in range(0,region): for y in range(0,region): # Do not check the current square if (top_left[0] + x == self.cursqre[0] and top_left[1] + y == self.cursqre[1]): continue item = self.sudo_number[top_left[0] + x][top_left[1] + y] othernumber = item.get_property('text').decode('UTF-8') if(number == othernumber): bad_square.append(self.sudo_square[top_left[0] + x][top_left[1] + y]) possible = False if not possible: self.set_on_error(bad_square) return possible # Return True or False if the given sudoku is solved # We don't really check it's solved, only that all squares # have a value. This works because only valid numbers can # be entered up front. # def is_solved(self): for x in range(0,self.sudo_size): for y in range(0,self.sudo_size): item = self.sudo_number[x][y] number = item.get_property('text').decode('UTF-8') if(number == ""): return False return True # # Display valid number (or chars) # def display_valid_chars(self, sudo_size, valid_chars): square_width = (gcompris.BOARD_HEIGHT-50)/sudo_size square_height = square_width x_init = 20 y_init = (gcompris.BOARD_HEIGHT - square_height*sudo_size)/2 for y in range(0, sudo_size): # For low levels, we symbolize the letters if(self.gcomprisBoard.level < self.symbolize_level_max): (pixmap, pixmap_grey) = self.get_pixmap_symbol(valid_chars, valid_chars[y]) zoom = (square_width*0.5) / pixmap.get_width() cx = int(x_init + (pixmap.get_width() * zoom)/2) cy = int(y_init + square_height * y + (square_height - pixmap.get_height()*zoom)/2) item = goocanvas.Image( parent = self.root_sudo, pixbuf = pixmap_grey, x = cx, y = cy / zoom) item.scale(zoom, zoom) item.set_data("pixmap_grey", pixmap_grey) item.set_data("pixmap", pixmap) item.set_data("text", valid_chars[y]) item.connect("button_press_event", self.symbol_item_event, valid_chars[y]) # This item is clickeable and it must be seen gcompris.utils.item_focus_init(item, None) # Select the first item if y == 0: self.selected_item = item item.props.pixbuf = pixmap else: # Text goocanvas.Text( parent = self.root_sudo, x= x_init, y= y_init + square_height * y + square_height/2, text= valid_chars[y], font=gcompris.skin.get_font("gcompris/title"), fill_color = "black" ) # Return a symbol pixmap def get_pixmap_symbol(self, valid_chars, text): if (not text in valid_chars): # Return our first item. It will be hidden anyway. return self.symbols[0] return self.symbols[valid_chars.index(text)] # # Display the given sudoku (the board and the data) # def display_sudoku(self, sudoku): # Reinit the sudoku globals if self.timer: gobject.source_remove(self.timer) self.sudo_square = [] # The square Rect Item self.sudo_number = [] # The square Text Item self.sudo_symbol = [] # The square Symbol Item # The valid chars for the sudoku are calculated from the dataset self.valid_chars = [] self.cursqre = None self.sudo_size = len(sudoku[0]) if(self.root_sudo): self.root_sudo.remove() # Create our rootitem. We put each canvas item in it so at the end we # only have to kill it. The canvas deletes all the items it contains # automaticaly. self.root_sudo = goocanvas.Group(parent = self.rootitem) # Region is the modulo place to set region (if defined) region = None if(self.sudo_region.has_key(self.sudo_size)): region = self.sudo_region[self.sudo_size] square_width = (gcompris.BOARD_HEIGHT-80) / self.sudo_size square_height = square_width x_init = (gcompris.BOARD_WIDTH - square_width*self.sudo_size)/2 - 40 y_init = (gcompris.BOARD_HEIGHT - 45 - square_height*self.sudo_size)/2 for x in range(0,self.sudo_size): line_square = [] line_number = [] line_symbol = [] for y in range(0,self.sudo_size): # Get the data from the dataset text = sudoku[y][x] if text == '.': text = "" color = self.user_number_color square_color = self.normal_square_color else: color = self.fixed_number_color square_color = self.fixed_square_color if(not text in self.valid_chars): self.valid_chars.append(text) # The background of the square item = goocanvas.Rect( parent = self.root_sudo, fill_color_rgba = square_color, x = x_init + square_width * x, y = y_init + square_height * y, width = square_width, height = square_height, line_width = 1.0, stroke_color_rgba = 0x144B9DFFL ) line_square.append(item) if text == '': item.connect("button_press_event", self.square_item_event, (x,y)) item.connect("enter_notify_event", self.square_item_event, (x,y)) item.connect("leave_notify_event", self.square_item_event, (x,y)) # Save it's sudo coord for the drag and drop item.set_data('sudo_x', str(x)) item.set_data('sudo_y', str(y)) # For low levels, we symbolize the letters if(self.gcomprisBoard.level < self.symbolize_level_max): (pixmap, pixmap_grey) = self.get_pixmap_symbol(self.valid_chars, text) zoom = (square_width*0.835) / pixmap.get_width() item = goocanvas.Image( parent = self.root_sudo, pixbuf = pixmap, x = (x_init + square_width * x + square_width/2 - (pixmap.get_width() * zoom)/2) / zoom, y = (y_init + square_height * y + square_height/2 - (pixmap.get_height() * zoom)/2) / zoom, ) item.scale(zoom, zoom) line_symbol.append(item) # Save it's sudo coord for the drag and drop item.set_data('sudo_x', str(x)) item.set_data('sudo_y', str(y)) if(not text): item.props.visibility = goocanvas.ITEM_INVISIBLE # This item is clickeable and it must be seen gcompris.utils.item_focus_init(item, None) item.connect("button_press_event", self.hide_symbol_event, (x, y)) # # # item = goocanvas.Text( parent = self.root_sudo, x= x_init + square_width * x + square_width/2 - 5, y= y_init + square_height * y + square_height/2 - 5, text = text, fill_color_rgba= color, font=gcompris.skin.get_font("gcompris/content"), ) if(self.gcomprisBoard.level0 and y%region==0): goocanvas.Polyline( parent = self.root_sudo, points = goocanvas.Points([(x_init - 5, y_init + square_height * y), (x_init + (square_width * self.sudo_size) + 5, y_init + square_height * y)]), stroke_color_rgba = self.lines_color, line_width = 2.5, ) self.sudo_square.append(line_square) self.sudo_number.append(line_number) self.sudo_symbol.append(line_symbol) if(region): if(x>0 and x%region==0): goocanvas.Polyline( parent = self.root_sudo, points = goocanvas.Points([(x_init + square_width * x, y_init - 5), (x_init + square_width * x, y_init + square_height * self.sudo_size + 5)]), stroke_color_rgba = self.lines_color, line_width = 2.5, ) if(self.gcomprisBoard.level >= self.symbolize_level_max): self.valid_chars.sort() self.display_valid_chars(self.sudo_size, self.valid_chars) # return the list of items (data) for this game def init_item_list(self): # It's hard coded that sudoku of size x have y region. # If not defined there, it means no region # # Sudoku size : Number of region # self.sudo_region = { 9: 3, 4: 2 } # It's a list of level which is a list of sudoku data sudoku_list = \ [ [ # Level 1 [ ['.','C','B'], ['.','B','A'], ['.','A','C'] ], [ ['C','A','B'], ['.','.','.'], ['B','C','A'] ], [ ['C','A','B'], ['A','B','C'], ['.','.','.'] ], [ ['A','.','C'], ['C','.','B'], ['B','.','A'] ], [ ['A','.','C'], ['B','C','.'], ['.','A','B'] ], [ ['A','B','C'], ['B','.','A'], ['.','A','.'] ], [ ['.','B','A'], ['B','.','C'], ['A','C','.'] ], [ ['A','B','C'], ['.','C','A'], ['.','A','.'] ], ], [ # Level 2 [ ['A','.','.'], ['D','.','.'], ['C','A','.'], ], [ ['C','.','D'], ['.','.','B'], ['.','D','C'], ], [ ['.','B','D'], ['D','.','.'], ['B','.','C'], ], [ ['A','.','.'], ['.','D','A'], ['D','.','C'], ], [ ['C','.','D'], ['.','C','.'], ['B','.','C'], ], ], [ # Level 3 [ ['.','A','.'], ['A','C','.'], ['.','B','.'], ], [ ['B','A','.'], ['A','C','.'], ['.','.','.'], ], [ ['.','A','C'], ['.','.','B'], ['C','.','.'], ], [ ['.','.','C'], ['D','.','A'], ['C','.','.'], ], [ ['.','.','C'], ['D','.','A'], ['.','A','.'], ], ], [ # Level 4 [ ['.','B','C','D'], ['D','C','.','A'], ['.','D','A','B'], ['B','A','.','C'], ], [ ['A','.','.','D'], ['D','C','B','.'], ['C','D','A','.'], ['.','.','D','C'], ], [ ['.','B','.','.'], ['.','C','B','A'], ['C','D','A','.'], ['.','.','D','.'], ], [ ['.','B','A','.'], ['D','.','B','C'], ['A','C','.','B'], ['.','D','C','.'] ], [ ['.','.','.','.'], ['D','A','B','C'], ['A','C','D','B'], ['.','.','.','.'] ], ], [ # Level 5 [ ['.','B','.','.'], ['D','A','B','.'], ['.','D','A','B'], ['.','.','D','.'] ], [ ['A','B','C','D'], ['.','.','.','.'], ['.','.','.','.'], ['B','C','D','A'] ], [ ['.','.','A','D'], ['D','.','.','C'], ['A','.','.','B'], ['B','D','.','.'] ], [ ['.','.','A','.'], ['D','A','B','.'], ['.','C','D','B'], ['.','D','.','.'] ], ['C','B','.','D'], ['.','.','.','C'], ['A','.','.','.'], ['B','.','C','A'] ], [ # Level 6 [ ['C','.','.','D'], ['.','.','B','.'], ['A','.','.','.'], ['.','.','D','.'] ], [ ['.','B','.','A'], ['.','.','B','.'], ['C','.','D','.'], ['.','.','.','C'] ], [ ['A','.','B','.'], ['.','C','.','A'], ['.','.','.','D'], ['D','.','C','.'] ], [ ['.','A','.','.'], ['C','.','A','B'], ['.','.','C','.'], ['D','.','.','A'] ], [ ['C','.','.','D'], ['B','.','A','.'], ['.','B','.','A'], ['.','.','.','.'] ], [ ['.','A','C','.'], ['.','.','.','D'], ['C','.','.','A'], ['.','B','.','.'] ], [ ['.','C','.','D'], ['B','.','.','.'], ['.','.','.','.'], ['C','A','.','B'] ], [ ['B','.','.','C'], ['.','A','.','.'], ['.','.','D','.'], ['.','B','.','.'] ], ], [ # Level 7 [ ['A','B','C','D','E'], ['.','A','B','C','D'], ['.','.','A','B','C'], ['.','.','.','A','B'], ['.','.','.','.','A'] ], [ ['A','B','.','D','.'], ['.','.','D','E','A'], ['C','.','.','A','.'], ['D','E','.','.','C'], ['.','A','B','.','D'] ], [ ['.','C','.','A','.'], ['A','.','B','.','C'], ['.','B','.','C','.'], ['D','.','C','.','A'], ['.','A','E','.','B'] ], [ ['C','B','.','.','D'], ['.','.','D','C','.'], ['D','.','B','.','E'], ['.','A','.','D','C'], ['E','.','.','B','.'] ], [ ['D','.','.','B','E'], ['.','E','A','.','.'], ['A','C','.','.','B'], ['.','.','B','C','.'], ['C','B','.','A','.'] ], [ ['.','.','C','D','.'], ['B','.','.','.','C'], ['.','C','.','B','D'], ['C','.','D','A','.'], ['D','E','.','.','A'] ], ], [ # Level 8 [ ['1','2','3','4','5'], ['.','1','2','3','4'], ['.','.','1','2','3'], ['.','.','.','1','2'], ['.','.','.','.','1'] ], [ ['1','2','.','4','.'], ['.','.','4','5','1'], ['3','.','.','1','.'], ['4','5','.','.','3'], ['.','1','2','.','4'] ], [ ['.','3','.','1','.'], ['1','.','2','.','3'], ['.','2','.','3','.'], ['4','.','3','.','1'], ['.','1','5','.','2'] ], [ ['3','2','.','.','4'], ['.','.','4','3','.'], ['4','.','2','.','5'], ['.','1','.','4','3'], ['5','.','.','2','.'] ], [ ['4','.','.','2','5'], ['.','5','1','.','.'], ['1','3','.','.','2'], ['.','.','2','3','.'], ['3','2','.','1','.'] ], [ ['.','.','3','4','.'], ['2','.','.','.','3'], ['.','3','.','2','4'], ['3','.','4','1','.'], ['4','5','.','.','1'] ], ], [ # Level 9 [ ['3','.','.','.','.','5','6','.','2'], ['.','6','2','7','1','.','.','4','.'], ['1','.','.','9','.','.','.','5','.'], ['8','.','.','.','.','.','2','6','.'], ['.','3','.','.','8','.','.','7','.'], ['.','9','7','.','.','.','.','.','1'], ['.','5','.','.','.','.','.','.','6'], ['.','8','.','.','6','7','4','2','.'], ['6','.','3','1','.','.','.','.','8'] ], [ ['9','3','1','.','.','7','.','2','8'], ['.','.','.','.','3','6','.','.','.'], ['4','.','6','.','.','2','.','.','.'], ['6','2','.','.','.','.','9','1','.'], ['1','.','.','.','2','.','.','.','4'], ['.','4','8','.','.','.','.','6','5'], ['.','.','.','9','.','.','3','.','2'], ['.','.','.','2','7','.','.','.','.'], ['3','7','.','4','.','.','5','9','1'] ], [ ['.','.','9','.','6','.','.','.','.'], ['2','.','6','4','.','.','1','.','.'], ['.','.','3','1','8','.','5','.','.'], ['.','.','2','.','.','.','.','.','1'], ['7','9','.','.','.','.','.','6','8'], ['1','.','.','.','.','.','3','.','.'], ['.','.','7','.','9','2','8','.','.'], ['.','.','1','.','.','8','6','.','5'], ['.','.','.','.','3','.','4','.','.'] ], [ ['.','7','6','.','.','5','.','.','8'], ['.','8','.','.','.','.','.','5','.'], ['.','.','2','.','6','1','4','3','.'], ['8','.','.','.','1','.','.','.','.'], ['.','.','.','6','.','3','.','.','.'], ['.','.','.','.','7','.','.','.','1'], ['.','9','5','4','8','.','3','.','.'], ['.','2','.','.','.','.','.','8','.'], ['7','.','.','9','.','.','1','6','.'] ], [ ['.','7','6','3','.','.','9','.','.'], ['3','8','.','7','4','.','.','5','.'], ['9','.','2','.','.','.','.','.','.'], ['.','.','9','.','.','.','.','.','.'], ['.','1','.','6','.','3','.','4','.'], ['.','.','.','.','.','.','6','.','.'], ['.','.','.','.','.','.','3','.','2'], ['.','2','.','.','3','7','.','8','9'], ['.','.','8','.','.','2','1','6','.'] ], [ ['.','7','6','.','.','5','.','1','.'], ['.','8','.','.','4','.','.','.','6'], ['9','.','2','.','.','.','4','.','.'], ['.','.','.','5','.','.','.','2','.'], ['.','1','7','.','.','.','8','4','.'], ['.','4','.','.','.','8','.','.','.'], ['.','.','5','.','.','.','3','.','2'], ['6','.','.','.','3','.','.','8','.'], ['.','3','.','9','.','.','1','6','.'] ], [ ['.','7','.','.','2','5','.','1','8'], ['3','.','.','.','.','9','2','.','.'], ['.','.','.','.','6','.','4','3','.'], ['.','.','.','.','.','4','7','2','.'], ['.','.','.','.','.','.','.','.','.'], ['.','4','3','2','.','.','.','.','.'], ['.','9','5','.','8','.','.','.','.'], ['.','.','4','1','.','.','.','.','9'], ['7','3','.','9','5','.','.','6','.'] ], [ ['.','.','.','3','.','5','9','.','.'], ['3','8','.','.','.','.','2','.','6'], ['9','5','.','.','6','.','.','.','.'], ['.','.','9','.','1','4','.','.','3'], ['.','.','.','.','.','.','.','.','.'], ['5','.','.','2','7','.','6','.','.'], ['.','.','.','.','8','.','.','7','2'], ['6','.','4','.','.','.','.','8','9'], ['.','.','8','9','.','2','.','.','.'] ], [ ['.','.','6','.','2','5','.','.','8'], ['.','8','.','.','.','9','.','.','6'], ['9','.','.','.','.','.','4','.','.'], ['.','6','.','.','1','.','.','2','3'], ['.','.','.','6','.','3','.','.','.'], ['5','4','.','.','7','.','.','9','.'], ['.','.','5','.','.','.','.','.','2'], ['6','.','.','1','.','.','.','8','.'], ['7','.','.','9','5','.','1','.','.'] ], [ ['.','.','6','.','.','5','9','1','8'], ['.','.','.','7','4','.','.','5','.'], ['9','.','.','.','6','.','.','3','.'], ['.','.','.','5','.','.','7','.','.'], ['2','.','.','.','.','.','.','.','5'], ['.','.','3','.','.','8','.','.','.'], ['.','9','.','.','8','.','.','.','2'], ['.','2','.','.','3','7','.','.','.'], ['7','3','8','9','.','.','1','.','.'] ], [ ['.','.','.','5','.','4','.','.','.'], ['2','3','4','8','.','.','.','1','.'], ['.','.','.','.','1','3','8','.','2'], ['.','5','.','4','7','2','.','.','1'], ['.','7','.','.','.','.','.','6','.'], ['4','.','.','6','9','5','.','2','.'], ['7','.','1','3','5','.','.','.','.'], ['.','9','.','.','.','1','4','5','7'], ['.','.','.','7','.','9','.','.','.'] ], [ ['.','.','.','.','.','.','6','.','.'], ['2','.','.','8','6','.','9','.','5'], ['5','.','7','.','1','3','8','.','2'], ['6','.','8','.','7','.','.','.','1'], ['.','7','.','.','3','.','.','6','.'], ['4','.','.','.','9','.','7','.','8'], ['7','.','1','3','5','.','2','.','9'], ['3','.','6','.','8','1','.','.','7'], ['.','.','5','.','.','.','.','.','.'] ], [ ['.','8','9','5','.','4','.','7','3'], ['2','.','.','.','6','7','.','.','5'], ['.','.','.','9','.','.','.','4','2'], ['6','5','.','.','.','.','.','.','.'], ['.','7','2','1','3','8','5','6','.'], ['.','.','.','.','.','.','.','2','8'], ['7','4','.','.','.','6','.','.','.'], ['3','.','.','2','8','.','.','.','7'], ['8','2','.','7','.','9','1','3','.'] ], [ ['.','8','9','.','2','4','.','.','3'], ['.','.','.','.','.','.','.','1','.'], ['5','.','.','.','1','3','8','.','2'], ['6','.','.','4','.','2','.','.','.'], ['.','7','2','1','.','8','5','6','.'], ['.','.','.','6','.','5','.','.','8'], ['7','.','1','3','5','.','.','.','9'], ['.','9','.','.','.','.','.','.','.'], ['8','.','.','7','4','.','1','3','.'] ], [ ['.','.','.','.','.','.','.','9','8'], ['.','.','.','.','.','4','1','.','.'], ['8','4','3','6','.','.','2','.','.'], ['9','.','5','.','.','3','.','.','.'], ['3','2','.','.','.','.','.','8','7'], ['.','.','.','9','.','.','3','.','1'], ['.','.','2','.','.','5','7','3','6'], ['.','.','7','1','.','.','.','.','.'], ['5','9','.','.','.','.','.','.','.'] ], [ ['2','.','.','3','5','7','.','.','.'], ['7','.','9','2','.','.','.','6','.'], ['.','.','.','.','.','.','.','.','.'], ['9','.','.','.','.','.','.','2','4'], ['.','.','6','5','4','1','9','.','.'], ['4','7','.','.','.','.','.','.','1'], ['.','.','.','.','.','.','.','.','.'], ['.','3','.','.','.','8','5','.','9'], ['.','.','.','7','3','6','.','.','2'] ], [ ['.','.','1','.','5','7','4','.','.'], ['.','.','9','2','.','.','.','.','.'], ['8','4','.','6','.','.','.','7','.'], ['.','.','5','.','.','3','.','2','.'], ['3','.','.','.','.','.','.','.','7'], ['.','7','.','9','.','.','3','.','.'], ['.','8','.','.','.','5','.','3','6'], ['.','.','.','.','.','8','5','.','.'], ['.','.','4','7','3','.','8','.','.'] ], [ ['2','6','.','3','.','.','.','9','.'], ['7','.','.','2','.','4','.','6','.'], ['.','.','.','.','.','9','.','.','.'], ['9','.','5','.','7','.','6','.','4'], ['.','.','.','.','.','.','.','.','.'], ['4','.','8','.','6','.','3','.','1'], ['.','.','.','4','.','.','.','.','.'], ['.','3','.','1','.','8','.','.','9'], ['.','9','.','.','.','6','.','1','2'] ], [ ['4','9','.','.','.','.','.','1','.'], ['.','8','.','.','.','2','5','.','.'], ['1','.','5','.','.','.','6','.','.'], ['7','.','.','6','4','.','.','.','.'], ['5','.','.','7','.','3','.','.','8'], ['.','.','.','.','2','1','.','.','4'], ['.','.','8','.','.','.','3','.','1'], ['.','.','1','9','.','.','.','7','.'], ['.','7','.','.','.','.','.','2','5'] ], [ ['9','6','.','4','1','7','.','2','3'], ['.','.','8','.','9','5','6','.','1'], ['.','.','.','6','.','.','.','.','9'], ['.','.','.','.','2','.','9','.','.'], ['4','7','.','.','5','.','.','8','6'], ['.','.','6','.','4','.','.','.','.'], ['8','.','.','.','.','3','.','.','.'], ['6','.','3','1','7','.','5','.','.'], ['1','9','.','5','8','4','.','6','2'] ], [ ['.','.','.','4','.','7','8','.','.'], ['7','3','.','.','.','5','6','.','.'], ['.','1','4','.','3','.','7','.','.'], ['5','8','.','.','.','6','.','.','.'], ['4','.','.','3','.','1','.','.','6'], ['.','.','.','8','.','.','.','7','5'], ['.','.','2','.','6','.','4','1','.'], ['.','.','3','1','.','.','.','9','8'], ['.','.','7','5','.','4','.','.','.'] ], [ ['9','.','5','.','.','7','8','2','.'], ['7','.','.','2','.','.','.','4','.'], ['.','1','.','6','3','.','.','.','9'], ['.','.','1','7','2','.','9','.','.'], ['.','.','.','3','.','1','.','.','.'], ['.','.','6','.','4','9','1','.','.'], ['8','.','.','.','6','3','.','1','.'], ['.','4','.','.','.','2','.','.','8'], ['.','9','7','5','.','.','3','.','2'] ], [ ['9','6','.','4','1','7','8','.','3'], ['.','.','8','2','9','5','.','.','.'], ['2','.','.','6','3','.','.','.','9'], ['.','.','.','7','.','.','.','3','4'], ['4','.','.','.','5','.','.','.','6'], ['3','2','.','.','.','9','.','.','.'], ['8','.','.','.','6','3','.','.','7'], ['.','.','.','1','7','2','5','.','.'], ['1','.','7','5','8','4','.','6','2'] ], [ ['.','.','1','.','.','4','7','.','3'], ['7','.','.','.','6','.','.','5','.'], ['.','.','2','7','.','8','.','.','6'], ['.','9','.','.','4','.','.','.','.'], ['.','.','.','3','.','9','.','.','.'], ['.','.','.','.','5','.','.','2','.'], ['6','.','.','9','.','7','4','.','.'], ['.','7','.','.','8','.','.','.','1'], ['4','.','8','6','.','.','3','.','.'] ], [ ['.','.','1','.','.','.','.','9','.'], ['7','.','.','1','.','3','.','5','.'], ['.','.','.','.','9','8','1','.','6'], ['.','9','.','.','4','.','.','.','.'], ['.','8','4','.','.','.','6','1','.'], ['.','.','.','.','5','.','.','2','.'], ['6','.','5','9','3','.','.','.','.'], ['.','7','.','4','.','2','.','.','1'], ['.','2','.','.','.','.','3','.','.'] ], [ ['8','.','.','.','2','4','.','.','.'], ['7','.','9','1','.','.','.','.','.'], ['.','5','.','.','9','.','.','4','.'], ['.','.','6','.','.','.','8','3','.'], ['2','.','4','.','.','.','6','.','5'], ['.','3','7','.','.','.','9','.','.'], ['.','1','.','.','3','.','.','8','.'], ['.','.','.','.','.','2','5','.','1'], ['.','.','.','6','1','.','.','.','9'] ], [ ['.','.','1','.','2','.','.','.','.'], ['.','.','9','.','6','3','.','.','.'], ['3','.','.','.','.','8','1','4','.'], ['.','9','.','.','.','.','8','3','.'], ['.','.','4','.','7','.','6','.','.'], ['.','3','7','.','.','.','.','2','.'], ['.','1','5','9','.','.','.','.','2'], ['.','.','.','4','8','.','5','.','.'], ['.','.','.','.','1','.','3','.','.'] ], [ ['.','6','.','5','.','4','7','.','3'], ['.','.','9','.','.','.','.','5','.'], ['3','.','2','.','9','.','.','.','.'], ['5','.','6','.','.','.','8','.','.'], ['.','8','.','.','.','.','.','1','.'], ['.','.','7','.','.','.','9','.','4'], ['.','.','.','.','3','.','4','.','2'], ['.','7','.','.','.','.','5','.','.'], ['4','.','8','6','.','5','.','7','.'] ], [ ['.','.','.','.','2','.','.','9','.'], ['.','.','.','.','6','3','.','.','8'], ['3','.','.','.','.','8','1','4','.'], ['.','.','.','.','4','.','8','.','7'], ['.','8','4','.','.','.','6','1','.'], ['1','.','7','.','5','.','.','.','.'], ['.','1','5','9','.','.','.','.','2'], ['9','.','.','4','8','.','.','.','.'], ['.','2','.','.','1','.','.','.','.'] ], [ ['8','.','1','.','.','4','.','.','.'], ['.','.','.','.','6','.','.','5','.'], ['3','.','2','7','.','.','.','.','6'], ['.','9','.','.','4','.','.','.','7'], ['2','.','.','3','.','9','.','.','5'], ['1','.','.','.','5','.','.','2','.'], ['6','.','.','.','.','7','4','.','2'], ['.','7','.','.','8','.','.','.','.'], ['.','.','.','6','.','.','3','.','9'] ], [ ['.','.','.','.','2','.','9','4','3'], ['5','3','.','9','.','.','.','8','.'], ['.','.','.','.','.','1','6','.','7'], ['.','.','.','3','.','.','8','.','4'], ['.','.','.','2','7','9','.','.','.'], ['9','.','3','.','.','5','.','.','.'], ['7','.','9','6','.','.','.','.','.'], ['.','6','.','.','.','4','.','7','5'], ['1','4','5','.','8','.','.','.','.'] ], [ ['.','7','1','5','.','.','9','4','.'], ['5','.','.','9','6','.','.','8','2'], ['.','9','.','.','.','.','.','.','.'], ['2','5','.','3','.','.','8','9','.'], ['.','.','.','2','7','9','.','.','.'], ['.','1','3','.','.','5','.','2','6'], ['.','.','.','.','.','.','.','1','.'], ['3','6','.','.','9','4','.','.','5'], ['.','4','5','.','.','2','3','6','.'] ], [ ['6','7','1','5','2','.','.','.','.'], ['5','.','.','9','6','7','.','.','2'], ['.','.','.','.','.','.','6','.','.'], ['.','.','7','3','.','6','8','9','.'], ['4','.','6','2','.','9','5','.','1'], ['.','1','3','8','.','5','7','.','.'], ['.','.','9','.','.','.','.','.','.'], ['3','.','.','1','9','4','.','.','5'], ['.','.','.','.','8','2','3','6','9'] ], [ ['.','7','.','5','2','.','.','4','3'], ['5','.','.','.','.','7','1','8','2'], ['.','9','.','.','.','1','6','.','.'], ['.','5','.','3','1','6','8','9','.'], ['.','.','.','.','.','.','.','.','.'], ['.','1','3','8','4','5','.','2','.'], ['.','.','9','6','.','.','.','1','.'], ['3','6','8','1','.','.','.','.','5'], ['1','4','.','.','8','2','.','6','.'] ], [ ['.','.','.','1','6','.','.','2','7'], ['.','.','7','.','8','9','.','6','.'], ['1','.','6','.','5','.','.','8','9'], ['.','.','.','5','.','.','2','3','8'], ['.','.','.','8','2','3','.','.','.'], ['8','2','3','.','.','1','.','.','.'], ['5','1','.','.','3','.','9','.','2'], ['.','8','.','7','1','.','4','.','.'], ['6','7','.','.','9','5','.','.','.'] ], [ ['.','.','8','1','.','.','.','2','7'], ['.','.','7','.','8','9','.','.','.'], ['.','.','6','2','.','.','3','8','.'], ['7','.','1','5','.','6','.','3','8'], ['.','.','.','.','.','.','.','.','.'], ['8','2','.','9','.','1','6','.','5'], ['.','1','4','.','.','8','9','.','.'], ['.','.','.','7','1','.','4','.','.'], ['6','7','.','.','.','5','8','.','.'] ], [ ['.','3','.','.','.','4','.','2','.'], ['2','.','.','.','8','9','1','.','4'], ['1','.','.','2','.','.','3','8','.'], ['7','.','1','.','.','6','.','.','8'], ['.','6','.','.','.','.','.','9','.'], ['8','.','.','9','.','.','6','.','5'], ['.','1','4','.','.','8','.','.','2'], ['3','.','9','7','1','.','.','.','6'], ['.','7','.','4','.','.','.','1','.'] ], [ ['9','.','8','.','.','.','5','2','.'], ['.','.','7','3','.','.','.','6','.'], ['.','4','.','.','.','.','.','8','9'], ['7','.','.','5','.','6','2','3','.'], ['.','.','5','.','2','.','7','.','.'], ['.','2','3','9','.','1','.','.','5'], ['5','1','.','.','.','.','.','7','.'], ['.','8','.','.','.','2','4','.','.'], ['.','7','2','.','.','.','8','.','3'] ], [ ['8','.','.','2','4','.','.','.','.'], ['7','.','.','.','1','3','.','8','2'], ['6','5','.','.','8','9','1','.','4'], ['.','.','.','.','.','7','2','1','6'], ['.','1','7','.','3','.','4','5','.'], ['5','9','6','1','.','.','.','.','.'], ['3','.','5','8','9','.','.','4','1'], ['1','7','.','3','6','.','.','.','8'], ['.','.','.','.','7','1','.','.','5'] ], [ ['8','.','.','2','.','6','.','.','.'], ['.','.','9','.','1','3','.','.','2'], ['6','.','2','7','8','.','.','3','.'], ['.','.','3','.','.','.','.','1','6'], ['.','.','7','6','.','8','4','.','.'], ['5','9','.','.','.','.','8','.','.'], ['.','6','.','.','9','2','7','.','1'], ['1','.','.','3','6','.','9','.','.'], ['.','.','.','4','.','1','.','.','5'] ], [ ['8','3','.','2','.','.','.','9','.'], ['.','4','.','.','.','3','.','8','.'], ['.','.','.','.','8','9','1','.','4'], ['.','8','.','9','.','.','2','.','.'], ['2','.','.','6','.','8','.','.','9'], ['.','.','6','.','.','4','.','7','.'], ['3','.','5','8','9','.','.','.','.'], ['.','7','.','3','.','.','.','2','.'], ['.','2','.','.','.','1','.','6','5'] ], [ ['.','3','1','2','4','.','.','.','.'], ['.','.','9','5','1','.','6','8','.'], ['6','.','.','.','.','.','.','3','.'], ['.','8','.','9','.','7','2','.','.'], ['2','.','7','.','.','.','4','.','9'], ['.','.','6','1','.','4','.','7','.'], ['.','6','.','.','.','.','.','.','1'], ['.','7','4','.','6','5','9','.','.'], ['.','.','.','.','7','1','3','6','.'] ], [ ['.','.','7','.','.','.','.','5','.'], ['1','.','4','.','.','3','7','.','6'], ['.','6','5','7','4','2','9','.','3'], ['2','.','.','4','.','5','6','3','9'], ['.','.','.','3','.','7','.','.','.'], ['4','8','3','9','.','6','.','.','5'], ['9','.','8','2','5','4','1','6','.'], ['5','.','2','6','.','.','3','.','8'], ['.','1','.','.','.','.','5','.','.'] ], [ ['.','.','7','.','.','.','.','.','2'], ['.','2','.','.','.','3','.','8','6'], ['.','6','5','7','4','.','9','.','3'], ['.','.','.','4','.','.','6','.','.'], ['.','5','9','.','.','.','8','4','.'], ['.','.','3','.','.','6','.','.','.'], ['9','.','8','.','5','4','1','6','.'], ['5','4','.','6','.','.','.','9','.'], ['7','.','.','.','.','.','5','.','.'] ], [ ['.','.','7','1','.','8','4','5','2'], ['1','.','4','.','.','3','.','.','6'], ['.','.','5','.','.','2','9','.','3'], ['.','.','.','.','.','5','.','3','.'], ['.','.','9','3','.','7','8','.','.'], ['.','8','.','9','.','.','.','.','.'], ['9','.','8','2','.','.','1','.','.'], ['5','.','.','6','.','.','3','.','8'], ['7','1','6','8','.','9','5','.','.'] ], [ ['3','.','7','.','.','.','.','5','.'], ['.','2','.','5','9','.','.','.','.'], ['8','6','.','.','.','2','.','1','.'], ['2','.','.','.','8','5','.','.','9'], ['.','5','.','.','2','.','.','4','.'], ['4','.','.','9','1','.','.','.','5'], ['.','3','.','2','.','.','.','6','7'], ['.','.','.','.','7','1','.','9','.'], ['.','1','.','.','.','.','5','.','4'] ], [ ['6','8','.','2','.','7','.','3','.'], ['.','2','9','.','.','6','8','7','.'], ['5','.','.','.','8','4','.','.','.'], ['3','.','5','.','.','.','.','8','.'], ['.','.','.','7','.','8','.','.','.'], ['.','7','.','.','.','.','4','.','3'], ['.','.','.','8','4','.','.','.','7'], ['.','5','8','1','.','.','9','4','.'], ['.','6','.','5','.','9','.','1','8'] ], [ ['6','.','4','2','1','7','.','.','.'], ['.','2','.','.','.','6','.','.','.'], ['5','3','7','9','.','.','2','.','1'], ['3','.','.','.','.','.','7','8','6'], ['.','4','6','.','.','.','1','9','.'], ['8','7','1','.','.','.','.','.','3'], ['9','.','3','.','.','2','6','5','7'], ['.','.','.','1','.','.','.','4','.'], ['.','.','.','5','7','9','3','.','8'] ], [ ['6','8','.','.','1','.','.','3','.'], ['1','.','.','3','.','6','.','7','4'], ['.','.','7','9','.','4','2','.','1'], ['3','.','5','4','.','.','.','.','6'], ['.','.','.','.','.','.','.','.','.'], ['8','.','.','.','.','5','4','.','3'], ['9','.','3','8','.','2','6','.','.'], ['7','5','.','1','.','3','.','.','2'], ['.','6','.','.','7','.','.','1','8'] ], [ ['6','.','4','.','.','.','5','.','9'], ['1','.','.','.','.','.','8','7','.'], ['5','3','.','9','8','.','.','.','1'], ['.','.','5','.','.','1','.','8','.'], ['.','4','.','7','3','8','.','9','.'], ['.','7','.','6','.','.','4','.','.'], ['9','.','.','.','4','2','.','5','7'], ['.','5','8','.','.','.','.','.','2'], ['4','.','2','.','.','.','3','.','8'] ], [ ['.','.','.','.','5','6','1','.','.'], ['.','.','.','8','1','.','.','6','4'], ['6','4','.','7','9','.','.','5','.'], ['9','.','7','.','8','.','5','4','.'], ['4','.','.','.','.','.','.','.','8'], ['.','5','6','.','2','.','7','.','3'], ['.','6','.','.','3','7','.','8','5'], ['3','9','.','.','4','8','.','.','.'], ['.','.','2','5','6','.','.','.','.'] ], [ ['.','.','.','.','.','.','1','.','9'], ['5','.','9','.','.','2','.','6','.'], ['6','.','.','7','9','.','8','5','.'], ['9','.','7','3','8','.','5','.','6'], ['.','.','.','6','.','5','.','.','.'], ['8','.','6','.','2','4','7','.','3'], ['.','6','4','.','3','7','.','.','5'], ['.','9','.','1','.','.','6','.','7'], ['7','.','2','.','.','.','.','.','.'] ], [ ['2','.','8','4','.','.','.','.','9'], ['5','.','9','8','1','2','.','.','.'], ['.','.','1','.','9','.','.','5','.'], ['.','.','7','.','.','.','5','4','6'], ['.','1','3','6','.','5','2','9','.'], ['8','5','6','.','.','.','7','.','.'], ['.','6','.','.','3','.','9','.','.'], ['.','.','.','1','4','8','6','.','7'], ['7','.','.','.','.','9','4','.','1'] ], [ ['2','.','8','4','5','.','.','7','.'], ['.','.','9','.','1','2','3','.','4'], ['6','.','.','7','.','.','8','5','.'], ['.','.','.','.','8','.','5','4','6'], ['4','1','.','.','.','.','.','9','8'], ['8','5','6','.','2','.','.','.','.'], ['.','6','4','.','.','7','.','.','5'], ['3','.','5','1','4','.','6','.','.'], ['.','8','.','.','6','9','4','.','1'] ], [ ['7','9','.','5','.','1','.','.','.'], ['.','5','1','.','.','.','.','.','6'], ['.','8','.','.','.','9','.','.','2'], ['.','.','.','2','5','.','.','8','1'], ['.','.','.','.','.','.','.','.','.'], ['8','4','.','.','7','3','.','.','.'], ['1','.','.','6','.','.','.','7','.'], ['5','.','.','.','.','.','8','1','.'], ['.','.','.','3','.','2','.','6','5'] ], [ ['.','.','.','.','6','.','.','.','.'], ['.','.','1','.','.','.','.','9','6'], ['.','.','4','.','3','9','.','.','.'], ['.','6','7','.','.','4','3','8','.'], ['2','.','.','8','.','6','.','.','7'], ['.','4','5','1','.','.','6','2','.'], ['.','.','.','6','8','.','2','.','.'], ['5','2','.','.','.','.','8','.','.'], ['.','.','.','.','1','.','.','.','.'] ], [ ['.','.','.','.','6','1','.','3','.'], ['.','.','.','.','.','.','7','9','.'], ['.','.','4','7','3','.','.','.','2'], ['.','6','.','.','5','.','.','8','.'], ['2','.','3','.','.','.','5','.','7'], ['.','4','.','.','7','.','.','2','.'], ['1','.','.','.','8','5','2','.','.'], ['.','2','6','.','.','.','.','.','.'], ['.','7','.','3','1','.','.','.','.'] ], [ ['.','.','.','.','.','1','4','3','8'], ['.','.','.','.','.','.','.','9','6'], ['.','.','.','.','.','9','1','.','2'], ['.','.','.','.','.','4','3','.','1'], ['2','.','.','8','.','6','.','.','7'], ['8','.','5','1','.','.','.','.','.'], ['1','.','9','6','.','.','.','.','.'], ['5','2','.','.','.','.','.','.','.'], ['4','7','8','3','.','.','.','.','.'] ], [ ['.','7','1','6','.','.','9','.','.'], ['4','.','.','.','.','.','3','.','1'], ['.','.','.','8','.','2','.','7','.'], ['.','5','.','.','.','.','4','.','.'], ['2','.','.','1','.','5','.','.','3'], ['.','.','3','.','.','.','.','9','.'], ['.','1','.','2','.','4','.','.','.'], ['6','.','8','.','.','.','.','.','2'], ['.','.','4','.','.','9','1','5','.'] ], [ ['2','.','7','.','6','.','.','.','.'], ['4','3','.','.','.','9','2','.','.'], ['.','6','5','4','.','.','.','.','.'], ['.','7','.','.','.','.','1','.','2'], ['.','.','6','8','1','7','5','.','.'], ['5','.','3','.','.','.','.','9','.'], ['.','.','.','.','.','8','3','5','.'], ['.','.','1','9','.','.','.','2','7'], ['.','.','.','.','3','.','6','.','1'] ], [ ['.','9','.','.','.','1','4','8','5'], ['.','.','8','7','.','.','2','.','6'], ['.','6','.','.','.','2','9','.','3'], ['8','7','.','.','9','.','1','.','.'], ['.','2','.','8','.','7','.','3','.'], ['.','.','3','.','2','.','.','9','8'], ['6','.','2','1','.','.','.','5','.'], ['3','.','1','.','.','6','8','.','.'], ['7','8','9','2','.','.','.','4','.'] ], [ ['2','.','.','3','.','.','.','8','.'], ['.','.','.','7','.','.','2','.','6'], ['.','6','.','4','8','.','9','7','3'], ['8','.','.','.','9','.','1','.','2'], ['9','.','.','8','1','7','.','.','4'], ['5','.','3','.','2','.','.','.','8'], ['6','4','2','.','7','8','.','5','.'], ['3','.','1','.','.','6','.','.','.'], ['.','8','.','.','.','5','.','.','1'] ], [ ['.','.','.','.','.','1','.','8','.'], ['4','.','.','.','.','.','2','1','6'], ['.','6','.','4','8','.','.','.','3'], ['.','.','4','5','9','.','.','6','.'], ['9','.','6','.','1','.','5','.','4'], ['.','1','.','.','2','4','7','.','.'], ['6','.','.','.','7','8','.','5','.'], ['3','5','1','.','.','.','.','.','7'], ['.','8','.','2','.','.','.','.','.'] ], [ ['.','.','9','2','.','.','.','.','4'], ['.','.','6','.','.','3','1','.','.'], ['4','.','.','1','.','.','5','.','.'], ['.','3','.','8','.','.','9','.','1'], ['.','.','.','3','.','4','.','.','.'], ['1','.','4','.','.','6','.','5','.'], ['.','.','7','.','.','2','.','.','3'], ['.','.','1','7','.','.','6','.','.'], ['9','.','.','.','.','1','4','.','.'] ], [ ['.','.','9','.','6','.','.','.','.'], ['2','.','6','4','.','.','1','.','.'], ['.','.','3','1','8','.','5','.','.'], ['.','.','2','.','.','.','.','.','1'], ['7','9','.','.','.','.','.','6','8'], ['1','.','.','.','.','.','3','.','.'], ['.','.','7','.','9','2','8','.','.'], ['.','.','1','.','.','8','6','.','5'], ['.','.','.','.','3','.','4','.','.'] ], ] ] # Randomize each level in the list for l in range(0, len(sudoku_list)): for j in range(0, len(sudoku_list[l])): # Select a random new position to set the J sudoku old_sudo = sudoku_list[l][j] new_pos = random.randint(0,len(sudoku_list[l])-1) sudoku_list[l][j] = sudoku_list[l][new_pos] sudoku_list[l][new_pos] = old_sudo return sudoku_list