-- 2048 Game for SimpleOS
-- CC: Tweaked compatible
local w, h = term.getSize()
-- Game settings
local gridSize = 4
local cellWidth = 6
local startX = math.floor((w - gridSize * cellWidth) / 2)
local startY = 4
-- Game state
local grid = {}
local score = 0
local bestScore = 0
local gameOver = false
local gameWon = false
-- Colors for tiles
local tileColors = {
[2] = colors.white,
[4] = colors.lightGray,
[8] = colors.orange,
[16] = colors.orange,
[32] = colors.red,
[64] = colors.red,
[128] = colors.yellow,
[256] = colors.yellow,
[512] = colors.yellow,
[1024] = colors.yellow,
[2048] = colors.lime
}
local textColors = {
[2] = colors.black,
[4] = colors.black,
[8] = colors.white,
[16] = colors.white,
[32] = colors.white,
[64] = colors.white,
[128] = colors.white,
[256] = colors.white,
[512] = colors.white,
[1024] = colors.white,
[2048] = colors.white
}
-- Initialize grid
local function initGrid()
grid = {}
for y = 1, gridSize do
grid[y] = {}
for x = 1, gridSize do
grid[y][x] = 0
end
end
score = 0
gameOver = false
gameWon = false
end
-- Add random tile
local function addRandomTile()
local empty = {}
for y = 1, gridSize do
for x = 1, gridSize do
if grid[y][x] == 0 then
table.insert(empty, {x = x, y = y})
end
end
end
if #empty > 0 then
local pos = empty[math.random(#empty)]
grid[pos.y][pos.x] = math.random(10) == 1 and 4 or 2
end
end
-- Check if moves available
local function movesAvailable()
for y = 1, gridSize do
for x = 1, gridSize do
if grid[y][x] == 0 then return true end
if x < gridSize and grid[y][x] == grid[y][x+1] then return true end
if y < gridSize and grid[y][x] == grid[y+1][x] then return true end
end
end
return false
end
-- Move tiles in direction
local function move(dx, dy)
local moved = false
local merged = {}
for y = 1, gridSize do
merged[y] = {}
for x = 1, gridSize do
merged[y][x] = false
end
end
local startX, endX, stepX = 1, gridSize, 1
local startY, endY, stepY = 1, gridSize, 1
if dx > 0 then startX, endX, stepX = gridSize, 1, -1 end
if dy > 0 then startY, endY, stepY = gridSize, 1, -1 end
for y = startY, endY, stepY do
for x = startX, endX, stepX do
if grid[y][x] ~= 0 then
local newX, newY = x, y
while true do
local nextX = newX + dx
local nextY = newY + dy
if nextX < 1 or nextX > gridSize or nextY < 1 or nextY > gridSize then
break
end
if grid[nextY][nextX] == 0 then
newX, newY = nextX, nextY
elseif grid[nextY][nextX] == grid[y][x] and not merged[nextY][nextX] then
newX, newY = nextX, nextY
merged[newY][newX] = true
break
else
break
end
end
if newX ~= x or newY ~= y then
moved = true
if grid[newY][newX] == grid[y][x] then
grid[newY][newX] = grid[y][x] * 2
score = score + grid[newY][newX]
if score > bestScore then bestScore = score end
if grid[newY][newX] == 2048 then gameWon = true end
else
grid[newY][newX] = grid[y][x]
end
grid[y][x] = 0
end
end
end
end
return moved
end
-- Draw a tile
local function drawTile(x, y, value)
local screenX = startX + (x - 1) * cellWidth
local screenY = startY + (y - 1) * 2
local bgColor = tileColors[value] or colors.purple
local fgColor = textColors[value] or colors.white
if value == 0 then bgColor = colors.gray end
term.setBackgroundColor(bgColor)
term.setCursorPos(screenX, screenY)
term.write(string.rep(" ", cellWidth))
term.setCursorPos(screenX, screenY + 1)
term.write(string.rep(" ", cellWidth))
if value > 0 then
term.setTextColor(fgColor)
local str = tostring(value)
local offset = math.floor((cellWidth - #str) / 2)
term.setCursorPos(screenX + offset, screenY)
term.write(str)
end
end
-- Draw game
local function draw()
term.setBackgroundColor(colors.black)
term.clear()
-- Title
term.setTextColor(colors.yellow)
term.setCursorPos(math.floor(w/2) - 2, 1)
term.write("2048")
-- Score
term.setTextColor(colors.white)
term.setCursorPos(2, 2)
term.write("Score: " .. score)
term.setCursorPos(w - 12, 2)
term.write("Best: " .. bestScore)
-- Draw grid
for y = 1, gridSize do
for x = 1, gridSize do
drawTile(x, y, grid[y][x])
end
end
-- Controls
term.setBackgroundColor(colors.black)
term.setTextColor(colors.gray)
term.setCursorPos(2, startY + gridSize * 2 + 1)
term.write("Arrow keys: Move [Q] Quit [R] Restart")
end
-- Game over screen
local function showGameOver()
term.setBackgroundColor(colors.black)
term.setTextColor(colors.red)
term.setCursorPos(math.floor(w/2) - 4, startY + gridSize)
term.write("GAME OVER!")
end
-- Win screen
local function showWin()
term.setBackgroundColor(colors.black)
term.setTextColor(colors.lime)
term.setCursorPos(math.floor(w/2) - 4, startY + gridSize)
term.write("YOU WIN!")
end
-- Main game loop
local function run()
initGrid()
addRandomTile()
addRandomTile()
while true do
draw()
if not movesAvailable() then
gameOver = true
showGameOver()
elseif gameWon then
showWin()
end
local event, key = os.pullEvent("key")
local moved = false
if key == keys.up then
moved = move(0, -1)
elseif key == keys.down then
moved = move(0, 1)
elseif key == keys.left then
moved = move(-1, 0)
elseif key == keys.right then
moved = move(1, 0)
elseif key == keys.r then
initGrid()
addRandomTile()
addRandomTile()
elseif key == keys.q then
return
end
if moved then
addRandomTile()
end
end
end
run()