g | x | w | all
Bytes Lang Time Link
1282 2048 256250805T022813Zuser1291
3340Ruby140729T201423ZMartin E

2 2048 256 128 128 64 16 32 2 8 4 8 0 0 0 0

Ruby, Into the Corner, Score: 3340

Here is a very simple strategy to kick this off. I do have an idea for a (near) perfect score, but I'm having trouble formalising it, so here is something simple to get things going.

def slide board, dir
    case dir
    when 'U'
        i0 = 0
        i_stride = 1
        i_dist = 4
    when 'D'
        i0 = 15
        i_stride = -1
        i_dist = -4
    when 'L'
        i0 = 0
        i_stride = 4
        i_dist = 1
    when 'R'
        i0 = 15
        i_stride = -4
        i_dist = -1
    end

    4.times do |x|
        column = []
        top_merged = false
        4.times do |y|
            tile = board[i0 + x*i_stride + y*i_dist]
            next if tile == 0
            if top_merged || tile != column.last
                column.push tile
                top_merged = false
            else
                column[-1] *= 2
                top_merged = true
            end
        end

        4.times do |y|
            board[i0 + x*i_stride + y*i_dist] = column[y] || 0
        end
    end

    board
end

def advance board
    if board.reduce(:*) > 0
        return board, board
    end

    16.times do |i|
        if board[15-i] == 0
            board[15-i] = 4
            break
        end
    end

    spawned = board.clone

    # Attention, dirty dirty hand-tweaked edge cases to avoid
    # the inevitable for a bit longer. NSFS!
    if board[11] == 8 && (board[12..15] == [32, 16, 4, 4] ||
                          board[12..15] == [16, 16, 4, 4] && board[8..10] == [256,64,32]) || 
       board[11] == 16 && (board[12..15] == [32, 8, 4, 4] || 
                           board[12..15] == [4, 32, 8, 8] || 
                           board[12..15] == [4, 32, 0, 4])

        dir = 'R'
    elsif board[11] == 16 && board[12..15] == [4, 4, 32, 4] ||
          board[11] == 8 && board[12..15] == [0, 4, 32, 8]
        dir = 'U'
    else
        dir = (board.reduce(:+)/4).even? ? 'U' : 'L'
    end

    board = slide(board, dir)

    if board == spawned
        dir = dir == 'U' ? 'L' : 'U'
        board = slide(board, dir)
    end
    return spawned, board
end

The advance function is the one your asking for. It takes a board as 1d array and returns the board after the tile has been spawned and after the move has been made.

You can test it with this snippet

board = [0]*16
loop do
    spawned, board = advance(board)
    board.each_slice(4) {|row| puts row*' '}
    puts
    break if board[15] > 0
end

puts "Score: #{board.reduce :+}"

The strategy is very simple, and is the one I actually used to skip to the 128 when I was playing 2048 myself: just alternate between up and left. To make this work for as long as possible, new 4s are spawned in the bottom right corner.

EDIT: I've added a hard coded switch to go right a few times at specific steps just before the end, which actually lets me reach 1024. This is getting somewhat out of hand though, so I'll stop with this for now and think about a generally better approach tomorrow. (Honestly, the fact that I can increase my score by a factor of 4 by adding hand-tweaked hacks only tells me that my strategy is crap.)

This is the board you end up with

1024 512 256 128
 512 256 128  16
 256 128  64   8
   8  32   8   4