Create a simple 2048 game clone

  • 2048 is an incredibly fun and addictive game in which the goal is to create a tile with 2048 on it.

    Here's a short description of the game:

    Pressing an arrow key will slide all the blocks in the stage in that direction. For example, if x represents a block, and you pressed the up arrow in this case:


    Then the board would become


    Furthermore, the blocks are numbered, starting at 2. If two of the same numbered blocks are moved together, they will merge into the next number. For example, pressing "up" on this board:


    Would create this:


    And then after pressing "right," it would become ..44, and therefore pressing right again would create an "8" block, and so on.

    Each turn, a new "2" block is created on a random open square. (It's actually not always a "2," but for simplicity let's keep it at that.) If there are no possible moves left (i.e., the board is full and you can't merge anything), the game is lost, and if a 2048 block is created, you win!

    Your challenge is to recreate this game, golfed!

    • For edge-cases, such as pressing "right" on this board:


      you must merge the tiles closest to the edge of the arrow key pressed. For example, this would become ..24, because the second and third "2"s are the closest to the right edge.

    • If the player presses an invalid move (such as "up" on a board like 2.2. / .... / .... / ....), you must ignore the move.

    • Moves can be accepted in any way, such as clicking, arrow keys, ULRD, etc.

    • The tiles must all be the same shape—a "1024" tile should be the same size as a "2" tile.

    • The tiles must be separated in some way. For example, |1024| 2|1024|1024| is a valid example of a row (assuming that the tiles are squares), while 1024 210241024 is not.

    • You must output "you win" if the player creates a 2048 tile, or "you lose" if there are no valid moves left.

    • This is , so the shortest code in bytes will win!

    Instead of accepting either rows of single characters (first five examples) and/or separated tiles (last one), why not assign ascending powers of two to individual characters to normalize the output?

    @millinon Because it's supposed to be as similar as possible to the actual 2048 game (it would make the title meaningless), and it would remove some of the challenge.

    "*If there are no possible merges left, the game is lost*" Shouldn't there be an "and the board is full" in there somewhere?

    does space suffice as a tile separator?

    If the starting board is a single `2`, no merges are possible. Does that mean the task is to render a 4x4 square with a random 2 inside, and then the message "you lose"?

    @Peter `s/merge/move/` :-P Edited

    @Jan Yes, space is a valid separator.

    Funny how all your questons get a ton of votes, but not many answers.

    @Doorknob Actually it is always a 2 on a random position (i played it to see how it worked) but it can be a 4 when the random position already contains a 2. At least thats what it seemed to be.

    @TheDoc I've been trying to post more interesting and difficult challenges; I'm beginning to feel more and more that challenges you can complete in only 5 minutes or so just aren't as fun.

    @Teun Well, for simplicity let's just assume it can only be a 2, since we're still not sure of the exact details (what happens if a 2 appears on a 8? Are there any other factors? Etc)

    @Doorknob probably find another cell :P but I agree.. My code is long enough already lol

    @TeunPronk The source code says: `var value = Math.random() < 0.9 ? 2 : 4;`, so on any given new tile there is a 10% chance it will be `4`.

    Now its your fault I´ve been playing 2048 the whole weekend and today the productivity of our office has dropped to 0.

    hmm... will Bash strike back here... hmm...

    @Doorknob I'm pretty sure that 2048 doesn't quit upon obtaining a 2048 tile. Many of my friends have gotten a 4096 tile or even higher. So making this as close as possible to the original would remove that restriction.

    @Doorknob Do the cells only need to always have the same shape, or does the number of rows (in a text based answer) used by a cell have to equal the number of columns? The currently accepted answer only keeps them constant, but not "square".

    @Adám Huh, the challenge claims that the tiles have to be congruent squares but apparently I didn't actually enforce that rule. I guess I can't really invalidate nearly all the answers, so I suppose I have to go with the former.

    @Doorknob In that case, you have a new winner ;-)

    Does outputting Colored squares count? @RohanRjhunjhunwala offered a no-deadline bounty on this (500 rep) for writing one in S.I.L.O.S, and an extra 250 with GUI. however, S.I.L.O.S only has rectangle/ellipse drawing. I could, however, draw different colored squares though.

  • Adám

    Adám Correct answer

    5 years ago

    APL (Dyalog APL), 153 150 167 156 155 151 bytes

    'you ',{2048∊⍵:'win'
    'lose'}4 4⍴0

    Prompts for move; 0=Left, 1=Up 2=Right, 3=Down

    Try it online!

    Ungolfed, with whitespace

    C ← ⎕UCS
    'you ', {
    2048 ∊ ⍵: 'win'
    n ← ⍵
    z ← 0 = ∊n
    (z / ∊n)[? +/z] ← 2
    ⎕ ← 4 ↑¨ ⍕¨n
    1 ∊ (⍉ 2 =⌿ n) , (2 =/ n) , 0 = n: ∇ {
    r ← R⍣¯1 ⎕UCS {
    t ← 2 /¨ ⍺⍺ 2 * ⍳16
    4 ↑ ⍺⍺ t ⎕R (1 ⌽ ∪¨t) ⍺⍺ ⍵ ~ 0
    }¨ R ⍵
    ⍵ ≡ r: ∇ ⍵
    } n
    } 4 4⍴0


    Blank lines indicate a newline, while blocks of lines belong on a single line

    'you ', "you" prepended to the result of the function {...

    2048 ∊ ⍵: 'win' if the argument (the board) contains 2048, then return "win"

    n ← ⍵ assign the right argument to n (so it may be modified in-place)

    z ← 0 = ∊nz gets the Boolean list where flattened z is 0

    (z / ∊n)z filters the flattened n (to get only the zeros)

    [? +/z] use a random number between 1 and the count of zeros (the sum of the Boolean z) to select which zero-containing position

    ← 2 gets a 2

    ⎕ ← output the

    4 ↑¨ each extended-to-length-4 (with spaces)

    ⍕¨n string representation of each number

    1 ∊ if any of the following are found;

    (⍉2=⌿n) pairwise vertical equalities (transposed to be concatenable)

    , or (concatenated to)

    (2=/n) pairwise horizontal equalities

    , or (concatenated to)

    0=n zeros

    : then:

     call this function on the result of the function {...

    R ←R (for Rows of Rotated) is

     the split-into-rows

    ⍉∘⌽⍣⎕ prompt for numeric input, then rotate (literally mirror horizontally, then transpose) the argument (the board) –90° times the inputted number

    r ←r (for result) gets

    R⍣¯1 the inverse of R (rotate back, then merge rows into matrix) applied to the result of the function ⎕UCS{... (where ⍺⍺ means convert to/from UCS points)

    t ←t gets

    2 /¨ two of each of

    ⍺⍺ the characters corresponding to the code points

    2 * ⍳16 2¹, 2², 2³,... 2¹⁶

    4↑ pad with zeros on the right until length 4

    C convert the following UCS characters to code points

    t ⎕R (1 ⌽ ∪¨t) regex replace each pair t with the unique characters from the next t on the right

    C ⍵~0 the argument (board) without zeros (compacted to the left), then converted to UCS code points

     [end of function] applied to each of

    R ⍵R applied to the argument (the board)

    ⍵ ≡ r: if the argument (the old board state) is identical to r (new board state), then:

    ∇⍵ call this function on the unmodified argument (because the user made an invalid move), else

    r return r (the new board state)

    } n [end of function] applied to n (the new board state), else

    'lose' return "lose"

    } 4 4 ⍴ 0 [end of function] applied to a 4-by-4 table of zeros (the initial state)

License under CC-BY-SA with attribution

Content dated before 7/24/2021 11:53 AM