Skip to content

Instantly share code, notes, and snippets.

@dermotbalson
Created July 11, 2014 09:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dermotbalson/c5d566720c24afc54238 to your computer and use it in GitHub Desktop.
Save dermotbalson/c5d566720c24afc54238 to your computer and use it in GitHub Desktop.
Threes part 2
function setup()
Settings()
CreateBoard()
Initialise()
state=states.PLAY --NEW
end
function Settings()
states={PLAY=1,END=2} --NEW
dragXY=nil
moves={vec2(-1,0),vec2(1,0),vec2(0,-1),vec2(0,1)}
moveText={"Left","Right","Down","Up"}
cellWidth,cellHeight,cellGap,textSize=100,133,10,48
boardValues={ [0]={0,0,0},
[1]={color(255),color(0,0,255),0},
[2]={color(255),color(255,0,0),0},
[3]={color(0),color(255),3},
[6]={color(0),color(255),9},
[12]={color(255,0,0),color(255),27},
[24]={color(255,0,0),color(255),81},
[48]={color(255,0,0),color(255),243},
[96]={color(255,0,0),color(255),729},
[192]={color(255,0,0),color(255),2187},
[384]={color(255,0,0),color(255),6561}}
end
function CreateBoard()
imgBoard=image(cellWidth*4+cellGap*5,cellHeight*4+cellGap*5)
setContext(imgBoard)
background(150, 192, 211, 255)
fill(177, 199, 210, 255)
local w=cellGap
for r=1,4 do
local h=cellGap
for c=1,4 do
rect(w,h,cellWidth,cellHeight)
h=h+cellHeight+cellGap
end
w=w+cellWidth+cellGap
end
setContext()
GetNextTile()
end
function Initialise()
--create 9 random tiles valued 1,2 or 3 and put them somewhere in the table called board
--board is a 4x4 table
--start off by creating an empty 4x4 table with all values = 0
board={}
for i=1,4 do
board[i]={0,0,0,0}
end
--now create the initial tiles
for i=1,9 do
local n=RandInt(3)
while true do
local r=RandInt(4)
local c=RandInt(4)
if board[c][r]==0 then
board[c][r]=n
break
end
end
end
NextTile=RandInt(3) --get the next tile to be added so we can show it to the player
--calculate the position of each tile on the screen
--first calculate bottom left position of board
bottomPos=vec2(WIDTH/2-cellWidth*2-cellGap*2.5,HEIGHT/2-cellHeight*2-cellGap*2.5)
boardPos={} --table to hold positions
for c=1,4 do
boardPos[c]={}
for r=1,4 do
boardPos[c][r]=vec2(bottomPos.x+(cellWidth+cellGap)*(c-1)+cellGap,
bottomPos.y+(cellHeight+cellGap)*(r-1)+cellGap)
end
end
nextTilePos=vec2(bottomPos.x-cellWidth-10,HEIGHT/2)
end
function draw()
background(135, 187, 213, 255)
DrawBoard()
end
function DrawBoard()
--draw board itself
sprite(imgBoard,WIDTH/2,HEIGHT/2)
--draw the tiles
for c=1,4 do
for r=1,4 do
if board[c][r]>0 then
DrawTile(boardPos[c][r],board[c][r])
end
end
end
--show next tile to come
DrawTile(nextTilePos,NextTile)
--show score --NEW
fontSize(24)
fill(color(0,0,255))
text("Score: " .. GetScore(),bottomPos.x+cellWidth*2,bottomPos.y-50)
if state==states.END then
fontSize(72)
fill(0,255,0)
text("Game Over\nTouch to Restart",WIDTH/2,HEIGHT/2)
end
end
function RandInt(a) --returns random integer between 1 and b (inclusive)
return math.floor(math.random()*a)+1
end
function DrawTile(p,v)
fill(boardValues[v][2])
rect(p.x,p.y,cellWidth,cellHeight)
fill(boardValues[v][1])
font("ArialRoundedMTBold")
fontSize(textSize)
text(v,p.x+cellWidth/2,p.y+cellHeight/2)
end
function GetScore(b,loadBlanks) --all NEW
loadBlanks=loadBlanks or false
b=b or board
blanks=0
local score=0
for c=1,4 do
for r=1,4 do
score=score+boardValues[b[c][r]][3]
if b[c][r]==0 then blanks=blanks+1 end
end
end
if loadBlanks then score=score*16/(16-blanks) end
return score
end
function touched(t) --all NEW
if t.state==BEGAN then --Started dragging (or touched a button)
if state==states.END then
Initialise()
state=states.PLAY
else
--reset movement variables
dragXY=vec2(t.x,t.y)
end
elseif t.state==ENDED and dragXY then --Ended
local dx=math.abs(t.x-dragXY.x)
local dy=math.abs(t.y-dragXY.y)
local d=dx-dy --is X or Y movement larger
local m=0
if d>0 then --X movement is larger
if dx<cellWidth/2 then return end
if t.x>dragXY.x then m=vec2(1,0) else m=vec2(-1,0) end
elseif d<0 then --Y movement is larger
if dy<cellHeight/2 then return end
if t.y>dragXY.y then m=vec2(0,1) else m=vec2(0,-1) end
end
MoveCells(m)
dragXY=nil
end
end
function MoveCells(m) --all NEW
local r1,r2,r3=1,4,1
local c1,c2,c3=1,4,1
if m.x<0 then c1,c2,c3=2,4,1
elseif m.x>0 then c1,c2,c3=3,1,-1
elseif m.y<0 then r1,r2,r3=2,4,1
elseif m.y>0 then r1,r2,r3=3,1,-1
end
for c=c1,c2,c3 do
for r=r1,r2,r3 do
if board[c][r]>0 then
if board[c+m.x][r+m.y]==0 then
board[c+m.x][r+m.y]=board[c][r]
board[c][r]=0
elseif (board[c+m.x][r+m.y]+board[c][r]==3) or
(board[c+m.x][r+m.y]==board[c][r] and board[c][r]>2) then
board[c+m.x][r+m.y]=board[c+m.x][r+m.y]+board[c][r]
board[c][r]=0
elseif board[c+m.x][r+m.y]==board[c][r] and board[c][r]>2 then
board[c+m.x][r+m.y]=board[c+m.x][r+m.y]+board[c][r]
board[c][r]=0
end
end
end
end
--add new cell at edge, get cell location
q={} --list of blank cells
a=nil
if m.x~=0 then
for r=1,4 do
if board[c2][r]==0 then table.insert(q,r) end
end
if #q>0 then a=vec2(c2,q[RandInt(#q)]) end
elseif m.y~=0 then
for c=1,4 do
if board[c][r2]==0 then table.insert(q,c) end
end
if #q>0 then a=vec2(q[RandInt(#q)],r2) end
end
if a then
board[a.x][a.y]=NextTile
GetNextTile()
end
local mov=CheckAvailableMoves()
if #mov==0 then state=states.END end
end
function CheckAvailableMoves() --all NEW
-- check for end of game
mov={}
--check if any blank squares left, if so, we aren't done
for c=1,4 do
for r=1,4 do
if board[c][r]==0 then
return {1,2,3,4} --we can move all four ways
end
end
end
--check if matching pairs are adjacent (or 1 & 2)
if #mov==0 then
for c=1,4 do
for r=2,4 do
if (board[c][r]>2 and board[c][r]==board[c][r-1]) or board[c][r]+board[c][r-1]==3 then
mov={3,4}
break
end
end
if #mov>0 then break end
end
for r=1,4 do
for c=2,4 do
if (board[c][r]>2 and board[c][r]==board[c-1][r]) or board[c][r]+board[c-1][r]==3 then
table.insert(mov,1,1)
table.insert(mov,2,2)
break
end
end
if #mov>0 and mov[1]==1 then break end
end
end
return mov
end
function GetNextTile() --all NEW
NextTile=RandInt(3)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment