Playable board creation ok
This commit is contained in:
parent
f47ed840cf
commit
b80297c45f
207
main.lua
207
main.lua
|
@ -86,37 +86,28 @@ function equal(tbl1, tbl2)
|
|||
return true
|
||||
end
|
||||
|
||||
function tostring(any)
|
||||
if (type(any)~="table") return tostr(any)
|
||||
local str = "{"
|
||||
for k,v in pairs(any) do
|
||||
if (str~="{") str=str..","
|
||||
str=str..tostring(k).."="..tostring(v)
|
||||
end
|
||||
return str.."}"
|
||||
end
|
||||
|
||||
--
|
||||
-- Board
|
||||
--
|
||||
|
||||
local Board = {}
|
||||
function Board.new()
|
||||
local debug = false
|
||||
local width = 10
|
||||
-- local t = [[
|
||||
-- 2,0,2,0,0,2,1,0,1,2,
|
||||
-- 0,0,0,0,0,0,0,0,0,1,
|
||||
-- 0,1,0,0,0,0,0,0,0,0,
|
||||
-- 0,2,0,0,0,0,0,1,0,2,
|
||||
-- 0,0,1,0,0,2,0,1,0,1,
|
||||
-- 0,0,0,0,1,1,0,0,0,0,
|
||||
-- 0,2,2,0,0,0,0,0,0,2,
|
||||
-- 0,0,0,0,2,0,0,0,0,0,
|
||||
-- 0,0,2,0,0,1,0,0,0,0,
|
||||
-- 0,2,0,0,2,0,2,0,0,0
|
||||
-- ]]
|
||||
local t = [[
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0
|
||||
local t = [[
|
||||
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0
|
||||
]]
|
||||
a = {foo = 3}
|
||||
local tiles = split(t)
|
||||
|
||||
return {
|
||||
|
@ -136,10 +127,25 @@ function Board.new()
|
|||
tiles = split(t)
|
||||
end,
|
||||
|
||||
getWidth = function()
|
||||
return width
|
||||
end,
|
||||
|
||||
getTile = function(self, idx)
|
||||
return tiles[idx]
|
||||
end,
|
||||
|
||||
-- returns a COPY of the tiles array
|
||||
getTilesCopy = function(self)
|
||||
return copy(tiles)
|
||||
end,
|
||||
|
||||
-- overwrites the whole tiles array
|
||||
setTiles = function(self, newtiles)
|
||||
assert(#newtiles == #tiles, "New tiles array must have a length of " .. #tiles)
|
||||
tiles = copy(newtiles)
|
||||
end,
|
||||
|
||||
idx_xy = function(self, idx)
|
||||
return idx_xy(idx, width)
|
||||
end,
|
||||
|
@ -178,22 +184,22 @@ function Board.new()
|
|||
|
||||
isValid = function(self)
|
||||
local rows = self:getRows()
|
||||
for row in all(rows) do
|
||||
for y,row in ipairs(rows) do
|
||||
-- check count
|
||||
if count(row, BLUE) ~= count(row, YELLOW) then
|
||||
printh("uneven count")
|
||||
if (debug) printh("uneven count on row "..y)
|
||||
return false
|
||||
end
|
||||
-- check identical lines
|
||||
for k,other in ipairs(rows) do
|
||||
if equal(other, row) and other ~= row then
|
||||
printh("equal rows "..k)
|
||||
if (debug) printh("equal rows "..k)
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- check triples
|
||||
if self:countConsecutives(row) > 2 then
|
||||
printh("triples")
|
||||
if (debug) printh("triples")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
@ -202,19 +208,19 @@ function Board.new()
|
|||
for col in all(cols) do
|
||||
-- check count
|
||||
if count(col, BLUE) ~= count(col, YELLOW) then
|
||||
printh("uneven count")
|
||||
if (debug) printh("uneven count")
|
||||
return false
|
||||
end
|
||||
-- check identical lines
|
||||
for other in all(cols) do
|
||||
if equal(other, col) and other ~= col then
|
||||
printh("equal cols")
|
||||
if (debug) printh("equal cols")
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- check triples
|
||||
if self:countConsecutives(col) > 2 then
|
||||
printh("triples")
|
||||
if (debug) printh("triples")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
@ -235,8 +241,8 @@ function Board.new()
|
|||
return count
|
||||
end,
|
||||
|
||||
-- Returns the index of a random zero
|
||||
getRandomZero = function(self, v)
|
||||
-- Returns the index of a random zero tile
|
||||
getRandomZero = function(self)
|
||||
assert(count(tiles, 0) > 0, "No zero left")
|
||||
local zeroes = filter(tiles, function(v) return v == 0 end, true)
|
||||
local z = {}
|
||||
|
@ -246,6 +252,17 @@ function Board.new()
|
|||
return rnd(z)
|
||||
end,
|
||||
|
||||
-- Returns the index of a random non-zero tile
|
||||
getRandomNonZero = function(self)
|
||||
assert(count(tiles, 0) < #tiles, "All zeroes")
|
||||
local numbers = filter(tiles, function(v) return v ~= 0 end, true)
|
||||
local z = {}
|
||||
for k,v in pairs(numbers) do
|
||||
add(z, k)
|
||||
end
|
||||
return rnd(z)
|
||||
end,
|
||||
|
||||
tostring = function(self)
|
||||
local str = ''
|
||||
for v in all(tiles) do
|
||||
|
@ -254,19 +271,24 @@ function Board.new()
|
|||
return str
|
||||
end,
|
||||
|
||||
solve = function(self, random)
|
||||
local old = self:tostring()
|
||||
-- Solves 1 step of the board
|
||||
-- Returns "valid" if it solved it without guessing
|
||||
-- Returns "invalid" if the board cannot be solved
|
||||
solveStep = function(self, random)
|
||||
local zeroes = count(tiles, 0)
|
||||
self:surroundDoubles()
|
||||
self:splitTriples()
|
||||
self:fillLines()
|
||||
self:noIdenticalLines()
|
||||
local changed = old ~= self:tostring()
|
||||
local changed = zeroes ~= count(tiles, 0)
|
||||
if not changed and random and not self:isComplete() then
|
||||
-- Set a random color
|
||||
local z = self:getRandomZero()
|
||||
self:fill(z, rnd({BLUE, YELLOW}))
|
||||
printh("!!!!!!!!!!!!!!!!! RANDOM FILL AT " .. z)
|
||||
if (debug) printh("!!!!!!!!!!!!!!!!! RANDOM FILL AT " .. z)
|
||||
return "invalid"
|
||||
end
|
||||
return (changed or self:isComplete()) and "valid" or "invalid"
|
||||
end,
|
||||
|
||||
surroundDoubles = function(self)
|
||||
|
@ -297,7 +319,7 @@ function Board.new()
|
|||
-- do the surrounding
|
||||
for item in all(neighbors) do
|
||||
if item[1] then
|
||||
printh("Surrounding at " .. item[1])
|
||||
if (debug) printh("Surrounding at " .. item[1])
|
||||
self:fill(item[1], tiles[item[2]], true)
|
||||
end
|
||||
end
|
||||
|
@ -315,7 +337,7 @@ function Board.new()
|
|||
local prev = tiles[idx-1]
|
||||
local next = tiles[idx+1]
|
||||
if prev ~= 0 and prev == next then
|
||||
printh("Splitting at " .. idx)
|
||||
if (debug) printh("Splitting at " .. idx)
|
||||
self:fill(idx, prev, true)
|
||||
end
|
||||
end
|
||||
|
@ -325,7 +347,7 @@ function Board.new()
|
|||
local prev = tiles[idx-width]
|
||||
local next = tiles[idx+width]
|
||||
if prev ~= 0 and prev == next then
|
||||
printh("Splitting at " .. idx)
|
||||
if (debug) printh("Splitting at " .. idx)
|
||||
self:fill(idx, prev, true)
|
||||
end
|
||||
end
|
||||
|
@ -359,7 +381,7 @@ function Board.new()
|
|||
end,
|
||||
|
||||
fillRow = function(self, y, color)
|
||||
printh("Filling line " .. y .. " in " .. (color == BLUE and "blue" or "yellow"))
|
||||
if (debug) printh("Filling line " .. y .. " in " .. (color == BLUE and "blue" or "yellow"))
|
||||
local idx = self:xy_idx(1, y)
|
||||
for i = idx, (idx+width-1) do
|
||||
if self:getTile(i) == 0 then
|
||||
|
@ -369,7 +391,7 @@ function Board.new()
|
|||
end,
|
||||
|
||||
fillCol = function(self, x, color)
|
||||
printh("Filling column " .. x .. " in " .. (color == BLUE and "blue" or "yellow"))
|
||||
if (debug) printh("Filling column " .. x .. " in " .. (color == BLUE and "blue" or "yellow"))
|
||||
local idx = self:xy_idx(x, 1)
|
||||
for i = idx, #tiles, width do
|
||||
if self:getTile(i) == 0 then
|
||||
|
@ -389,16 +411,20 @@ function Board.new()
|
|||
-- Check if a dupe exists
|
||||
for x2,col in ipairs(cols) do
|
||||
if equal(col, ab) then
|
||||
printh("No-dupe at col " .. x .. " from col " .. x2)
|
||||
printh(" " .. self:xy_idx(x,y1) .. " in yellow")
|
||||
printh(" " .. self:xy_idx(x,y2) .. " in blue")
|
||||
if debug then
|
||||
printh("No-dupe at col " .. x .. " from col " .. x2)
|
||||
printh(" " .. self:xy_idx(x,y1) .. " in yellow")
|
||||
printh(" " .. self:xy_idx(x,y2) .. " in blue")
|
||||
end
|
||||
self:fill(self:xy_idx(x,y1), YELLOW)
|
||||
self:fill(self:xy_idx(x,y2), BLUE)
|
||||
goto continue
|
||||
elseif equal(col, ba) then
|
||||
printh("No-dupe at col " .. x .. " from col " .. x2)
|
||||
printh(" " .. self:xy_idx(x,y1) .. " in blue")
|
||||
printh(" " .. self:xy_idx(x,y2) .. " in yellow")
|
||||
if debug then
|
||||
printh("No-dupe at col " .. x .. " from col " .. x2)
|
||||
printh(" " .. self:xy_idx(x,y1) .. " in blue")
|
||||
printh(" " .. self:xy_idx(x,y2) .. " in yellow")
|
||||
end
|
||||
self:fill(self:xy_idx(x,y1), BLUE)
|
||||
self:fill(self:xy_idx(x,y2), YELLOW)
|
||||
goto continue
|
||||
|
@ -418,16 +444,20 @@ function Board.new()
|
|||
-- Check if a dupe exists
|
||||
for y2,row in ipairs(rows) do
|
||||
if equal(row, ab) then
|
||||
printh("No-dupe at row " .. y .. " from row " .. y2)
|
||||
printh(" " .. self:xy_idx(x1,y) .. " in yellow")
|
||||
printh(" " .. self:xy_idx(x2,y) .. " in blue")
|
||||
if debug then
|
||||
printh("No-dupe at row " .. y .. " from row " .. y2)
|
||||
printh(" " .. self:xy_idx(x1,y) .. " in yellow")
|
||||
printh(" " .. self:xy_idx(x2,y) .. " in blue")
|
||||
end
|
||||
self:fill(self:xy_idx(x1,y), YELLOW)
|
||||
self:fill(self:xy_idx(x2,y), BLUE)
|
||||
goto continue
|
||||
elseif equal(row, ba) then
|
||||
printh("No-dupe at row " .. y .. " from row " .. y2)
|
||||
printh(" " .. self:xy_idx(x1,y) .. " in blue")
|
||||
printh(" " .. self:xy_idx(x2,y) .. " in yellow")
|
||||
if debug then
|
||||
printh("No-dupe at row " .. y .. " from row " .. y2)
|
||||
printh(" " .. self:xy_idx(x1,y) .. " in blue")
|
||||
printh(" " .. self:xy_idx(x2,y) .. " in yellow")
|
||||
end
|
||||
self:fill(self:xy_idx(x1,y), BLUE)
|
||||
self:fill(self:xy_idx(x2,y), YELLOW)
|
||||
goto continue
|
||||
|
@ -439,13 +469,21 @@ function Board.new()
|
|||
end,
|
||||
|
||||
draw = function(self)
|
||||
local w = 10
|
||||
local padding = 1
|
||||
local margin = 4
|
||||
for k,v in ipairs(tiles) do
|
||||
local x,y = self:idx_xy(k)
|
||||
local color = v == BLUE and 9 or v == YELLOW and 3 or 1
|
||||
local w = 10
|
||||
local p = 1
|
||||
rectfill((x-1)*w + (x-1)*(p+1), (y-1)*w + (y-1)*(p+1), w, w, color)
|
||||
print(k, (x-1)*w + (x-1)*(p+1), (y-1)*w + (y-1)*(p+1), 8)
|
||||
rectfill(
|
||||
margin + (x-1)*w + (x-1)*(padding+1),
|
||||
margin + (y-1)*w + (y-1)*(padding+1),
|
||||
w, w, color)
|
||||
if debug then
|
||||
print(k,
|
||||
margin + (x-1)*w + (x-1)*(padding+1),
|
||||
margin + (y-1)*w + (y-1)*(padding+1), 8)
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
|
@ -456,19 +494,58 @@ end
|
|||
--
|
||||
|
||||
local board = Board.new()
|
||||
local create = true
|
||||
|
||||
function _init()
|
||||
cls()
|
||||
printh(" ")
|
||||
printh(" ")
|
||||
-- srand(42)
|
||||
|
||||
if create then
|
||||
-- Create a board
|
||||
repeat
|
||||
board:reset()
|
||||
repeat
|
||||
board:solveStep(true)
|
||||
until board:isComplete()
|
||||
until board:isValid()
|
||||
|
||||
-- Remove tiles until randomness is unavoidable
|
||||
local previous = {board:getTilesCopy()} -- initial state
|
||||
local invalidcount = 0
|
||||
while true do
|
||||
-- remove a random tile
|
||||
board:setTiles(previous[#previous])
|
||||
local i = board:getRandomNonZero()
|
||||
board:fill(i, 0)
|
||||
add(previous, board:getTilesCopy())
|
||||
|
||||
-- try to solve the board
|
||||
local solved = ""
|
||||
repeat
|
||||
solved = board:solveStep()
|
||||
until board:isComplete() or solved == "invalid"
|
||||
if board:isComplete() then
|
||||
invalidcount = 0
|
||||
end
|
||||
if solved == "invalid" then
|
||||
deli(previous)
|
||||
invalidcount += 1
|
||||
end
|
||||
if invalidcount == 100 then
|
||||
break
|
||||
end
|
||||
end -- end while
|
||||
|
||||
board:setTiles(previous[#previous])
|
||||
printh(board:tostring())
|
||||
end
|
||||
end
|
||||
|
||||
function _update60()
|
||||
board:solve(true)
|
||||
-- if time() % .01 == 0 then
|
||||
-- end
|
||||
if board:isComplete() then
|
||||
if not board:isValid() then
|
||||
printh("NOT VALID")
|
||||
board:reset()
|
||||
end
|
||||
if not create then
|
||||
board:solveStep()
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user