add check for conflict
This commit is contained in:
		
							parent
							
								
									231612cce4
								
							
						
					
					
						commit
						98c245fb9e
					
				
							
								
								
									
										6
									
								
								main.lua
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								main.lua
									
									
									
									
									
								
							| @ -1,4 +1,4 @@ | |||||||
| require "sudoku.utils" | sudoku = require "sudoku.sudoku" | ||||||
| uiUtils = require "ui.utils" | uiUtils = require "ui.utils" | ||||||
| config = require "config" | config = require "config" | ||||||
| SudokuCanvas = require "ui.sudokucanvas" | SudokuCanvas = require "ui.sudokucanvas" | ||||||
| @ -11,10 +11,10 @@ function love.load() | |||||||
|     love.mouse.setGrabbed(false) |     love.mouse.setGrabbed(false) | ||||||
|     love.keyboard.setKeyRepeat(true) |     love.keyboard.setKeyRepeat(true) | ||||||
|     math.randomseed(os.time()) |     math.randomseed(os.time()) | ||||||
|     local board = loadBoard(config.board.filePath) |     board = sudoku.loadBoard(config.board.filePath) | ||||||
|     local width, height = love.graphics.getDimensions() |     local width, height = love.graphics.getDimensions() | ||||||
|     sudokuCanvas = SudokuCanvas:new(200, 100, height/1.5, config.SudokuCanvas) |     sudokuCanvas = SudokuCanvas:new(200, 100, height/1.5, config.SudokuCanvas) | ||||||
|     sudokuCanvas:setBoard(board) |     sudokuCanvas:setBoard(board[1]) | ||||||
|     myFont = love.graphics.newFont(24) |     myFont = love.graphics.newFont(24) | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										132
									
								
								sudoku/check.lua
									
									
									
									
									
								
							
							
						
						
									
										132
									
								
								sudoku/check.lua
									
									
									
									
									
								
							| @ -1,132 +0,0 @@ | |||||||
| local function checkCT(ct) |  | ||||||
|     local r = {} |  | ||||||
|     for i = 1, 8 do |  | ||||||
|         for j = i+1, 9 do |  | ||||||
|             if ct[i] == ct[j] and ct[i] ~= 0 then |  | ||||||
|                 table.insert(r, {i, j}) |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     if #r > 0 then return false, r end |  | ||||||
|     return true |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| local function findThisTable(this, that) |  | ||||||
|     for i = 1, #that do |  | ||||||
|         if #that[i] == #this then |  | ||||||
|             local flag = true |  | ||||||
|             for j = 1, #this do |  | ||||||
|                 if this[j] ~= that[i][j] then flag = false; break end |  | ||||||
|             end |  | ||||||
|             if flag then return true, i end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     return false |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function check(board) |  | ||||||
|     local rr = {} |  | ||||||
|     for x = 1, 9 do |  | ||||||
|         local ct = {} |  | ||||||
|         for y = 1, 9 do |  | ||||||
|             ct[y] = board[x][y] |  | ||||||
|         end |  | ||||||
|         local ok, r = checkCT(ct) |  | ||||||
|         if not ok then |  | ||||||
|             for _, p in ipairs(r) do |  | ||||||
|                 local t = {x, p[1], x, p[2], board[x][p[1]]} |  | ||||||
|                 if not findThisTable(t, rr) then |  | ||||||
|                     table.insert(rr, t) |  | ||||||
|                 end |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     for y = 1, 9 do |  | ||||||
|         local ct = {} |  | ||||||
|         for x = 1, 9 do |  | ||||||
|             ct[x] = board[x][y] |  | ||||||
|         end |  | ||||||
|         local ok, r = checkCT(ct) |  | ||||||
|         if not ok then |  | ||||||
|             for _, p in ipairs(r) do |  | ||||||
|                 local t = {p[1], y, p[2], y, board[p[1]][y]} |  | ||||||
|                 if not findThisTable(t, rr) then |  | ||||||
|                     table.insert(rr, t) |  | ||||||
|                 end |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     for i = 0, 2 do |  | ||||||
|         for j = 0, 2 do |  | ||||||
|             local ct = {} |  | ||||||
|             for x = 1, 3 do |  | ||||||
|                 for y = 1, 3 do |  | ||||||
|                     ct[(x-1)*3+y] = board[x+i*3][y+j*3] |  | ||||||
|                 end |  | ||||||
|             end |  | ||||||
|             local ok, r = checkCT(ct) |  | ||||||
|             if not ok then |  | ||||||
|                 for _, p in ipairs(r) do |  | ||||||
|                     -- local x1 = ((p[1] - 1) // 3 + 1) + i * 3 |  | ||||||
|                     local x1 = math.floor((p[1] - 1) / 3 + 1) + i * 3 |  | ||||||
|                     local y1 = ((p[1] - 1) % 3 + 1) + j * 3 |  | ||||||
|                     -- local x2 = ((p[2] - 1) // 3 + 1) + i * 3 |  | ||||||
|                     local x2 = math.floor((p[2] - 1) / 3 + 1) + i * 3 |  | ||||||
|                     local y2 = ((p[2] - 1) % 3 + 1) + j * 3 |  | ||||||
|                     local t = {x1, y1, x2, y2, board[x1][y1]} |  | ||||||
|                     if not findThisTable(t, rr) then |  | ||||||
|                         table.insert(rr, t) |  | ||||||
|                     end |  | ||||||
|                 end |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     if #rr > 0 then |  | ||||||
|         return false, rr |  | ||||||
|     end |  | ||||||
|     return true |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function checkSolved(board) |  | ||||||
|     local r = {} |  | ||||||
|     for i = 1, 9 do |  | ||||||
|         for j = 1, 9 do |  | ||||||
|             if board[i][j] < 1 or board[i][j] > 9 then |  | ||||||
|                 table.insert(r, {i, j, board[i][j]}) |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     local ok, rr = check(board) |  | ||||||
|     if #r > 0 or (rr and #rr > 0) then |  | ||||||
|         return false, r, rr |  | ||||||
|     end |  | ||||||
|     return true |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function pcheck(board) |  | ||||||
|     local ok, r, rr = checkSolved(board) |  | ||||||
|     if ok then |  | ||||||
|         print("Board is solved!") |  | ||||||
|         return  |  | ||||||
|     end |  | ||||||
|     for _, p in ipairs(r) do |  | ||||||
|         print(S("(%d, %d) = %d", unpack(p))) |  | ||||||
|     end |  | ||||||
|     for _, p in ipairs(rr) do |  | ||||||
|         print(S("(%d, %d) = (%d, %d) = %d", unpack(p))) |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function scheck(board) |  | ||||||
|     local msg = {} |  | ||||||
|     local ok, r = check(board) |  | ||||||
|     if ok then |  | ||||||
|         return {"No Error!"} |  | ||||||
|     end |  | ||||||
|     for _, p in ipairs(r) do |  | ||||||
|         local s = string.format("(%d, %d) = (%d, %d) = %d", unpack(p)) |  | ||||||
|         print(s) |  | ||||||
|         table.insert(msg, s) |  | ||||||
|     end |  | ||||||
|     return msg |  | ||||||
| end |  | ||||||
| @ -1,47 +1,85 @@ | |||||||
| require "sudoku.utils" | local utils = require "sudoku.utils" | ||||||
| require "sudoku.check" |  | ||||||
| 
 | 
 | ||||||
| function calValidOptions(b, x, y) | local sudoku = {} | ||||||
|     if b[x][y] ~= 0 then return {} end | 
 | ||||||
|     local elm | function sudoku.iterZones(board) | ||||||
|     local u = {} |     local row = 0 | ||||||
|     local v = {} |     local column = 0 | ||||||
|  |     local block = 0 | ||||||
|  |     return function() | ||||||
|  |         local a = {} | ||||||
|  |         local p = {} | ||||||
|  |         if row < 9 then | ||||||
|  |             row = row + 1 | ||||||
|             for i = 1, 9 do |             for i = 1, 9 do | ||||||
|         elm = b[x][i] |                 a[i] = board[row][i] | ||||||
|         if elm ~= 0 and find(u, elm) == 0 then |                 p[i] = {row, i} | ||||||
|             table.insert(u, elm) |  | ||||||
|             end |             end | ||||||
|         elm = b[i][y] |             return a, p | ||||||
|         if elm ~= 0 and find(u, elm) == 0 then |  | ||||||
|             table.insert(u, elm) |  | ||||||
|         end |         end | ||||||
|  |         if column < 9 then | ||||||
|  |             column = column + 1 | ||||||
|  |             for i = 1, 9 do | ||||||
|  |                 a[i] = board[i][column] | ||||||
|  |                 p[i] = {i, column} | ||||||
|             end |             end | ||||||
|     -- local xc = ((x - 1) // 3) * 3 |             return a, p | ||||||
|     -- local yc = ((y - 1) // 3) * 3 |         end | ||||||
|     local xc = math.floor((x - 1) / 3) * 3 |         if block < 9 then | ||||||
|     local yc = math.floor((y - 1) / 3) * 3 |             block = block + 1 | ||||||
|  |             local dx = math.floor((block - 1) / 3) | ||||||
|  |             local dy = (block - 1) % 3 | ||||||
|  |             local n = 0 | ||||||
|             for i = 1, 3 do |             for i = 1, 3 do | ||||||
|                 for j = 1, 3 do |                 for j = 1, 3 do | ||||||
|             elm = b[i+xc][j+yc] |                     local x = i + 3 * dx | ||||||
|             if elm ~= 0 and find(u, elm) == 0 then |                     local y = j + 3 * dy | ||||||
|                 table.insert(u, elm) |                     n = n + 1 | ||||||
|  |                     a[n] = board[x][y] | ||||||
|  |                     p[n] = {x, y} | ||||||
|                 end |                 end | ||||||
|             end |             end | ||||||
|  |             return a, p | ||||||
|         end |         end | ||||||
|     for i = 1, 9 do |  | ||||||
|         if find(u, i) == 0 then table.insert(v, i) end |  | ||||||
|     end |     end | ||||||
|     return v |  | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| function buildSearchSpace(b) | local function checkAUX(zone, pos) | ||||||
|     local s = {} |     local isComplete = true | ||||||
|     for i = 1, 9 do |     local ok = true | ||||||
|         s[i] = {} |     local conflictList = {} | ||||||
|         for j = 1, 9 do |     local n = 0 | ||||||
|             s[i][j] = calValidOptions(b, i, j) |     for i = 1, 8 do | ||||||
|  |         for j = i+1, 9 do | ||||||
|  |             if zone[i] == 0 then | ||||||
|  |                 isComplete = false | ||||||
|  |             elseif zone[i] == zone[j] then | ||||||
|  |                 ok = false | ||||||
|  |                 n = n + 1 | ||||||
|  |                 conflictList[n] = {x1=pos[i][1], y1=pos[i][2], x2=pos[j][1], y2=pos[j][2]} | ||||||
|             end |             end | ||||||
|         end |         end | ||||||
|     return s |     end | ||||||
|  |     return ok, isComplete, conflictList | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | function sudoku.checkBoard(board) | ||||||
|  |     local ok = true | ||||||
|  |     local isComplete = true | ||||||
|  |     local conflictList = {} | ||||||
|  |     for zone, pos in sudoku.iterZones(board) do | ||||||
|  |         local tOk, tIsComplete, tConflictList = checkAUX(zone, pos) | ||||||
|  |         if not tOk then ok = false end | ||||||
|  |         if not tIsComplete then isComplete = false end | ||||||
|  |         for _, conflict in ipairs(tConflictList) do | ||||||
|  |             table.insert(conflictList, conflict) | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return ok, isComplete, conflictList | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | sudoku.cloneBoard = utils.cloneBoard | ||||||
|  | sudoku.createEmptyBoard = utils.createEmptyBoard | ||||||
|  | sudoku.loadBoard = utils.loadBoard | ||||||
|  | return sudoku | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -1,4 +1,21 @@ | |||||||
| function find(array, element) | local function table2string(t) | ||||||
|  |     local myself = table2string | ||||||
|  |     local l = {} | ||||||
|  |     local n = 0 | ||||||
|  |     for k, v in pairs(t) do | ||||||
|  |         n = n + 1 | ||||||
|  |         if type(v) == "table" then | ||||||
|  |             l[n] = k .. ': ' .. myself(v) | ||||||
|  |         elseif type(v) == "string" then | ||||||
|  |             l[n] = k .. ': ' .. '"' .. v .. '"' | ||||||
|  |         else | ||||||
|  |             l[n] = k .. ': ' .. v | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return "{" .. table.concat(l, ", ") .. "}" | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | local function find(array, element) | ||||||
|     local index = 0 |     local index = 0 | ||||||
|     for i = 1, #array do |     for i = 1, #array do | ||||||
|         if array[i] == element then |         if array[i] == element then | ||||||
| @ -9,13 +26,18 @@ function find(array, element) | |||||||
|     return index |     return index | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| function showBoard(board) | local function createEmptyBoard() | ||||||
|     for row = 1, 9 do |     local b = {} | ||||||
|         print(table.concat(board[row], " ")) |     for i = 1, 9 do | ||||||
|  |         b[i] = {} | ||||||
|  |         for j = 1, 9 do | ||||||
|  |             b[i][j] = 0 | ||||||
|         end |         end | ||||||
|     end |     end | ||||||
|  |     return b | ||||||
|  | end | ||||||
| 
 | 
 | ||||||
| function cloneBoard(b) | local function cloneBoard(b) | ||||||
|     local c = {} |     local c = {} | ||||||
|     for i = 1, 9 do |     for i = 1, 9 do | ||||||
|         c[i] = {} |         c[i] = {} | ||||||
| @ -26,14 +48,14 @@ function cloneBoard(b) | |||||||
|     return c |     return c | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| function loadBoard(fn) | local function loadBoard(fn) | ||||||
|     local problem = {} |     local boards = {} | ||||||
|     local solution = {} |  | ||||||
|     local board = problem |  | ||||||
|     local r = 0 |     local r = 0 | ||||||
|  |     local board = {} | ||||||
|     for line in io.lines(fn) do |     for line in io.lines(fn) do | ||||||
|         if line:gsub("%s+", "") == "" then |         if line:gsub("%s+", "") == "" then | ||||||
|             board = solution |             table.insert(boards, board) | ||||||
|  |             board = {} | ||||||
|             r = 0 |             r = 0 | ||||||
|         else |         else | ||||||
|             r = r + 1 |             r = r + 1 | ||||||
| @ -45,5 +67,18 @@ function loadBoard(fn) | |||||||
|             end |             end | ||||||
|         end |         end | ||||||
|     end |     end | ||||||
|     return problem, solution |     table.insert(boards, board) | ||||||
|  |     return boards | ||||||
| end | end | ||||||
|  | 
 | ||||||
|  | local function showBoard(board) | ||||||
|  |     for row = 1, 9 do | ||||||
|  |         print(table.concat(board[row], " ")) | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | return { | ||||||
|  |     createEmptyBoard = createEmptyBoard, | ||||||
|  |     cloneBoard = cloneBoard, | ||||||
|  |     loadBoard = loadBoard, | ||||||
|  | } | ||||||
|  | |||||||
| @ -1,20 +1,3 @@ | |||||||
| function table2string(t) |  | ||||||
|     local myself = table2string |  | ||||||
|     local l = {} |  | ||||||
|     local n = 0 |  | ||||||
|     for k, v in pairs(t) do |  | ||||||
|         n = n + 1 |  | ||||||
|         if type(v) == "table" then |  | ||||||
|             l[n] = k .. ': ' .. myself(v) |  | ||||||
|         elseif type(v) == "string" then |  | ||||||
|             l[n] = k .. ': ' .. '"' .. v .. '"' |  | ||||||
|         else |  | ||||||
|             l[n] = k .. ': ' .. v |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     return "{" .. table.concat(l, ", ") .. "}" |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| SudokuCanvas = {} | SudokuCanvas = {} | ||||||
| SudokuCanvas.__index = SudokuCanvas | SudokuCanvas.__index = SudokuCanvas | ||||||
| 
 | 
 | ||||||
| @ -187,9 +170,11 @@ end | |||||||
| function SudokuCanvas:setBoard(board, board2) | function SudokuCanvas:setBoard(board, board2) | ||||||
|     local board2 = board2 or board |     local board2 = board2 or board | ||||||
|     self.board = {} |     self.board = {} | ||||||
|     self.board[1] = cloneBoard(board) |     self.board[1] = sudoku.cloneBoard(board) | ||||||
|     self.board[2] = cloneBoard(board2) |     self.board[2] = sudoku.cloneBoard(board2) | ||||||
|     self.board[3] = cloneBoard(board2) |     self.board[3] = sudoku.cloneBoard(board2) | ||||||
|  |     -- self.board[4] = createEmptyBoard() | ||||||
|  |     self:checkBoard() | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| function SudokuCanvas:new(x, y, size, options) | function SudokuCanvas:new(x, y, size, options) | ||||||
| @ -225,6 +210,15 @@ end | |||||||
| function SudokuCanvas:focus() | function SudokuCanvas:focus() | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | function SudokuCanvas:checkBoard() | ||||||
|  |     local ok, isComplete, conflictList = sudoku.checkBoard(self.board[2]) | ||||||
|  |     self.board[4] = sudoku.createEmptyBoard() | ||||||
|  |     for _, c in ipairs(conflictList) do | ||||||
|  |         self.board[4][c.x1][c.y1] = 1 | ||||||
|  |         self.board[4][c.x2][c.y2] = 1 | ||||||
|  |     end | ||||||
|  | end | ||||||
|  | 
 | ||||||
| function SudokuCanvas:draw() | function SudokuCanvas:draw() | ||||||
|     local grid = self.grid |     local grid = self.grid | ||||||
| 
 | 
 | ||||||
| @ -270,14 +264,22 @@ function SudokuCanvas:draw() | |||||||
|                 local px = self.bigNumbers[x][y][num].typed.x |                 local px = self.bigNumbers[x][y][num].typed.x | ||||||
|                 local py = self.bigNumbers[x][y][num].typed.y |                 local py = self.bigNumbers[x][y][num].typed.y | ||||||
|                 love.graphics.setFont(self.bigNumbers.typedFont) |                 love.graphics.setFont(self.bigNumbers.typedFont) | ||||||
|  |                 if self.board[4][y][x] ~= 0 then | ||||||
|  |                     uiUtils.setColor(self.colors.bigNumbersError) | ||||||
|  |                 else | ||||||
|                     uiUtils.setColor(self.colors.bigNumbersTyped) |                     uiUtils.setColor(self.colors.bigNumbersTyped) | ||||||
|  |                 end | ||||||
|                 love.graphics.print(tostring(num), px, py) |                 love.graphics.print(tostring(num), px, py) | ||||||
|             elseif self.board[2][y][x] ~= 0 then |             elseif self.board[2][y][x] ~= 0 then | ||||||
|                 local num = self.board[2][y][x] |                 local num = self.board[2][y][x] | ||||||
|                 local px = self.bigNumbers[x][y][num].handWritten.x |                 local px = self.bigNumbers[x][y][num].handWritten.x | ||||||
|                 local py = self.bigNumbers[x][y][num].handWritten.y |                 local py = self.bigNumbers[x][y][num].handWritten.y | ||||||
|                 love.graphics.setFont(self.bigNumbers.handWrittenFont) |                 love.graphics.setFont(self.bigNumbers.handWrittenFont) | ||||||
|  |                 if self.board[4][y][x] ~= 0 then | ||||||
|  |                     uiUtils.setColor(self.colors.bigNumbersError) | ||||||
|  |                 else | ||||||
|                     uiUtils.setColor(self.colors.bigNumbersHandWritten) |                     uiUtils.setColor(self.colors.bigNumbersHandWritten) | ||||||
|  |                 end | ||||||
|                 love.graphics.print(tostring(num), px, py) |                 love.graphics.print(tostring(num), px, py) | ||||||
|             end |             end | ||||||
|         end |         end | ||||||
| @ -315,17 +317,25 @@ function SudokuCanvas:keypressed(key) | |||||||
|         local num = key:byte() - 48 |         local num = key:byte() - 48 | ||||||
|         if self.board[1][y][x] == 0 then |         if self.board[1][y][x] == 0 then | ||||||
|             if mode == "big" then |             if mode == "big" then | ||||||
|  |                 if self.board[2][y][x] == num then | ||||||
|  |                     self.board[2][y][x] = 0 | ||||||
|  |                     self.board[3][y][x] = 0 | ||||||
|  |                 else | ||||||
|                     self.board[2][y][x] = num |                     self.board[2][y][x] = num | ||||||
|                     self.board[3][y][x] = num |                     self.board[3][y][x] = num | ||||||
|  |                 end | ||||||
|  |                 self:checkBoard() | ||||||
|             else |             else | ||||||
|                 self.smallNumbers[x][y][num].enabled = not self.smallNumbers[x][y][num].enabled |                 self.smallNumbers[x][y][num].enabled = not self.smallNumbers[x][y][num].enabled | ||||||
|             end |             end | ||||||
|  |             self:checkBoard() | ||||||
|         end |         end | ||||||
|     elseif key == "delete" or key == "0" then |     elseif key == "delete" or key == "0" then | ||||||
|         if self.board[1][y][x] == 0 then |         if self.board[1][y][x] == 0 then | ||||||
|             if mode == "big" then |             if mode == "big" then | ||||||
|                 self.board[2][y][x] = 0 |                 self.board[2][y][x] = 0 | ||||||
|                 self.board[3][y][x] = 0 |                 self.board[3][y][x] = 0 | ||||||
|  |                 self:checkBoard() | ||||||
|             else |             else | ||||||
|                 for num = 1, 9 do |                 for num = 1, 9 do | ||||||
|                     self.smallNumbers[x][y][num].enabled = false |                     self.smallNumbers[x][y][num].enabled = false | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user