mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2026-01-10 21:22:39 +01:00
Дап!
This commit is contained in:
parent
d869a4b833
commit
3c2f6b2e5e
@ -1,206 +1,277 @@
|
||||
local c = require("component")
|
||||
local modem = c.modem
|
||||
local gpu = c.gpu
|
||||
|
||||
|
||||
local component = require("component")
|
||||
local buffer = require("doubleBuffering")
|
||||
local unicode = require("unicode")
|
||||
local serialization = require("serialization")
|
||||
local context = require("context")
|
||||
local event = require("event")
|
||||
local keyboard = require("keyboard")
|
||||
local modem = component.modem
|
||||
|
||||
local port = 512
|
||||
modem.open(port)
|
||||
--------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local direction = 1
|
||||
buffer.start()
|
||||
local xStart = math.floor(buffer.screen.width / 2)
|
||||
local yStart = math.floor(buffer.screen.height / 2 + 2)
|
||||
local port = 1337
|
||||
|
||||
local xSize, ySize = gpu.getResolution()
|
||||
local topBarElements = { "Карта", "Инвентарь", "Редстоун", "Геоанализатор", "Бак" }
|
||||
local currentTopBarElement = 2
|
||||
|
||||
local xPos, yPos = math.floor(xSize/2), math.floor(ySize/2)
|
||||
local xScreen, yScreen = 0, 0
|
||||
|
||||
local points = {
|
||||
local map = {
|
||||
robotPosition = {
|
||||
x = 0, y = 0, z = 0,
|
||||
rotation = 1,
|
||||
},
|
||||
currentLayer = 0,
|
||||
{ type = "empty", x = 0, y = 0, z = 0 },
|
||||
}
|
||||
|
||||
local robotPicture = {
|
||||
"▲", "►", "▼", "◄"
|
||||
}
|
||||
|
||||
local homePoint = {x = xPos, y = yPos}
|
||||
local colors = {
|
||||
white = 0xFFFFFF,
|
||||
lightGray = 0xCCCCCC,
|
||||
gray = 0x333333,
|
||||
black = 0x000000,
|
||||
robot = 0xFF3333,
|
||||
entity = 0xFFCC33,
|
||||
homePoint = 0x6699FF,
|
||||
passable = 0xFF3333,
|
||||
keyPoint = 0xFF3333,
|
||||
keyPointText = 0xFFFFFF,
|
||||
}
|
||||
|
||||
local function checkRange(xCoord, yCoord)
|
||||
local xRelative, yRelative = xCoord, yCoord
|
||||
if xRelative >= (0 + xScreen) and xRelative <= (xSize + xScreen) and yRelative >= (0 + yScreen) and yRelative <= (ySize + yScreen) then return true end
|
||||
modem.open(port)
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local function sendMessage(...)
|
||||
modem.broadcast(port, "ECSRobotControl", ...)
|
||||
end
|
||||
|
||||
local function drawTurtle()
|
||||
if checkRange(xPos, yPos) then
|
||||
ecs.square(xPos - xScreen - 2, yPos - yScreen - 1, 5, 3, 0x880000)
|
||||
ecs.colorText(xPos - xScreen, yPos - yScreen, 0xffffff, "R")
|
||||
|
||||
local xDir, yDir = xPos - xScreen, yPos - yScreen
|
||||
if direction == 1 then
|
||||
gpu.set(xDir, yDir - 1, "^")
|
||||
elseif direction == 2 then
|
||||
gpu.set(xDir + 2, yDir, ">")
|
||||
elseif direction == 4 then
|
||||
gpu.set(xDir - 2, yDir, "<")
|
||||
else
|
||||
gpu.set(xDir, yDir + 1, "|")
|
||||
end
|
||||
|
||||
end
|
||||
local function drawTopBar()
|
||||
buffer.square(1, 1, buffer.screen.width, 3, colors.gray)
|
||||
local x = 1
|
||||
for i = 1, #topBarElements do
|
||||
local textLength = unicode.len(topBarElements[i]) + 4
|
||||
if i == currentTopBarElement then
|
||||
buffer.square(x, 1, textLength, 3, colors.lightGray)
|
||||
buffer.text(x + 2, 2, colors.gray, topBarElements[i])
|
||||
else
|
||||
buffer.text(x + 2, 2, colors.lightGray, topBarElements[i])
|
||||
end
|
||||
x = x + textLength
|
||||
end
|
||||
end
|
||||
|
||||
local function drawPoints()
|
||||
if #points > 0 then
|
||||
for i = 1, #points do
|
||||
if points[i] then
|
||||
if not points[i].completed then
|
||||
if checkRange(points[i].x, points[i].y) then
|
||||
ecs.colorTextWithBack(points[i].x - xScreen, points[i].y - yScreen, 0xffffff - points[i].color, points[i].color, tostring(i))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local function drawMap()
|
||||
--Рисуем карту
|
||||
for i = 1, #map do
|
||||
--Если слой совпадает с текущим Y
|
||||
if map[i].y == map.currentLayer then
|
||||
--Если координаты в границах экрана
|
||||
if map[i].type == "empty" then
|
||||
buffer.set(xStart + map[i].x, yStart - map[i].z, colors.gray, 0x000000, " ")
|
||||
elseif map[i].type == "solid" then
|
||||
buffer.set(xStart + map[i].x, yStart - map[i].z, colors.lightGray, colors.gray, "▒")
|
||||
elseif map[i].type == "passable" then
|
||||
buffer.set(xStart + map[i].x, yStart - map[i].z, colors.lightGray, colors.passable, "▒")
|
||||
elseif map[i].type == "entity" then
|
||||
buffer.text(xStart + map[i].x, yStart - map[i].z, colors.entity, "☺")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Рисуем точку дома
|
||||
if map.currentLayer == 0 then buffer.set(xStart, yStart, colors.homePoint, colors.gray, "⌂") end
|
||||
|
||||
--Рисуем ключевые точки
|
||||
if map.keyPoints and #map.keyPoints > 0 then
|
||||
for i = 1, #map.keyPoints do
|
||||
buffer.set(xStart + map.keyPoints[i].x, yStart + map.keyPoints[i].z, colors.keyPoint, colors.keyPointText, "*")
|
||||
end
|
||||
end
|
||||
|
||||
--Рисуем робота
|
||||
buffer.text(xStart + map.robotPosition.x, yStart - map.robotPosition.z, colors.robot, robotPicture[map.robotPosition.rotation])
|
||||
end
|
||||
|
||||
local function drawHome()
|
||||
if checkRange(homePoint.x, homePoint.y) then
|
||||
ecs.colorTextWithBack(homePoint.x - xScreen, homePoint.y - yScreen, 0xffffff, ecs.colors.blue, "H")
|
||||
end
|
||||
local function requestInventoryInfo()
|
||||
sendMessage("giveMeInfoAboutInventory")
|
||||
end
|
||||
|
||||
local function drawInventory()
|
||||
-- sendMessage("giveMeInfoAboutInventory")
|
||||
local x, y = 3, 5
|
||||
local xPos, yPos = x, y
|
||||
if map.robotInventory and #map.robotInventory > 0 then
|
||||
for i = 1, #map.robotInventory do
|
||||
--Квадратик
|
||||
buffer.square(xPos, yPos, 8, 4, colors.gray)
|
||||
--Имя шмотки
|
||||
local name = unicode.sub(map.robotInventory[i].label, 1, 16)
|
||||
local firstPart = unicode.sub(name, 1, 8)
|
||||
local secondPart = unicode.sub(name, 9, 16) or ""
|
||||
buffer.text(xPos, yPos, colors.lightGray, firstPart)
|
||||
buffer.text(xPos, yPos + 1, colors.lightGray, secondPart)
|
||||
--Колво шмотки
|
||||
buffer.text(xPos, yPos + 2, 0xFFFFFF, tostring(map.robotInventory[i].size))
|
||||
--Процент износа
|
||||
if map.robotInventory[i].maxDamage ~= 0 then
|
||||
local percentOfNotDamage = 1 - (map.robotInventory[i].damage / map.robotInventory[i].maxDamage)
|
||||
local widthOfNotDamage = math.floor(percentOfNotDamage * 6)
|
||||
buffer.text(xPos + 1, yPos + 3, 0x000000, "━━━━━━")
|
||||
buffer.text(xPos + 1, yPos + 3, 0x33CC33, string.rep("━", widthOfNotDamage))
|
||||
end
|
||||
|
||||
xPos = xPos + 10
|
||||
if i % 4 == 0 then xPos = x; yPos = yPos + 5 end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function drawMain()
|
||||
--Очищаем главную зону
|
||||
buffer.square(1, 4, buffer.screen.width, buffer.screen.height - 3, colors.lightGray)
|
||||
|
||||
if topBarElements[currentTopBarElement] == "Карта" then
|
||||
drawMap()
|
||||
elseif topBarElements[currentTopBarElement] == "Карта" then
|
||||
drawInventory()
|
||||
end
|
||||
end
|
||||
|
||||
local function drawAll()
|
||||
gpu.setBackground(0xffffff)
|
||||
gpu.setForeground(0xcccccc)
|
||||
gpu.fill(1, 1, xSize, ySize, "*")
|
||||
drawHome()
|
||||
drawTurtle()
|
||||
drawPoints()
|
||||
drawTopBar()
|
||||
drawMain()
|
||||
buffer.draw()
|
||||
end
|
||||
|
||||
local function turtleExecute(command)
|
||||
modem.broadcast(port, command)
|
||||
os.sleep(0.4)
|
||||
local function getTargetCoords(direction)
|
||||
if direction == "forward" then
|
||||
if map.robotPosition.rotation == 1 then
|
||||
return map.robotPosition.x, map.robotPosition.y, map.robotPosition.z + 1, xStart, yStart + 1
|
||||
elseif map.robotPosition.rotation == 2 then
|
||||
return map.robotPosition.x + 1, map.robotPosition.y, map.robotPosition.z, xStart - 1, yStart
|
||||
elseif map.robotPosition.rotation == 3 then
|
||||
return map.robotPosition.x, map.robotPosition.y, map.robotPosition.z - 1, xStart, yStart - 1
|
||||
elseif map.robotPosition.rotation == 4 then
|
||||
return map.robotPosition.x - 1, map.robotPosition.y, map.robotPosition.z, xStart + 1, yStart
|
||||
end
|
||||
elseif direction == "back" then
|
||||
if map.robotPosition.rotation == 1 then
|
||||
return map.robotPosition.x, map.robotPosition.y, map.robotPosition.z - 1, xStart, yStart - 1
|
||||
elseif map.robotPosition.rotation == 2 then
|
||||
return map.robotPosition.x - 1, map.robotPosition.y, map.robotPosition.z, xStart + 1, yStart
|
||||
elseif map.robotPosition.rotation == 3 then
|
||||
return map.robotPosition.x, map.robotPosition.y, map.robotPosition.z + 1, xStart, yStart + 1
|
||||
elseif map.robotPosition.rotation == 4 then
|
||||
return map.robotPosition.x + 1, map.robotPosition.y, map.robotPosition.z, xStart - 1, yStart
|
||||
end
|
||||
elseif direction == "up" then
|
||||
return map.robotPosition.x, map.robotPosition.y + 1, map.robotPosition.z, xStart, yStart
|
||||
elseif direction == "down" then
|
||||
return map.robotPosition.x, map.robotPosition.y - 1, map.robotPosition.z, xStart, yStart
|
||||
end
|
||||
end
|
||||
|
||||
local function changeDirection(newDirection)
|
||||
if newDirection ~= direction then
|
||||
if direction == 1 then
|
||||
if newDirection == 2 then
|
||||
turtleExecute("turnRight")
|
||||
elseif newDirection == 3 then
|
||||
turtleExecute("turnRight")
|
||||
turtleExecute("turnRight")
|
||||
elseif newDirection == 4 then
|
||||
turtleExecute("turnLeft")
|
||||
end
|
||||
elseif direction == 2 then
|
||||
if newDirection == 1 then
|
||||
turtleExecute("turnLeft")
|
||||
elseif newDirection == 3 then
|
||||
turtleExecute("turnRight")
|
||||
elseif newDirection == 4 then
|
||||
turtleExecute("turnRight")
|
||||
turtleExecute("turnRight")
|
||||
end
|
||||
elseif direction == 3 then
|
||||
if newDirection == 1 then
|
||||
turtleExecute("turnLeft")
|
||||
turtleExecute("turnLeft")
|
||||
elseif newDirection == 2 then
|
||||
turtleExecute("turnLeft")
|
||||
elseif newDirection == 4 then
|
||||
turtleExecute("turnRight")
|
||||
end
|
||||
elseif direction == 4 then
|
||||
if newDirection == 1 then
|
||||
turtleExecute("turnRight")
|
||||
elseif newDirection == 2 then
|
||||
turtleExecute("turnRight")
|
||||
turtleExecute("turnRight")
|
||||
elseif newDirection == 3 then
|
||||
turtleExecute("turnLeft")
|
||||
end
|
||||
end
|
||||
direction = newDirection
|
||||
end
|
||||
local function getOptimalKeyPoint()
|
||||
local optimalID
|
||||
local optimalDistance = math.huge
|
||||
for i = 1, #map.keyPoints do
|
||||
local distance = math.sqrt(map.keyPoints.x ^ 2 + map.keyPoints.y ^ 2 + map.keyPoints.x ^ z)
|
||||
if distance < optimalDistance then
|
||||
optimalID = i
|
||||
optimalDistance = distance
|
||||
end
|
||||
end
|
||||
return optimalID
|
||||
end
|
||||
|
||||
local function moveTurtle()
|
||||
if direction == 1 then
|
||||
yPos = yPos - 1
|
||||
elseif direction == 2 then
|
||||
xPos = xPos + 1
|
||||
elseif direction == 3 then
|
||||
yPos = yPos + 1
|
||||
else
|
||||
xPos = xPos - 1
|
||||
end
|
||||
turtleExecute("forward")
|
||||
end
|
||||
|
||||
local function moveToPoint(number)
|
||||
local xToMove, yToMove = points[number].x + xScreen, points[number].y + yScreen
|
||||
local xDifference, yDifference = xPos + xScreen - xToMove, yPos + yScreen - yToMove
|
||||
|
||||
--ecs.error("xDifference = "..tostring(xDifference)..", yDifference = "..tostring(yDifference))
|
||||
|
||||
if yDifference > 0 then
|
||||
changeDirection(1)
|
||||
elseif yDifference < 0 then
|
||||
changeDirection(3)
|
||||
end
|
||||
|
||||
for i = 1, math.abs(yDifference) do
|
||||
moveTurtle()
|
||||
drawAll()
|
||||
end
|
||||
|
||||
if xDifference > 0 then
|
||||
changeDirection(4)
|
||||
elseif xDifference < 0 then
|
||||
changeDirection(2)
|
||||
end
|
||||
|
||||
for i = 1, math.abs(xDifference) do
|
||||
moveTurtle()
|
||||
drawAll()
|
||||
end
|
||||
|
||||
drawAll()
|
||||
end
|
||||
|
||||
local function moveToEveryPoint()
|
||||
for i = 1, #points do
|
||||
moveToPoint(i)
|
||||
points[i].completed = true
|
||||
end
|
||||
points = {}
|
||||
drawAll()
|
||||
--ecs.error("Все точки пройдены!")
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
drawAll()
|
||||
requestInventoryInfo()
|
||||
|
||||
while true do
|
||||
local e = {event.pull()}
|
||||
|
||||
if e[1] == "key_down" then
|
||||
if e[4] == 200 then
|
||||
yScreen = yScreen - 1
|
||||
elseif e[4] == 208 then
|
||||
yScreen = yScreen + 1
|
||||
elseif e[4] == 203 then
|
||||
xScreen = xScreen - 1
|
||||
elseif e[4] == 205 then
|
||||
xScreen = xScreen + 1
|
||||
elseif e[4] == 28 then
|
||||
moveToEveryPoint()
|
||||
end
|
||||
|
||||
drawAll()
|
||||
|
||||
elseif e[1] == "touch" then
|
||||
local xPoint, yPoint = e[3] + xScreen, e[4] + yScreen
|
||||
table.insert(points, {x = xPoint, y = yPoint, color = math.random(0x000000, 0xffffff)})
|
||||
drawAll()
|
||||
|
||||
end
|
||||
|
||||
local e = { event.pull() }
|
||||
if e[1] == "touch" then
|
||||
map.keyPoints = map.keyPoints or {}
|
||||
table.insert(map.keyPoints, { x = e[3] - xStart, y = map.currentLayer, z = e[4] - yStart })
|
||||
drawAll()
|
||||
elseif e[1] == "key_down" then
|
||||
--W
|
||||
if e[4] == 17 then
|
||||
sendMessage("forward")
|
||||
--S
|
||||
elseif e[4] == 31 then
|
||||
sendMessage("back")
|
||||
--SHIFT
|
||||
elseif e[4] == 42 then
|
||||
sendMessage("down")
|
||||
--SPACE
|
||||
elseif e[4] == 57 then
|
||||
sendMessage("up")
|
||||
--A
|
||||
elseif e[4] == 30 then
|
||||
sendMessage("turnLeft")
|
||||
--D
|
||||
elseif e[4] == 32 then
|
||||
sendMessage("turnRight")
|
||||
--E
|
||||
elseif e[4] == 18 then
|
||||
if keyboard.isControlDown() then sendMessage("use") else sendMessage("swing") end
|
||||
--Q
|
||||
elseif e[4] == 16 then
|
||||
sendMessage("drop")
|
||||
-- elseif e[4] == 28 then
|
||||
-- if map.keyPoints and #map.keyPoints > 0 then
|
||||
-- sendMessage("executeKeyPoints", serialization.serialize(map.keyPoints))
|
||||
-- end
|
||||
end
|
||||
elseif e[1] == "modem_message" then
|
||||
if e[4] == port then
|
||||
if e[6] == "ECSRobotAnswer" then
|
||||
if e[7] == "cantMoveTo" then
|
||||
local x, y, z = getTargetCoords(e[8])
|
||||
table.insert(map, { type = e[9], x = x, y = y, z = z })
|
||||
drawAll()
|
||||
elseif e[7] == "successfullyMovedTo" then
|
||||
local x, y, z; x, y, z, xStart, yStart = getTargetCoords(e[8])
|
||||
if e[8] == "up" then
|
||||
map.currentLayer = map.currentLayer + 1
|
||||
elseif e[8] == "down" then
|
||||
map.currentLayer = map.currentLayer - 1
|
||||
end
|
||||
map.robotPosition.x = x; map.robotPosition.y = y; map.robotPosition.z = z
|
||||
table.insert(map, { type = "empty", x = x, y = y, z = z })
|
||||
drawAll()
|
||||
elseif e[7] == "successfullyRotatedTo" then
|
||||
local adder = -1; if e[8] == "turnRight" then adder = 1 end
|
||||
map.robotPosition.rotation = map.robotPosition.rotation + adder
|
||||
if map.robotPosition.rotation < 1 then
|
||||
map.robotPosition.rotation = 4
|
||||
elseif map.robotPosition.rotation > 4 then
|
||||
map.robotPosition.rotation = 1
|
||||
end
|
||||
drawAll()
|
||||
elseif e[7] == "successfullySwingedTo" then
|
||||
if e[8] == "swing" then e[8] = "forward" elseif e[8] == "swingUp" then e[8] = "up" elseif e[8] == "swingDown" then e[8] = "down" end
|
||||
local x, y, z = getTargetCoords(e[8])
|
||||
table.insert(map, { type = "empty", x = x, y = y, z = z })
|
||||
drawAll()
|
||||
elseif e[7] == "inventoryInfo" then
|
||||
map.robotInventory = serialization.unserialize(e[8])
|
||||
drawAll()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
74
Applications/Robot/RobotReciever.lua
Normal file
74
Applications/Robot/RobotReciever.lua
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
|
||||
local event = require("event")
|
||||
local robot = require("robot")
|
||||
local component = require("component")
|
||||
local serialization = require("serialization")
|
||||
local modem = component.modem
|
||||
local inventoryController = component.inventory_controller
|
||||
local port = 1337
|
||||
local moveSleepDelay = 0.05
|
||||
|
||||
modem.open(port)
|
||||
|
||||
------------------------------------------------------------------------------------------
|
||||
|
||||
local function sendMessage(...)
|
||||
modem.broadcast(port, "ECSRobotAnswer", ...)
|
||||
end
|
||||
|
||||
local function try(functionName, successMessage, errorMessage)
|
||||
local success, reason = robot[functionName]()
|
||||
if success then
|
||||
sendMessage(successMessage, functionName)
|
||||
else
|
||||
print("Ошибка try:", functionName, reason)
|
||||
sendMessage(errorMessage, functionName, reason)
|
||||
end
|
||||
os.sleep(moveSleepDelay)
|
||||
end
|
||||
|
||||
local function sendInventory()
|
||||
local inventory = {}
|
||||
local inventorySize = robot.inventorySize()
|
||||
|
||||
for slot = 1, inventorySize do
|
||||
table.insert(inventory, inventoryController.getStackInInternalSlot(slot))
|
||||
end
|
||||
|
||||
sendMessage("inventoryInfo", serialization.serialize(inventory))
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------
|
||||
|
||||
while true do
|
||||
local e = { event.pull() }
|
||||
if e[1] == "modem_message" then
|
||||
if e[4] == port then
|
||||
if e[6] == "ECSRobotControl" then
|
||||
if e[7] == "forward" or e[7] == "back" or e[7] == "up" or e[7] == "down" then
|
||||
try(e[7], "successfullyMovedTo", "cantMoveTo")
|
||||
elseif e[7] == "turnLeft" or e[7] == "turnRight" then
|
||||
try(e[7], "successfullyRotatedTo", "cantRotateWTF")
|
||||
elseif e[7] == "swing" then
|
||||
try(e[7], "successfullySwingedTo", "cantSwingTo")
|
||||
elseif e[7] == "use" then
|
||||
robot.use()
|
||||
elseif e[7] == "drop" then
|
||||
robot.drop(e[8] or 1)
|
||||
elseif e[7] == "giveMeInfoAboutInventory" then
|
||||
sendInventory()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
249
Applications/Sudoku/Sudoku.lua
Normal file
249
Applications/Sudoku/Sudoku.lua
Normal file
@ -0,0 +1,249 @@
|
||||
|
||||
---------------------------------------------------- Библиотеки ----------------------------------------------------------------
|
||||
|
||||
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()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
9
Applications/Sudoku/testSudokuFile.txt
Normal file
9
Applications/Sudoku/testSudokuFile.txt
Normal file
@ -0,0 +1,9 @@
|
||||
2 8
|
||||
169 32
|
||||
37 94
|
||||
257 94
|
||||
8 6 3
|
||||
95 287
|
||||
95 21
|
||||
41 685
|
||||
5 9
|
||||
9
Applications/Sudoku/testSudokuFile2.txt
Normal file
9
Applications/Sudoku/testSudokuFile2.txt
Normal file
@ -0,0 +1,9 @@
|
||||
9 2 5
|
||||
8 2 9 1
|
||||
4 6 3 2
|
||||
4 2 9 6
|
||||
3 4
|
||||
5 8 1 7
|
||||
3 9 5 8
|
||||
6 1 3 7
|
||||
8 7 1
|
||||
@ -7,16 +7,15 @@
|
||||
" корпусе было подобрано лучшими специалистами ",
|
||||
" нашей компании специально для вас. ",
|
||||
" ",
|
||||
" Данный компьютер оснащен квантовым генератором, ",
|
||||
" что позволит вам навсегда забыть о бесконечных ",
|
||||
" счетах за свет. Также в нем установлена передовая ",
|
||||
" материнская плата без ограничений на уровень ",
|
||||
" компонентов. Кроме того, мы встроили сверхбыстрый ",
|
||||
" преобразователь энергии, распределяющий ее между ",
|
||||
" компонентами более эффективно.",
|
||||
" Хотим напомнить, что простые смертные ",
|
||||
" не имеют права открывать содержимое корпуса, ",
|
||||
" это сделал автор мода OpenComputers. Однако ",
|
||||
" вы можете спользовать хопперы и закидывать",
|
||||
" нужные компоненты в компьютер через них ;) ",
|
||||
" ",
|
||||
" Ну, или используйте этот корпус для создания ",
|
||||
" крутых и мощных роботов.",
|
||||
" ",
|
||||
" Спасибо за покупку!",
|
||||
" "
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user