Guest User

Sample Sudoku Generator v1.0

a guest
Feb 12th, 2013
308
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.56 KB | None | 0 0
  1. --[[ Sample Sudoku generator code v1.0 . Made by Orwell. ]]--
  2.  
  3. local Attempts = {}
  4. Attempts.__index = Attempts
  5.  
  6. --[[ Creates an instance of Attempts.
  7.   Attemps will keep track of attempted numbers for each square and
  8.   supplies random numbers for them on each call to getNextNumber. ]]--
  9. function Attempts.create()
  10.   math.randomseed(os.time()*1000)  -- set the time in milliseconds as seed for the RNG
  11.   local attempts = {}
  12.   setmetatable(attempts, Attempts)
  13.   return attempts
  14. end
  15.  
  16. --[[ Resets the array of attempted number for the square at given index. ]]--
  17. function Attempts.clear(self, index)
  18.   self[index] = {}
  19. end
  20.  
  21. --[[ Returns an unattempted random number for the square at given index.
  22.   It will return nil when all numbers have been tried. ]]--
  23. function Attempts.getNextNumber(self, index)
  24.   if not self[index] then  -- initialize the array at this index if it doesn't exist yet
  25.     self[index] = {}
  26.   end
  27.  
  28.   if self:isExhausted(index) then  -- return nil if there is no number left
  29.     return
  30.   end
  31.  
  32.   local nextNumber
  33.   repeat
  34.     nextNumber = math.random(1,9)
  35.   until not self[index][nextNumber]  -- grab random numbers until we get an unused one
  36.  
  37.   self[index][nextNumber] = true  -- set the number to used
  38.   return nextNumber
  39. end
  40.  
  41. --[[ Returns true if all numbers have been tried for the square at given index. ]]--
  42. function Attempts.isExhausted(self, index)
  43.   return #self[index] == 9  -- if all keys from 1 to 9 have 'true' as value, the 'length' of it will be 9
  44. end
  45.  
  46. local Sudoku = {}
  47. Sudoku.__index = Sudoku
  48.  
  49. --[[ Sets the square at x,y to value. ]]--
  50. function Sudoku.setSquare(sudoku, x, y, value)
  51.   sudoku[x][y] = value
  52. end
  53.  
  54. --[[ Sets the square at x,y to nil. ]]--
  55. function Sudoku.resetSquare(sudoku, x, y)
  56.   sudoku[x][y] = nil
  57. end
  58.  
  59. --[[ Returns true if this square contains given value. ]]--
  60. function Sudoku.checkSquare(sudoku, x, y, value)
  61.   return sudoku[x][y] and sudoku[x][y] == value
  62. end
  63.  
  64. --[[ Returns true if this column contains given value. ]]--
  65. function Sudoku.checkColumn(sudoku, x, value)
  66.   local occupied = false
  67.   for y=1,9 do
  68.     occupied = occupied or sudoku:checkSquare(x, y, value)
  69.   end
  70.   return occupied
  71. end
  72.  
  73. --[[ Return true if this row contains given value. ]]--
  74. function Sudoku.checkRow(sudoku, y, value)
  75.   local occupied = false
  76.   for x=1,9 do
  77.     occupied = occupied or sudoku:checkSquare(x, y, value)
  78.   end
  79.   return occupied
  80. end
  81.  
  82. --[[ Returns true if this region contains given value. ]]--
  83. function Sudoku.checkRegion(sudoku, x, y, value)
  84.   local occupied = false
  85.   local X = math.floor((x-1)/3)*3
  86.   local Y = math.floor((y-1)/3)*3
  87.   for i = X+1,X+3 do
  88.     for j = Y+1,Y+3 do
  89.       occupied = occupied or sudoku:checkSquare(i, j, value)
  90.     end
  91.   end
  92.   return occupied
  93. end
  94.  
  95. --[[ Returns true if the spot at x,y can have specified value. ]]--
  96. function Sudoku.isValid(sudoku, x, y, value)
  97.   return not ( sudoku:checkColumn(x, value) or sudoku:checkRow(y, value) or sudoku:checkRegion(x, y, value) )
  98. end
  99.  
  100. --[[ Creates a Sudoku object; it's basically a table of tables with the Sudoku metatable set. ]]--
  101. function Sudoku.generateBlank()
  102.   local sudoku = {}
  103.   setmetatable(sudoku, Sudoku)
  104.   for i = 1,9 do
  105.     sudoku[i]={}
  106.   end
  107.   return sudoku
  108. end
  109.  
  110. --[[ Set text color if possible. ]]--
  111. local function setColor(color)
  112.   if term.isColor and term.isColor() then
  113.     term.setTextColor(color)
  114.   end
  115. end
  116.  
  117. --[[ Prints the sudoku to the screen in a typical table-style. ]]--
  118. function Sudoku.print(sudoku)
  119.   setColor(colors.white)
  120.   write("+-----+-----+-----+\n")
  121.   setColor(colors.red)
  122.   for y=1,9 do
  123.     setColor(colors.white)
  124.     write("|")
  125.     setColor(colors.red)
  126.     for x=1,9 do
  127.       local num = sudoku[x][y]
  128.       write(num and string.format("%d",num) or " ")
  129.       setColor(colors.white)
  130.       write(x%3==0 and "|" or " ")
  131.       setColor(colors.red)
  132.     end
  133.     write("\n")
  134.     if y%3==0 then
  135.       setColor(colors.white)
  136.       write("+-----+-----+-----+\n")
  137.       setColor(colors.red)
  138.     end
  139.   end
  140.   setColor(colors.white)
  141. end
  142.  
  143. --[[ Generates a random valid sudoku. ]]--
  144. function Sudoku.generate()
  145.   local sudoku = Sudoku.generateBlank()  -- generate an empty sudoku matrix
  146.  
  147.   local attempts = Attempts.create()  -- generate a new instance of Attempts
  148.  
  149.   local sleepCount = 0
  150.   local index = 1  -- the index of the square we are at during calculations
  151.   while index <= 81 do  -- repeat until we reached the last square
  152.     local x = (index-1)%9+1  -- calculate x out of the index
  153.     local y = math.floor((index-1)/9)+1  -- calculate y out of the index
  154.     local nextNumber = attempts:getNextNumber(index)  -- get the next random number for current index
  155.     if not nextNumber then  -- if there is no next number, then backtrack!
  156.       attempts:clear(index)  -- reset the attempted numbers for current index
  157.       sudoku:resetSquare(x,y)  -- reset the square we temporarily set
  158.       index = index-1  -- go back one square
  159.     elseif sudoku:isValid(x, y, nextNumber) then  -- else, if this is a valid number for the square at index, set it
  160.       sudoku:setSquare(x, y, nextNumber)
  161.       index = index+1  -- proceed to the next square
  162.     end  -- if there were numbers left and this wasn't a valid number, we will stay at the same index and try a new number on the next iteration
  163.     sleepCount = sleepCount+1
  164.     if sleepCount%10000==0 then  -- yield once every 10000 calculations
  165.       sleep(0)
  166.     end
  167.   end
  168.   return sudoku
  169. end
  170.  
  171. --[[ Only usefull if this file is being used as API. The Sudoku metatable
  172.   isn't public. ]]--
  173. function generateSudoku()
  174.   return Sudoku.generate()
  175. end
  176.  
  177. local sudoku = Sudoku.generate()
  178. sudoku:print()
Advertisement
Add Comment
Please, Sign In to add comment