mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2025-12-20 19:19:21 +01:00
250 lines
7.4 KiB
Lua
250 lines
7.4 KiB
Lua
|
||
---------------------------------------------------- Библиотеки ----------------------------------------------------------------
|
||
|
||
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()
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|