# Project 13

In this project we practice to use the Jack language. Start with the template in pp13.zip.

The task is to implement the 2048 game. I'm making your life very easy—all you have to do is to finish the implementation of the Board class. (You must not touch the three other source files.)

In particular, you need to finish seven methods: the constructor, drawField, insert, pushLeft, pushUp, pushRight, and pushDown. You can create additional internal methods, if you like.

If you are not familiar with the game, you can try my web-based implementation. It is written in Kotlin and compiled to Javascript, so that it runs in your web browser. Use the keys L, R, U, D to push the blocks.

#### Compiling and running

To compile, it suffices to call JackCompiler inside the directory containing the four source files. It will automatically compile all four files to VM files.

Then start the VMEmulator, use "Load program" and select the directory containing the four VM files. Turn animation off, set the speed to fastest, and run the code.

#### Constructor

The constructor needs to create an array with 16 cells, set them all to zero, and store the array reference in the field a.

#### drawField

This method draws each cell of the 4x4 board. You need to handle cells with contents zero differently, so that the output will look like this:

In particular, the 0 is not displayed, and the boundary is thinner than for number tiles.

#### insert

The insert method randomly selects an empty cell (a cell with contents zero) and set its contents to $$2$$ or $$4$$. You should set the cell to $$2$$ with probability 90%, and to $$4$$ with probability 10%.

Use the function LCGRandom.randRange(a, b). It will return a random number in the range from a to b (inclusive).

The function must return true if it inserted a new number, and false if the board is full and nothing can be inserted.

#### Pushing

The 2048 game has four basic moves: Pushing cells left, right, up, and down. The four methods pushLeft(), pushRight(), pushUp(), and pushDown() implement these moves.

Here is a precise description of the move, for the example of pushLeft():

• The left push happens independently on each row.
• Each non-empty cell moves as far to the left as possible. For instance, the row 0 2 0 4 becomes 2 4 0 0.
• When a cell moves to the left and hits another cell with the same value, then the two cells merge. The value of the merged cell is the sum of the two original cells. For instance, the row 0 2 0 2 becomes 4 0 0 0.
• A cell that is created by merging cannot merge again in the same left push. For instance, the row 0 2 2 4 will become 4 4 0 0 (the second 2 hits the first 2 and merges to become 4, but the second 4 cannot merge with this one). So the row 2 2 4 4 would become 4 8 0 0.
• Every time two cells merge, you receive the value of the newly created cell as points.
The pushLeft method returns the number of points received by the left push.

Here are some examples to clarify the rules:

>>> b
o----o----o----o----o
|    |    |    |    |
|  2 |  2 |    |    |
|    |    |    |    |
o----o----o----o----o
|    |    |    |    |
|  4 |    |  2 |  2 |
|    |    |    |    |
o----o----o----o----o
|    |    |    |    |
|  2 |  2 |    |    |
|    |    |    |    |
o----o----o----o----o
|    |    |    |    |
|    |  2 |    |  4 |
|    |    |    |    |
o----o----o----o----o

>>> b.pushLeft()
12
>>> b
o----o----o----o----o
|    |    |    |    |
|  4 |    |    |    |
|    |    |    |    |
o----o----o----o----o
|    |    |    |    |
|  4 |  4 |    |    |
|    |    |    |    |
o----o----o----o----o
|    |    |    |    |
|  4 |    |    |    |
|    |    |    |    |
o----o----o----o----o
|    |    |    |    |
|  2 |  4 |    |    |
|    |    |    |    |
o----o----o----o----o

>>> b.insert(); b.insert()
>>> b
o----o----o----o----o
|    |    |    |    |
|  4 |    |    |    |
|    |    |    |    |
o----o----o----o----o
|    |    |    |    |
|  4 |  4 |    |    |
|    |    |    |    |
o----o----o----o----o
|    |    |    |    |
|  4 |    |    |    |
|    |    |    |    |
o----o----o----o----o
|    |    |    |    |
|  2 |  4 |  2 |  2 |
|    |    |    |    |
o----o----o----o----o

>>> b.pushLeft()
12
>>> b
o----o----o----o----o
|    |    |    |    |
|  4 |    |    |    |
|    |    |    |    |
o----o----o----o----o
|    |    |    |    |
|  8 |    |    |    |
|    |    |    |    |
o----o----o----o----o
|    |    |    |    |
|  4 |    |    |    |
|    |    |    |    |
o----o----o----o----o
|    |    |    |    |
|  2 |  4 |  4 |    |
|    |    |    |    |
o----o----o----o----o


The other three moves work exactly the same, only the direction is different. One way to implement this would be to write private methods for mirroring the board horizontally and for transposing it (that is, flipping rows and columns). Then you can implement the right push as mirror, left push, mirror, and the upwards push as transpose, left push, transpose, etc.

Upload Board.jack to our submission server.