77 lines
2.4 KiB
Lua
77 lines
2.4 KiB
Lua
-- 2048 for Lua 5.1-5.4, 12/3/2020 db
|
|
local unpack = unpack or table.unpack -- for 5.3 +/- compatibility
|
|
game = {
|
|
cell = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
|
best = 0,
|
|
draw = function(self)
|
|
local t = self.cell
|
|
print("+----+----+----+----+")
|
|
for r=0,12,4 do
|
|
print(string.format("|%4d|%4d|%4d|%4d|\n+----+----+----+----+",t[r+1],t[r+2],t[r+3],t[r+4]))
|
|
end
|
|
end,
|
|
incr = function(self)
|
|
local t,open = self.cell,{}
|
|
for i=1,16 do if t[i]==0 then open[#open+1]=i end end
|
|
t[open[math.random(#open)]] = math.random()<0.1 and 4 or 2
|
|
end,
|
|
pack = function(self,ofr,oto,ost,ifr,ito,ist)
|
|
local t = self.cell
|
|
for outer=ofr,oto,ost do
|
|
local skip = 0
|
|
for inner=ifr,ito,ist do
|
|
local i = outer+inner
|
|
if t[i]==0 then skip=skip+1 else if skip>0 then t[i-skip*ist],t[i],self.diff = t[i],0,true end end
|
|
end
|
|
end
|
|
end,
|
|
comb = function(self,ofr,oto,ost,ifr,ito,ist)
|
|
local t = self.cell
|
|
for outer=ofr,oto,ost do
|
|
for inner=ifr,ito-ist,ist do
|
|
local i,j = outer+inner,outer+inner+ist
|
|
if t[i]>0 and t[i]==t[j] then t[i],t[j],self.diff,self.best = t[i]*2,0,true,math.max(self.best,t[i]*2) end
|
|
end
|
|
end
|
|
end,
|
|
move = function(self,dir)
|
|
local loopdata = {{0,12,4,1,4,1},{0,12,4,4,1,-1},{1,4,1,0,12,4},{1,4,1,12,0,-4}}
|
|
local ofr,oto,ost,ifr,ito,ist = unpack(loopdata[dir])
|
|
self:pack(ofr,oto,ost,ifr,ito,ist)
|
|
self:comb(ofr,oto,ost,ifr,ito,ist)
|
|
self:pack(ofr,oto,ost,ifr,ito,ist)
|
|
end,
|
|
full = function(self)
|
|
local t = self.cell
|
|
for r=0,12,4 do
|
|
for c=1,4 do
|
|
local i,v = r+c,t[r+c]
|
|
if (v==0) or (c>1 and t[i-1]==v) or (c<4 and t[i+1]==v) or (r>0 and t[i-4]==v) or (r<12 and t[i+4]==v) then
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
return true
|
|
end,
|
|
play = function(self)
|
|
math.randomseed(os.time())
|
|
self:incr()
|
|
self:incr()
|
|
while true do
|
|
self:draw()
|
|
if self.best==2048 then print("WIN!") break end
|
|
if self:full() then print("LOSE!") break end
|
|
io.write("Your move (wasd + enter, or q + enter to quit): ")
|
|
local char = io.read()
|
|
self.diff = false
|
|
if (char=="a") then self:move(1)
|
|
elseif (char=="d") then self:move(2)
|
|
elseif (char=="w") then self:move(3)
|
|
elseif (char=="s") then self:move(4)
|
|
elseif (char=="q") then break end
|
|
if self.diff then self:incr() end
|
|
end
|
|
end
|
|
}
|
|
game:play()
|