Skip to content

153. Recreating the Threes game app – part 2

July 14, 2014

Now we’ll get Threes to play properly, so you can swipe to slide the tiles until you run out of space, and we will show a score.

Game states

If you haven’t heard of game states before, think about what is shown on the screen. When you start the game, there will be

  • a splash screen, then
  • a menu, then
  • the game itself, and when it’s over,
  • the final score

Each of these is drawn differently, so you need to tell Codea which one to draw, and you can do this easily with a state variable that holds a number or string.

So you could have a variable state, and if it equals 1, then we show the menu, whereas if it equals 2, we are playing, and Codea can use if tests on state to figure out what to draw.

I did it a little differently here. In the Settings function, I defined just two states (because I’m not bothering with splash screen, menus or end of game screens) in a table


So when I write state=states.PLAY, it is the same as writing state=1, except that anyone reading the code can see more easily what I’m doing.¬† That’s the only reason for doing this, to make the code readable and reduce errors.

In the draw function, I’ve included “Game Over” text that is written across the board, with this code

    if state==states.END then
        text("Game Over\nTouch to Restart",WIDTH/2,HEIGHT/2)

So if state == states.END, then we draw “Game Over”.

And when people talk about “finite state machines” in game programming, this is pretty much what they mean.


This is pretty easy. We just run through the values of each tile, and look up the score in the boardValues table.

function GetScore()
    local score=0
    for c=1,4 do
        for r=1,4 do
    return score
end if a tile value in board[c][r]=6, then boardValues[6][3] = 9, and we add it to the score.

..and there is a little code in DrawBoard to show it on screen, which I haven’t bothered showing here.

Moving – handling swiping

To handle user swiping, I have defined these variables in Settings 


dragXY will store the x,y start position of the swipe, and I will compare this with the position at the end of the swipe, to help me decide which direction it was in.

I’ve defined the four possible moves as one tile to the left, right, down or up (in each vec2, the first number is the x movement, sideways, and the second is the y movement, vertical). You’ll see how we use these below. I also defined a text description of each move in case I want to print it out for some reason.

Here is the touch handling. See the numbered comments and explanations underneath.

function touched(t)
    if t.state==BEGAN then --Started dragging --[1]
        if state==states.END then --[2]
            --reset movement variables  --[3]
    elseif t.state==ENDED and dragXY then --[4]
        local dx=math.abs(t.x-dragXY.x)  --[5]
        local dy=math.abs(t.y-dragXY.y)
        local m=nil                               --[6]
        if dx>dy then  --X movement is larger       --[7]
            if dx<cellWidth/2 then return end     --[8]
            if t.x>dragXY.x then m=vec2(1,0) else m=vec2(-1,0) end --[9]]
        else 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
        if m then MoveCells(m) end  --[10]

[1] – when you first touch the screen, the touch state will be BEGAN. If you don’t know this, you may want to read up on how basic touch works.

[2] – if the game is finished, then this touch will restart it. We initialise the board tiles again, and set the game state to play.

[3] – if we are playing the game, then the player has started to swipe. Store the x,y position in dragXY

[4] – if the touch has ended, and if we have values in dragXY, then we need to process the swipe.

[5] – calculate the absolute change in x and y position

[6] – m will store the final move, start it with nothing

[7] – if x change is larger,we’ll move left or right

[8] – check if we’ve swiped at least half a tile width. If not, it doesn’t count, exit

[9] – set m based on whether the change is positive or negative

[10] – if we have a move, make it

Moving tiles

Suppose we have swiped left. The left hand column can’t go anywhere, so we look at the second column, and if has a number, and

  • if the square to the left is blank, we move the number to the left, else if
  • the total of the number and the square to the left is 3, we put 3 in the cell to the left, else if
  • the cell to the left has the same number, and both are 3 or larger, we add them together in the left hand cell

and that is what the MoveCells function does.  Of course, if the swipe is upwards, then it has to check the rows instead of columns starting from the second row and working down. At the end, it runs CheckAvailableMoves to see if there are any valid moves left. If not, it sets state = states.Ended.

I won’t go through these two functions in detail, because there is nothing clever about them, and the code is a bit messy.

Here is the code so far.

Next, we’ll try some monte carlo simulation to figure what is the best move to make. This will be the fun part.


From → Games

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: