2048 in C / C++

2048 is perhaps one of the most addictive mathematical puzzle games. For starters, it is played on a 4 × 4 game board which begins with an initial configuration of two tiles, of value 2 or 4, placed at arbitrary locations on the grid.

The player then selects to move Up, Down, Left, or Right. Each move shifts all tiles on the grid in the direction chosen. If two adjacent tiles have the same value, they combine, and the single resulting tile after the combination will be the sum (twice). Following the player’s move, a tile of value 2 or 4 will be generated at a random position on the board.

The goal of the game is to combine equally-valued tiles to reach the 2048 tile without getting stuck.

HOW I CODED 2048  ( Source code at the end of this page)

9

THE LOOP

  1. Display the grid.
  2. Take direction input.
  3. Check for game-over.
  4. Update the grid.
  5. Spawn a new tile.
  6. Refresh the grid.

LAYOUT

First thing you notice is that the game is basically a 4×4 matrix, a two dimensional array. Initialize all elements in it to zero. But then the empty tiles do not display ‘0’ on the game, so while printing the array elements, if the element is zero, print a space.

INPUT WITHOUT PRESSING ENTER KEY

You don’t want to press enter after every key press, a quick and easy way would be to modify the Linux Terminal behavior using 2 system functions. ( Beware, System() functions are vulnerable. Read here )

system("stty raw");
cin>>control;
system("stty cooked");

ESSENTIAL VARIABLES AND FUNCTIONS

> We require 2 grids, one that keeps the current state of the game ( current grid ) and another that keeps the previous state , i.e a move before ( backup grid ). The backup grid serves 2 purposes:

  1. For the UNDO functionality, resuming to the previous state.
  2. To check if the grid moves.

> Random function to generate random positions ( rows and columns ) for the initial two tiles on the board and for the further tiles which will be generated on each move. The thing to note here is that probability of occurrence of 4 is less than that of 2.

> Greatest function to find the greatest tile in the grid at any state ( max tile ).

MOVING TILES IN THE GRID

// Case of Moving UP
for(int i=0; i<4 ;i++)       // Traverse from Top to bottom of a column
   for(int j=0; j<4 ;j++)
   {
      if(!grid[j][i])    // If tile is empty
      {
         for(int k=j+1; k<4 ;k++)  // Traverse below to find a non-zero element
            if(grid[k][i])
            {
               grid[j][i]=grid[k][i]; // Move the non-zero element to the empty tile
               grid[k][i]=0;          // Assign the non-zero element with zero
               break;
            }
      }
  }

10

UPDATING THE GRID

  • Check if adjacent tile is equal.
  • Sum / double the tile(s) if they are equal.
// When moving UP 

if(grid[j][i]&&grid[j][i]==grid[j+1][i]) // Check Tile is non zero and
{                                        // adjacent tile is equal
   grid[j][i]+=grid[j+1][i];             // add to first element or double
   grid[j+1][i]=0;                       // assign second element with zero
}

11

GAME OVER LOGIC

12

13

The game ends when

  • Grid is full and a new tile cannot be spawned.
  • The game is won, 2048 has been created.

To check whether the grid is full, check if all the elements are non-zero. Spawn mentioned below.

14

To check whether the game is won, check If the max tile is equal to the win (2048), display the win screen and update the win to win*2 ( 4096, 8192, 16384 …)

SPAWNING A NEW TILE

With every move, a new tile should be spawned in a random position under the condition that the selected direction moves at least 1 tile in the grid. So this is where the backup grid comes into use, before updating the grid :

  • Check if the current grid is equal to the backup grid.

So that we know if at least one tile in the grid has moved. Then spawn a new tile in an empty cell.

SCORING ALGORITHM

Merging two lower tier blocks together will give you the score of the higher tier block (score of +8 gained from merging two 4’s). For any specific tile score, you have to add up all the scores from the lower tiers.

  • Creating a 2 tile = +0pts
  • Creating a 4 tile = 4 = +4pts
  • Creating a 8 tile = 8 + 2×4 = +16pts
  • Creating a 16 tile = 16 + 2×8 + 4×4 = +48pts
  • Creating a 32 tile = 32 + 2×16 + 4×8 + 8×4 = +128pts …

Which can be simplified as

  • Tile 21 = 0 x 21 = 0pts
  • Tile 22 = 1 x 22 = 4pts
  • Tile 23 = 2 x 23 = 16pts
  • Tile 24 = 3 x 24 = 48pts

i.e tile-value times ( one less than ( log of tile-value to the base 2 ))

So the algorithm would be:

score+=(((log2(grid[j][i]))-1)*grid[j][i]);

 

UNDO

To perform UNDO operation, copy the backup grid to the current grid.

 

RANDOM GENERATION

Make the computer play the game on its own ! For that, remove the input call and  create a char array with all the four direction keys ( w,a,s,d ) and choose a key in random. But if you’ve played 2048 long enough, you’d know that skipping a direction is the best strategy, so choose any 3 directions.

char keys[]="wad";
input=keys[rand()%3+0;]; // this function chooses 0,1 or 2 randomly
                           // assigns key in that index to input variable

 

SOURCE CODE

CPP here
C will be posted soon
Advertisements