2048: Difference between revisions

57,285 bytes added ,  16 days ago
m
→‎{{header|FutureBasic}}: Remove FutureBasic 'Output' label
No edit summary
m (→‎{{header|FutureBasic}}: Remove FutureBasic 'Output' label)
 
(38 intermediate revisions by 16 users not shown)
Line 6:
Implement a 2D sliding block puzzle game where blocks with numbers are combined to add their values.
 
 
The rules are that on each turn the player must choose a direction (up, down, left or right) and all tiles move as far as possible in that direction, some more than others. Two adjacent tiles (in that direction only) with matching numbers combine into one bearing the sum of those numbers. A move is valid when at least one tile can be moved, if only by combination. A new tile with the value of 2 is spawned at the end of each turn at a randomly chosen empty square, if there is one. To win, the player must create a tile with the number 2048. The player loses if no valid moves are possible.
;Rules of the game:
:*   The rules are that on each turn the player must choose a direction   (up, down, left or right).
:*   All tiles move as far as possible in that direction, some move more than others.
:*   Two adjacent tiles (in that direction only) with matching numbers combine into one bearing the sum of those numbers.
:*   A move is valid when at least one tile can be moved, including by combination.
:*   A new tile is spawned at the end of each turn at a randomly chosen empty square   (if there is one).
:*   Most of the time, a new '''2''' is to be added, but occasionally ('''10%''' of the time), a '''4'''.
:*   To win, the player must create a tile with the number '''2048'''.
:*   The player loses if no valid moves are possible.
 
 
The name comes from the popular open-source implementation of this game mechanic, [https://gabrielecirulli.github.io/2048/ 2048].
 
Requirements:
* "Non-greedy" movement. The tiles that were created by combining other tiles should not be combined again during the same turn (move). That is to say that moving the tile row of
 
;Requirements:
[2][2][2][2]
* &nbsp; "Non-greedy" movement.<br>&nbsp; The tiles that were created by combining other tiles should not be combined again during the same turn (move).<br>&nbsp; That is to say, that moving the tile row of:
 
<big><big> [2][2][2][2] </big></big>
to the right should result in
 
:: to the right should result in:
......[4][4]
 
<big><big> ......[4][4] </big></big>
and not
 
:: and not:
.........[8]
 
<big><big> .........[8] </big></big>
* "Move direction priority". If more than one variant of combining is possible, move direction shall indicate which combination will take effect. For example, moving the tile row of
 
* &nbsp; "Move direction priority".<br>&nbsp; If more than one variant of combining is possible, move direction shall indicate which combination will take effect. <br>&nbsp; For example, moving the tile row of:
...[2][2][2]
 
<big><big> ...[2][2][2] </big></big>
to the right should result in
 
:: to the right should result in:
......[2][4]
 
<big><big> ......[2][4] </big></big>
and not
 
:: and not:
......[4][2]
 
<big><big> ......[4][2] </big></big>
* Adding a new tile on a blank space. Most of the time, a new "2" is to be added and occasionally (10% of the time) - a "4".
 
* Check for valid moves. The player shouldn't be able to skip their turn by trying a move that doesn't change the board.
 
* Win condition.
 
* Lose condition.
* &nbsp; Check for valid moves. The player shouldn't be able to gain new tile by trying a move that doesn't change the board.
* &nbsp; Check for a win condition.
* &nbsp; Check for a lose condition.
<br><br>
 
=={{header|AArch64 Assembly}}==
{{works with|as|Raspberry Pi 3B version Buster 64 bits}}
<syntaxhighlight lang="aarch64 assembly">
<lang AArch64 Assembly>
/* ARM assembly AARCH64 Raspberry PI 3B */
/* program 2048_64.s */
Line 1,093 ⟶ 1,106:
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
</syntaxhighlight>
</lang>
=={{header|Ada}}==
{{works with|GNAT}}
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO; use Ada.Text_IO;
with System.Random_Numbers;
procedure Play_2048 is
Line 1,133 ⟶ 1,146:
when others => Invalid),
when others => Invalid);
 
-- ----- Game data
function Random_Int is new System.Random_Numbers.Random_Discrete(Integer);
Line 1,144 ⟶ 1,157:
Score : Natural;
Generator : System.Random_Numbers.Generator;
 
-- ----- Displaying the board
procedure Display_Board is
Line 1,163 ⟶ 1,176:
Put_Line("Score =" & Score'Img);
end Display_Board;
 
-- ----- Game mechanics
procedure Add_Block is
Line 1,182 ⟶ 1,195:
end loop;
end Add_Block;
 
procedure Reset_Game is
begin
Line 1,191 ⟶ 1,204:
Add_Block;
end Reset_Game;
 
-- Moving and merging will always be performed leftward, hence the following transforms
function HFlip (What : in t_Row) return t_Row is
Line 1,207 ⟶ 1,220:
end return;
end Transpose;
 
-- For moving/merging, recursive expression functions will be used, but they
-- can't contain statements, hence the following sub-function used by Merge
Line 1,216 ⟶ 1,229:
return (1 => 0);
end Add_Blank;
 
function Move_Row (What : in t_List) return t_List is
(if What'Length = 1 then What
Line 1,222 ⟶ 1,235:
then Move_Row(What(What'First+1..What'Last)) & (1 => 0)
else (1 => What(What'First)) & Move_Row(What(What'First+1..What'Last)));
 
function Merge (What : in t_List) return t_List is
(if What'Length <= 1 or else What(What'First) = 0 then What
Line 1,228 ⟶ 1,241:
then (1 => 2*What(What'First)) & Merge(What(What'First+2..What'Last)) & Add_Blank(What(What'First))
else (1 => What(What'First)) & Merge(What(What'First+1..What'Last)));
 
function Move (What : in t_Board) return t_Board is
(Merge(Move_Row(What(1))),Merge(Move_Row(What(2))),Merge(Move_Row(What(3))),Merge(Move_Row(What(4))));
 
begin
System.Random_Numbers.Reset(Generator);
Reset_Game;
Main_Game_LoopMain_Loop: loop
Display_BoardReset_Game;
Game_Loop: loop
case Get_Keystroke is
when Restart => Reset_Game;
when Quit => exit Main_Game_Loop;
when Left => New_Board := Move(Board);
when Right => New_Board := VFlip(Move(VFlip(Board)));
when Up => New_Board := Transpose(Move(Transpose(Board)));
when Down => New_Board := Transpose(VFlip(Move(VFlip(Transpose(Board)))));
when others => null;
end case;
 
if New_Board = Board then
Put_Line ("Invalid move...");
elsif (for some Row of New_Board => (for some Cell of Row => Cell = 2048)) then
Display_Board;
Put_Linecase ("WinGet_Keystroke !");is
when Restart => exit Main_Game_LoopGame_Loop;
when Quit => exit Main_Loop;
else
Board : when Left => New_Board := Move(Board);
when Right => New_Board := VFlip(Move(VFlip(Board)));
Add_Block; -- OK since the board has changed
when Up => New_Board := Transpose(Move(Transpose(Board)));
if Blanks = 0
andwhen thenDown (for all Row in=> 1..4New_Board :=> Transpose(VFlip(Move(VFlip(Transpose(Board)))));
when others (for all Column in 1..3 => null;
end case;
(Board(Row)(Column) /= Board(Row)(Column+1))))
and then (for all Row in 1..3 =>
if New_Board = Board then
(for all Column in 1..4 =>
Put_Line ("Invalid move...");
(Board(Row)(Column) /= Board(Row+1)(Column)))) then
elsif (for some Row of New_Board => (for some Cell of Row => Cell = 2048)) then
Display_Board;
Put_Line ("LostWin !");
exit Main_Game_LoopMain_Loop;
else
Board := New_Board;
Add_Block; -- OK since the board has changed
if Blanks = 0
and then (for all Row in 1..4 =>
(for all Column in 1..3 =>
(Board(Row)(Column) /= Board(Row)(Column+1))))
and then (for all Row in 1..3 =>
(for all Column in 1..4 =>
(Board(Row)(Column) /= Board(Row+1)(Column)))) then
Display_Board;
Put_Line ("Lost !");
exit Main_Loop;
end if;
end if;
end ifloop Game_Loop;
end loop Main_Game_LoopMain_Loop;
end Play_2048;</lang>
</syntaxhighlight>
{{out}}
<pre>+----+----+----+----+
Line 1,283 ⟶ 1,300:
 
=={{header|ALGOL 68}}==
<langsyntaxhighlight lang="algol68">
main:(
INT side = 4;
Line 1,426 ⟶ 1,443:
lose: print(("you lose!", new line))
)
</syntaxhighlight>
</lang>
=={{header|Amazing Hopper}}==
<pre>
VERSION 1: "Hopper" flavour.
</pre>
<syntaxhighlight lang="amazing hopper">
#context-free select Position of aleatory tail
#context-free show Table
#context-free chek Winner or Game Over
#context-free print Table structure
#proto MovingRightDown(_X_)
#proto MovingLeftUp(_X_)
#proto checkPointLeftUp(_X_)
#proto checkPointRightDown(_X_)
#proto checkMoveRightDown(_X_)
#proto checkMoveLeftUp(_X_)
#define KUP 5
#define KDOWN 24
#define KLEFT 19
#define KRIGHT 4
#define KESCAPE 27
#define MOVEHORZ 1
#define MOVEVERT 0
#define equaltables(_X_,_Y_) _I_=1,\
__LOOP_ROW__:,\
_J_=1,\
__LOOP_COL__:,\
[_I_,_J_]get(_X_),get(_Y_),neq? do{{0},jmp(__OUT__LOOP__)},\
++_J_,{4,_J_}jle(__LOOP_COL__),\
++_I_,{4,_I_}jle(__LOOP_ROW__),\
{1},__OUT__LOOP__:,clear mark
#include <hopper.h>
 
main:
.ctrl c
contador de movimientos=0
score=0
table=0,{4,4}zeros array(table) // create table
oldTable=0, show Structure=1
/* define initial positions */
{""}tok sep
select Position of aleatory tail
select Position of aleatory tail
home
hide cursor
show Table
c=0, go=1,swFin=1
 
/* game! */
__PLAY_GAME__:
if key pressed?
lastkey(c)
oldTable = table
switch(c)
case(KRIGHT) :: do{ _check Move Right Down(MOVEHORZ), exit }
case(KDOWN) :: do{ _check Move Right Down(MOVEVERT), exit }
case(KLEFT) :: do{ _check Move Left Up(MOVEHORZ), exit }
case(KUP) :: do{ _check Move Left Up(MOVEVERT), exit }
case(KESCAPE):: do{ go=0,swFin=0 }
end switch
kbfree
chek Winner or Game Over
{go}do{
if ( not( equal tables(oldTable, table) ) )
select Position of aleatory tail
++contador de movimientos
end if
show Table
}
end if
{go},jt(__PLAY_GAME__)
 
if ( {swFin} )
{" \LG","YOU WIN!!!\OFF"}
else
{" \LR","GAME OVER\OFF"}
end if
println
show cursor
exit(0)
 
.locals
Moving Right Down(tmpTab)
{tmpTab} compact,ht=0,cpy(ht), length,{4}sub,sizet=0,mov(sizet)
clear(tmpTab),{sizet}zerosarray(tmpTab)
{ht,tmpTab}array(CONCAT)
{tmpTab}
back
Moving Left Up(tmpTab)
{tmpTab} compact,clear(tmpTab),cpy(tmpTab), length,{4}sub,sizet=0,mov(sizet)
{sizet}zero?,not,do{ ht=0,{sizet}zerosarray(ht)
{ht,tmpTab}array(CONCAT) }
{tmpTab}
back
check Point Right Down(tmpTab)
v1=0,v2=0,tScore=0,totScore=0
for(k=4,{k}gthan(1),--k)
[k]get(tmpTab),mov(v1)
[{k}minus(1)]get(tmpTab),mov(v2)
if( {v1} eqto (v2) )
{v1,v2}add,cpy(tScore),[k]put(tmpTab),[{k}minus(1)]{0}put(tmpTab)
{tScore}plus(totScore),mov(totScore)
end if
next
{tmpTab,totScore}
back
check Move Right Down (_DIRECTION_)
tmpTab=0
for(i=1,{i}lethan(4),++i)
if ( {_DIRECTION_} ) // rows or cols??
[i,1:4] // rows!
else
[1:4,i] // cols!
end if
get(table), mov(tmpTab)
if( {tmpTab}stats(SUMMATORY) ) // exist numbers in the row??
clear mark
_Moving Right Down(tmpTab),mov(tmpTab) // move its!
clear mark
_check Point Right Down(tmpTab),plus(score),mov(score) // check score...
mov(tmpTab)
_Moving Right Down(tmpTab),mov(tmpTab) // move remanents!
if( {_DIRECTION_} )
[i,1:4]
else
[1:4,i]
end if
{tmpTab}, put(table)
end if
next
clear mark.
back
 
check Point Left Up(tmpTab)
v1=0,v2=0,tScore=0,totScore=0
for(k=1,{k}lthan(4),++k)
[k]get(tmpTab),mov(v1)
[{k}plus(1)]get(tmpTab),mov(v2)
if( {v1} eqto (v2) )
{v1,v2}add,cpy(tScore),[k]put(tmpTab),[{k}plus(1)]{0}put(tmpTab)
{tScore}plus(totScore),mov(totScore)
end if
next
{tmpTab,totScore}
back
 
check Move Left Up(_DIRECTION_)
tmpTab=0
for(i=1,{i}lethan(4),++i)
if( {_DIRECTION_} )
[i,1:4]
else
[1:4,i]
end if
get(table),mov(tmpTab)
if( {tmpTab}stats(SUMMATORY) ) // exist numbers in the row??
clear mark
_Moving Left Up(tmpTab),mov(tmpTab) // move its!
clear mark
_check Point Left Up(tmpTab),plus(score),mov(score) // check score...
mov(tmpTab)
_Moving Left Up(tmpTab),mov(tmpTab) // move remanents!
if( {_DIRECTION_} )
[i,1:4]
else
[1:4,i]
end if
{tmpTab},put(table)
end if
next
clear mark.
back
 
chek Winner or Game Over:
{table}gthan(0),xtonum,stats(SUMMATORY),{16} eq? do{{0}mov(go),{0}mov(swFin),back} // You loose!
{0}reshape(table),{2048,table}array(SCAN){0} neq? do{{0}mov(go),back} // you Win!
{4,4}reshape(table)
back
 
select Position of aleatory tail:
prec(-1)
__NO_VALID_POS__:
{10}rand, mulby(10),ceil,module(5),x=0,cpy(x),zero?,do{x=1}
{10}rand, mulby(10),ceil,module(5),y=0,cpy(y),zero?,do{y=1}
[x,y]get(table),jnz(__NO_VALID_POS__)
newTail=2
{1}rand,gthan(0.9), do{ newTail=4 }
{newTail},put(table), clear mark.
prec(0)
back
 
show Table:
tmpTable=0
{" ",6,table}xtostr,padcenter,mov(tmpTable)
// prepare colours of tiles
{"\BGLGR\BK \OFF"," 0 ",tmpTable} transform, mov(tmpTable)
{"\BGLGR\BK 2 \OFF"," 2 ",tmpTable} transform, mov(tmpTable)
{"\BGLGR\B 4 \OFF"," 4 ",tmpTable} transform, mov(tmpTable)
{"\BGLGR\B 8 \OFF"," 8 ",tmpTable} transform, mov(tmpTable)
{"\BGR\W 16 \OFF"," 16 ",tmpTable} transform, mov(tmpTable)
{"\BGY\BK 32 \OFF"," 32 ",tmpTable} transform, mov(tmpTable)
{"\BGB\W 64 \OFF"," 64 ",tmpTable} transform, mov(tmpTable)
{"\BGLM\BK 128 \OFF"," 128 ",tmpTable} transform, mov(tmpTable)
{"\BGG\W 256 \OFF"," 256 ",tmpTable} transform, mov(tmpTable)
{"\BGB\W 512 \OFF"," 512 ",tmpTable} transform, mov(tmpTable)
{"\BGR\W 1024 \OFF"," 1024 ",tmpTable} transform, mov(tmpTable)
{"\BGBK\W\ENF 2048 \OFF"," 2048 ",tmpTable} transform, mov(tmpTable)
 
// and PRINT!!
{show Structure} do{ print Table structure,{0} mov(show Structure) }
 
clear mark
scrx=2
for (i=1, {i}lethan(4),++i)
{2,scrx}goxy,[1,i]get(tmpTable),print
{4,scrx}goxy,[2,i]get(tmpTable),print
{6,scrx}goxy,[3,i]get(tmpTable),print
{8,scrx}goxy,[4,i]get(tmpTable),print
clear mark
scrx += 7
next
 
{"\BGB\W\ENF","\n\n\t 2 0 4 8 \OFF\n\n"}
{"Movimiento # ",contador de movimientos,", \INVSCORE=",score,"\OFF\n"}//,tmpTable}
println
 
back
 
print Table structure:
{"┌──────┬──────┬──────┬──────┐\n"},strtoutf8,
{"│ 2048 │ 2048 │ 2048 │ 2048 │\n"},strtoutf8,
{"├──────┼──────┼──────┼──────┤\n"},strtoutf8,
{"│ 2048 │ 2048 │ 2048 │ 2048 │\n"},strtoutf8,
{"├──────┼──────┼──────┼──────┤\n"},strtoutf8,
{"│ 2048 │ 2048 │ 2048 │ 2048 │\n"},strtoutf8,
{"├──────┼──────┼──────┼──────┤\n"},strtoutf8,
{"│ 2048 │ 2048 │ 2048 │ 2048 │\n"},strtoutf8,
{"└──────┴──────┴──────┴──────┘"},strtoutf8,
println
back
</syntaxhighlight>
{{out}}
<pre>
Begin play...
┌──────┬──────┬──────┬──────┐
│ │ │ 2 │ │
├──────┼──────┼──────┼──────┤
│ │ │ │ │
├──────┼──────┼──────┼──────┤
│ │ │ │ │
├──────┼──────┼──────┼──────┤
│ 2 │ │ │ │
└──────┴──────┴──────┴──────┘
2 0 4 8
 
Movimiento # 0, SCORE=0
 
</pre>
<pre>
Playing...
┌──────┬──────┬──────┬──────┐
│ │ 2 │ │ │
├──────┼──────┼──────┼──────┤
│ │ │ 2 │ 4 │
├──────┼──────┼──────┼──────┤
│ │ 2 │ 32 │ 128 │
├──────┼──────┼──────┼──────┤
│ │ 8 │ 4 │ 16 │
└──────┴──────┴──────┴──────┘
2 0 4 8
 
Movimiento # 90, SCORE=940
</pre>
<pre>
Game Over...
┌──────┬──────┬──────┬──────┐
│ 2 │ 16 │ 2 │ 4 │
├──────┼──────┼──────┼──────┤
│ 4 │ 128 │ 4 │ 8 │
├──────┼──────┼──────┼──────┤
│ 16 │ 8 │ 512 │ 4 │
├──────┼──────┼──────┼──────┤
│ 2 │ 4 │ 32 │ 2 │
└──────┴──────┴──────┴──────┘
2 0 4 8
 
Movimiento # 347, SCORE=5040
 
GAME OVER
$
</pre>
 
<pre>
VERSION 2: "Hopper-BASIC" flavour.
</pre>
<syntaxhighlight lang="amazing hopper">
 
// Definicion de "contextos"
#context-free select Position of aleatory tail
set Decimal (-1)
tSIZE=0,
Let( tSIZE := var(SIZE) Plus (1) )
__NO_VALID_POS__:
x=0, y=0
When( Is Zero? ( Ceil( Rand(10) Mul by(10) ) Module (tSIZE) » (x) )){ x = 1 }
When( Is Zero? ( Ceil( Rand(10) Mul by(10) ) Module (tSIZE) » (y) )){ y = 1 }
At Interval [x,y], Get (table), Goto If Not Zero(__NO_VALID_POS__)
newTail=2
When ( Rand(1) Is Gt (0.9) ) { newTail=4 }
Take( newTail ), and SPut(table).
set Decimal(0)
Return\\
 
#context-free check Winner or Game Over
When ( Summatory ( Val( var(table) Is Gt (0) ) ), Is Eq? ( var(SIZE) Mulby(SIZE) ) ) {
MStore( 0, go, swFin ), and Back // You loose!
}
ReDim( table, 0 ) // convierte en vector
When( Scan(1, 2048, table ) Is Not Eq? (0) ){
ReDim( table, SIZE, SIZE ), Let ( go:=0 ) and Back // You Win!
}
ReDim( table, SIZE, SIZE )
Return\\
 
#context-free show Table
tmpTable=0
Let ( tmpTable := CPad$(" ", 6, Str$(table)) )
Let ( tmpTable := Tran$("\BGLGR\BK \OFF"," 0 ", tmpTable) )
Let ( tmpTable := Tran$("\BGLGR\BK 2 \OFF"," 2 ", tmpTable) )
Let ( tmpTable := Tran$("\BGLGR\B 4 \OFF"," 4 ", tmpTable) )
Let ( tmpTable := Tran$("\BGLGR\B 8 \OFF"," 8 ", tmpTable) )
Let ( tmpTable := Tran$("\BGR\W 16 \OFF"," 16 ", tmpTable) )
Let ( tmpTable := Tran$("\BGY\BK 32 \OFF"," 32 ", tmpTable) )
Let ( tmpTable := Tran$("\BGB\W 64 \OFF"," 64 ", tmpTable) )
Let ( tmpTable := Tran$("\BGLM\BK 128 \OFF"," 128 ", tmpTable) )
Let ( tmpTable := Tran$("\BGG\W 256 \OFF"," 256 ", tmpTable) )
Let ( tmpTable := Tran$("\BGB\W 512 \OFF"," 512 ", tmpTable) )
Let ( tmpTable := Tran$("\BGR\W 1024 \OFF"," 1024 ", tmpTable) )
Let ( tmpTable := Tran$("\BGBK\W\ENF 2048 \OFF"," 2048 ", tmpTable) )
When( show Structure ) { print Table structure, and Let ( show Structure := 0 ) }
Clear Mark
scrx=2
For (i=1, var(i) Is Le (SIZE), ++i)
Locate in Column (scrx)
Locate in Row (2), At Interval [1,i], Print( Get (tmpTable) )
Locate in Row (4), At Interval [2,i], Print( Get (tmpTable) )
Locate in Row (6), At Interval [3,i], Print( Get (tmpTable) )
Locate in Row (8), At Interval [4,i], Print( Get (tmpTable) )
When( var(SIZE) Is Ge? (5) ) {Locate in Row (10), At Interval [5,i], Print( Get (tmpTable) )}
When( var(SIZE) Is Ge? (6) ) {Locate in Row (12), At Interval [6,i], Print( Get (tmpTable) )}
scrx += 7
Next
Clear Mark
Take( "\BGB\W\ENF","\n\n\t 2 0 4 8 \OFF\n\n",\
"Movimiento # ",contador de movimientos,", \INVSCORE=",score,"\OFF\n" )
and Print It
Return\\
 
#context-free print Table structure
Locate (1,1)
If ( var(SIZE) Is Eq? (4) )
Str2Utf8$("┌──────┬──────┬──────┬──────┐\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("├──────┼──────┼──────┼──────┤\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("├──────┼──────┼──────┼──────┤\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("├──────┼──────┼──────┼──────┤\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("└──────┴──────┴──────┴──────┘")
Else If( var(SIZE) Is Eq? (5) )
Str2Utf8$("┌──────┬──────┬──────┬──────┬──────┐\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("├──────┼──────┼──────┼──────┼──────┤\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("├──────┼──────┼──────┼──────┼──────┤\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("├──────┼──────┼──────┼──────┼──────┤\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("├──────┼──────┼──────┼──────┼──────┤\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("└──────┴──────┴──────┴──────┴──────┘")
Else If( var(SIZE) Is Eq? (6) )
Str2Utf8$("┌──────┬──────┬──────┬──────┬──────┬──────┐\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("├──────┼──────┼──────┼──────┼──────┼──────┤\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("├──────┼──────┼──────┼──────┼──────┼──────┤\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("├──────┼──────┼──────┼──────┼──────┼──────┤\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("├──────┼──────┼──────┼──────┼──────┼──────┤\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("├──────┼──────┼──────┼──────┼──────┼──────┤\n")
Str2Utf8$("│ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │ 2048 │\n")
Str2Utf8$("└──────┴──────┴──────┴──────┴──────┴──────┘")
End If
now Print It
Return\\
 
// definicion de prototipos:
#proto MovingRightDown(_X_)
#proto MovingLeftUp(_X_)
#proto checkPointLeftUp(_X_)
#proto checkPointRightDown(_X_)
#proto checkMoveRightDown(_X_)
#proto checkMoveLeftUp(_X_)
 
// definiciones varias:
#define KUP 5
#define KDOWN 24
#define KLEFT 19
#define KRIGHT 4
#define KESCAPE 27
#define MOVEHORZ 1
#define MOVEVERT 0
 
// archivo de inclusión de macros H-BASIC:
#include <hbasic.h>
 
Begin
Option Ctrl+C
Option Stack 16
contador de movimientos=0
score=0, SIZE=4
When( ArgCount, Is Eq? (2) ){ get ArgNumber(2,SIZE) }
 
If ( var(SIZE) Is Not Between?(4,includ,6,includ) )
Print("Usage: hopper 2048.bas [4(default)-6]\n")
Stop
End If
Dim (SIZE,SIZE) for Zeros Array (table)
 
oldTable=0, show Structure=1
/* define initial positions */
Token Sep("")
select Position of aleatory tail
select Position of aleatory tail
Cls
Hide Cursor
show Table
c=0, go=1,swFin=1
 
/* game! */
While ( go )
Let ( c:=GetCh )
oldTable = table
Switch(c)
Case(KRIGHT) { _check Move Right Down(MOVEHORZ), Exit }
Case(KDOWN) { _check Move Right Down(MOVEVERT), Exit }
Case(KLEFT) { _check Move Left Up(MOVEHORZ), Exit }
Case(KUP) { _check Move Left Up(MOVEVERT), Exit }
Case(KESCAPE){ go=0, swFin=0 }
End Switch
 
check Winner or Game Over
When( go ){
If ( are Not EqArray? (oldTable, table) ) //( not( equal tables(oldTable, table) ) )
select Position of aleatory tail
++contador de movimientos
End If
show Table
}
Wend
 
If ( swFin )
show Table
Print(" \LG","YOU WIN!!!\OFF")
Else
Print(" \LR","GAME OVER\OFF")
End If
Put a Newl
Show Cursor
End
 
Subrutines
 
Moving Right Down(tmpTab)
ht=0, sizet=0
Let( sizet := var(SIZE) Minus ( Length( Compact(tmpTab), Copy to (ht) ) ) )
If ( Is Not Zero?(sizet) )
Clear(tmpTab)
Dim (sizet) for Zeros Array (tmpTab)
Concat( ht,tmpTab )
End If
Return (tmpTab)
 
Moving Left Up(tmpTab)
sizet=0
Compact( tmpTab ),Clear(tmpTab) and Copy to (tmpTab); get Length It, Subtracted from (SIZE); then Move to (sizet)
//When( Is Not Zero?(sizet) ){
When( var(sizet) Is Not Zero? ){
ht=0
Dim (sizet) for Zeros Array (ht)
Concat( ht, tmpTab )
}
Return (tmpTab)
 
check Point Right Down(tmpTab)
v1=0,v2=0,tScore=0,totScore=0
For(k=SIZE, var(k) Is Gt (1), --k)
Set Interval [k] and Get (tmpTab); then Move to (v1)
Set Interval [ var(k) Minus(1)], Get(tmpTab), and Move to (v2)
If( var(v1) Is Eq? (v2) )
Add(v1,v2), Copy to(tScore);
At Interval [k] Put(tmpTab)
At Interval [ var(k) Minus(1) ], now Take(0); then Put (tmpTab)
Let( totScore := var(tScore) Plus (totScore) )
End If
Next
Take(tmpTab,totScore) and Return
 
check Move Right Down (_DIRECTION_)
tmpTab=0
For(i=1, while var(i) Is Le (SIZE), ++i)
If ( _DIRECTION_ ) // rows or cols??
Set Interval [i,1:SIZE] // rows!
Else
Set Interval [1:SIZE,i] // cols!
End If
now Let( tmpTab := Get(table) )
If( Summatory ( tmpTab ) ) // exist numbers in the row??
Clear Mark
Let( tmpTab := _Moving Right Down(tmpTab) ) // move its!
Clear Mark
Store ( _check Point Right Down(tmpTab) Plus (score), tmpTab, score ) // check score...
Clear Mark
Let ( tmpTab := _Moving Right Down(tmpTab) ) // move remanents!
If( _DIRECTION_ )
Set Interval [i,1:SIZE]
Else
Set Interval [1:SIZE,i]
End If
Take( tmpTab ), and Put(table)
End If
Next
Clear(tmpTab) and Clear Mark.
Return
 
check Point Left Up(tmpTab)
v1=0,v2=0,tScore=0,totScore=0
For(k=1, while var(k) Is Lt (SIZE),++k)
At Interval [k] Get (tmpTab), and Move to (v1)
At Interval [ var(k) Plus(1) ] Get(tmpTab), and Move to (v2)
If( var(v1) Is Eq? (v2) )
Add(v1, v2),Copy to (tScore)
At Interval [k] Put(tmpTab), At Interval [ var(k) Plus(1)]; then Take(0) and Put(tmpTab)
Let( totScore := var(tScore) Plus (totScore) )
End If
Next
Take (tmpTab,totScore)
Return
 
check Move Left Up(_DIRECTION_)
tmpTab=0
For(i=1, while var(i) Is Le (SIZE),++i)
If( _DIRECTION_ )
Set Interval [i,1:SIZE]
Else
Set Interval [1:SIZE,i]
End If
now Get(table), and Move to (tmpTab)
If( Summatory (tmpTab) ) // exist numbers in the row??
Clear Mark
Let ( tmpTab := _Moving Left Up(tmpTab) ) // move its!
Clear Mark
Store ( _check Point Left Up(tmpTab) Plus (score), tmpTab, score ) // check score...
 
Clear Mark
Let ( tmpTab := _Moving Left Up(tmpTab) ) // move remanents!
If( _DIRECTION_ )
Set Interval [i,1:SIZE]
Else
Set Interval [1:SIZE,i]
End If
now Take (tmpTab), and Put(table)
End If
Next
Clear Mark.
Return
</syntaxhighlight>
{{out}}
<pre>
Se invoca como:
 
rxvt -g 79x38 -fn "xft:FantasqueSansMono-Regular:pixelsize=25" -e hopper bas/2048.bas
 
</pre>
[[File:Captura_de_pantalla_de_2022-10-07_14-43-23.png]]
 
=={{header|APPLESOFTApplesoft BASIC}}==
<langsyntaxhighlight Applesoftlang="applesoft">PRINT "Game 2048"
 
10 REM ************
Line 1,635 ⟶ 2,246:
 
 
</syntaxhighlight>
</lang>
 
=={{header|ARM Assembly}}==
{{works with|as|Raspberry Pi}}
<syntaxhighlight lang="arm assembly">
<lang ARM Assembly>
/* ARM assembly Raspberry PI */
/* program 2048.s */
Line 2,530 ⟶ 3,142:
/***************************************************/
.include "../affichage.inc"
</syntaxhighlight>
</lang>
{{Output}}
<pre>
Line 2,553 ⟶ 3,165:
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">Grid := [], s := 16, w := h := S * 4.5
Gui, font, s%s%
Gui, add, text, y1
Line 2,776 ⟶ 3,388:
Grid[StrSplit(rnd, ",").1, StrSplit(rnd, ",").2] := 2
}
;------------------------------</langsyntaxhighlight>
 
=={{header|Batch File}}==
<langsyntaxhighlight lang="dos">:: 2048 Game Task from RosettaCode
:: Batch File Implementation v2.0.1
 
Line 2,950 ⟶ 3,562:
echo(Press any key to exit . . .
pause>nul
exit /b 0</langsyntaxhighlight>
{{out}}
<pre>2048 Game in Batch
Line 2,967 ⟶ 3,579:
 
Keys: WASD (Slide Movement), N (New game), P (Exit)</pre>
 
 
=={{header|BASIC}}==
==={{header|QBasic}}===
El código es de MichD (https://github.com/michd/2048-qbasic)
 
Yo solo lo transcribo.
<syntaxhighlight lang="qbasic">
SCREEN 13
PALETTE 1, pColor(35, 33, 31)
PALETTE 2, pColor(46, 46, 51)
PALETTE 3, pColor(59, 56, 50)
PALETTE 4, pColor(61, 44, 30)
PALETTE 5, pColor(61, 37, 25)
PALETTE 6, pColor(62, 31, 24)
PALETTE 7, pColor(62, 24, 15)
PALETTE 8, pColor(59, 52, 29)
PALETTE 9, pColor(59, 51, 24)
PALETTE 10, pColor(59, 50, 20)
PALETTE 11, pColor(59, 49, 16)
PALETTE 12, pColor(59, 49, 12)
PALETTE 13, pColor(15, 15, 13)
PALETTE 14, pColor(23, 22, 20)
 
DIM SHARED gDebug
DIM SHARED gOriginX
DIM SHARED gOriginY
DIM SHARED gTextOriginX
DIM SHARED gTextOriginY
DIM SHARED gSquareSide
DIM SHARED gGridSize
 
gGridSize = 4 ' grid size (4 -> 4x4)
 
DIM SHARED gGrid(gGridSize, gGridSize)
DIM SHARED gScore
 
' Don't touch these numbers, seriously
 
gOriginX = 75 'pixel X of top left of grid
gOriginY = 12 'pixel Y of top right of grid
gTextOriginX = 11
gTextOriginY = 3
gSquareSide = 38 'width/height of block in pixels
 
 
'set up all the things!
gDebug = 0
 
RANDOMIZE TIMER
CLS
 
start:
initGrid
initGraphicGrid
renderGrid
updateScore
 
gScore = 0
 
LOCATE 23, 1
PRINT "Move with arrow keys. (R)estart, (Q)uit"
 
' keyboard input loop
DO
DO
k$ = INKEY$
LOOP UNTIL k$ <> ""
 
SELECT CASE k$
CASE CHR$(0) + CHR$(72) 'up
processMove ("u")
CASE CHR$(0) + CHR$(80) 'down
processMove ("d")
CASE CHR$(0) + CHR$(77) 'right
processMove ("r")
CASE CHR$(0) + CHR$(75) 'left
processMove ("l")
CASE CHR$(27) 'escape
GOTO programEnd
CASE "q"
GOTO programEnd
CASE "Q"
GOTO programEnd
CASE "r"
GOTO start
CASE "R"
GOTO start
END SELECT
LOOP
 
programEnd:
 
SUB addblock
DIM emptyCells(gGridSize * gGridSize, 2)
emptyCellCount = 0
 
FOR x = 0 TO gGridSize - 1
FOR y = 0 TO gGridSize - 1
IF gGrid(x, y) = 0 THEN
emptyCells(emptyCellCount, 0) = x
emptyCells(emptyCellCount, 1) = y
emptyCellCount = emptyCellCount + 1
END IF
NEXT y
NEXT x
 
IF emptyCellCount > 0 THEN
index = INT(RND * emptyCellCount)
num = CINT(RND + 1) * 2
gGrid(emptyCells(index, 0), emptyCells(index, 1)) = num
END IF
 
END SUB
 
SUB drawNumber (num, xPos, yPos)
SELECT CASE num
CASE 0: c = 16
CASE 2: c = 2
CASE 4: c = 3
CASE 8: c = 4
CASE 16: c = 5
CASE 32: c = 6
CASE 64: c = 7
CASE 128: c = 8
CASE 256: c = 9
CASE 512: c = 10
CASE 1024: c = 11
CASE 2048: c = 12
CASE 4096: c = 13
CASE 8192: c = 13
CASE ELSE: c = 13
END SELECT
 
x = xPos * (gSquareSide + 2) + gOriginX + 1
y = yPos * (gSquareSide + 2) + gOriginY + 1
LINE (x + 1, y + 1)-(x + gSquareSide - 1, y + gSquareSide - 1), c, BF
 
IF num > 0 THEN
LOCATE gTextOriginY + 1 + (yPos * 5), gTextOriginX + (xPos * 5)
PRINT " "
LOCATE gTextOriginY + 2 + (yPos * 5), gTextOriginX + (xPos * 5)
PRINT pad$(num)
LOCATE gTextOriginY + 3 + (yPos * 5), gTextOriginX + (xPos * 5)
'PRINT " "
END IF
 
END SUB
 
FUNCTION getAdjacentCell (x, y, d AS STRING)
 
IF (d = "l" AND x = 0) OR (d = "r" AND x = gGridSize - 1) OR (d = "u" AND y = 0) OR (d = "d" AND y = gGridSize - 1) THEN
getAdjacentCell = -1
ELSE
SELECT CASE d
CASE "l": getAdjacentCell = gGrid(x - 1, y)
CASE "r": getAdjacentCell = gGrid(x + 1, y)
 
CASE "u": getAdjacentCell = gGrid(x, y - 1)
CASE "d": getAdjacentCell = gGrid(x, y + 1)
END SELECT
END IF
 
END FUNCTION
 
'Draws the outside grid (doesn't render tiles)
SUB initGraphicGrid
 
gridSide = (gSquareSide + 2) * gGridSize
 
LINE (gOriginX, gOriginY)-(gOriginX + gridSide, gOriginY + gridSide), 14, BF 'outer square, 3 thick
LINE (gOriginX, gOriginY)-(gOriginX + gridSide, gOriginY + gridSide), 1, B 'outer square, 3 thick
LINE (gOriginX - 1, gOriginY - 1)-(gOriginX + gridSide + 1, gOriginY + gridSide + 1), 1, B
LINE (gOriginX - 2, gOriginY - 2)-(gOriginX + gridSide + 2, gOriginY + gridSide + 2), 1, B
 
FOR x = gOriginX + gSquareSide + 2 TO gOriginX + (gSquareSide + 2) * gGridSize STEP gSquareSide + 2 ' horizontal lines
LINE (x, gOriginY)-(x, gOriginY + gridSide), 1
NEXT x
 
FOR y = gOriginY + gSquareSide + 2 TO gOriginY + (gSquareSide + 2) * gGridSize STEP gSquareSide + 2 ' vertical lines
LINE (gOriginX, y)-(gOriginX + gridSide, y), 1
NEXT y
 
END SUB
 
'Init the (data) grid with 0s
SUB initGrid
FOR x = 0 TO 3
FOR y = 0 TO 3
gGrid(x, y) = 0
NEXT y
NEXT x
 
addblock
addblock
 
END SUB
 
SUB moveBlock (sourceX, sourceY, targetX, targetY, merge)
 
IF sourceX < 0 OR sourceX >= gGridSize OR sourceY < 0 OR sourceY >= gGridSize AND gDebug = 1 THEN
LOCATE 0, 0
PRINT "moveBlock: source coords out of bounds"
END IF
 
IF targetX < 0 OR targetX >= gGridSize OR targetY < 0 OR targetY >= gGridSize AND gDebug = 1 THEN
LOCATE 0, 0
PRINT "moveBlock: source coords out of bounds"
END IF
 
sourceSquareValue = gGrid(sourceX, sourceY)
targetSquareValue = gGrid(targetX, targetY)
 
IF merge = 1 THEN
 
IF sourceSquareValue = targetSquareValue THEN
gGrid(sourceX, sourceY) = 0
gGrid(targetX, targetY) = targetSquareValue * 2
gScore = gScore + targetSquareValue * 2 ' Points!
ELSEIF gDebug = 1 THEN
LOCATE 0, 0
PRINT "moveBlock: Attempted to merge unequal sqs"
END IF
 
ELSE
 
IF targetSquareValue = 0 THEN
gGrid(sourceX, sourceY) = 0
gGrid(targetX, targetY) = sourceSquareValue
ELSEIF gDebug = 1 THEN
LOCATE 0, 0
PRINT "moveBlock: Attempted to move to non-empty block"
END IF
 
END IF
 
END SUB
 
FUNCTION pad$ (num)
strNum$ = LTRIM$(STR$(num))
 
SELECT CASE LEN(strNum$)
CASE 1: pad = " " + strNum$ + " "
CASE 2: pad = " " + strNum$ + " "
CASE 3: pad = " " + strNum$
CASE 4: pad = strNum$
END SELECT
 
END FUNCTION
 
FUNCTION pColor (r, g, b)
pColor = (r + g * 256 + b * 65536)
END FUNCTION
 
SUB processMove (dir AS STRING)
' dir can be 'l', 'r', 'u', or 'd'
 
hasMoved = 0
 
IF dir = "l" THEN
 
FOR y = 0 TO gGridSize - 1
wasMerge = 0
FOR x = 0 TO gGridSize - 1
GOSUB processBlock
NEXT x
NEXT y
 
ELSEIF dir = "r" THEN
 
FOR y = 0 TO gGridSize - 1
wasMerge = 0
FOR x = gGridSize - 1 TO 0 STEP -1
GOSUB processBlock
NEXT x
NEXT y
 
ELSEIF dir = "u" THEN
FOR x = 0 TO gGridSize - 1
wasMerge = 0
FOR y = 0 TO gGridSize - 1
GOSUB processBlock
NEXT y
NEXT x
 
ELSEIF dir = "d" THEN
FOR x = 0 TO gGridSize - 1
wasMerge = 0
FOR y = gGridSize - 1 TO 0 STEP -1
GOSUB processBlock
NEXT y
NEXT x
 
END IF
 
GOTO processMoveEnd
 
moveToObstacle:
curX = x
curY = y
 
DO WHILE getAdjacentCell(curX, curY, dir) = 0
SELECT CASE dir
CASE "l": curX = curX - 1
CASE "r": curX = curX + 1
CASE "u": curY = curY - 1
CASE "d": curY = curY + 1
END SELECT
LOOP
RETURN
 
processBlock:
 
merge = 0
IF gGrid(x, y) <> 0 THEN ' have block
 
GOSUB moveToObstacle ' figure out where it can be moved to
IF getAdjacentCell(curX, curY, dir) = gGrid(x, y) AND wasMerge = 0 THEN ' obstacle can be merged with
merge = 1
wasMerge = 1
ELSE
wasMerge = 0
END IF
 
IF curX <> x OR curY <> y OR merge = 1 THEN
mergeDirX = 0
mergeDirY = 0
IF merge = 1 THEN
SELECT CASE dir
CASE "l": mergeDirX = -1
CASE "r": mergeDirX = 1
CASE "u": mergeDirY = -1
CASE "d": mergeDirY = 1
END SELECT
END IF
 
CALL moveBlock(x, y, curX + mergeDirX, curY + mergeDirY, merge) ' move to before obstacle or merge
hasMoved = 1
END IF
END IF
RETURN
 
processMoveEnd:
 
IF hasMoved = 1 THEN addblock
renderGrid
updateScore
 
END SUB
 
SUB renderGrid
FOR x = 0 TO gGridSize - 1
FOR y = 0 TO gGridSize - 1
CALL drawNumber(gGrid(x, y), x, y)
NEXT y
NEXT x
END SUB
 
SUB updateScore
LOCATE 1, 10
PRINT "Score:" + STR$(gScore)
END SUB
</syntaxhighlight>
 
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> SIZE = 4 : MAX = SIZE-1
Won% = FALSE : Lost% = FALSE
@% = 5
Line 3,039 ⟶ 4,014:
IF Board(z DIV SIZE,z MOD SIZE) = 0 THEN Board(z DIV SIZE,z MOD SIZE) = 2-(RND(10)=1)*2 : EXIT FOR
NEXT
ENDPROC</langsyntaxhighlight>
{{out}}
<pre> _ _ _ _
Line 3,071 ⟶ 4,046:
--------------------
You lost :-(</pre>
 
=={{header|BQN}}==
<syntaxhighlight lang="bqn">
#!/usr/bin/env BQN
# 2048 game
# The game is controlled with the vim movement keys:
# h: left, j: down, k: up, l: right, q: quit
# needs a VT-100 compatible terminal
 
Merge←{𝕩 0⊸≠⊸/↩ ⋄ m←<`=⟜«𝕩 ⋄ 4↑(¬»m)/𝕩×1+m}⌾⌽ # Merge a single row to the right
Step←Merge˘ # Merges each row of the board
Up←Step⌾(⌽⍉∘⌽) # Each direction merges the board
Down←Step⌾⍉ # by rotating it to the correct orientation, merging the rows
Right←Step # and reversing the rotation
Left←Step⌾(⌽˘)
# Spawns a 2 or a 4 (10% chance) at a random empty position
Spawn←{i←•rand.Range∘≠⊸⊑(0⊸= /○⥊ ↕∘≢)𝕩 ⋄ (•rand.Range∘≠⊸⊑9‿1/2‿4)⌾(i⊸⊑) 𝕩}
Lose←Left∘Right∘Down∘Up⊸≡ # Losing condition, no moves change the board
Win←∨´·∨˝2048⊸= # Winning condition, 2048!
 
Quit←{•Out e∾"[?12l"∾e∾"[?25h" ⋄ •Exit 𝕩} # Restores the terminal and exits
Display←{ # Displays the board, score and controls
•Out e∾"[H"∾e∾"[2J" # Cursor to origin and clear screen
•Out "Controls: h: left, j: down, k: up, l: right, q: quit"
•Show 𝕩
•Out "score: "∾•Repr ⌈´⌈˝ 𝕩
}
 
board←Spawn 4‿4⥊0
e←@+27 # Escape character for the ANSI escape codes
•term.RawMode 1
•Out e∾"[?25l"∾e∾"[2J"∾e∾"[H" # Cursor to origin, hide it and clear screen
{𝕤⋄
Display board
{𝕤⋄•Out "You win!" ⋄ Quit 0}⍟Win board
{𝕤⋄•Out "You lose!"⋄ Quit 1}⍟Lose board
key←•term.CharB @ # Read key
⊑key∊"hjklq"? # Valid key?
{𝕤⋄ Quit 0}⍟(key='q')@ # Quit key?
move←⊑(key="hjkl")/Left‿Down‿Up‿Right # Get movement function from the key
{𝕤⋄board↩Spawn∘Move 𝕩}⍟(Move⊸≢) board # Generate the next board if the move is valid
; @
}•_While_{𝕤⋄1}@
</syntaxhighlight>
 
=={{header|C}}==
===Version 1===
Supports limited colours through vt100 escape codes. Requires a posix machine for <tt>termios.h</tt> and <tt>unistd.h</tt> headers. Provides simplistic animations when moving and merging blocks.
<syntaxhighlight lang="c">
<lang c>
#include <stdio.h>
#include <stdlib.h>
Line 3,355 ⟶ 4,374:
return 0;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,372 ⟶ 4,391:
 
 
<syntaxhighlight lang="c">
<lang c>
 
#include <stdio.h>
Line 3,714 ⟶ 4,733:
return 0;
}
</syntaxhighlight>
</lang>
 
=={{header|C sharp|C#}}==
{{trans|C++}}
<langsyntaxhighlight lang="csharp">using System;
 
namespace g2048_csharp
Line 4,112 ⟶ 5,131:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 4,132 ⟶ 5,151:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">
#include <time.h>
#include <iostream>
Line 4,326 ⟶ 5,345:
return system( "pause" );
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 4,345 ⟶ 5,364:
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">
(ns 2048
(:require [clojure.string :as str]))
Line 4,464 ⟶ 5,483:
:default (recur (handle-turn field)))))
 
(play-2048)</langsyntaxhighlight>
 
{{out}}
Line 4,479 ⟶ 5,498:
=={{header|Common Lisp}}==
Depends on Windows msvcrt.dll for _getch. Depends on quicklisp. Use arrow keys to make moves and press "Q" to quit. Tested with SBCL.
<langsyntaxhighlight lang="lisp">(ql:quickload '(cffi alexandria))
 
(defpackage :2048-lisp
Line 4,679 ⟶ 5,698:
(format t "~% Score: ~D~%" score)
(print-board board 4)
(prompt-input board score))</langsyntaxhighlight>
{{out}}
<pre>* (2048-lisp::prompt)
Line 4,707 ⟶ 5,726:
=={{header|D}}==
{{trans|C++}}
<langsyntaxhighlight lang="d">import std.stdio, std.string, std.random;
import core.stdc.stdlib: exit;
 
struct G2048 {
public void gameLoop() /*@safe @nogc*/ {
addTile;
while (true) {
Line 4,725 ⟶ 5,744:
 
private:
static struct Tile {
uint val = 0;
bool blocked = false;
Line 4,737 ⟶ 5,756:
uint score = 0;
 
void drawBoard() const /*@safe @nogc*/ {
writeln("SCORE: ", score, "\n");
foreach (immutable y; 0 .. side) {
write("+------+------+------+------+\n| ");
foreach (immutable x; 0 .. side) {
if (board[x][y].val)
writef("%4d", board[x][y].val);
Line 4,750 ⟶ 5,769:
writeln;
}
writeln("+------+------+------+------+\n".writeln);
}
 
void waitKey() /*@safe*/ {
moved = false;
write("(W)Up (S)Down (A)Left (D)Right (Q)Quit: ".write);
immutableauto c = readln.strip.toLower;
 
switch (c) {
Line 4,767 ⟶ 5,786:
}
 
foreach (immutable y; 0 .. side)
foreach (immutable x; 0 .. side)
board[x][y].blocked = false;
}
Line 4,777 ⟶ 5,796:
}
 
void addTile() /*nothrow*/ @safe /*@nogc*/ {
foreach (immutable y; 0 .. side) {
foreach (immutable x; 0 .. side) {
if (!board[x][y].val) {
uint a, b;
Line 4,796 ⟶ 5,815:
}
 
bool canMove() const pure nothrow @safe @nogc {
foreach (immutable y; 0 .. side)
foreach (immutable x; 0 .. side)
if (!board[x][y].val)
return true;
 
foreach (immutable y; 0 .. side) {
foreach (immutable x; 0 .. side) {
if (testAdd(x + 1, y, board[x][y].val) ||
testAdd(x - 1, y, board[x][y].val) ||
Line 4,814 ⟶ 5,833:
}
 
bool testAdd(in uint x, in uint y, in uint v) const pure nothrow @safe @nogc {
if (x > 3 || y > 3)
return false;
Line 4,820 ⟶ 5,839:
}
 
void moveVertically(in uint x, in uint y, in uint d) pure nothrow @safe @nogc {
if (board[x][y + d].val && board[x][y + d].val == board[x][y].val &&
!board[x][y].blocked && !board[x][y + d].blocked) {
Line 4,843 ⟶ 5,862:
}
 
void moveHorizontally(in uint x, in uint y, in uint d) pure nothrow @safe @nogc {
if (board[x + d][y].val && board[x + d][y].val == board[x][y].val &&
!board[x][y].blocked && !board[x + d][y].blocked) {
Line 4,866 ⟶ 5,885:
}
 
void move(in moveDir d) pure nothrow @safe @nogc {
final switch (d) with(moveDir) {
case up:
foreach (immutable x; 0 .. side)
foreach (immutable y; 1 .. side)
if (board[x][y].val)
moveVertically(x, y, -1);
break;
case down:
foreach (immutable x; 0 .. side)
foreach_reverse (immutable y; 0 .. 3)
if (board[x][y].val)
moveVertically(x, y, 1);
break;
case left:
foreach (immutable y; 0 .. side)
foreach (immutable x; 1 .. side)
if (board[x][y].val)
moveHorizontally(x, y, -1);
break;
case right:
foreach (immutable y; 0 .. side)
foreach_reverse (immutable x; 0 .. 3)
if (board[x][y].val)
moveHorizontally(x, y, 1);
Line 4,898 ⟶ 5,917:
G2048 g;
g.gameLoop;
}</langsyntaxhighlight>
The output is the same as the C++ version.
 
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{libheader| Velthuis.Console}}Thanks for Rudy Velthuis [https://github.com/rvelthuis/Consoles].
{{Trans|C++}}
<syntaxhighlight lang="delphi">
<lang Delphi>
program Game2048;
 
Line 5,309 ⟶ 6,329:
Writeln('Press Enter to exit');
Readln;
end.</langsyntaxhighlight>
{{out}}
<pre>
Line 5,330 ⟶ 6,350:
=={{header|Elixir}}==
{{works with|Elixir|1.3}}
<langsyntaxhighlight lang="elixir">defmodule Game2048 do
@size 4
@range 0..@size-1
Line 5,444 ⟶ 6,464:
end
 
Game2048.play 512</langsyntaxhighlight>
 
{{out}}
Line 5,476 ⟶ 6,496:
{{works with|Elm 0.18.0}}
Try online [https://ellie-app.com/3ZMMpYsbfcMa1/3]
<langsyntaxhighlight Elmlang="elm">module Main exposing (..)
 
import Html exposing (Html, div, p, text, button, span, h2)
Line 5,878 ⟶ 6,898:
viewGrid model.tiles
]
</syntaxhighlight>
</lang>
 
=={{header|F Sharp|F#}}==
 
The following code can be executed as is using F# Interactive from system command line ("fsi.exe 2048.fsx") but not from Visual Studio F# Interactive window due to the way it access keyboard (the System.Console.ReadKey() function).
 
<langsyntaxhighlight lang="fsharp">
// the board is represented with a list of 16 integers
let empty = List.init 16 (fun _ -> 0)
Line 5,944 ⟶ 6,964:
 
play()
</syntaxhighlight>
</lang>
 
=={{header|Factor}}==
Line 5,959 ⟶ 6,979:
 
 
<syntaxhighlight lang="factor">
<lang>
USE: accessors
FROM: arrays => <array> array ;
Line 6,280 ⟶ 7,300:
 
MAIN: start-2048
</syntaxhighlight>
</lang>
 
=={{header|Forth}}==
Line 6,288 ⟶ 7,308:
Just like my implementation of [[15 Puzzle Game#Forth|15 Puzzle Game]], this uses Vim's h/j/k/l for movement.
 
<langsyntaxhighlight lang="forth">\ in Forth, you do many things on your own. This word is used to define 2D arrays
: 2D-ARRAY ( height width )
CREATE DUP ,
Line 6,522 ⟶ 7,542:
 
INIT
MAIN-LOOP</langsyntaxhighlight>
 
{{out}}
Line 6,549 ⟶ 7,569:
 
===Source===
The initial attempt at showing the board relied rather heavily on FORMAT tricks, in particular the use of the <''n''> facility whereby the value of an integer expression can be inserted into a format statement's coding on-the-fly, as in the following. <langsyntaxhighlight Fortranlang="fortran">
WRITE (MSG,1) !Roll forth a top/bottom boundary. No corner characters (etc.), damnit.
1 FORMAT ("|",<NC>(<W>("-"),"|")) !Heavy reliance on runtime values in NC and W. But see FORMAT 22.
Line 6,555 ⟶ 7,575:
WRITE (MSG,22) ((" ",L1 = 1,W),"|",C = 1,NC) !Compare to FORMAT 2.
22 FORMAT ("|",666A1) !A constant FORMAT, a tricky WRITE.
4 FORMAT ("|",<NC - 1>(<W>("-"),"+"),<W>("-"),"|") !With internal + rather than |.</langsyntaxhighlight>
This sort of thing is not necessarily accepted by all compilers, so instead the next stage was to convert to using complicated WRITE statements. If one regarded the various sizes (the values of NR, NC, W in the source) as truly fixed, literal constants could be used throughout. This would however mean that they would appear without explanation, and if one eventually attempted to recode with different values, mistakes would be likely. Thus below, FORMAT 3 has <code> (<NC>(A1,I<W>),A1)</code> and if the <> scheme were unavailable, you'd have to use <code>(4(A1,I6),A1)</code> instead, not too troublesome a change. Or, the text of the format sequence could be written to a CHARACTER variable, as demonstrated in [[Multiplication_tables#Traditional_approach]]. Yet another approach might be <code>(666(A1,I6))</code> which relies on the addendum <code>A1</code> happening to be the same as the start of the <code>(A1,I6)</code> pair, but there is still the appearance of the literal constant six instead of <W>, and if there were to be any change to be made, it would have to be remembered...
<langsyntaxhighlight Fortranlang="fortran"> SUBROUTINE SHOW(NR,NC,BOARD) !Mess about.
INTEGER NR,NC !Number of rows and columns.
INTEGER BOARD(NR,NC) !The board. Actual storage is transposed!
Line 6,747 ⟶ 7,767:
601 FORMAT ("None! Oh dear.") !Nothing more can be done.
END !That was fun.
</syntaxhighlight>
</lang>
 
===Output===
Line 6,800 ⟶ 7,820:
Move 2, score 6. Moves RULD ... Your move:
</pre>
 
=={{header|FreeBASIC}}==
Based On MichD's original code (https://github.com/michd/2048-qbasic)
<syntaxhighlight lang="freebasic">#define EXTCHAR Chr(255)
 
'--- Declaration of global variables ---
Dim Shared As Integer gGridSize = 4 'grid size (4 -> 4x4)
Dim Shared As Integer gGrid(gGridSize, gGridSize)
Dim Shared As Integer gScore
Dim Shared As Integer curX, curY
Dim Shared As Integer hasMoved, wasMerge
' Don't touch these numbers, seriously
Dim Shared As Integer gOriginX, gOriginY
gOriginX = 75 'pixel X of top left of grid
gOriginY = 12 'pixel Y of top right of grida
Dim Shared As Integer gTextOriginX, gTextOriginY, gSquareSide
gTextOriginX = 11
gTextOriginY = 3
gSquareSide = 38 'width/height of block in pixels
 
'set up all the things!
Dim Shared As Integer gDebug = 0
 
'--- SUBroutines and FUNCtions ---
Sub addblock
Dim As Integer emptyCells(gGridSize * gGridSize, 2)
Dim As Integer emptyCellCount = 0
Dim As Integer x, y, index, num
For x = 0 To gGridSize - 1
For y = 0 To gGridSize - 1
If gGrid(x, y) = 0 Then
emptyCells(emptyCellCount, 0) = x
emptyCells(emptyCellCount, 1) = y
emptyCellCount += 1
End If
Next y
Next x
If emptyCellCount > 0 Then
index = Int(Rnd * emptyCellCount)
num = Cint(Rnd + 1) * 2
gGrid(emptyCells(index, 0), emptyCells(index, 1)) = num
End If
End Sub
 
Function pad(num As Integer) As String
Dim As String strNum = Ltrim(Str(num))
Select Case Len(strNum)
Case 1: Return " " + strNum + " "
Case 2: Return " " + strNum + " "
Case 3: Return " " + strNum
Case 4: Return strNum
End Select
End Function
 
Sub drawNumber(num As Integer, xPos As Integer, yPos As Integer)
Dim As Integer c, x, y
Select Case num
Case 0: c = 16
Case 2: c = 2
Case 4: c = 3
Case 8: c = 4
Case 16: c = 5
Case 32: c = 6
Case 64: c = 7
Case 128: c = 8
Case 256: c = 9
Case 512: c = 10
Case 1024: c = 11
Case 2048: c = 12
Case 4096: c = 13
Case 8192: c = 13
Case Else: c = 13
End Select
x = xPos *(gSquareSide + 2) + gOriginX + 1
y = yPos *(gSquareSide + 2) + gOriginY + 1
Line(x + 1, y + 1)-(x + gSquareSide - 1, y + gSquareSide - 1), c, BF
If num > 0 Then
Locate gTextOriginY + 1 +(yPos * 5), gTextOriginX +(xPos * 5) : Print " "
Locate gTextOriginY + 2 +(yPos * 5), gTextOriginX +(xPos * 5) : Print pad(num)
Locate gTextOriginY + 3 +(yPos * 5), gTextOriginX +(xPos * 5)
End If
End Sub
 
Function getAdjacentCell(x As Integer, y As Integer, d As String) As Integer
If (d = "l" And x = 0) Or (d = "r" And x = gGridSize - 1) Or (d = "u" And y = 0) Or (d = "d" And y = gGridSize - 1) Then
getAdjacentCell = -1
Else
Select Case d
Case "l": getAdjacentCell = gGrid(x - 1, y)
Case "r": getAdjacentCell = gGrid(x + 1, y)
Case "u": getAdjacentCell = gGrid(x, y - 1)
Case "d": getAdjacentCell = gGrid(x, y + 1)
End Select
End If
End Function
 
'Draws the outside grid(doesn't render tiles)
Sub initGraphicGrid
Dim As Integer x, y, gridSide =(gSquareSide + 2) * gGridSize
Line(gOriginX, gOriginY)-(gOriginX + gridSide, gOriginY + gridSide), 14, BF 'outer square, 3 thick
Line(gOriginX, gOriginY)-(gOriginX + gridSide, gOriginY + gridSide), 1, B 'outer square, 3 thick
Line(gOriginX - 1, gOriginY - 1)-(gOriginX + gridSide + 1, gOriginY + gridSide + 1), 1, B
Line(gOriginX - 2, gOriginY - 2)-(gOriginX + gridSide + 2, gOriginY + gridSide + 2), 1, B
For x = gOriginX + gSquareSide + 2 To gOriginX +(gSquareSide + 2) * gGridSize Step gSquareSide + 2 ' horizontal lines
Line(x, gOriginY)-(x, gOriginY + gridSide), 1
Next x
For y = gOriginY + gSquareSide + 2 To gOriginY +(gSquareSide + 2) * gGridSize Step gSquareSide + 2 ' vertical lines
Line(gOriginX, y)-(gOriginX + gridSide, y), 1
Next y
End Sub
 
'Init the(data) grid with 0s
Sub initGrid
Dim As Integer x, y
For x = 0 To 3
For y = 0 To 3
gGrid(x, y) = 0
Next y
Next x
addblock
addblock
End Sub
 
Sub moveBlock(sourceX As Integer, sourceY As Integer, targetX As Integer, targetY As Integer, merge As Integer)
If sourceX < 0 Or sourceX >= gGridSize Or sourceY < 0 Or sourceY >= gGridSize And gDebug = 1 Then
Locate 0, 0 : Print "moveBlock: source coords out of bounds"
End If
If targetX < 0 Or targetX >= gGridSize Or targetY < 0 Or targetY >= gGridSize And gDebug = 1 Then
Locate 0, 0 : Print "moveBlock: source coords out of bounds"
End If
Dim As Integer sourceSquareValue = gGrid(sourceX, sourceY)
Dim As Integer targetSquareValue = gGrid(targetX, targetY)
If merge = 1 Then
If sourceSquareValue = targetSquareValue Then
gGrid(sourceX, sourceY) = 0
gGrid(targetX, targetY) = targetSquareValue * 2
gScore += targetSquareValue * 2 ' Points!
Elseif gDebug = 1 Then
Locate 0, 0 : Print "moveBlock: Attempted to merge unequal sqs"
End If
Else
If targetSquareValue = 0 Then
gGrid(sourceX, sourceY) = 0
gGrid(targetX, targetY) = sourceSquareValue
Elseif gDebug = 1 Then
Locate 0, 0 : Print "moveBlock: Attempted to move to non-empty block"
End If
End If
End Sub
 
Function pColor(r As Integer, g As Integer, b As Integer) As Integer
Return (r + g * 256 + b * 65536)
End Function
 
Sub moveToObstacle(x As Integer, y As Integer, direcc As String)
curX = x : curY = y
Do While getAdjacentCell(curX, curY, direcc) = 0
Select Case direcc
Case "l": curX -= 1
Case "r": curX += 1
Case "u": curY -= 1
Case "d": curY += 1
End Select
Loop
End Sub
 
Sub processBlock(x As Integer, y As Integer, direcc As String)
Dim As Integer merge = 0, mergeDirX, mergeDirY
If gGrid(x, y) <> 0 Then ' have block
moveToObstacle(x, y, direcc) ' figure out where it can be moved to
If getAdjacentCell(curX, curY, direcc) = gGrid(x, y) And wasMerge = 0 Then ' obstacle can be merged with
merge = 1
wasMerge = 1
Else
wasMerge = 0
End If
If curX <> x Or curY <> y Or merge = 1 Then
mergeDirX = 0
mergeDirY = 0
If merge = 1 Then
Select Case direcc
Case "l": mergeDirX = -1
Case "r": mergeDirX = 1
Case "u": mergeDirY = -1
Case "d": mergeDirY = 1
End Select
End If
moveBlock(x, y, curX + mergeDirX, curY + mergeDirY, merge) ' move to before obstacle or merge
hasMoved = 1
End If
End If
End Sub
 
Sub renderGrid
Dim As Integer x, y
For x = 0 To gGridSize - 1
For y = 0 To gGridSize - 1
drawNumber(gGrid(x, y), x, y)
Next y
Next x
End Sub
 
Sub updateScore
Locate 1, 10 : Print Using "Score: #####"; gScore
End Sub
 
Sub processMove(direcc As String) '' direcc can be 'l', 'r', 'u', or 'd'
Dim As Integer x, y
hasMoved = 0
If direcc = "l" Then
For y = 0 To gGridSize - 1
wasMerge = 0
For x = 0 To gGridSize - 1
processBlock(x,y,direcc)
Next x
Next y
Elseif direcc = "r" Then
For y = 0 To gGridSize - 1
wasMerge = 0
For x = gGridSize - 1 To 0 Step -1
processBlock(x,y,direcc)
Next x
Next y
Elseif direcc = "u" Then
For x = 0 To gGridSize - 1
wasMerge = 0
For y = 0 To gGridSize - 1
processBlock(x,y,direcc)
Next y
Next x
Elseif direcc = "d" Then
For x = 0 To gGridSize - 1
wasMerge = 0
For y = gGridSize - 1 To 0 Step -1
processBlock(x,y,direcc)
Next y
Next x
End If
If hasMoved = 1 Then addblock
renderGrid
updateScore
End Sub
 
 
'--- Main Program ---
Screen 8
Windowtitle "2048"
Palette 1, pColor(35, 33, 31)
Palette 2, pColor(46, 46, 51)
Palette 3, pColor(59, 56, 50)
Palette 4, pColor(61, 44, 30)
Palette 5, pColor(61, 37, 25)
Palette 6, pColor(62, 31, 24)
Palette 7, pColor(62, 24, 15)
Palette 8, pColor(59, 52, 29)
Palette 9, pColor(59, 51, 24)
Palette 10, pColor(59, 50, 20)
Palette 11, pColor(59, 49, 16)
Palette 12, pColor(59, 49, 12)
Palette 13, pColor(15, 15, 13)
Palette 14, pColor(23, 22, 20)
 
Randomize Timer
Cls
Do
initGrid
initGraphicGrid
renderGrid
updateScore
gScore = 0
Locate 23, 10 : Print "Move with arrow keys."
Locate 24, 12 : Print "(R)estart, (Q)uit"
Dim As String k
Do
Do
k = Inkey
Loop Until k <> ""
Select Case k
Case EXTCHAR + Chr(72) 'up
processMove("u")
Case EXTCHAR + Chr(80) 'down
processMove("d")
Case EXTCHAR + Chr(77) 'right
processMove("r")
Case EXTCHAR + Chr(75) 'left
processMove("l")
Case "q", "Q", Chr(27) 'escape
End
Case "r", "R"
Exit Do
End Select
Loop
Loop</syntaxhighlight>
 
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
begin enum 123
_lf
_rt
_dn
_up
_new
_end
end enum
str63 bd
colorref color(11)
byte zs
 
void local fn initialize
subclass window 1, @"2048",(0,0,438,438)
fn WindowSetBackgroundColor( 1, fn ColorBlack )
color(0) = fn ColorDarkGray
color(1) = fn ColorGray
color(2) = fn ColorLightGray
color(3) = fn ColorBlue
color(4) = fn ColorBrown
color(5) = fn ColorCyan
color(6) = fn ColorGreen
color(7) = fn ColorMagenta
color(8) = fn ColorOrange
color(9) = fn ColorPurple
color(10) = fn ColorYellow
color(11) = fn ColorRed
end fn
 
void local fn drawBoard
int x, y,r = 1, add
cls
for y = 320 to 20 step -100
for x = 20 to 320 step 100
rect fill (x,y,98,98),color( bd[r] )
select bd[r]
case < 4 : add = 40
case < 7 : add = 30
case < 10 : add = 20
case else : add = 6
end select
if bd[r] then print %(x+add, y+25)2^bd[r]
r++
next
next
end fn
 
local fn finish( won as bool )
CFStringRef s = @"GAME OVER"
CGRect r = fn windowContentRect( 1 )
r.origin.y += r.size.height - 20
r.size.height = 100
window 2,,r,NSwindowStyleMaskBorderless
if won
fn windowSetBackgroundColor( 2, color(11) )
s = @"CONGRATULATIONS—YOU DID IT!!"
text,24,fn ColorBlack,,NSTextAlignmentCenter
else
fn windowSetBackgroundColor( 2, fn ColorBlack )
text,24,fn ColorWhite,,NSTextAlignmentCenter
end if
print s
button _new,,,@"New Game", (229,20,100,32)
button _end,,,@"Quit", (109,20,100,32)
end fn
 
void local fn newGame
int r
text @"Arial bold", 36, fn ColorBlack, fn ColorClear
bd = chr$(0)
for r = 1 to 4
bd += bd
next
bd[rnd(16)] ++
do
r = rnd(16)
until bd[r] == 0
bd[r]++
zs = 14
fn drawBoard
end fn
 
local fn play( st as short, rd as short, cd as short )
short a, b, c, t, moved = 0
for a = st to st + rd * 3 step rd
// SHIFT
t = a
for b = a to a + cd * 3 step cd
if bd[b]
if t <> b then swap bd[t], bd[b] : moved ++
t += cd
end if
next
// MERGE
for b = a to a + cd * 2 step cd
if bd[b] > 0 && bd[b] == bd[b+cd]
bd[b]++ : c = b + cd
// FILL IN
while c <> a+cd*3
bd[c] = bd[c+cd] : c += cd
wend
bd[c] = 0
// CHECK FOR WIN
if bd[b] == 11 then fn drawBoard : fn finish( yes ) : exit fn
zs ++ : moved ++
end if
next
next
fn drawBoard
if moved == 0 then exit fn
// GROW
b = 0 : c = rnd(zs)
while c
b ++
if bd[b] == 0 then c--
wend
if rnd(10) - 1 then bd[b]++ else bd[b] = 2
zs--
timerbegin 0.25
fn drawBoard
timerend
if zs then exit fn
// IS GAME OVER?
for a = 1 to 12
if bd[a] == bd[a+4] then exit fn
next
for a = 1 to 13 step 4
if bd[a] == bd[a+1] || bd[a+1] == bd[a+2] || bd[a+2] == bd[a+3]¬
then exit fn
next
fn finish( no )
end fn
 
local fn doDialog(ev as long,tag as long, wnd as long)
select ev
case _windowKeyDown : if window() == 2 then exit fn
select fn EventKeyCode
case _up : fn play(13, 1, -4)
case _dn : fn play( 1, 1, 4)
case _lf : fn play( 1, 4, 1)
case _rt : fn play( 4, 4, -1)
case else : exit fn
end select
DialogEventSetBool(yes)
case _btnClick : window close 2
if tag == _end then end
fn newGame
case _windowWillClose : if wnd == 1 then end
end select
end fn
 
fn initialize
fn newGame
on dialog fn doDialog
 
handleevents
</syntaxhighlight>
[[File:FutureBasic 2048.png]]
 
=={{header|Go}}==
 
<langsyntaxhighlight Golang="go">package main
 
import (
Line 7,072 ⟶ 8,573:
}
}
</syntaxhighlight>
</lang>
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import System.IO
import Data.List
import Data.Maybe
Line 7,207 ⟶ 8,708:
setCursorPosition 1 1
putStrLn $ intercalate "\n\n\n\ESC[C" $ concatMap showTile `map` pos
</syntaxhighlight>
</lang>
 
=={{header|J}}==
'''Solution'''
<langsyntaxhighlight lang="j">NB. 2048.ijs script
NB. =========================================================
NB. 2048 game engine
Line 7,316 ⟶ 8,817:
- start a new game:
grd=: g2048Con ''
)</langsyntaxhighlight>
'''Usage'''
<langsyntaxhighlight lang="j"> grd=: g2048Con ''
 
Score is 0
Line 7,337 ⟶ 8,838:
0 0 4 4
0 0 0 2
...</langsyntaxhighlight>
 
=={{header|Java}}==
[[File:game_2048_java2.png|300px|thumb|right]]
{{works with|Java|8}}
<langsyntaxhighlight lang="java">import java.awt.*;
import java.awt.event.*;
import java.util.Random;
Line 7,639 ⟶ 9,140:
return -1;
}
}</langsyntaxhighlight>
 
=={{header|JavaScript}}==
Uses the P5.js library.
<syntaxhighlight lang="javascript">
<lang JavaScript>
/* Tile object: */
 
Line 7,823 ⟶ 9,324:
game.keyHandler(keyCode);
}
</syntaxhighlight>
</lang>
 
=={{header|Julia}}==
Uses the Gtk toolkit. Includes scoring, a choice of board size and toolbar buttons for Undo and New Game.
<syntaxhighlight lang="julia">using Gtk.ShortNames
<lang julia>
using Gtk.ShortNames
 
@enum Direction2048 Right Left Up Down
Line 7,908 ⟶ 9,408:
toolbar = Toolbar()
newgame = ToolButton("New Game")
setpropertyset_gtk_property!(newgame, :label, "New Game")
setpropertyset_gtk_property!(newgame, :is_important, true)
undomove = ToolButton("Undo Move")
setpropertyset_gtk_property!(undomove, :label, "Undo Move")
setpropertyset_gtk_property!(undomove, :is_important, true)
map(w->push!(toolbar,w),[newgame,undomove])
grid = Grid()
map(w -> push!(box, w),[toolbar, grid])
buttons = Array{Gtk.GtkButtonLeaf,2}(undef, bsize, bsize)
for i in 1:bsize, j in 1:bsize
grid[i,j] = buttons[i,j] = Button()
setpropertyset_gtk_property!(buttons[i,j], :expand, true)
end
board = zeros(Int, (bsize,bsize))
Line 7,930 ⟶ 9,430:
function update!()
for i in 1:bsize, j in 1:bsize
label = (board[i,j] > 0) ? board[i,j] : " "
setpropertyset_gtk_property!(buttons[i,j], :label, label)
end
setpropertyset_gtk_property!(win, :title, "$won 2048 Game (Score: $score)")
end
function newrandomtile!()
Line 7,954 ⟶ 9,454:
for i in 1:bsize, j in 1:bsize
board[i,j] = 0
setpropertyset_gtk_property!(buttons[i,j], :label, " ")
end
newrandomtile!()
Line 7,991 ⟶ 9,491:
signal_connect(undo!,undomove, :clicked)
signal_connect(endit, win, :destroy)
signal_connect(keypress, win, "key-press-event")
Gtk.showall(win)
wait(condition)
end
Line 7,999 ⟶ 9,499:
const boardsize = 4
app2048(boardsize)
</syntaxhighlight>
</lang>
 
=={{header|Koka}}==
Based on F#
<syntaxhighlight lang="koka">
import std/num/random
import std/os/readline
 
val empty = list(0, 15).map(fn(_) 0)
fun win(l)
l.any(fn(x) x == 2048)
 
fun stack(l)
match l
Cons(0, tl) -> tl.stack ++ [0]
Cons(hd, tl) -> Cons(hd, tl.stack)
Nil -> Nil
 
fun join(l: list<int>)
match l
Cons(a, Cons(b, c)) | a == b -> Cons((a + b), c.join) ++ [0]
Cons(a, b) -> Cons(a, b.join)
Nil -> Nil
 
fun hit(l)
l.stack.join
 
fun hitBack(l)
l.reverse.hit.reverse
 
fun splitBy(l: list<a>, i: int): div list<list<a>>
val (a, b) = l.split(i)
match b
Cons -> Cons(a, b.splitBy(i))
Nil -> Cons(a, Nil)
 
fun transpose(l: list<list<a>>): <exn> list<list<a>>
match l
Cons(Cons(a, b), c) -> Cons(Cons(a, c.map(fn(x) x.head.unjust)), transpose(Cons(b, c.map(fn(x) x.tail)).unsafe-decreasing))
Cons(Nil, b) -> transpose(b)
Nil -> Nil
 
fun rows(l)
l.splitBy(4)
 
fun left(l)
l.rows.map(hit).concat
 
fun right(l)
l.rows.map(hitBack).concat
 
fun up(l)
l.rows.transpose.map(hit).transpose.concat
 
fun down(l)
l.rows.transpose.map(hitBack).transpose.concat
 
fun (==)(l1: list<int>, l2: list<int>): bool
match l1
Cons(a, b) -> match l2
Cons(c, d) -> a == c && b == d
Nil -> False
Nil -> match l2
Cons -> False
Nil -> True
 
fun lose(l)
l.left == l && l.right == l && l.up == l && l.down == l
 
fun numZeros(l: list<int>): int
l.filter(fn(x) x == 0).length
 
fun insert(l: list<int>, what: int, toWhere: int)
match l
Cons(0, tail) | tail.numZeros == toWhere -> Cons(what, tail)
Cons(head, tail) -> Cons(head, tail.insert(what, toWhere))
Nil -> Nil
 
fun spawnOn(l)
val newTileValue = if random-int() % 10 == 0 then 4 else 2
val newPosition = random-int() % (l.numZeros - 1)
l.insert(newTileValue, newPosition)
 
fun show-board(l: list<int>): div string
"\n" ++ l.rows.map(fn(r) r.map(fn(x) x.show.pad-left(4)).join("")).intersperse("\n").join("") ++ "\n"
 
fun quit(l)
[]
 
fun quitted(l)
l.is-nil
 
fun dispatch(c)
match c
'i' -> up
'j' -> left
'k' -> down
'l' -> right
'q' -> quit
_ ->
println("Unknown command: keys are ijkl to move, q to quit")
id
 
fun key()
readline().head-char.default('_')
 
fun turn(l)
l.show-board.println
val next = dispatch(key())(l)
if !(next == l) && next.quitted.not then
spawnOn(next)
else
next
 
fun play(state)
if state.win || state.lose || state.quitted then
if state.quitted then
"You quit!".println
else if state.win then
"You won!".println
else
"You lost!".println
else
"play".println
play(turn(state))
 
fun main()
print("ijkl to move, q to quit\n")
val initial = empty.spawnOn
println("Starting game...")
play(initial)
 
</syntaxhighlight>
 
=={{header|Kotlin}}==
Stateless with focus on clarity rather than conciseness.
 
<langsyntaxhighlight lang="scala">import java.io.BufferedReader
import java.io.InputStreamReader
 
Line 8,173 ⟶ 9,805:
}
println("+----+----+----+----+")
}</langsyntaxhighlight>
 
Sample output:
Line 8,194 ⟶ 9,826:
Takes input on stdin using the words "left", "right", "up", "down".
 
<syntaxhighlight lang="latitude">
<lang Latitude>
use 'format import '[format].
use 'random.
Line 8,421 ⟶ 10,053:
$stdout putln: "Better luck next time!".
}.
</syntaxhighlight>
</lang>
 
Sample output:
Line 8,437 ⟶ 10,069:
=={{header|Lua}}==
Sadly, ANSI C doesn't have low-level keyboard input, so neither does vanilla Lua, so the input is a bit cumbersome (wasd PLUS enter).
<langsyntaxhighlight lang="lua">-- 2048 for Lua 5.1-5.4, 12/3/2020 db
local unpack = unpack or table.unpack -- for 5.3 +/- compatibility
game = {
Line 8,512 ⟶ 10,144:
end
}
game:play()</langsyntaxhighlight>
{{out}}
<pre>+----+----+----+----+
Line 8,526 ⟶ 10,158:
 
=={{header|M2000 Interpreter}}==
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Game2048 {
\\ 10% 4 and 90% 2
Line 8,650 ⟶ 10,282:
}
Game2048
</syntaxhighlight>
</lang>
 
Each move copied to clipboard
Line 8,682 ⟶ 10,314:
 
Next is the main body of code:
<syntaxhighlight lang="maple">
<lang Maple>
macro(SP=DocumentTools:-SetProperty, GP=DocumentTools:-GetProperty);
G := module()
Line 8,902 ⟶ 10,534:
end module;
G:-reset();SP("Score/Lose",caption,"Click an Arrow to begin.");
</syntaxhighlight>
</lang>
 
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">SetOptions[InputNotebook[],NotebookEventActions->{
"LeftArrowKeyDown":>(stat=Coalesce[stat];AddNew[]),
"RightArrowKeyDown":>(stat=Reverse/@Coalesce[Reverse/@stat];AddNew[]),
Line 8,939 ⟶ 10,571:
 
stat=Nest[AddRandomNumber[#,RandomChoice[{2,4}]]&,ConstantArray[0,{n,n}],4];
Dynamic[PrintStat@stat]</langsyntaxhighlight>
 
 
=={{header|MATLAB}}==
 
<langsyntaxhighlight MATLABlang="matlab">function field = puzzle2048(field)
 
if nargin < 1 || isempty(field)
Line 9,075 ⟶ 10,707:
vector(vector==0) = [];
 
end</langsyntaxhighlight>
 
You can start with an empty 4 x 4 board and save the last state of the playing field with:
<langsyntaxhighlight MATLABlang="matlab">field = puzzle2048();</langsyntaxhighlight>
 
Or you start from a saved playing field:
<langsyntaxhighlight MATLABlang="matlab">field = puzzle2048(savedField);</langsyntaxhighlight>
 
=={{header|Nim}}==
Line 9,087 ⟶ 10,719:
{{works with|Nim Compiler|0.19.4}}
 
<langsyntaxhighlight lang="nim">import random, strutils, terminal
 
const
Line 9,271 ⟶ 10,903:
for i in 1..BoardLength + 7:
eraseLine()
cursorUp()</langsyntaxhighlight>
 
=={{header|OCaml}}==
 
<langsyntaxhighlight lang="ocaml">
let list_make x v =
let rec aux acc i =
Line 9,424 ⟶ 11,056:
loop grid
in
loop grid</langsyntaxhighlight>
 
{{out}}
Line 9,464 ⟶ 11,096:
 
=={{header|Pascal}}==
<syntaxhighlight lang="pascal">
<lang Pascal>
program game2048;
uses Crt;
Line 9,827 ⟶ 11,459:
until end_game;
end.
</syntaxhighlight>
</lang>
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">#!/usr/bin/perl
 
use strict; # https://rosettacode.org/wiki/2048
Line 9,916 ⟶ 11,548:
add2(2) for 1, 2;
$winner = '';
}</langsyntaxhighlight>
 
=={{header|Phix}}==
{{libheader|Phix/pGUI}}
{{libheader|Phix/online}}
Faithful desktop gui reproduction of the above link (https://gabrielecirulli.github.io/2048/)
Now I just got figure out how to win...
You can run this online [http://phix.x10.mx/p2js/2048.htm here].
<!--<lang Phix>-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">-- demo\rosetta\2048.exw</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
Line 9,949 ⟶ 11,584:
<span style="color: #004080;">integer</span> <span style="color: #000000;">newgame</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">prev</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nxt</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bxy</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">add_rand</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- (nb infinite loop if board is full)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">count</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- blank</span>
<span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">+(</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
Line 9,965 ⟶ 11,599:
<span style="color: #008080;">procedure</span> <span style="color: #000000;">move_x</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">bxy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">][</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bxy</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (not blank)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bxy</span><span style="color: #0000FF;">=</span><span style="color: #000000;">prev</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">][</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
Line 9,975 ⟶ 11,609:
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">prev</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- (blank)</span>
<span style="color: #008080;">or</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">nxt</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">prev</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span>
Line 9,993 ⟶ 11,627:
<span style="color: #008080;">procedure</span> <span style="color: #000000;">move_y</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">bxy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">][</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bxy</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (not blank)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bxy</span><span style="color: #0000FF;">=</span><span style="color: #000000;">prev</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">][</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
Line 10,003 ⟶ 11,637:
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">prev</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- (blank)</span>
<span style="color: #008080;">or</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">nxt</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">prev</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span>
Line 10,023 ⟶ 11,657:
<span style="color: #000080;font-style:italic;">-- a non-zero result means it changed something.</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">key</span><span style="color: #0000FF;">=</span><span style="color: #000000004600;">K_LEFT</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">13</span>
Line 10,031 ⟶ 11,665:
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">key</span><span style="color: #0000FF;">=</span><span style="color: #000000004600;">K_UP</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">13</span>
Line 10,039 ⟶ 11,673:
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">key</span><span style="color: #0000FF;">=</span><span style="color: #000000004600;">K_RIGHT</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">13</span>
Line 10,047 ⟶ 11,681:
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">key</span><span style="color: #0000FF;">=</span><span style="color: #000000004600;">K_DOWN</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">13</span>
Line 10,066 ⟶ 11,700:
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">valid_keys</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000004600;">K_LEFT</span><span style="color: #0000FF;">,</span><span style="color: #000000004600;">K_DOWN</span><span style="color: #0000FF;">,</span><span style="color: #000000004600;">K_RIGHT</span><span style="color: #0000FF;">,</span><span style="color: #000000004600;">K_UP</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">no_valid_moves</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">saved_board</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid_keys</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">move</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid_keys</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
Line 10,079 ⟶ 11,713:
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">redraw_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000080;font-style:italic;">/*posx*/</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">/*posy*/</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">txox</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tyoy</span><span style="color: #0000FF;">,</span> <span style="color: #000000000080;">bxy</span><span font-style="color: #0000FFitalic;">,-- top right coords</span>
<span style="color: #000000;">ox</span><span style="color: #0000FF;">,</span><span style="color: #000000;">oy</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- top right coords</span>
<span style="color: #000000;">os</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ts</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- overall and tile size</span>
<span style="color: #000000;">ts2</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- half tile, for number positioning</span>
Line 10,109 ⟶ 11,742:
<span style="color: #7060A8;">cdCanvasRoundedBox</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ox</span><span style="color: #0000FF;">+</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ox</span><span style="color: #0000FF;">+</span><span style="color: #000000;">os</span><span style="color: #0000FF;">-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">oy</span><span style="color: #0000FF;">+</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">oy</span><span style="color: #0000FF;">+</span><span style="color: #000000;">os</span><span style="color: #0000FF;">-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">tx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ox</span><span style="color: #0000FF;">+</span><span style="color: #000000;">15</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ty</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">oy</span><span style="color: #0000FF;">+</span><span style="color: #000000;">15</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">bxy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">][</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">cdCanvasSetForeground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tile_colours</span><span style="color: #0000FF;">[</span><span style="color: #000000;">bxy</span><span style="color: #0000FF;">])</span>
<span style="color: #7060A8;">cdCanvasRoundedBox</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tx</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">ts</span><span style="color: #0000FF;">-</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ty</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ty</span><span style="color: #0000FF;">+</span><span style="color: #000000;">ts</span><span style="color: #0000FF;">-</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bxy</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">cdCanvasSetForeground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bxy</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">3</span><span style="color: #0000FF;">?</span><span style="color: #000000;">#776E65</span><span style="color: #0000FF;">:</span><span style="color: #000000;">#F9F6F2</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">cdCanvasFont</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Calibri"</span><span style="color: #0000FF;">,</span> <span style="color: #000000004600;">CD_BOLD</span><span style="color: #0000FF;">,</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bxy</span><span style="color: #0000FF;">></span><span style="color: #000000;">10</span><span style="color: #0000FF;">?</span><span style="color: #000000;">32</span><span style="color: #0000FF;">:</span><span style="color: #000000;">40</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">cdCanvasText</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">ts2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ty</span><span style="color: #0000FF;">+</span><span style="color: #000000;">ts2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">25</span><span style="color: #0000FF;">-</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bxy</span><span style="color: #0000FF;"><</span><span style="color: #000000;">11</span><span style="color: #0000FF;">?</span><span style="color: #000000;">7</span><span style="color: #0000FF;">:</span><span style="color: #000000;">0</span><span style="color: #0000FF;">),</span> <span style="color: #7060A8;">sprint</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bxy</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
Line 10,132 ⟶ 11,765:
<span style="color: #000000;">cdcanvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_IUP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">cddbuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_DBUFFER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCanvasTextAlignmentcdCanvasSetTextAlignment</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000004600;">CD_SOUTH</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
Line 10,146 ⟶ 11,779:
<span style="color: #008080;">else</span>
<span style="color: #000000;">add_rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- repaintWindow(main)</span>
<span style="color: #7060A8;">IupUpdate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">no_valid_moves</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">then</span>
Line 10,153 ⟶ 11,785:
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mbmsg</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">IupAlarmplatform</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Game Over"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mbmsg</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Yes"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"No"</span><span style="color: #0000FF;">)=</span><span style="color: #000000004600;">1JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupMessage</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Game Over"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mbmsg</span><span style="color: #0000FF;">);</span>
<span style="color: #000000;">newgame</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">IupAlarm</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Game Over"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mbmsg</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Yes"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"No"</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CLOSE</span>
<span style="color: #000000;">newgame</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CLOSE</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
Line 10,186 ⟶ 11,823:
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<!--</langsyntaxhighlight>-->
 
=={{header|PHP}}==
Works from PHP5 and upwards in CLI mode.
<syntaxhighlight lang="php">
<lang PHP>
<?php
 
Line 10,418 ⟶ 12,055:
 
}
</syntaxhighlight>
</lang>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/simul.l")
 
(symbols 'simul 'pico)
 
(seed (in "/dev/urandom" (rd 8)))
Line 10,553 ⟶ 12,192:
(T (fish '((This) (= 512 (: N))) *G)
(println 'Maximum) ) )
(bye)</langsyntaxhighlight>
 
=={{header|Pony}}==
{{works with|ponyc|0.10.0}}
<langsyntaxhighlight lang="pony">
use "term"
use "random"
Line 10,824 ⟶ 12,463:
 
input(consume notify)
</syntaxhighlight>
</lang>
 
=={{header|Prolog}}==
Works with swi-prolog, any version.
<langsyntaxhighlight Prologlang="prolog">/* -------------------------------------------------------------
Entry point, just create a blank grid and enter a 'game loop'
-------------------------------------------------------------*/
Line 10,986 ⟶ 12,625:
dbl(' ', ' ').
dbl(2,4). dbl(4,8). dbl(8,16). dbl(16,32). dbl(32,64). dbl(64,128). dbl(128,256). dbl(256,512). dbl(512,1028). dbl(1028,2048).
</syntaxhighlight>
</lang>
{{out}}
<pre>?- play_2048.
Line 11,006 ⟶ 12,645:
=={{header|Python}}==
===Python: Original, with output===
<langsyntaxhighlight lang="python">#!/usr/bin/env python3
 
import curses
Line 11,207 ⟶ 12,846:
 
curses.wrapper(main)
</syntaxhighlight>
</lang>
 
===Python: using tkinter===
<langsyntaxhighlight lang="python">#!/usr/bin/env python3
 
''' Python 3.6.5 code using Tkinter graphical user interface.
Line 11,504 ⟶ 13,143:
root.bind_all('<Key>', g.key)
root.mainloop()
</syntaxhighlight>
</lang>
 
=={{header|QB64}}==
<syntaxhighlight lang="qb64">
<lang QB64>
_DEFINE A-Z AS _INTEGER64
DIM SHARED Grid(0 TO 5, 0 TO 5) AS INTEGER
Line 11,795 ⟶ 13,434:
COLOR dc&, bg&
END SUB
</syntaxhighlight>
</lang>
 
=={{header|R}}==
orginal R package : https://github.com/ThinkRstat/r2048
<syntaxhighlight lang="r">
<lang R>
GD <- function(vec) {
c(vec[vec != 0], vec[vec == 0])
Line 11,963 ⟶ 13,602:
}
 
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
Line 11,969 ⟶ 13,608:
Play the RacketScript fork online here: http://rapture.twistedplane.com:8080/#example/2048-game
 
<syntaxhighlight lang="racket">
<lang Racket>
;; LICENSE: See License file LICENSE (MIT license)
;;
Line 12,774 ⟶ 14,413:
 
(start)
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
Line 12,780 ⟶ 14,419:
Uses termios to set the terminal options, so only compatible with POSIX terminals. This version does not include a specific "win" or "lose" condition. (though it would be trivial to add them.) You can continue to play this even after getting a 2048 tile; and if there is no valid move you can make, you can't do anything but quit.
{{works with|Rakudo|2018.05}}
<syntaxhighlight lang="raku" perl6line>use Term::termios;
 
constant $saved = Term::termios.new(fd => 1).getattr;
Line 12,894 ⟶ 14,533:
move %dir{$key} if so %dir{$key};
last if $key eq 'q'; # (q)uit
}</langsyntaxhighlight>
Sample output:
<pre>
Line 12,919 ⟶ 14,558:
{{works with|Red|0.6.4}}
 
<langsyntaxhighlight Redlang="red">Red [Needs: 'View]
 
random/seed now
Line 13,007 ⟶ 14,646:
display
view lay
</syntaxhighlight>
</lang>
 
{{out}}
Line 13,026 ⟶ 14,665:
::* &nbsp; displays a message if a winning move was entered.
::* &nbsp; displays the game board as a grid &nbsp; (with boxes).
<langsyntaxhighlight lang="rexx">/*REXX program lets a user play the 2048 game on an NxN grid (default is 4x4 grid).*/
parse arg N win seed . /*obtain optional arguments from the CL*/
if N=='' | N=="," then N= 4 /*Not specified? Then use the default.*/
Line 13,115 ⟶ 14,754:
do s=r to sTo by #; @.s.c= @(s + #, c) /*slide ↑ or ↓ */
end /*s*/; @.sTo.c= b /*handle the last one.*/
end /*r*/; return</langsyntaxhighlight>
Programming note: &nbsp; with a little more program complexity, &nbsp; the &nbsp; '''moveLR''' &nbsp; and &nbsp; '''moveUD''' &nbsp; subroutines could've
<br>been combined, &nbsp; as well as the &nbsp; '''packLR''' &nbsp; and &nbsp; '''packUD''' &nbsp; subroutines.
Line 13,284 ⟶ 14,923:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : 2048 Game
 
Line 13,721 ⟶ 15,360:
on '2048' setStylesheet(C_BUTTON2048STYLE)
off
</syntaxhighlight>
</lang>
 
=={{header|Ruby}}==
inspired by the Raku version
<langsyntaxhighlight lang="ruby">
#!/usr/bin/ruby
 
Line 13,924 ⟶ 15,563:
end
end
</syntaxhighlight>
</lang>
 
=={{header|Rust}}==
Line 13,930 ⟶ 15,569:
A simple implementation in rust. The user has to input an endline since i did not find a way to read a key press
{{libheader|rand}}
<langsyntaxhighlight lang="rust">
use std::io::{self,BufRead};
extern crate rand;
Line 14,115 ⟶ 15,754:
}
}
</syntaxhighlight>
</lang>
 
=={{header|Scala}}==
<langsyntaxhighlight lang="scala">import java.awt.event.{KeyAdapter, KeyEvent, MouseAdapter, MouseEvent}
import java.awt.{BorderLayout, Color, Dimension, Font, Graphics2D, Graphics, RenderingHints}
import java.util.Random
Line 14,310 ⟶ 15,949:
}
 
}</langsyntaxhighlight>
 
=={{header|Seed7}}==
Line 14,322 ⟶ 15,961:
STD_CONSOLE works also always the same, independent from the operating system or terminal/console.
 
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "console.s7i";
include "keybd.s7i";
Line 14,511 ⟶ 16,150:
until moveOkay;
until quit;
end func;</langsyntaxhighlight>
 
=={{header|Tcl}}==
===Text mode===
<langsyntaxhighlight lang="tcl">
# A minimal implementation of the game 2048 in Tcl.
# For a maintained version with expanded functionality see
Line 14,792 ⟶ 16,431:
 
main
</syntaxhighlight>
</lang>
 
===Tk===
See https://tcl.wiki/39566.
 
=={{header|XPL0}}==
<lang XPL0>include c:\cxpl\codes; \intrinsic 'code' declarations
int Box(16), Moved;
 
proc ShiftTiles(I0, DI); \Shift tiles, add adjacents, shift again
int I0, DI;
int Done, M, N, I;
[Done:= false;
loop [for M:= 1 to 3 do \shift all tiles in a single row or column
[I:= I0;
for N:= 1 to 3 do
[if Box(I)=0 & Box(I+DI)#0 then
[Box(I):= Box(I+DI); Box(I+DI):= 0; Moved:= true];
I:= I+DI;
];
];
if Done then return;
Done:= true;
I:= I0; \add identical adjacent tiles into a new tile
for N:= 1 to 3 do
[if Box(I)=Box(I+DI) & Box(I)#0 then
[Box(I):= Box(I)+1; Box(I+DI):= 0; Moved:= true];
I:= I+DI;
];
]; \loop back to close any gaps that were opened
]; \ShiftTiles
 
int I, J, X, Y, C;
[Clear;
for I:= 0 to 15 do Box(I):= 0; \empty the box of tiles
loop [repeat I:= Ran(16) until Box(I)=0; \in a random empty location
Box(I):= if Ran(10) then 1 else 2; \insert a 2^1=2 or 2^2=4
for I:= 0 to 15 do \show board with its tiles
[X:= ((I&3)+5)*6; \get coordinates of tile
Y:= I>>2*3+6;
Attrib(((Box(I)+1)&7)<<4 + $F);\set color based on tile value
for J:= 0 to 2 do \draw a square (6*8x3*16)
[Cursor(X, Y+J);
Text(6, " ");
];
if Box(I)#0 then \box contains a tile
[J:= 1; \center numbers somewhat
if Box(I) <= 9 then J:= 2;
if Box(I) <= 3 then J:= 3;
Cursor(X+J, Y+1);
IntOut(6, 1<<Box(I));
];
];
Moved:= false; \a tile must move to continue
repeat repeat C:= ChIn(1) until C#0; \get key scan code, or ASCII
for I:= 3 downto 0 do \for all rows or columns
[case C of
$4B: ShiftTiles(I*4, 1); \left arrow
$4D: ShiftTiles(I*4+3, -1); \right arrow
$50: ShiftTiles(I+12, -4); \down arrow
$48: ShiftTiles(I, 4); \up arrow
$1B: [Clear; exit] \Esc
other []; \ignore all other keys
];
until Moved;
];
]</lang>
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<langsyntaxhighlight lang="vbnet">Friend Class Tile
Public Sub New()
Me.Value = 0
Line 15,100 ⟶ 16,677:
End Sub
End Module
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 15,118 ⟶ 16,695:
(W) Up (S) Down (A) Left (D) Right
</pre>
 
=={{header|Wren}}==
{{trans|C#}}
{{libheader|Wren-dynamic}}
{{libheader|Wren-ioutil}}
{{libheader|Wren-fmt}}
{{libheader|Wren-str}}
<syntaxhighlight lang="wren">import "./dynamic" for Enum, Struct
import "random" for Random
import "./ioutil" for Input
import "./fmt" for Fmt
import "./str" for Str
 
var MoveDirection = Enum.create("MoveDirection", ["up", "down", "left", "right"])
 
var Tile = Struct.create("Tile", ["value", "isBlocked"])
 
class G2048 {
construct new() {
_isDone = false
_isWon = false
_isMoved = true
_score = 0
_board = List.filled(4, null)
for (i in 0..3) {
_board[i] = List.filled(4, null)
for (j in 0..3) _board[i][j] = Tile.new(0, false)
}
_rand = Random.new()
initializeBoard()
}
 
initializeBoard() {
for (y in 0..3) {
for (x in 0..3) _board[x][y] = Tile.new(0, false)
}
}
 
loop() {
addTile()
while (true) {
if (_isMoved) addTile()
drawBoard()
if (_isDone) break
waitKey()
}
var endMessage = _isWon ? "You've made it!" : "Game Over!"
System.print(endMessage)
}
 
drawBoard() {
System.print("\e[2J") // clear terminal
System.print("Score: %(_score)\n")
for (y in 0..3) {
System.print("+------+------+------+------+")
System.write("| ")
for (x in 0..3) {
if (_board[x][y].value == 0) {
System.write(" ")
} else {
Fmt.write("$-4s", _board[x][y].value)
}
System.write(" | ")
}
System.print()
}
System.print("+------+------+------+------+\n\n")
}
 
waitKey() {
_isMoved = false
var input = Str.upper(Input.option("(W) Up (S) Down (A) Left (D) Right: ", "WSADwsad"))
if (input == "W") {
move(MoveDirection.up)
} else if (input == "A") {
move(MoveDirection.left)
} else if (input == "S") {
move(MoveDirection.down)
} else if (input == "D") {
move(MoveDirection.right)
}
for (y in 0..3) {
for (x in 0..3) _board[x][y].isBlocked = false
}
}
 
addTile() {
for (y in 0..3) {
for (x in 0..3) {
if (_board[x][y].value != 0) continue
var a
var b
while (true) {
a = _rand.int(4)
b = _rand.int(4)
if (_board[a][b].value == 0) break
}
var r = _rand.float()
_board[a][b].value = (r > 0.89) ? 4 : 2
if (canMove()) return
}
}
_isDone = true
}
 
canMove() {
for (y in 0..3) {
for (x in 0..3) {
if (_board[x][y].value == 0) return true
}
}
 
for (y in 0..3) {
for (x in 0..3) {
if (testAdd(x + 1, y, _board[x][y].value) ||
testAdd(x - 1, y, _board[x][y].value) ||
testAdd(x, y + 1, _board[x][y].value) ||
testAdd(x, y - 1, _board[x][y].value)) return true
}
}
 
return false
}
 
testAdd(x, y, value) {
if (x < 0 || x > 3 || y < 0 || y > 3) return false
return _board[x][y].value == value
}
 
moveVertically(x, y, d) {
if (_board[x][y + d].value != 0 &&
_board[x][y + d].value == _board[x][y].value &&
!_board[x][y].isBlocked &&
!_board[x][y + d].isBlocked) {
_board[x][y].value = 0
_board[x][y + d].value = _board[x][y + d].value * 2
_score = _score + _board[x][y + d].value
_board[x][y + d].isBlocked = true
_isMoved = true
} else if (_board[x][y + d].value == 0 && _board[x][y].value != 0) {
_board[x][y + d].value = _board[x][y].value
_board[x][y].value = 0
_isMoved = true
}
 
if (d > 0) {
if (y + d < 3) moveVertically(x, y + d, 1)
} else {
if (y + d > 0) moveVertically(x, y + d, -1)
}
}
 
moveHorizontally(x, y, d) {
if (_board[x + d][y].value != 0 &&
_board[x + d][y].value == _board[x][y].value &&
!_board[x + d][y].isBlocked &&
!_board[x][y].isBlocked) {
_board[x][y].value = 0
_board[x + d][y].value = _board[x + d][y].value * 2
_score = _score + _board[x + d][y].value
_board[x + d][y].isBlocked = true
_isMoved = true
} else if (_board[x + d][y].value == 0 && _board[x][y].value != 0) {
_board[x + d][y].value = _board[x][y].value
_board[x][y].value = 0
_isMoved = true
}
 
if (d > 0) {
if (x + d < 3) moveHorizontally(x + d, y, 1)
} else {
if (x + d > 0) moveHorizontally(x + d, y, -1)
}
}
 
move(direction) {
if (direction == MoveDirection.up) {
for (x in 0..3) {
for (y in 1..3) {
if (_board[x][y].value != 0) moveVertically(x, y, -1)
}
}
} else if (direction == MoveDirection.down) {
for (x in 0..3) {
for (y in 2..0) {
if (_board[x][y].value != 0) moveVertically(x, y, 1)
}
}
} else if (direction == MoveDirection.left) {
for (y in 0..3) {
for (x in 1..3) {
if (_board[x][y].value != 0) moveHorizontally(x, y, -1)
}
}
} else if (direction == MoveDirection.right) {
for (y in 0..3) {
for (x in 2..0) {
if (_board[x][y].value != 0) moveHorizontally(x, y, 1)
}
}
}
}
}
 
var runGame // forward declaration
 
var checkRestart = Fn.new {
var input = Str.upper(Input.option("(N) New game (P) Exit: ", "NPnp"))
if (input == "N") {
runGame.call()
} else if (input == "P") return
}
 
runGame = Fn.new {
var game = G2048.new()
game.loop()
checkRestart.call()
}
 
runGame.call()</syntaxhighlight>
 
{{out}}
Sample game:
<pre>
Score: 3016
 
+------+------+------+------+
| 2 | 8 | 2 | 4 |
+------+------+------+------+
| 16 | 64 | 128 | 2 |
+------+------+------+------+
| 8 | 256 | 4 | 8 |
+------+------+------+------+
| 2 | 4 | 2 | 32 |
+------+------+------+------+
 
 
Game Over!
(N) New game (P) Exit: p
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang="xpl0">include c:\cxpl\codes; \intrinsic 'code' declarations
int Box(16), Moved;
 
proc ShiftTiles(I0, DI); \Shift tiles, add adjacents, shift again
int I0, DI;
int Done, M, N, I;
[Done:= false;
loop [for M:= 1 to 3 do \shift all tiles in a single row or column
[I:= I0;
for N:= 1 to 3 do
[if Box(I)=0 & Box(I+DI)#0 then
[Box(I):= Box(I+DI); Box(I+DI):= 0; Moved:= true];
I:= I+DI;
];
];
if Done then return;
Done:= true;
I:= I0; \add identical adjacent tiles into a new tile
for N:= 1 to 3 do
[if Box(I)=Box(I+DI) & Box(I)#0 then
[Box(I):= Box(I)+1; Box(I+DI):= 0; Moved:= true];
I:= I+DI;
];
]; \loop back to close any gaps that were opened
]; \ShiftTiles
 
int I, J, X, Y, C;
[Clear;
for I:= 0 to 15 do Box(I):= 0; \empty the box of tiles
loop [repeat I:= Ran(16) until Box(I)=0; \in a random empty location
Box(I):= if Ran(10) then 1 else 2; \insert a 2^1=2 or 2^2=4
for I:= 0 to 15 do \show board with its tiles
[X:= ((I&3)+5)*6; \get coordinates of tile
Y:= I>>2*3+6;
Attrib(((Box(I)+1)&7)<<4 + $F);\set color based on tile value
for J:= 0 to 2 do \draw a square (6*8x3*16)
[Cursor(X, Y+J);
Text(6, " ");
];
if Box(I)#0 then \box contains a tile
[J:= 1; \center numbers somewhat
if Box(I) <= 9 then J:= 2;
if Box(I) <= 3 then J:= 3;
Cursor(X+J, Y+1);
IntOut(6, 1<<Box(I));
];
];
Moved:= false; \a tile must move to continue
repeat repeat C:= ChIn(1) until C#0; \get key scan code, or ASCII
for I:= 3 downto 0 do \for all rows or columns
[case C of
$4B: ShiftTiles(I*4, 1); \left arrow
$4D: ShiftTiles(I*4+3, -1); \right arrow
$50: ShiftTiles(I+12, -4); \down arrow
$48: ShiftTiles(I, 4); \up arrow
$1B: [Clear; exit] \Esc
other []; \ignore all other keys
];
until Moved;
];
]</syntaxhighlight>
408

edits