A crucial skill for any new programmer to learn is debugging their code. But before you can learn to debug faulty code, you have to learn to efficiently use the debugger.
This assignment introduces students to debugging techniques such as breakpoints, the debugging toolbar, inspecting variable values, stepping through code, and more. It does this using a Murder Mystery simulation, which is randomly determined by a given ID (the student's school login ID). This simulation is framed as a Clue-style game, with a cast of six characters at a Mansion party. One character is a murderer who pursues and murders the other characters until they are the last one left, or until the night ends.
Many aspects of the simulation are randomized for each user including: player names, size of mansion, rooms of the mansion, number of items, item names/locations, player/murderer decisions, assigned questions, and more.
The MurderMystery.java Driver runs the simulation using Mansion.java and other classes, then it prints 10 questions, allowing students to input answers for each. The student Answers file can be submitted and automatically compared against the correct answers for their questions. Students do NOT have to code to complete this assignment.
Summary | Students debug a murder mystery simulation to answer questions about in-game attributes as well as when in-game characters dropped and picked up items, were murdered, or were at certain times. The students' unique login ID randomly determines characters, rooms, items, decisions, questions, and more. |
Audience | Targeted towards CS2 students. Assigned at the beginning of the semester, to teach them strategies they can use moving forwards, as well as to reacquaint them with Java code. Game difficulty can be easily adjusted to CS1/APCS level by giving fewer questions, removing some question options altogether, or simplifying game code. |
Topics | Java, Debugging, OOP, Simple Data Structures, Conditionals, Loops |
Difficulty | This assignment can be done in less than a week with some learning support. The assignment can easily be optimally solved with 8 or fewer breakpoints/conditional breakpoints in less than 3 minutes, but will generally take students much longer. |
Strengths |
|
Weaknesses |
|
Dependencies | Understanding of Java syntax, selection statements, loops, and boolean conditions as well as knowledge about basic objects and 2D arrays. |
Variants | The most clear outcome of this assignment was that small additions can make big differences in a semester. Compared to previous semesters, many students and tutors report increased confidence in debugging ability, which also follows true in students ability to complete coding tasks. Students agreed that the assignment theme made it an approachable task, and helped them become familiar with understanding code. |
Download Student Code - This is the code provided to students, which they can run and debug to solve questions, then submit their Answers.out file
Download GameResults File - You can add this GameResults.java file to the student code, and then use it to generate the correct reference answers for any students login ID. You can enter the ID via terminal, or args[0]. This allows you to write a simple auto-grader to compare batch student answer files and return which lines (questions) are incorrect for each. The student ID the program was run with will be the first line of the output file. The filename will always be -> "refAnswers.out".
Download Student Handout - This is the student handout, describing the game as well as a basic tutorial on using the debugger.
To use this assignment in your course, support should be given on how to use the debugger, including breakpoints (especially conditional breakpoints), the debug console, and variable viewer.
In MurderMystery.java, a blank method "isValidLoginID(String id)" is provided, which you can fill out to limit valid login IDs.
If any changes are made to Mansion.java, be sure to update the line number answers in GameResults.java, for each corresponding code line question. Or set the number of these questions to zero in MurderMystery.java
You can create a program for your autograding service, which iterates over all student answer files and uses GameResults (with the loginID the student submitted) to generate the correct answers. Your program can then compare and generate a grade/feedback for the student. You should confirm that each student submitted the correct loginID.
The minimal answers for equal question are given below under "Question Types".
When the student runs the MurderMystery.java file, they will be asked via the terminal for their login ID.
They will then be asked if they want to print an intro. This intro has a title screen, as well as the characters' names for the mystery.
If no breakpoints are set, the game immediately ends and prints a game over screen. It then says the outcome (# survivors / if the murderer won).
The student will then be asked a series of questions via the terminal, which they can type the answers to. These answers are printed to a “Answers.out” file, which the student can submit (the student's login ID is printed as the first line in the file, for submission verification reasons).
To find the answers to the given questions, students should investigate the Mansion.java file, where the game is created, stored, and run.
Students will be almost exclusively debugging the Mansion nextTurn() method, which simulates one single turn (five minutes in-game). This method gets repeatedly called by the Driver, which makes the game run.
The five set questions can be solved using a single breakpoint. Many random questions can be solved with a single conditional breakpoint, but some will require up to 4 to cover all possible cases (specifically in the logic for items being picked up / dropped). Code line questions require no breakpoints, just investigating the unmodified Mansion.java file.
Examples of breakpoint conditions:
- (droppedItem.getItemName().equals("Frying Pan"))
- (victim.getName().equals("Monsieur Verde"))
- (pickedUpItem.getItemName().equals("Wrench") || pickedUpItem.getItemName().equals("Piano Wire"))
- (player.getItemName().equals("Revolver"))
- (time == 95 || time == 230)
By default, the game asks 10 questions. 5 set questions (which are the same for everyone), 3 random game questions, and 2 questions about line numbers for certain code functions.
The code comes including 21 questions, including the 5 set questions, plus 9 possible random questions and 7 possible code line number questions.
The 5 set questions are:
- Who was the murderer?
- How many items were spawned?
- How many rooms are in the mansion?
- Who moved first on each turn?
- How many murder weapons were used?
The 9 possible random questions are:
- When did itemName get dropped last?
- When did itemName get picked up first?
- Where did itemName get dropped first?
- Where did itemName get picked up last?
- Where was playerName at XX:YYpm?
- What time/room did playerName get murdered? (2 Questions)
- How many players were dead / alive at XX:YYpm? (2 Questions)
The 7 possible code line number questions are:
- What line number in the Mansion nextTurn() method decides how many moves a player gets?
- What line number in Mansion.java decides the cooldown when a murderer kills someone?
- What line number in the Mansion nextTurn() method increments the time at the end of each turn?
- What line number in Mansion.java changes the current player's location attribute after they move?
- What line number in Mansion.java returns false if the murderer wins?
- What line number in the Mansion constructor calls the createMansion method?
- What line number in the Mansion constructor sets the StdRandom seed with the calculated loginID hash?
To answer the questions minimally;
One breakpoint at line 105 in Mansion.java. Check 1) Murderer Name 2) Num Items 3) Num Rooms 4) Who Moves First
One conditional breakpoint at line 143 in Mansion.java if any information is needed about a player's murdered (time of death, place of death, etc..). The condition should use "peopleInRoom.get(p)" to access the murdered player and then check their name.
If information about an item drop is needed, place conditional breakpoints on lines 191, 195, 217, and 228. The conditions should use "player.getItemName()" to check if they are dropping the required item.
If information about an item pick up is needed, place conditional breakpoints on lines 204, 219, and 227. The conditions should use "room.getItemName()" to check if they are picking up the required item.
One conditional breakpoint should be placed on line 236 to check questions which ask about information at a specific time. You can use the condition "time == X" to check a certain time, where X is a int, in minutes past 6pm. Note: time increments at the end of the turn for the next turn. So we place the breakpoint before "time+=5" happens.
After the game ends, the number of players who died will be the number of murder weapons.
While the provided game is complete, it is also modifiable to adjust difficulty. The GameResults.java class will adapt to these following changes.
In MurderMystery.java:
In res/Questions.in:
In Mansion.java: