Skip to Main Content

Data Structures

Computer Science Department

Board Game Debugger - 10 Course Points

What is Debugging?

Writing code is prone to bugs (mistakes), and when bugs do occur we need an efficient way to pinpoint where they are coming from. Often, when programs have mistakes they show a Compiler Error (red squiggily underline on VSCode), or throw an Exception, which is a Runtime Error, and crash the program. These both tell you their direct cause, allowing you to fix them.
  • Compiler error: VSCode shows you a red squiggly underline. Basically like a grammar/spelling issue.
  • Runtime error: Java shows you the call stack and which lines generated the exception. This is an error which signals an issue with the program while it’s running.
But what if we can’t visually identify why the program throws a Runtime Error? Or if the cause of a bug is not so clear? For example, if the program is compiling and running successfully, but outputting the wrong value? In that case, we need a way to investigate the code to see what is happening. This process of investigation is called Debugging, and we can use a helpful tool called the Debugger to do so. The debugger allows us to pause code at certain spots/on certain conditions, and then investigate the values of each variable, in order to determine what is happening and if the code is functioning properly.

Using the Java Debugger

As with the rest of the course, we will be working within VSCode for this Lab. Make sure you’ve installed all required extensions and removed any unnecessary ones, as stated on our Course FAQ page. So far, you have most likely been running your programs using either the commands line (with compile commands), or using the VSCode run button. Now, you can use the drop down menu on the Run Button and select “Debug Java” to run the program in Debug mode instead. Alternatively, you can click “Start Debugging” under the “Run” menu on the top toolbar. If you simply do this instead of the normal Run Java / Run Without Debugging, it will appear to be exactly the same result. Your program will run and exit, and produce any expected output. HOWEVER, running in debug mode allows us to make use of breakpoints, which pause the code at certain spots.

Breakpoints

Breakpoints allow you to define certain lines for the program to pause running at, while running in debug mode. This is extremely useful, as it allows you to investigate specific edge cases, or specific parts of the bugged code. You can place a breakpoint by clicking to the left of the line number you want pause at. Breakpoints are represented by a red circle. Then when you run in debug mode, the debugger will stop the program before executing that line, and will highlight that line to show it. Nothing gets printed to the terminal yet, since that line of code has NOT been run yet. You can also set Conditional Breakpoints, which will only pause if their given boolean condition is met. In this lab, you will use conditional breakpoints to pause the program at certain places, to investigate the happenings of the board game. Once the breakpoint has been placed, edit it by left clicking on the breakpoint (red circle) and select Edit. Then place a boolean condition in the text box that appears. These boolean conditions can be any valid condition, using any variables which are accessible from that line. i.e. “turn == 13”, or even chained conditions like “turn == 13 && piece.getName().equals(“Car”)” For example, we can set a breakpoint in the following code snippet, then set the breakpoint to only pause when i==4. Then if we run in debug mode, we will see that it pauses at that line when i == 4. And we can see in the terminal that everything before i == 4 has already been printed. Note: If you set a breakpoint but the program does not stop when run in debug mode, it means that line was never executed. This is usually because the line was never reached, or because the program is infinitely looping somewhere earlier on (thus never progressing).

Debugger Toolbar

After the program pauses at a breakpoint, we want to be able to control it from there, and execute any number of lines, or continue running until the end. To do this, we can use the Debugger Toolbar. The debugger toolbar appears when running a program (even in non-debug mode). For any program that is actively running (for example, when you have the Driver open), the toolbar will appear as follows: When paused at a breakpoint, the debugger toolbar will look like this instead: You can then use this toolbar to navigate forward through the code, either line by line, or section by section. The buttons work as followed:   Continue button – Will resume running the code, until it hits another (or the same) breakpoint, OR the program ends. Step Over – Will execute the highlighted line of code, and pause on the next line of code Step Into – IF the highlighted line of code is a method call, you can use this to “step into” the method, and pause inside of it. This allows you to follow the logic when methods are being called. Step Out – IF you have Stepped Into a method call, you can use this step back out. Aka to finish the method instantly, and stop on the next line after the method call. The green circular arrow is the Restart button, which allows you to stop and rerun the program. The red square is the Stop button, which will stop running the program. It is important to become familiar with the Debugger toolbar, in particular the “Continue” and “Step Over” buttons. They allow you to easily navigate code after breakpoints, and jump to other breakpoints to ease the search while debugging.

Memory Viewer

Also while the program is paused, you can use the Memory Viewer to inspect variable values. The memory viewer can be accessed through the left sidebar, under the “Run and Debug Menu” You can then see all the current variables in scope at the paused line. This allows you to inspect values, to ensure they get initialized/updated as expected. This is important for bug-hunting errors like NullPointerExceptions, as it lets you identify when things do/don’t get set to a value or null. In the above example, the only two variables in scope are “args” (from the parameters of the main() method), and “i” which is the for loop variable from the conditional breakpoint example above. If we define another String variable, and pause the program after that variable has been created, we can see it too. Note: since the for loop has ended, the “i” variable has disappeared and been garbage-collected by Java. The String variable has a drop down menu in the variable viewer, since it is an object which has attributes. We can open this to see the attributes. This is an important concept, as it allows us to investigate objects fully. Since the majority of Java code consists of objects, we need this to properly debug.

Debug Console

The final tool you will need to debug (and complete this Lab) is the Debug Console. The Debug Console is a special terminal, which can be accessed with Ctrl + Shift + Y (for Mac, use Command instead of Ctrl). The debug console allows you to write and run singular lines of code, and print their output. For example, you can simply enter primitive values, and it will print those values back to you. In the above screenshot, first “Hello!” is typed into the Debug Console (including the quote marks), then after pressing Enter, it is printed back to us. Second, the number 2 is entered, which again simply prints 2 back to us. If we have a visible method which is accessible from the paused spot, we can call that as well and the Debug Console will print the output. If we use the previous example of the “String temp = “TempVariable”;”, and pause at the same spot, we can call that String object’s methods and see the output. This allows us to call getter methods to get values. In the lab, you will use this in combination with conditional breakpoints in order to get info from variables regarding the game’s status.

Overview

To complete this Lab, you will not need to write ANY code. Instead, you will run the Driver.java class and use it with the debugger to generate your submitted file.
  • The Driver class prints a small intro in the terminal, then asks for your netID. Enter your correct netID (ex: abc123, not your 9-digit RUID), then click the “Run Island” button. You can change the SKIP_INTRO variable in Driver.java to true, to disable this intro.
  • After receiving your netID, the game will instantly simulate and end. Then, you will be asked a series of random questions about your game. Your netID + answers will print to an answers.out file.
    • This “answers.out” file is the one you submit.
  • In other words, you are going on a scavenger hunt using the debugger. You must find the requested pieces of information and enter them in the driver, then submit the printed “answers.out” file to Autolab.
Getting Started: Once you run the driver, enter your NetID (ex: abc123, NOT your RUID). We recommend writing down your questions or screenshotting them before you start debugging. Then, you can set breakpoints using the debugger (see above), and rerun with those breakpoints. Remember that questions won’t show up until all turns are complete.  When you’re ready to submit, use the Driver to generate the answers.out file. It’ll include your NetID as well as a hash (a string representing your NetID). Make sure you enter all answers exactly as asked – don’t include any punctuation or wording (ex: if you’re asked for a number, ONLY write that number). 

Provided Classes

You are provided a number of supporting classes which comprise the game. The game/stdlib package contains the StdInStdOut, and StdRandom classes, used for input/output and the random chances  The game/values package contains:
  • Effects.java – all of the random tile effects
  • Questions.java – all of the possible game questions
  • RandomChances.java – holds max/min game board length, roll, and pieces.
The game package contains the game itself, with Piece.java, Tile.java, and TileNode.java making up the board and pieces. BoardGame.java is where the game is run, mainly in the nextTurn() method (this is where you will mainly investigate). Do not modify or remove any of these classes.

Directions

You MUST use your own NetID when running the Driver, or you will receive a zero on the Lab.
  • DO NOT add new import statements.
  • DO NOT add any new class attributes
  • DO NOT change any of the method’s signatures.
  • DO NOT modify the given constructor.
  • DO NOT modify any code related to game behavior.
    • Modifying game behavior may cause you to find different answers than Autolab.
    • You may mainly add if-statements to check logic for print statements. Do not use breakcontinuereturn, or other similar keywords.

To Run: Run in Debug Mode through VSCode, ensuring you open the correct innermost BoardGameDebugger directory.

Driver

The Driver class will at first show a short intro, welcoming you to the board game. Then, it will prompt you for your netID (abc123 form NOT your 9-digit RUID). After you enter it, the game will automatically start. The game will instantly simulate, and end. After this, the driver will ask you 6 random questions from the 10 below about the game in general as well as your specific random game. You must use the debugger to find the answers to these questions, then enter them in the driver. NOTE: You must use the “Continue” or “Step Out” buttons to continue past ALL breakpoints after starting the game with your netID. While you are paused at any breakpoint, you will not be able to interact with the Driver. The Driver will print a questions.out file, which is provided for you to reference the questions without rerunning the program. You will NOT submit this file. After all questions are answered, the driver will print them to an “answers.out” file in your project directory. This is the file you will submit. Make sure to save your answers somewhere when you rerun, so they don’t get overwritten.

Answer Formatting

  • For number answers, DO NOT add use words or punctuation.
    • EX: if there are 5 pieces, don’t write “Five” or “5 pieces”, write “5” (without quotes).
  • Answers are case insensitive, and leading/trailing spaces are trimmed.
  • Make sure to check your spelling of piece names. 
Make sure you always run in Debug mode, or breakpoints will not work. Always run with YOUR netID.

Question Help

(the question numbers below may not line up with your question numbers)

Question 1: How many turns did the game last?
  • Look in BoardGame.java. Set a breakpoint wherever the game ends in nextTurn(), and check what turn it is using the variable viewer.
Question 2: How many pieces were on your board?
  • Look in BoardGame.java. Set a breakpoint anywhere in nextTurn(), and check the numPieces class attribute.
Question 3: What is the maximum number of pieces possible for a game?
  • Look in RandomChances.java, for the corresponding static variable.
Question 4: What is the minimum dice roll possible?
  • Look in RandomChances.java, for the corresponding static variable.
Question 5: What is the maximum dice roll possible?
  • Look in RandomChances.java, for the corresponding static variable.
Question 6: How many tiles are on your board?
  • Look in BoardGame.java. Set a breakpoint anywhere in nextTurn(), and check the boardLength class attribute.
Question 7: How many BONUS tiles are on your board?
  • Look in BoardGame.java. Set a breakpoint at line 135 in createBoard(). Right click on it, to edit it, and add the condition tile == Tile.BONUS. Finally, run the program and count how many times it hits that breakpoint, to count the number of BONUS tiles placed on the board.
Question 8: How many pieces finished the game?
  • Look in BoardGame.java. Set a breakpoint wherever the game ends in nextTurn(), and check what tile each piece is on using the variable viewer.
Question 9: What is the name of the piece which had the most coins at the end of the game?
  • Look in BoardGame.java. Set a breakpoint wherever the game ends in nextTurn(), and check how many coins each piece has on using the variable viewer.
    • If this question has more than one correct answer, give only one of them.
Question 10: What is the name of the piece which had the least coins at the end of the game?
  • Look in BoardGame.java. Set a breakpoint wherever the game ends in nextTurn(), and check how many coins each piece has on using the variable viewer.
    • If this question has more than one correct answer, give only one of them.

Before submission

DO NOT MODIFY THE answers.out FILE. You MUST print this file using the Driver.

You MUST use your own NetID when running the island in the Driver, or you will receive a zero on the lab.

Collaboration policy. Read our collaboration policy on our course syllabus.

Submitting the assignment. Submit your answers.out file separately via the web submission system called Autolab.  

Getting help

If anything is unclear, don’t hesitate to drop by office hours or post a question on Piazza.

  • Find instructors and Lead TA office hours here
  • Find tutors office hours on Canvas -> Tutoring
  • In addition to office hours we have the Coding and Social Lounge (CSL) , a community space staffed with ilab assistants which are undergraduate students further along the CS major to answer questions.

By Colin Sullivan