CS计算机代考程序代写 jvm Java gui cache junit CS 61BL Summer 2021

CS 61BL Summer 2021
About Beacon Ed Gradescope Queue Resources Staff
Project 0: 2048
Introduction
Getting Started
Partnerships
Intellij Setup
The Game
Assignment Philosophy and Program Design Getting Started
The Model Class and Constructors The Methods
The Game Logic
Tips and Tricks
Testing
Submission and Version Control Frequently Asked Questions Getting Help Acknowledgements
Note: The due date has been extended to 6/27 at 11:59pm
􏰀

Introduction Learning Goals
The goal of this project is to give you a crash course in Java. Since CS 61BL is not intended to be a course about Java, we will be moving quickly, learning fundamental aspects of the Java language in just two weeks.
Before starting this project, we are assuming that you either have prior Java experience, or have done the rst few labs and also (ideally) completed Java introduction. In addition, Chapter 1.1 and Chapter 1.2 of our online textbook can also be of help if you’d like a refresher on the material, or if you nd yourself stuck anywhere.
The main purpose of this project is to help you build some comfort with the material in these rst few weeks of the course, so it’s not necessary to have a deep understanding of everything just yet.
Unlike later projects, this assignment has a great deal of scaffolding. Future assignments will require signicantly more independence. For this project, we recommend that you work in pairs with a partner from your lab section.
Overview
A high level overview of this project can be found at https://youtu.be/Xzihuj_JZBI.
The intent of this project is to give you a chance to get familiar with Java and the various tools used in the course like the IntelliJ IDE and JUnit for writing and running unit tests. Though you’ll nd many les and lots of code in the proj0 folder, your task only resides in Model.java and is constrained to just four methods and two constructors.

We will be grading solely on whether you manage to get your program to work (according to our tests) and to hand in the assigned pieces. There are no hidden tests.
The spec for this assignment is quite long, and there is a lot of starter code. We recommend that you read the entire spec before you start doing any programming. It will probably feel overwhelming at rst. You’ll probably need to reread sections of the spec several times to fully digest it, and some of the later parts might not make total sense until you’ve nished earlier parts of the project. Ultimately, we hope you leave this experience with a sense of empowerment that you were able to navigate such a large task.
If you run into problems, be sure to check out the FAQ section before posting to Ed. We’ll keep this section updated as questions arise during the assignment. Always try googling before asking questions on Ed. Knowing how to nd what you want on Google is a valuable skill. However, know when to give up! If you start getting frustrated with your search attempts, then turn to Ed.
Getting Started
Before proceeding, make sure you have completed Lab 1 and any required setup if using your own computer.
Partnerships
Make sure you have submitted the partner registration form so that your submission will not be flagged by the cheating detection software.
The above link will give you the ability to create a partnership.
Note that changing team repository partners requires instructor assistance!

Get the project skeleton
Now, as with Lab01, make sure you have the latest copy of the skeleton les.
Merging Git histories
If the folder you’re pulling into already has an older copy of the skeleton repository (from lab 1, for example), this will cause a so-called
merge . The text editor you congured from lab 1 will automatically open asking you to provide a message on why you are merging.
If everything from lab 1 went correctly and the text editor you expected was what opened up, save and close the le like you would any other le.
If an unexpected, in-terminal text editor opened up, don’t panic. We need to rst identify which editor it is. Sometimes, your terminal’s title bar will tell you what program is currently running, but other times, we’ll need to rely on what the editor looks like to gure it out. (Sorry—there’s no better way to do it than that!)
Depending on the settings on the computer you’re using, you will possibly nd yourself in one of three terminal-based text editors:
nano
See the Gentoo Wiki. vim
See this StackOverflow post. emacs
git pull skeleton main

If you’re not in nano or vim, you’re probably in emacs. See this clever post from Emacs Doctor.
Once you’ve successfully merged, you should see an game2048 directory appear with les that match the skeleton repository.
Note that if you did not already have a copy of the skeleton repo in your current folder, you will not be asked for a merge message.
If you somehow end up having a merge conflict, consult the git weird technical failure scenarios.
If you get some sort of error, stop and either gure it out by carefully reading the git guide or seek help from a lab assistant. You’ll potentially save yourself a lot of trouble vs. guess-and-check with git commands. If you nd yourself trying to use commands you Google that involve
force or hard : don’t. Intellij Setup
If you haven’t downloaded/set up IntelliJ yet, follow the instructions in lab01.
Let’s now open the les in IntelliJ. Firstly, launch IntelliJ. It will show you a list of your recent projects, but since you haven’t started this assignment yet, it won’t be there. To open the project, click the “Open” button at the top right of the application window which should bring up your operating system’s le browser. Navigate to the proj0 folder in your student repo, and then hit open. Note the images below use an older version of IntelliJ, but the steps are the same.

On the top left of the screen, you’ll see a list of the les/folders inside the directory. If you don’t, click the down arrow on the
folder which will expand the folder below. It should look like this:
proj0
proj0

The .idea folder is something that IntelliJ generates to store miscellaneous settings. You can ignore this folder.
The game2048 folder is the source for all the Java les. Everything you need to do lies in this folder.
The library-su21/ folder is a Java library. It holds eight .jar les which are pre-compiled les of things we want to use. The three les it has allow us to run JUnit and then some UC Berkeley specic things to render the game in a nice window.
If you need to update your library, the following command should do the trick:
IntelliJ is usually smart enough to set up the rest of the things for you, but in case your IntelliJ application is having a hard time we’ll walk through the setup procedures.
Firstly, let’s tell IntelliJ that we’re using Java 15. Navigate to File > Project Structure:
cd library-su21/ && git submodule update –init
–recursive && cd ..

Click on the box on the left-hand side of the “Edit” button which should allow you to select your JDK (i.e. your version of Java). Now we’ll tell IntelliJ that we want to use those .jar les in the library- su21/ folder. Still in the Project Structure, on the left-hand side click the secttion of the Project Settings called “Library”. If you see that
library-su21/ is already added, there is nothing to do. Else, we will click on the “+” button and then “Java” which will launch our operating system’s le browser, and we’ll click on the library-su21/ folder. Then, in the bottom right of the screen, hit “Apply” and then the blue “OK” button.

In all, the setup would look like this:
Then, open the game2048/ folder and right click on the Main Java le: you’ll see a few options, but the one we care about is the green “Run Main.main()” button. It should look like the following image:

In the future, this button is what we will use to run our code.

If the imports are red underlined, it means your setup is incorrect. You should redo the above steps to make sure you didn’t miss anything, but don’t spend more than 10 minutes on this. It’s best to get setup problems xed with a TAs help, meaning you should post on Ed or go to Ofce Hours. If you post on Ed, you need to tell us everything you’ve done/tried so we can get a clear picture of what the error is. Include screenshots of everything, especially any error messages you might get.
One weird quirk you might run into is that the code compiles and runs correctly, but you still get red underlines in IntelliJ. Go to the Model class, and nd the method. This is a method we provided, but you might see that the variable is underlined in red with the following error message:
But we know that clearly it’s correct because 1). that type exists and 2). it’s the starter code! While IntelliJ is incredibly powerful, it does get things wrong sometimes like this. To x this, you should go to File > Invalidate / Restart, then in the following window hit “Invalidate and Restart”
addTile
tile

This will take a minute or two as IntelliJ is re-indexing your JDK and setting up your project from scratch. After it nishes, you should see no red underlines in the source les.
You won’t be able to work on the project unless the above setup is ne, so make it your priority to get setup as soon as you can.
Invalidating your caches will not harm your project and xes a lot of Intellij errors and failures! Intellij is, after all, software itself!
The Game

You’ve probably seen and perhaps played the game “2048,” a single- player computer game written by Gabriele Cirulli, and based on an earlier game “1024” by Veewo Studio (see his on-line version of 2048).
In this project, you’ll be building the core logic of this game. That is, we’ve already put together all the GUI code, handle key-presses, and a ton of other scaffolding. Your job will be to do the most important and interesting part.
Specically, you will ll out 4 methods in the Model.java le which governs what happens after certain key-presses from the user and you will create the constructors set the starting state.
The game itself is quite simple. It’s played on a grid of squares, each of which can either be empty or contain a tile bearing an integer–a power of 2 greater than or equal to 2. Before the rst move, the application adds a tile containing either 2 or 4 to a random square on the initially empty board. The choice of 2 or 4 is random, with a 75% chance of choosing 2 and a 25% chance of choosing 4.
The player then chooses a direction via their arrow keys to tilt the board: north, south, east, or west. All tiles slide in that direction until there is no empty space left in the direction of motion (there might not be any to start with). A tile can possibly merge with another tile which earns the player points.
The below GIF is an example to see what the result of a few moves looks like.
4×4

Here are the full rules for when merges occur that are shown in the image above.
1. Two tiles of the same value merge into one tile containing double the initial number.
2. A tile that is the result of a merge will not merge again on that tilt. For example, if we have [X, 2, 2, 4], where X represents an empty space, and we move the tiles to the left, we should end up with [4, 4, X, X], not [8, X, X, X]. This is because the leftmost 4 was already part of a merge so should not merge again.
3. When three adjacent tiles in the direction of motion have the same number, then the leading two tiles in the direction of motion merge,

and the trailing tile does not. For example, if we have [X, 2, 2, 2] and move tiles left, we should end up with [4, 2, X, X] not [2, 4, X, X].
As a corollary of these rules, if there are four adjacent tiles with the same number in the direction of motion, they form two merged tiles. For example, if we have [4, 4, 4, 4], then if we move to the left, we end up with [8, 8, X, X]. This is because the leading two tiles will be merged as a result of rule 3, then the trailing two tiles will be merged, but because of rule 2 these merged tiles (8 in our example) will not merge themselves on that tilt. You’ll nd applications of each of the 3 rules listed above in the animated GIF above, so watch through it a few times to get a good understanding of these rules.
To test your understanding, you should complete this Google Form quiz. This quiz (and the following quizzes) are completely optional (i.e. not graded) but highly suggested as it’ll nd any conceptual misunderstandings you might have about the game mechanics. You may attempt this quiz as many times as you’d like and can optionally email the results to yourself.
If the tilt did not change the board state, then no new tiles will be randomly generated. Otherwise, a single randomly generated tile will be added to the board on an empty square. Note: Your code will not be adding any new tiles! We’ve already done that part for you.
You might also notice that there is a eld “Score” at the bottom of the screen that is being updated with each move. The score will not always change every move, but only when two tiles merge. Your code will need to update the score.
Each time two tiles merge to form a larger tile, the player earns the number of points on the new tile. The game ends when the current player has no available moves (no tilt can change the board), or a move forms a square containing 2048. Your code will be responsible for detecting when the game is over.

The “Max Score” is the maximum score the user has achieved in that game session. It isn’t updated until the game is over, so that is why it remains 0 throughout the animated GIF example.
Assignment Philosophy and Program Design
A video overview of this section of the spec can be found at https://youtu.be/3YbIOga6ZdQ.
In this project, we’re giving you a TON of starter code that uses many pieces of Java syntax that we have not covered yet, and even some syntax that we’ll never cover in our class.
The idea here is that in the real world, you’ll often work with codebases that you don’t fully understand and will have to do some tinkering and experimentation to get the results you want. Don’t worry, when we get to project 1 next week, you’ll have a chance to start from scratch.
Below, we describe some of the ideas behind the architecture of the given skeleton code, which was created by Paul Hilnger. It is not important that you understand every detail, but you might nd it interesting.
The skeleton exhibits two design patterns in common use: the Model- View-Controller Pattern (MVC), and the Observer Pattern.
The MVC pattern divides our problem into three parts:
The model represents the subject matter being represented and acted upon – in this case incorporating the state of a board game and the rules by which it may be modied. Our model resides in the
Model , , , and Tile classes. The instance variables of fully determine what the state of the game is. Note: You’ll only be modifying the class.
Side
Board
Model
Model

A view of the model, which displays the game state to the user. Our view resides in the GUI and BoardWidget classes.
A controller for the game, which translates user actions into operations on the model. Our controller resides mainly in the
Game class, although it also uses the GUI class to read keystrokes.
The MVC pattern is not a topic of 61B, nor will you be expected to know or understand this design pattern on exams or future projects.
The second pattern utilized is the “Observer pattern”. Basically this means that the model doesn’t actually report changes to the view. Instead, the view registers itself as an observer of the Model object. This is a somewhat advanced topic so we will provide no additional information here.
We’ll now go over the different classes that you will interact with.
Tile
This class represents numbered tiles on the board. If a variable of type Tile is null , it’s treated as an empty tile on the board. You will not
need to create any of these objects, though you will need have an understanding of them since you will be using them in the
class. The only method of this class you’ll need to use is
which returns the value of the given tile. For example if corresponds to a tile with the value 8, then
8. Side
The Side class is a special type of class called an Enum . An enum is similar has restricted functionality. Specically, enums may take on only one of a nite set of values. In this case, we have a value for each of the 4 sides: NORTH , SOUTH , EAST , and WEST . You will not need to
Model
.value()
Tile t
t.value()
will return

use any of the methods of this class nor manipulate the instance variables.
Enums can be assigned with syntax like Side s = Side.NORTH . Note that rather than using the new keyword, we simply set the
Side value equal to one of the four values. Similarly if we have a function like , we can call this function as follows: , which will pass the value NORTH to the function.
If you’re curious to learn more about Java enums, see https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html.
Model
This class represents the entire state of the game. A Model object represents a game of 2048. It has instance variables for the state of the board (i.e. where all the Tile objects are, what the score is, etc) as well as a variety of methods. You will be responsible for writing two constructors: an empty, base constructor that creates an empty Board and a copy constructor, which creates a Board from a supplied setting. One of the challenges when you get to the fourth nal task of this project (writing the tilt method) will be to gure out which of these methods and instance variables are useful.
Board
This class represents the board of tiles itself. It has three methods that you’ll use: , , . Optionally,
public static void printSide(Side s)
printSide(Side.NORTH)
setViewingPerspective
for experimentation, you can use
Getting Started
.
tile
move
getRandomNonNullTile

Your job for this project is to modify and complete the specically the two constructors,
class, ,
emptySpaceExists
atLeastOneMoveExists
Model
maxTileExists , and
Everything else has been implemented for you. We recommend completing them in this order. The constructors and rst two methods are relatively straightforward. The third ( atLeastOneMoveExists ) is harder, and the nal method tilt will probably be quite difcult. We anticipate that tilt will take you 3 to 10 hours to complete. The rst three methods will handle the game over conditions, and the nal method tilt will modify the board after key-presses from the user. You can read the very short body of the checkGameOver method to get an idea of how your methods will be used to check if the game is over.
The Model Class and Constructors
You’ll start by completing the Model class.
All of the numbers for this project will be integers. We’ll go over what exactly an integer is later in the course, but for now, think of it as a whole number, so int x = 3 .
Instance Variables
Begin by reading through the Model class and understanding the role of the associated instance variables.
You should NOT modify the name or type of the provided instance variables in Model.java, but you may add any additional instance variables of any type that you desire.
public Model(int size)
tilt
methods.

This constructor should create a board of size size and set the instance variables for the start of the game.
Note: We’ve designed the Board class using a special keyword that disallows you from using the instance variables of
directly. For example, if you try to access b.values[0][0] , this will not work. This is a good thing! It forces you to learn to use the
tile method, which you’ll use throughout the rest of the project. You can open Board.java to see the method and Tile.java to get an understanding of the function.
Try opening the TestEmptyConstructor.java folder. Run the tests. You should see that 6 of the tests fail and 2 of them pass. After you’ve correctly written the constructor, all 8 tests in should pass.
private
Board
tile
.value()
Model(int size)
TestEmptyConstructor
Note: For parameter names which are the same as the corresponding instance variable name, make sure to use the
this keyword appropriately.
New Addition Please be aware that the constructor tests provided to you are (unfortunately) not comprehensive. This means there is a possibility you might pass these tests while missing certain elements that need to be initialized or otherwise set up. Take this as an opportunity to consider the “real world” implications of testing– our understand of the correctness of our program is entirely limited by the robustness of our tests! We will not be updating the AG, meaning the credit you have now will not change, but in order to get more familiar with testing (and to make your testing output more helpful) consider which elements of the constructor are and are not being tested (what information is being passed in) and how this could affect later methods!

public Model(int[][] rawValues, int score, int maxScore, boolean gameOver)
This constructor creates a new instance of the game with a Board state that reflects the given rawValues array. The instance variables of the object should be updated based on the provided input. Note that
rawValues is in row major form, meaning it is indexed (row, column) and (0, 0) refers to the bottom left corner.
This constructor is vital for our testing les! Once you’ve completed it, check out the provided testing les to see where it is used (hint, look at the rst method of TestEmptySpace.java ).
After you’ve written the constructor, the tests in TestArgsConstructor.java should pass.
If you pass this test, you’re ready to move on to the next step. Do not proceed until you have passed this test.
The Methods
Now, let’s look at the rst three methods:
public static boolean emptySpaceExists(Board b)
This method should return true if any of the tiles in the given board are null. You should NOT modify the Board.java le in any way for this project. For this method, you’ll want to use the tile(int col, int row) method of the Board class. No other board methods are necessary.
After you’ve written the method, the tests in TestEmptySpace.java should pass.

A quick overview of how to get started writing this method is provided in this video.
public static boolean maxTileExists(Board b)
This method should return true if any of the tiles in the board are equal to the winning tile value 2048. Note that rather than hard coding the constant 2048 into your code, you should use MAX_PIECE, which is a constant that is part of the class. In other words, you shouldn’t do if (x == 2048) but rather .
Leaving in hard coded numbers like 2048 is a bad programming practice sometimes referred to as a “magic number”. The danger of such magic numbers is that if you change them in one part of your code but not another, you might get unexpected results. By using a variable like MAX_PIECE you can ensure they all get changed together.
After you’ve written the method, the tests in TestMaxTileExists.java should pass.
public static boolean atLeastOneMoveExists(Board b)
This method is more challenging. It should return true if there are any valid moves. By a “valid move”, we mean that if there is a button (UP, DOWN, LEFT, or RIGHT) that a user can press while playing 2048 that causes at least one tile to move, then such a keypress is considered a valid move.
There are two ways that there can be valid moves:
1. There is at least one empty space on the board. 2. There are two adjacent tiles with the same value.
For example, for the board below, we should return true because there is at least one empty space.
Model
if (x == MAX_PIECE)

For the board below, we should return false. No matter what button you press in 2048, nothing will happen, i.e. there are no two adjacent tiles with equal values.
| 2| 4| 2| 4| |16| 2| 4| 2| | 2| 4| 2| 4| | 4| 2| 4| 2|
For the board below, we would return true since a move to the right or left would merge the two 64 tiles, and also a move up or down would merge the 32 tiles. Or in other words, there exist at least two adjacent tiles with equal values.
| 2| 4| 64| 64| |16| 2| 4| 8| | 2| 4| 2|32| | 4| 2| 4|32|
After you’ve written the method, the tests in TestAtLeastOneMoveExists.java should pass.
The Game Logic
|2| |2| | | 4| 4| 2| 2| | | 4| | | | 2| 4| 4| 8|

The fourth and nal part of the assignment is to implement . You should only start this method once you’re passing all the tests in
TestEmptySpace
,
and
TestMaxTileExists
TestAtLeastOneMoveExists
.
Computer science is essentially about one thing: Managing complexity. Writing the tilt method is a rich experience that will give you a chance to try just that. I must warn you, this is probably going to be a frustrating experience. It is likely that you will attempt several approaches that will ultimately fail before you have to start back over.
Before we start talking about how tilt should work, let’s try running the game.
Open the Main class and click the run button. You should see the game pop up. Try pressing the arrow keys. You should see that nothing is happening. This is because you have not implemented the tilt method yet. When you’re done writing tilt , you’ll be able to play the game.
public boolean tilt(Side side)
The tilt method does the work of actually moving all the tiles around. For example, if we have the board given by:
|2| |2| | | 4| 4| 2| 2| | | 4| | | | 2| 4| 4| 8|
And press up, tilt will modify the board instance variable so that the state of the game is now:
tilt

In addition to modifying the board, two other things must happen:
1. The score instance variable must be updated to reflect the total value of all tile merges (if any). For the example above, we merged two 4s into an 8, and two 2s into a 4, so the score should be incremented by 8 + 4 = 12.
2. If anything about the board changes, we must set the changed local variable to true . That’s because at the end of the skeleton code for tilt , you can see we call a setChanged() method: this informs the GUI that there is something to draw. You will not make any calls to setChanged yourself: only modifying the
changed local variable.
All movements of tiles on the board must be completed using the move method provided by the class. All tiles of the board must be accessed using the method provided by the Board
class. Due to some details in the GUI implementation, you should only call move on a given tile once per call to tilt . We’ll discuss this constraint further in the Tips section of this document.
A quick overview of how to get started writing this method is provided in this video.
Tips and Tricks
We strongly recommend starting by thinking only about the up direction, i.e. when the provided side parameter is equal to Side.NORTH . To support you in this, we provide a class that has four
Board
tile
| 2| 8| 4| 2| | 4| 4| 4| 8| | 2| | | | |||||
TestUpOnly

tests: , , , and
these tests involve only a single move up.
. You’ll note that
testUpNoMerge
testUpBasicMerge
testUpTripleMerge
testUpTrickyMerge
When considering how to implement the up direction, consider the following:
In a given column, the piece on the top row (row 3) stays put. The piece on row 2 can move up if the space above it is empty, or it can move up one if the space above it has the same value as itself. In other words, when iterating over rows, it is safe to iterate starting from row 3 down, since there’s no way a tile will have to move again after moving once.
While this sounds like it’s not going to be very hard, it really is. Be ready to bust out a notepad and work out a bunch of examples. Strive for elegant code, though elegance is hard to achieve with this problem. We strongly recommend the creation of one or more helper methods to keep your code clean. For example, you might have a helper function that processes a single column of the board, since each column is handled independently. Or you might have a helper function that can return a desired row value.
Reminder: You should only call move on a given tile once. In other words, suppose you have the board below and press up.
||||| ||||| ||||| | | | | 2|
One way we could accomplish this would be as follows:

However, the GUI will get confused because the same tile is not supposed to move multiple times with only one call to setChanged. Instead, you’ll need to complete the entire move with one call to
move , e.g.
In a sense, the hard part is guring out which row each tile should end up on.
To test your understanding, you should complete this Google Form quiz. This quiz will not factor into your CS61BL grade.
To know when you should update the score, note that the board.move(c, r, t) method returns true if moving the tile t to column c and row r would replace an existing tile (i.e. you
have a merge operation).
To make matters seemingly much worse, even after you get tilt working for the up direction, you’ll have to do the same thing for the other three directions. If you do so naively, you’ll get a lot of repeated, slightly modied code, with ample opportunity to introduce obscure errors.
Tile t = board.tile(3, 0)
board.move(3, 3, t);
Tile t = board.tile(3, 0)
board.move(3, 1, t);
board.move(3, 2, t);
board.move(3, 3, t);
setChanged();
return true;

For this problem, we’ve given away a clean solution. This will allow you to handle the other three directions with only two additional lines of code! Specically, the class has a
function that will change the behavior of the and classes so that they behave as if the
given side was NORTH.
For example, consider the board below:
setViewingPerspective(Side s)
Board
tile
move
||||| |16| |16| | ||||| | | | | 2|
If we call , we’ll get , since 16 is in column
board.tile(0, 2)
0, row 2. If we call
is WEST , then the board will behave as if WEST was NORTH, i.e. you had your head turned 90 degrees to the left, as shown below:
16
board.setViewingPerspective(s)
where s
| | | 16| | ||||| | | | 16| | | 2| | | |
In other words, the we had before would be at 3) . If we were to call
implemented tilt , the board would become:
with a properly
16
board.tile(2,
board.tilt(Side.NORTH)
| 2| | 32| | |||||

To get the board to go back to the original viewing perspective, we simply call , which will make the board behave as if was . If we do this, the board will now behave as if it were:
board.setViewingPerspective(Side.NORTH)
NORTH
||||| | 32| | | | ||||| | 2| | | |
Observe that this is the same thing as if you’d slid the tiles of the original board to the WEST .
Important: Make sure to use to set the perspective back to before you nish your call to
tilt , otherwise weird stuff will happen.
To test your understanding, try this third and nal Google Form quiz. You
may attempt this quiz as many times as you’d like.
Testing
While in the future we expect you to be able to test your own programs, for this project we’ve given you the full test suite.
The tests are split over 7 les: , ,,
,
, and . Each le tests a specic portion of
board.setViewingPerpsective
NORTH
Side.NORTH
TestEmptyConstructor
TestArgsConstructor
TestEmptySpace
TestMaxTileExists
,
TestAtLeastOneMoveExists
TestUpOnly
TestModel
||||| |||||

the code with the exception of which tests all the things you write in coordination with each other. Such a test is called an integration test and are incredibly important in testing. While unit tests run things in isolation, integration tests run things all together and are designed to catch obscure bugs that occur as a result of the interaction between different functions you’ve written.
So do not attempt to debug TestModel until you’re passing the rest of the tests! In fact, the order in which we discuss the tests is the order you should attempt them in.
We’ll now take a look at each of these tests and show you how to read the error messages.
TestConstructors
These two testing les contain tests to assess the correctness of your constructor implementations.
These tests create a Model instance by invoking the associated constructor. They then loop through the newly created object to ensure 1. the object exists and 2. the object contains the data we expect it to.
TestEmptySpace
These tests will check the correctness of your emptySpaceExists method. Here is what the error message would look like if you failed one of the tests:
TestModel

On the left-hand side, you’ll see the list of all tests that were run. The yellow X means we failed a test while the green check means we passed it. On the right, you’ll see some useful error messages. To look at a single test and its error message in isolation, click the test on the left- hand side. For example, let’s say we want to look at the
testCompletelyEmpty test.
The right-hand side is now the isolated error message for this test. The top line has a useful message: “Board is full of empty space” followed by a String representation of the board. You’ll see that it’s clearly empty, yet our emptySpaceExists method is returning false and causing this test to fail. The javadoc comment at the top of the code for the test also has some useful information in case you’re failing a test.

TestMaxTileExists
These tests will check the correctness of your maxTileExists method. The error messages will be similar to those for
TestEmptySpace , and you can still click on each individual test to look at them in isolation. Remember that your maxTileExists method should only look for the max tile and not anything else (i.e. shouldn’t look for empty space). If yours does, you will not pass all of these tests.
TestAtLeastOneMoveExists
These tests will check the correctness of your
method. The error messages are similar to
the above two. Since the method depends on the method, you shouldn’t expect to pass these tests until you are passing all of the tests in TestEmptySpace .
TestUpOnly
These tests will check the correctness of your tilt method, but only in the up ( Side.NORTH ) direction. The error messages for these are different, so let’s look at one. Say we run all the tests, notice we’re failing the testUpTrickyMerge test. After clicking that test, we’ll see this:
atLeastOneMoveExists
atLeastOneMoveExists
emptySpaceExists

The rst line tells us the direction that was tilted (for these tests it’ll always be North), then what your board looked like before the tilt, then what we expected the board to look like, and nally what your board actually looked like.
You’ll see that we’re merging a tile twice on a single call to tilt which results in a single tile with value 8 instead of two tiles both with value 4. As a result, our score is also incorrect as you can see in the bottom of the representation of the board.
For other tests it might be difcult to notice the difference between the expected and actual boards right away; for those, you can click the blue “Click to see difference” text at the very bottom of the error message to get a side-by-side comparison of the expected (on the left) and actual (on the right) boards in a separate window. Here is what it looks like for this test:

Debugging these can be a bit tricky because it’s hard to tell what you’re doing wrong. First, you should identify which of the 3 rules listed above you’re violating. In this case, we can see that it’s rule 2 since a tile is merging more than once. The javadoc comments on these methods are good resources for this as they specically lay out what rule/conguration they’re testing. You might also be able to gure out what rule you’re violating by just looking at the before and after boards. Then, comes the tricky party: refactoring your existing code to properly account for that rule. We suggest writing out on pen and paper the steps your code takes so you can rst understand why your board looks the way it does, then coming up with a x. These tests only call tilt
once, so you don’t need to worry about debugging multiple calls to tilt.
TestModel
These tests will check the correctness of everything together. The majority of these tests are similar to the tests in as they
only call
test all of your
many calls to
once, but we also have tests for (which , , and
methods together) and tests that make in a sequence.
tilt
atLeastOneMoveExists
emptySpaceExists
The error messages for these look exactly the same as those in TestUpOnly , and the javadoc comments are similarly useful in
guring out what the test is testing.
Don’t worry about the actual code for the tests: you’re not required to understand or modify any of these, though you’re welcome to read through and get an idea for how test writing works and even add some of your own if you are feeling really ambitious.
Submission and Version Control
TestUpOnly
maxTileExists
gameOver
tilt

As always, make sure to save, add, commit, and push all of your java les.
It is important that you commit work to your repository at frequent intervals. Version control is a powerful tool for saving yourself when you mess something up or your dog eats your project, but you must use it regularly if it is to be of any use. Feel free to commit every 15 minutes; Git only saves what has changed, even though it acts as if it takes a snapshot of your entire project.
The command git status will tell you what les you have modied, removed, or possibly added since the last commit. It will also tell you how much you have not yet sent to your GitHub repository.
The typical commands would look something like this:
e g
Then you can carry on working on the project until you’re ready to commit and push again, in which case you’ll repeat the above. It is in your best interest to get into the habit of comitting frequently with informative commit messages so that in the case that you need to revert back to an old version of code, it is not only possible but easy. We suggest you commit every time you add a signicant portion of code or reach some milestone (passing a new test, for example).
Once you’ve pushed your code to GitHub (i.e. ran git push ), then you can submit to Gradescope. Keep in mind that the version of code that Gradescope uses is the most recent commit you’ve pushed, so if you do not run git push before you submit on Gradescope, old code
git status # To see what ne
git add # To add, or sta
git commit -m “Commit message” # To commit changes
git push

will be tested instead of the most recent code you have on your computer. If you pass all the tests, you get all the points. Hoorah!
You may submit every half an hour. If you have multiple submissions, select the one you wish for us to grade by pressing activate. Both partners need to submit. If you submit through tags in your shared repo, you will both be automatically added. Otherwise, you’ll both need to submit through Gradescope.
We’ve set up a le called that will restricts you to only adding .java and les.
This is to keep your repository small so that the autograder moves quickly. We ask that you do not force-add other types of les to your repository, especially if they are large. The autograder has failed in the past when testing extremely large repositories.
.gitignore
.txt
Frequently Asked Questions
When I run the autograder, it says my API is wrong, but I have all the variables and constructors they are asking for
Make sure your instance variables are public! If they are package protected (which is the default if you do not specify) the autograder will not be able to access them!
What is a constructor? How do I write one?
A constructor is a block of code that runs when a class is instantiated with the new keyword. Constructors serve the purpose of initializing a new object’s elds. Consider an example below:
public class Dog {
String _name;

The Dog class has three non-static elds. Each instance of the Dog class can have a name, a breed, and an age. Our simple constructor, which takes three arguments, initializes these elds for all new Dog objects.
I’m having trouble with the second constructor.
Let’s walk through an example of how a constructor works. Suppose you use the Dog constructor above to create a new Dog :
When this line of code gets executed, Java rst creates a new
object that’s empty. In essence, Java is creating a “box” for the , and that box is big enough to hold a box for each of the Dog ’s declared instance variables. This all happens before the constructor is executed.
At this point, here’s how you can think about what our new fluffy friend fido looks like (note that this is a simplication! We’ll learn about a
more correct view of this when we learn about Objects and pointers later this semester):
Dog fido = new Dog(“Fido”, “Poodle”, 1);
Dog
Dog
String _breed;
int _age;
public Dog(String name, String breed, int age) {
_name = name;
_breed = breed;
_age = age; }
}

Java will put some default values in each instance variable. We’ll learn more about where these defaults come from (and what null means) later this semester. For now, just remember that there’s space for all of the instance variables, but those instance variables haven’t been assigned meaningful values yet. If you ever want to see this in action, you can add some print statements to your constructor:
public Dog(String name, String breed, int age) {
_name = name;
_breed = breed;
_age = age;
}
System.out.println(“_name: ” + _name + “, _breed
If this constructor had been used to create fido above, it would have printed:
OK, back to making . Now that the JVM has made some “boxes” for fido , it calls the constructor function that we wrote. At this point, the constructor executes just like any other function would. In the rst line of the constructor, _name is assigned the value name , so that fido looks like:
_name: null, _breed: null, _age: 0
fido
Dog

When the constructor completes, fido looks like:
Now, suppose you want to create a new Dog constructor that handles cross-breeding. You want the new constructor to accept a name, an age, and two breeds, and create a new Dog that is a mixture of the two breeds. Your rst guess for how to make this constructor might look something like this:
Dog dog = new Dog(name, breed1 + breed2, age);
}
public Dog(String name, String breed1, String breed2
,
However, if you try to create a new Dog using this constructor:
Dog tommy = new Dog(“Tommy”, “Poodle”, “Golden Retri
This won’t do what you want! As above, the rst thing that happens is that the JVM creates empty “boxes” for each of tommy ’s instance variables:
e

But then when the 4-argument constructor got called, it created a second and assigned it to the variable dog . It didn’t change any of ’s instance variables. Here’s how the world looks after the line in our new constructor nishes:
dog isn’t visible outside of the constructor method, so when the constructor completes, dog will be destroyed by the garbage collector (more on this later!) and all we’ll have is the still un-initialized tommy variable.
Dog
tommy
Here’s a cross-breed constructor that works in the way we’d like:
this(name, breed1 + breed2, age);
}
public Dog(String name, String breed1, String breed2
,

Here, we’re calling the old 3-argument constructor on ; rather than creating a new Dog , we’re using the 3-argument constructor to ll in all of the instance variables on this dog. After calling this new constructor to create tommy , tommy will correctly be initialized to:
We could have also written a new constructor that assigned each instance variable directly, rather than calling the existing constructor:
,
this
_name = name;
_breed = breed1 + breed2;
_age = age;
}
public Dog(String name, String breed1, String breed2
I’m getting an “unmappable character” error when compiling, and there are weird
blocky characters in the error message.
This is a system locale issue that primarily affects Windows systems. Try one of the following xes.
1. Compile with the correct encoding flags.
javac -encoding UTF8 Model.java
javac -encoding ISO-8859-1 Model.java

2. Change your system locale to US English. There are guides online with screenshots of how to do this for your specic version of Windows.
Getting Help
While a little struggle and debugging is normal and even healthy, if you nd yourself stuck for hours with no progress after doing all of the suggestions above, please get help from staff!
The two ways of getting help in CS 61B are coming to Ofce Hours or posting on Ed so that a TA or another student can help you become unstuck.
Remember that TAs will spend a maximum of 10 minutes per student in Ofce Hours. To speed things up, we ask that you bring a clear problem that you can voice to a TA rather than just telling us a test isn’t passing. For example, if a test isn’t passing, gure out which part isn’t passing and why there is a discrepancy. Maybe the score isn’t updating properly, or perhaps things don’t merge the way they should be. This helps speed things up and might even lead you to nd your own bug.
If you’re posting on Ed, please read our Ed policies to make sure you’re not accidentally posting part of your solution and hence violating our academic integrity policies. Otherwise, we welcome constructive discussion on our megathreads. Remember to search for your issue before posting a follow-up as many students have very similar bugs!
Acknowledgements
This project was created by Professors Paul Hilnger and Josh Hug. It was modied by Omar Khan and Zoe Plaxco.