Igor Timofeev 3c2f6b2e5e Дап!
2016-04-05 15:48:09 +03:00

250 lines
7.4 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---------------------------------------------------- Библиотеки ----------------------------------------------------------------
local serialization = require("serialization")
local event = require("event")
local ecs = require("ECSAPI")
local fs = require("filesystem")
local buffer = require("doubleBuffering")
local unicode = require("unicode")
local component = require("component")
---------------------------------------------------- Константы ----------------------------------------------------------------
buffer.start()
local tablica = {}
-------------------------------------------------------------------------------------------------------------------------------
local function drawGrid(x, y)
local gridWidth = 74
local gridHeight = 39
buffer.clear(0xFFFFFF)
local lines = {
" ┃ ┃ ",
" ┃ ┃ ",
" ┃ ┃ ",
"━━━━━━━╋━━━━━━━╋━━━━━━━",
" ┃ ┃ ",
" ┃ ┃ ",
" ┃ ┃ ",
"━━━━━━━╋━━━━━━━╋━━━━━━━",
" ┃ ┃ ",
" ┃ ┃ ",
" ┃ ┃ ",
}
--Тонкие
local xPos, yPos = x, y
for a = 1, 3 do
for j = 1, 3 do
for i = 1, #lines do
buffer.text(xPos, yPos, 0x000000, lines[i])
yPos = yPos + 1
end
yPos = yPos + 1
end
yPos = y
xPos = xPos + unicode.len(lines[1]) + 2
end
--Толстые
--Горизонтальные
buffer.square(x, y + (#lines + 1) - 1, (unicode.len(lines[1]) + 2) * 3, 1, 0x000000)
buffer.square(x, y + (#lines + 1) * 2 - 1, (unicode.len(lines[1]) + 2) * 3, 1, 0x000000)
--Вертикальные
buffer.square(x + (unicode.len(lines[1]) + 1) - 1, y, 2, (#lines + 1) * 3, 0x000000)
buffer.square(x + (unicode.len(lines[1]) * 2 + 3 ) - 1, y, 2, (#lines + 1) * 3, 0x000000)
--Значения
yPos = y
for j = 1, #tablica do
xPos = x + 1
for i = 1, #tablica[j] do
if i == 4 or i == 7 then xPos = xPos + 1 end
if tablica[j][i].value then
buffer.set(xPos + 2, yPos + 1, 0xFFFFFF, 0x000000, tostring(tablica[j][i].value))
elseif tablica[j][i].possibleValues and #tablica[j][i].possibleValues > 0 then
local xPossible, yPossible = xPos, yPos
for a = 1, #tablica[j][i].possibleValues do
local background, foreground = 0xFFFFFF, 0xAAAAAA
if #tablica[j][i].possibleValues == 1 then background = 0x88FF88; foreground = 0x000000 end
buffer.set(xPossible, yPossible, background, foreground, tablica[j][i].possibleValues[a])
xPossible = xPossible + 2
if a % 3 == 0 then xPossible = xPos; yPossible = yPossible + 1 end
end
end
xPos = xPos + 8
end
yPos = yPos + 4
end
buffer.draw()
end
local function checkCellValue(xCell, yCell, requestedValue)
if tablica[yCell][xCell].value and tablica[yCell][xCell].value == requestedValue then
return false
end
return true
end
local function checkCellForRules(xCell, yCell, requestedValue)
--Чекаем горизонтально, включая эту же ячейку
for i = (xCell + 1), 9 do if not checkCellValue(i, yCell, requestedValue) then return false end end
for i = 1, (xCell - 1) do if not checkCellValue(i, yCell, requestedValue) then return false end end
--Вертикально
for i = (yCell + 1), 9 do if not checkCellValue(xCell, i, requestedValue) then return false end end
for i = 1, (yCell - 1) do if not checkCellValue(xCell, i, requestedValue) then return false end end
--И вокруг
local xFrom, yFrom = 1, 1
if xCell >= 4 and xCell <= 6 then xFrom = 4 elseif xCell >= 7 and xCell <= 9 then xFrom = 7 end
if yCell >= 4 and yCell <= 6 then yFrom = 4 elseif yCell >= 7 and yCell <= 9 then yFrom = 7 end
for j = yFrom, (yFrom + 2) do
for i = xFrom, (xFrom + 2) do
if not checkCellValue(i, j, requestedValue) then return false end
end
end
return true
end
local function clearTablica()
tablica = {}
for i = 1, 9 do table.insert(tablica, { {},{},{}, {},{},{}, {},{},{} }) end
end
local function generateSudoku(startCountOfNumbers)
clearTablica()
for i = 1, startCountOfNumbers do
while true do
local randomNumber = math.random(1, 9)
local randomX = math.random(1, 9)
local randomY = math.random(1, 9)
if not tablica[randomY][randomX].value and checkCellForRules(randomX, randomY, randomNumber) then
tablica[randomY][randomX].value = randomNumber
break
end
end
end
end
local function getpossibleValuesForCell(xCell, yCell)
--Получаем невозможные числа
local impossibleValues = {}
--Горизонтально
for i = 1, (xCell - 1) do if tablica[yCell][i].value then impossibleValues[tablica[yCell][i].value] = true end end
for i = (xCell + 1), 9 do if tablica[yCell][i].value then impossibleValues[tablica[yCell][i].value] = true end end
--Вертикально
for i = 1, (yCell - 1) do if tablica[i][xCell].value then impossibleValues[tablica[i][xCell].value] = true end end
for i = (yCell + 1), 9 do if tablica[i][xCell].value then impossibleValues[tablica[i][xCell].value] = true end end
--Квадратно
local xFrom, yFrom = 1, 1
if xCell >= 4 and xCell <= 6 then xFrom = 4 elseif xCell >= 7 and xCell <= 9 then xFrom = 7 end
if yCell >= 4 and yCell <= 6 then yFrom = 4 elseif yCell >= 7 and yCell <= 9 then yFrom = 7 end
for j = yFrom, (yFrom + 2) do
for i = xFrom, (xFrom + 2) do
if tablica[j][i].value then impossibleValues[tablica[j][i].value] = true end
end
end
--А теперь берем возможные числа из невозможных
local possibleValues = {}
for i = 1, 9 do
if not impossibleValues[i] then table.insert(possibleValues, i) end
end
return possibleValues
end
local function getpossibleValues()
local countOfPossibleValues = 0
for j = 1, 9 do
for i = 1, 9 do
if not tablica[j][i].value then
local possibleValues = getpossibleValuesForCell(i, j)
tablica[j][i].possibleValues = possibleValues
countOfPossibleValues = countOfPossibleValues + #possibleValues
end
end
end
return countOfPossibleValues
end
local function loadSudokuFromFile(path)
clearTablica()
local file = io.open(path, "r")
local counter = 1
for line in file:lines() do
if unicode.len(line) > 9 then error("Неверный файл Судоку: длина линии больше 9 символов") end
for i = 1, 9 do
local symbol = unicode.sub(line, i, i)
if symbol ~= " " and not tonumber(symbol) then error("Неверный файл Судоку: символ не может быть представлен как число") end
tablica[counter][i].value = tonumber(symbol)
end
counter = counter + 1
end
file:close()
end
local function convertSinglePossibleValuesToValues()
for j = 1, 9 do
for i = 1, 9 do
if tablica[j][i].possibleValues and #tablica[j][i].possibleValues == 1 then
tablica[j][i].value = tablica[j][i].possibleValues[1]
tablica[j][i].possibleValues = nil
end
end
end
end
local function solveEasySudoku()
while true do
ecs.wait()
local countOfPossibleValues = getpossibleValues()
if countOfPossibleValues <= 0 then
drawGrid(1, 1)
ecs.wait()
ecs.error("Все решено!")
buffer.clear(0x262626)
ecs.prepareToExit()
break
end
drawGrid(1, 1)
convertSinglePossibleValuesToValues()
end
end
loadSudokuFromFile("testSudokuFile.txt")
drawGrid(1, 1)
solveEasySudoku()