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
|
||||||
for i = 1, 9 do
|
local block = 0
|
||||||
elm = b[x][i]
|
return function()
|
||||||
if elm ~= 0 and find(u, elm) == 0 then
|
local a = {}
|
||||||
table.insert(u, elm)
|
local p = {}
|
||||||
|
if row < 9 then
|
||||||
|
row = row + 1
|
||||||
|
for i = 1, 9 do
|
||||||
|
a[i] = board[row][i]
|
||||||
|
p[i] = {row, i}
|
||||||
|
end
|
||||||
|
return a, p
|
||||||
end
|
end
|
||||||
elm = b[i][y]
|
if column < 9 then
|
||||||
if elm ~= 0 and find(u, elm) == 0 then
|
column = column + 1
|
||||||
table.insert(u, elm)
|
for i = 1, 9 do
|
||||||
|
a[i] = board[i][column]
|
||||||
|
p[i] = {i, column}
|
||||||
|
end
|
||||||
|
return a, p
|
||||||
|
end
|
||||||
|
if block < 9 then
|
||||||
|
block = block + 1
|
||||||
|
local dx = math.floor((block - 1) / 3)
|
||||||
|
local dy = (block - 1) % 3
|
||||||
|
local n = 0
|
||||||
|
for i = 1, 3 do
|
||||||
|
for j = 1, 3 do
|
||||||
|
local x = i + 3 * dx
|
||||||
|
local y = j + 3 * dy
|
||||||
|
n = n + 1
|
||||||
|
a[n] = board[x][y]
|
||||||
|
p[n] = {x, y}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return a, p
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- local xc = ((x - 1) // 3) * 3
|
end
|
||||||
-- local yc = ((y - 1) // 3) * 3
|
|
||||||
local xc = math.floor((x - 1) / 3) * 3
|
local function checkAUX(zone, pos)
|
||||||
local yc = math.floor((y - 1) / 3) * 3
|
local isComplete = true
|
||||||
for i = 1, 3 do
|
local ok = true
|
||||||
for j = 1, 3 do
|
local conflictList = {}
|
||||||
elm = b[i+xc][j+yc]
|
local n = 0
|
||||||
if elm ~= 0 and find(u, elm) == 0 then
|
for i = 1, 8 do
|
||||||
table.insert(u, elm)
|
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
|
||||||
end
|
end
|
||||||
for i = 1, 9 do
|
return ok, isComplete, conflictList
|
||||||
if find(u, i) == 0 then table.insert(v, i) end
|
|
||||||
end
|
|
||||||
return v
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function buildSearchSpace(b)
|
function sudoku.checkBoard(board)
|
||||||
local s = {}
|
local ok = true
|
||||||
for i = 1, 9 do
|
local isComplete = true
|
||||||
s[i] = {}
|
local conflictList = {}
|
||||||
for j = 1, 9 do
|
for zone, pos in sudoku.iterZones(board) do
|
||||||
s[i][j] = calValidOptions(b, i, j)
|
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
|
||||||
end
|
end
|
||||||
return s
|
return ok, isComplete, conflictList
|
||||||
end
|
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
|
||||||
|
return b
|
||||||
end
|
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)
|
||||||
uiUtils.setColor(self.colors.bigNumbersTyped)
|
if self.board[4][y][x] ~= 0 then
|
||||||
|
uiUtils.setColor(self.colors.bigNumbersError)
|
||||||
|
else
|
||||||
|
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)
|
||||||
uiUtils.setColor(self.colors.bigNumbersHandWritten)
|
if self.board[4][y][x] ~= 0 then
|
||||||
|
uiUtils.setColor(self.colors.bigNumbersError)
|
||||||
|
else
|
||||||
|
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
|
||||||
self.board[2][y][x] = num
|
if self.board[2][y][x] == num then
|
||||||
self.board[3][y][x] = num
|
self.board[2][y][x] = 0
|
||||||
|
self.board[3][y][x] = 0
|
||||||
|
else
|
||||||
|
self.board[2][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