Sudoku.py

Python Example:


import sys
from Tkinter import Canvas, Button, YES, BOTH, mainloop
from MplSudoku import *

dataFilename = "Sudoku.dat"

headerFont = 'Helvetica 20 bold'
fixedFont = 'Helvetica 14 bold'
solutionFont = 'Helvetica 13'


def createSudokuCanvas(boxCount, cellCount):
   xoff = 40
   yoff = 80
   cellSize = 30
   totalCount = boxCount * cellCount
   sudokuSize = totalCount * cellSize + totalCount + boxCount + 2
   width = sudokuSize + xoff * 2 - 2
   height = sudokuSize + yoff * 2 - 2
   canvas = Canvas(width=width, height=height, bg='white')
   canvas.pack(expand=YES, fill=BOTH)

   canvas.totalCount = totalCount
   canvas.boxCount = boxCount
   canvas.cellCount = cellCount
   canvas.cellSize = cellSize
   canvas.xoff = xoff
   canvas.yoff = yoff
   canvas.sudokuSize = sudokuSize
   canvas.width = width
   canvas.height = height
   return canvas


def showSudokuHeader(canvas, headerText):
   canvas.create_text(canvas.width / 2 + 2, canvas.yoff / 2 + 2, text=headerText, font=headerFont)


def showSudokuGrid(canvas):
   lineLen = canvas.sudokuSize
   xoff = canvas.xoff
   yoff = canvas.yoff
   x = xoff + 1
   y = yoff + 1
   for i in range(canvas.totalCount + 1):
      if i % canvas.cellCount:
         lineWidth = 1
      else:
         lineWidth = 2
      canvas.create_line(x, yoff, x, yoff+lineLen, width=lineWidth)
      canvas.create_line(xoff, y, xoff+lineLen, y, width=lineWidth)
      x += canvas.cellSize + lineWidth
      y += canvas.cellSize + lineWidth


def readSudokuDataFile(filename, size):
   fixedValues = []
   k = 0
   file = open(filename, 'r')
   for i, line in enumerate(file):
      items = line[:-1].split(',')
      if len(items) > 1:
         if len(items) < size:
            raise ValueError("The file '%s' contains %d items in line %d, instead of the
                              required %d." % (filename, len(items), i+1, size))
         if k < size:
            for j, item in enumerate(items):
               if j < size:
                  fixedValues.append(int(item.strip()))
         k += 1
   file.close()
   return fixedValues


def readSudokuSparseDataFile(filename):
   fixedValues = []
   file = open(filename, 'r')
   for i, line in enumerate(file):
      items = line[:-1].split(',')
      if len(items) > 1:
         if not len(items) == 3:
            raise ValueError("The file '%s' contains '%' in line %d, instead of the correct
                              format 'Row, Col, Num'." % (filename, line[:-1], i+1))
         entry = tuple(int(i) for i in items)
         fixedValues.append(entry)
   file.close()
   return fixedValues


def getSudokuCellPos(canvas, rowcol):
   return (rowcol-0.5) * (canvas.cellSize + 1) + ((rowcol-1)/canvas.cellCount) + 1


def getValue(row, col, size, values):
   if values == None or len(values) == 0:
      return 0
   if type(values[0]).__name__ == 'list' or type(values[0]).__name__ == 'tuple':
      for entry in values:
         if row == entry[0] and col == entry[1]:
            return entry[2]
      return 0
   else:
      nr = (row - 1) * size + (col - 1)
      return values[nr]



def showSudokuEntries(solValues, fixedValues, size, fontStr, canvas):
   row = 1
   col = 1
   for nr in range(size * size):
      ypos = canvas.yoff + getSudokuCellPos(canvas, row)
      xpos = canvas.xoff + getSudokuCellPos(canvas, col)
      if solValues == None:
         fix = getValue(row, col, size, fixedValues)
         if fix > 0:
            canvas.create_text(xpos, ypos, text=str(fix), font=fontStr)
      else:
         val = getValue(row, col, size, solValues)
         if val > 0:
            canvas.create_text(xpos, ypos, text=str(val), font=fontStr)
      if col < size:
         col += 1
      else:
         col = 1
         row += 1


def doLoadButton(canvas):
   size = 9
   dataDir = MplSudoku().DataDir
   canvas.fixedValues = readSudokuDataFile(dataDir + dataFilename, size)
   showSudokuEntries(None, canvas.fixedValues, size, fixedFont, canvas)


def doSolveButton(canvas):
   size = 9
   sudoku = MplSudoku()
   result = sudoku.SolveModel("CoinMP", size, canvas.fixedValues)
   if result == False:
      print("There is no solution available with this input.\n" +
         "The solver returned the following message:\n" +
         str(sudoku.ResultString))
      return
   showSudokuEntries(sudoku.SolValues, canvas.fixedValues, size, solutionFont, canvas)


def doCloseButton(canvas):
   sys.exit()


def createButton(canvas, text, x, y, cmd):
   button = Button(canvas, text=text, width=8, command=cmd)
   button.pack()
   canvas.create_window(x, y, window=button)


def showSudokuButtons(canvas):
   x = canvas.width / 2 - 100
   y = canvas.height - canvas.yoff / 2
   createButton(canvas, 'Load',  x, y, lambda: doLoadButton(canvas))
   createButton(canvas, 'Solve', x + 100, y, lambda: doSolveButton(canvas))
   createButton(canvas, 'Close', x + 200, y, lambda: doCloseButton(canvas))


def runSudoku():
   canvas = createSudokuCanvas(3,3)
   showSudokuHeader(canvas, "MPL Sudoku")
   showSudokuGrid(canvas)
   showSudokuButtons(canvas)
   mainloop()


if __name__ == '__main__':
   runSudoku()

        

Back To Top | Maximal Home Page | List of Samples | Previous Page | Next Page