Clickable buttons

This commit is contained in:
Simon Cambier 2022-05-29 18:38:07 +02:00
parent 9fd3208aaf
commit 977d2c342b
5 changed files with 514 additions and 423 deletions

View File

@ -2,6 +2,9 @@ pico-8 cartridge // http://www.pico-8.com
version 36
__lua__
#include main.lua
#include board.lua
#include states/menu.lua
#include states/game.lua
__gfx__
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

388
board.lua Normal file
View File

@ -0,0 +1,388 @@
local Board = {}
function Board.new()
local debug = false
local width = 10
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 {
reset = function(self)
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
]]
tiles = split(t)
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,
xy_idx = function(self, x, y)
return xy_idx(x, y, width)
end,
fill = function(self, idx, color, invert)
if invert then
color = color == YELLOW and BLUE or YELLOW
end
tiles[idx] = color
end,
getRows = function(self)
local ret = {}
for i = 1, width do
add(ret, slice(tiles, ((i - 1) * width) + 1, i * width))
end
return ret
end,
getCols = function(self)
local ret = {}
local rows = self.getRows(self)
for i = 1, width do
add(ret, map(rows, function(v) return v[i] end))
end
return ret
end,
isComplete = function(self)
return count(tiles, 0) == 0
end,
isValid = function(self)
local rows = self:getRows()
for y,row in ipairs(rows) do
-- check count
if count(row, BLUE) ~= count(row, YELLOW) then
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
if (debug) printh("equal rows "..k)
return false
end
end
-- check triples
if self:countConsecutives(row) > 2 then
if (debug) printh("triples")
return false
end
end
local cols = self:getCols()
for col in all(cols) do
-- check count
if count(col, BLUE) ~= count(col, YELLOW) then
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
if (debug) printh("equal cols")
return false
end
end
-- check triples
if self:countConsecutives(col) > 2 then
if (debug) printh("triples")
return false
end
end
return true
end,
countConsecutives = function(self, line)
local count = 0
local last = 0
for v in all(line) do
if v ~= last then
last = 0
else
last = v
count += 1
end
end
return count
end,
--
-- 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 = {}
for k,v in pairs(zeroes) do
add(z, k)
end
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
str ..= ", " .. v
end
return str
end,
-- 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 = 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}))
if (debug) printh("!!!!!!!!!!!!!!!!! RANDOM FILL AT " .. z)
return "invalid"
end
return (changed or self:isComplete()) and "valid" or "invalid"
end,
surroundDoubles = function(self)
for idx,v in ipairs(tiles) do
local x,y = self:idx_xy(idx)
if v == 0 then
local neighbors = {}
-- 2 tiles on the left
if x >= 3 then
add(neighbors, {idx, idx-1, idx-2})
end
-- 2 tiles on the right
if x <= width-2 then
add(neighbors, {idx, idx+1, idx+2})
end
-- 2 tiles on top
if y >= 3 then
add(neighbors, {idx, idx-width, idx - width*2})
end
-- 2 tiles under
if y <= width-2 then
add(neighbors, {idx, idx+width, idx + width*2})
end
-- only keep pairs that are identical (and not 0)
neighbors = filter(neighbors, function (o) return tiles[o[2]] == tiles[o[3]] and tiles[o[2]] ~= 0 end)
-- do the surrounding
for item in all(neighbors) do
if item[1] then
if (debug) printh("Surrounding at " .. item[1])
self:fill(item[1], tiles[item[2]], true)
end
end
end
end
end,
splitTriples = function(self)
for idx, col in ipairs(tiles) do
local x,y = self:idx_xy(idx)
if col == 0 then
if x > 1 and x < width then
-- check horizontal
local prev = tiles[idx-1]
local next = tiles[idx+1]
if prev ~= 0 and prev == next then
if (debug) printh("Splitting at " .. idx)
self:fill(idx, prev, true)
end
end
if y>1 and y < width then
-- check vertical
local prev = tiles[idx-width]
local next = tiles[idx+width]
if prev ~= 0 and prev == next then
if (debug) printh("Splitting at " .. idx)
self:fill(idx, prev, true)
end
end
end
end
end,
fillLines = function(self)
local rows = self:getRows()
local cols = self:getCols()
-- rows
for y,row in ipairs(rows) do
local a = count(row, BLUE)
local b = count(row, YELLOW)
if a ~= b then
if a == width/2 then self:fillRow(y, YELLOW) end
if b == width/2 then self:fillRow(y, BLUE) end
end
end
-- columns
for x,col in ipairs(cols) do
local a = count(col, BLUE)
local b = count(col, YELLOW)
if a ~= b then
if a == width/2 then self:fillCol(x, YELLOW) end
if b == width/2 then self:fillCol(x, BLUE) end
end
end
end,
fillRow = function(self, y, color)
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
self:fill(i, color)
end
end
end,
fillCol = function(self, x, color)
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
self:fill(i, color)
end
end
end,
noIdenticalLines = function(self)
-- columns
local cols = self:getCols()
for x,col in ipairs(cols) do
if count(col, 0) == 2 and count(col, BLUE) == count(col, YELLOW) then
local y1, y2 = unpack(find(col, 0))
local ab = copy(col) ab[y1] = BLUE ab[y2] = YELLOW
local ba = copy(col) ba[y1] = YELLOW ba[y2] = BLUE
-- Check if a dupe exists
for x2,col in ipairs(cols) do
if equal(col, ab) then
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
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
end
end
end
::continue::
end
-- rows
local rows = self:getRows()
for y,row in ipairs(rows) do
if count(row, 0) == 2 and count(row, BLUE) == count(row, YELLOW) then
local x1, x2 = unpack(find(row, 0))
local ab = copy(row) ab[x1] = BLUE ab[x2] = YELLOW
local ba = copy(row) ba[x1] = YELLOW ba[x2] = BLUE
-- Check if a dupe exists
for y2,row in ipairs(rows) do
if equal(row, ab) then
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
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
end
end
end
::continue::
end
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
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
}
end

465
main.lua
View File

@ -1,4 +1,4 @@
poke(0x5F2D, 3)
poke(0x5F2D, 1)
--
-- constants
@ -104,462 +104,81 @@ end
-- return str.."}"
-- end
--
-- Board
--
local Board = {}
function Board.new()
local debug = false
local width = 10
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)
function makeButton(x, y, w, h, text, f)
local state = 0 -- 0 = normal, 1 = hovered, 2 = pressed
return {
reset = function(self)
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
]]
tiles = split(t)
x = x,
y = y,
w = w,
h = h,
text = text,
draw=function(self)
rectfill(self.x, self.y, self.w, self.h, 8)
print(self.text.." "..state, self.x+1, self.y+1, 6)
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,
xy_idx = function(self, x, y)
return xy_idx(x, y, width)
end,
fill = function(self, idx, color, invert)
if invert then
color = color == YELLOW and BLUE or YELLOW
update=function(self)
if mouse_x >= self.x and mouse_x <= self.x + self.w and
mouse_y >= self.y and mouse_y <= self.y + self.h then
if stat(34)&1 == 0 and state == 2 and f then
f()
end
tiles[idx] = color
end,
getRows = function(self)
local ret = {}
for i = 1, width do
add(ret, slice(tiles, ((i - 1) * width) + 1, i * width))
end
return ret
end,
getCols = function(self)
local ret = {}
local rows = self.getRows(self)
for i = 1, width do
add(ret, map(rows, function(v) return v[i] end))
end
return ret
end,
isComplete = function(self)
return count(tiles, 0) == 0
end,
isValid = function(self)
local rows = self:getRows()
for y,row in ipairs(rows) do
-- check count
if count(row, BLUE) ~= count(row, YELLOW) then
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
if (debug) printh("equal rows "..k)
return false
end
end
-- check triples
if self:countConsecutives(row) > 2 then
if (debug) printh("triples")
return false
end
end
local cols = self:getCols()
for col in all(cols) do
-- check count
if count(col, BLUE) ~= count(col, YELLOW) then
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
if (debug) printh("equal cols")
return false
end
end
-- check triples
if self:countConsecutives(col) > 2 then
if (debug) printh("triples")
return false
end
end
return true
end,
countConsecutives = function(self, line)
local count = 0
local last = 0
for v in all(line) do
if v ~= last then
last = 0
if stat(34)&1 == 1 then
state = 2
else
last = v
count += 1
end
end
return count
end,
--
-- 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 = {}
for k,v in pairs(zeroes) do
add(z, k)
end
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
str ..= ", " .. v
end
return str
end,
-- 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 = 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}))
if (debug) printh("!!!!!!!!!!!!!!!!! RANDOM FILL AT " .. z)
return "invalid"
end
return (changed or self:isComplete()) and "valid" or "invalid"
end,
surroundDoubles = function(self)
for idx,v in ipairs(tiles) do
local x,y = self:idx_xy(idx)
if v == 0 then
local neighbors = {}
-- 2 tiles on the left
if x >= 3 then
add(neighbors, {idx, idx-1, idx-2})
end
-- 2 tiles on the right
if x <= width-2 then
add(neighbors, {idx, idx+1, idx+2})
end
-- 2 tiles on top
if y >= 3 then
add(neighbors, {idx, idx-width, idx - width*2})
end
-- 2 tiles under
if y <= width-2 then
add(neighbors, {idx, idx+width, idx + width*2})
end
-- only keep pairs that are identical (and not 0)
neighbors = filter(neighbors, function (o) return tiles[o[2]] == tiles[o[3]] and tiles[o[2]] ~= 0 end)
-- do the surrounding
for item in all(neighbors) do
if item[1] then
if (debug) printh("Surrounding at " .. item[1])
self:fill(item[1], tiles[item[2]], true)
end
end
end
end
end,
splitTriples = function(self)
for idx, col in ipairs(tiles) do
local x,y = self:idx_xy(idx)
if col == 0 then
if x > 1 and x < width then
-- check horizontal
local prev = tiles[idx-1]
local next = tiles[idx+1]
if prev ~= 0 and prev == next then
if (debug) printh("Splitting at " .. idx)
self:fill(idx, prev, true)
end
end
if y>1 and y < width then
-- check vertical
local prev = tiles[idx-width]
local next = tiles[idx+width]
if prev ~= 0 and prev == next then
if (debug) printh("Splitting at " .. idx)
self:fill(idx, prev, true)
end
end
end
end
end,
fillLines = function(self)
local rows = self:getRows()
local cols = self:getCols()
-- rows
for y,row in ipairs(rows) do
local a = count(row, BLUE)
local b = count(row, YELLOW)
if a ~= b then
if a == width/2 then self:fillRow(y, YELLOW) end
if b == width/2 then self:fillRow(y, BLUE) end
end
end
-- columns
for x,col in ipairs(cols) do
local a = count(col, BLUE)
local b = count(col, YELLOW)
if a ~= b then
if a == width/2 then self:fillCol(x, YELLOW) end
if b == width/2 then self:fillCol(x, BLUE) end
end
end
end,
fillRow = function(self, y, color)
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
self:fill(i, color)
end
end
end,
fillCol = function(self, x, color)
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
self:fill(i, color)
end
end
end,
noIdenticalLines = function(self)
-- columns
local cols = self:getCols()
for x,col in ipairs(cols) do
if count(col, 0) == 2 and count(col, BLUE) == count(col, YELLOW) then
local y1, y2 = unpack(find(col, 0))
local ab = copy(col) ab[y1] = BLUE ab[y2] = YELLOW
local ba = copy(col) ba[y1] = YELLOW ba[y2] = BLUE
-- Check if a dupe exists
for x2,col in ipairs(cols) do
if equal(col, ab) then
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
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
end
end
end
::continue::
end
-- rows
local rows = self:getRows()
for y,row in ipairs(rows) do
if count(row, 0) == 2 and count(row, BLUE) == count(row, YELLOW) then
local x1, x2 = unpack(find(row, 0))
local ab = copy(row) ab[x1] = BLUE ab[x2] = YELLOW
local ba = copy(row) ba[x1] = YELLOW ba[x2] = BLUE
-- Check if a dupe exists
for y2,row in ipairs(rows) do
if equal(row, ab) then
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
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
end
end
end
::continue::
end
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
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)
state = 1
end
else
state = 0
end
end
}
end
function setState(state, ...)
local args = {...}
if gs and gs._leave then gs._leave() end
gs = state
if gs and gs._enter then gs._enter(unpack(args)) end
end
--
-- main loop
--
local board = Board.new()
local create = true
function _init()
cls()
printh(" ")
printh(" ")
-- srand(42)
mouse_x = 0
mouse_y = 0
if create then
-- Create a board
repeat
board:reset()
repeat
board:solveStep(true)
until board:isComplete()
until board:isValid()
states = {
menu = stateMenu(),
game = stateGame()
}
-- 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())
setState(states.menu)
-- 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()
gs._update()
-- if not create then
-- board:solveStep()
-- end
-- mouse
mouse_x = stat(32)
mouse_y = stat(33)
end
function _draw()
cls()
board:draw()
gs._draw()
circfill(stat(32), stat(33), 0, 7)
circ(stat(32), stat(33), 1, 0)
end

54
states/game.lua Normal file
View File

@ -0,0 +1,54 @@
function stateGame()
local board = Board.new()
function _enter()
-- 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
return {
_enter = _enter,
_update = function()
end,
_draw = function()
board:draw()
end,
}
end

27
states/menu.lua Normal file
View File

@ -0,0 +1,27 @@
function stateMenu()
local items = {"play", "rules"}
local buttons = {}
function _enter()
for k,v in ipairs(items) do
local button = makeButton(10, k*10, 30, 6, v, function() printh("click") end)
add(buttons, button)
end
end
return {
_enter = _enter,
_update = function()
for button in all(buttons) do
button:update()
end
end,
_draw = function()
for button in all(buttons) do
button:draw()
end
end
}
end