Assignment #2
Value: 15%
Due Date: Friday 17 May 2024 9:00pm
1 day LATE: Saturday 18 May 2024 9:00pm
2 days LATE: Sunday 19 May 2024 9:00pm
Learning Outcomes:
- Gain more confidence programming in Java.
- Design an object-oriented programming (OOP) solution to a problem.
- Apply OO design patterns
Warning about static fields
You should not need to use static
fields in this assignment. If you are using static
fields, you will encounter lots of problems.
Static Methods are fine, Static Fields are not (unless are final)!. See this ED post
If you use static fields, you will be penalised
If you use static
fields, you will notice a weird behaviour that your test cases will pass when executed one at a time, but mostly fail when executed in one go. This is because the static
field values are shared across all test cases, and the test cases are executed with this persistant value. This is not the behaviour you want.
So, be sure to always test your final submission using the command we have provided below, as this is how you will be marked:
./mvnw clean compile test
for Unix/Mac OS or .\mvnw.cmd clean compile test
for Windows
Table of Contents
- Recommended Approach
- Odds and Evens Game
- Files Provided
- OOP Requirements
- The Commands
- Tasks
- Marking Scheme
- Important Instructions
Recommended Approach
To make sure that your machine is properly set for doing the assignment (and all assignments in this course), refer to the FAQ on the course website.
Then it’s a matter of:
- Clone the GitHub repository.
- Use Visual Studio Code for doing the assignment.
- Use the graphical “Testing” view in Visual Studio Code to run the tests (details below).
- As a final check before submitting, use the Maven wrapper to check that everything compiles and the test cases pass (details below).
- To debug your program you should use the debugging mode step by step as we did in class, this will drastically help you to debug and understand your program. Recall that if a test case runs for more than 10 seconds, it will fail. We have to do this check because some students might create infinite loops and the marking of the assignments will run for eternity. This poses a problem for the debugging mode as you will likely spend more than 10 seconds inspectioning the execution. To solve the issue, you have to comment line 51 of
CliTest.java
.
// @Rule public Timeout timeout = new Timeout(10, TimeUnit.SECONDS);
Remember to uncomment that line when you finish the assignment to make sure that each test does not run for more than 10 seconds
Let’s begin!
Clone the GitHub repository
STOP! You MUST use the same GitHub account that you used in Assignment 1!
Clone the assignment repository by accepting the following GitHub Classroom invitation:
Odds and evens (hand game)
Odds and evens game is a very simple game.
- Setup: Two players face each other.
- Decision: One player decides if they want to be odds or evens. Let’s say Player A chooses evens.
- Gameplay: Both players simultaneously show any number of fingers from 0 to 5.
- Counting: If the total number of fingers shown by both players is even (0, 2, 4, 6, 8, 10), Player A wins because they chose evens. If it’s odd (1, 3, 5, 7, 9), Player B wins because they didn’t choose evens.
- Winner: The player who correctly predicted the total (odd or even) wins that round.
- Repeat: Players can play multiple rounds to determine an overall winner.
Consider that it is not really important what the exact numbers the players show are; what is important is whether they are odds or evens.
When you add two numbers:
-
Odd + Odd = Even: When you add two odd numbers together, the result is always even. For example: 1 (odd) + 3 (odd) = 4 (even)
-
Even + Even = Even: When you add two even numbers together, the result is always even. For example: 2 (even) + 4 (even) = 6 (even)
-
Odd + Even = Odd: When you add an odd number and an even number together, the result is always odd. For example: 1 (odd) + 2 (even) = 3 (odd)
-
Even + Odd = Odd: This is the same as above, just in reverse order. When you add an even number and an odd number together, the result is always odd. For example: 2 (even) + 3 (odd)= 5 (odd)
In this assignment you need to implement this game in Java. A human player plays against an artificial intelligence (AI), called HAL-9000
(I hope you get the reference :)). This is a game of chance, but also a game of psychology! The AI will try to learn the behaviour of the human player and attempt to guess the player’s next move.
Files Provided
Below is a list of the files provided to you for this assignment. You should not modify any of the files provided to you, except for the Game.java
file (where you will need to implement the logic for the commands), the MainTest.java
file (where you can add your own test cases if you wish), and Utils.java
if you want to add more methods (but cannot change existing ones).
maven wrapper
(mvnw
for Unix/Mac OS or mvnw.cmd
for Windows)
This file will allow you to build and run this assignment. We will use a Maven wrapper to guarantee that we all have a common configuration to run and test the assignment. This is how your project will be marked. There are three main Maven commands relevant to this assignment:
-
compile
(./mvnw compile
for Unix/Mac OS or.\mvnw.cmd compile
for Windows) Compiles the Java classes (will only compile the Java source files that have changed from the previous build). To make sure your code is compiling correctly, you should see aBUILD SUCCESS
output. However, note that at the very beginning you will see aBUILD FAILURE
output (more information below). -
test
(./mvnw test
for Unix/Mac OS or.\mvnw.cmd test
for Windows) Compiles the Java classes and runs the test cases (will only compile the files that have changed from the previous build). You should see aBUILD SUCCESS
output if the code compiles and all the tests pass. If the code doesn’t compile, or if any of the tests fail, you will see aBUILD FAILURE
output. -
clean
(./mvnw clean
for Unix/Mac OS or.\mvnw.cmd clean
for Windows) Removes the Java binary files (*.class
) by clearing the target directory into which Maven normally builds your project. Runningclean
periodically is useful, for example to remove those.class
files referring to deleted or renamed Java source files.
You can append commands together. For example, ./mvnw clean test
for Unix/Mac OS or .\mvnw.cmd clean test
for Windows will execute the clean
command followed by the test
command. This is generally a good idea, as a clean
will remove any old compiled files that may be causing problems, and you can feel more reassured that the tests are running on a clean slate.
For more information about Maven, visit the related page about development environment.
Note: The first time you run the wrapper, it might take some time (a couple of minutes) to download the required libraries and dependencies. This is normal. Subsequent runs will be much faster.
src/main/java/nz/ac/auckland/se281/Main.java
This class implements the command line interface (CLI).
You should not modify this class.
src/main/java/nz/ac/auckland/se281/MessageCli.java
This class declares most of the messages of the system.
You should not modify this class, but you are encouraged to use it.
You are encouraged to refer to these messages in the code you write, as it will be easier for you to avoid spelling and formatting issues that might otherwise cause you to fail test cases.
There are two ways to use these messages in your code:
- Get the message so that you can print it yourself by calling the
getMessage()
method, or - Request for the message to be printed directly by calling the
printMessage()
method.
You will notice that most of the messages have %s
placeholders in their values. For example, have a look at the definition of the WELCOME_PLAYER
message:
public enum MessageCli {
// ...
WELCOME_PLAYER("Welcome %s!")
// ...
}
There are two %s
placeholders, which means this message expects you to pass two arguments when you want to getMessage()
or printMessage()
it.
For example, consider you want to construct the message "Welcome Alice!"
If you want to get the message to print it yourself, you would do:
String message = MessageCli.WELCOME_PLAYER.getMessage("Alice"); // get the message
System.out.println(message); // print it yourself
But, of course, it will often be easier to just print the message directly:
MessageCli.WELCOME_PLAYER.printMessage("Alice"); // print the message directly
Be sure to dedicate time to understand how this works, as it will be very useful to use and make your job easier. You should already be familiar with this concept from how printf()
works in C.
src/main/java/nz/ac/auckland/se281/Game.java
This class declares the methods that are invoked by the command line interface (Main.java
). This is where you need to start your coding.
You must NOT change the signature of the existing methods of this class (such as changing method names, parameters, and return types).
Of course, you can (and you should) add instance fields and new methods of your own (just cannot add static
fields, here or anywhere else).
You should not create constructors in the Game
class, as they will not be used by the command line or test cases. And you don’t need to for completing the exercise. The only constructor that you can use is the default constructor public Game(){ ... }
that takes in input zero arguments. If you need it, you can add it to the class.
src/main/java/nz/ac/auckland/se281/Utils.java
This class contains several helper methods and objects that are essential for completing the assignment. Specifically, this class must be used to obtain random numbers or read input from the console. We’ve designed it this way to ensure that test cases can override and utilize the same static objects. However, please note that this is not an example of good design, but it is necessary for testing purposes. You are not permitted to modify this class, except for changing the random seed to the Random object, which will make your program pseudo-deterministic and aid in debugging. In fact, the AI may make random decisions, and you might want to reproduce a specific behavior when debugging. To change the random seed, simply insert a number here (for example 2):
public static Random random = new Random(2);
You can choose any number, and you may refer to the test cases to see which numbers are being used. It is crucial that your code works with any random seed, as you will not know which seed will be used by the hidden test cases :P. Occasionally, test your game with the following code:
public static Random random = new Random();
By not specifying a number, the seed will be generated randomly based on your system’s clock time.
src/test/java/nz/ac/auckland/se281/CliTest.java
This is the custom testing framework we created to allow system level testing of your assignment, you cannot change this class.
src/test/java/nz/ac/auckland/se281/MainTest.java
This Java file contains the test cases for this assignment. These test cases make sure that you have implemented most of the assignment correctly.
Making sure that your program passes all of the provided tests will not guarantee that you will get full marks for this assignment, but it will mean that you should get at least half of the marks for the parts that work according to those tests. In fact, we only provided to you half of the test cases that we will use for marking your assignment. You should also note that the test cases we will use for marking your assignment will use slightly different inputs, to ensure you are not hardcoding the expected outputs.
Since we want to give you freedom in designing the system following the object-oriented concepts you learned in class, these are not traditional JUnit test cases like those used in the Hello GitHub assignment. Here, the tests do not directly invoke the code (as we don’t know how you are going to implement it, which classes and methods you will create, and so on). Instead, they test the system from the command line interface, simulating a user typing the commands with the keyboard and observing the result shown on the screen.
Writing your own tests or extending the ones you have been given is strongly recommended. Add them inside MainTest.YourTests
, which you can find at the bottom of the MainTest.java
class. You also need to uncomment each Suite Class near the top of this file:
@RunWith(Suite.class)
@SuiteClasses({MainTest.Task1.class,
// MainTest.Task2.class,
// MainTest.Task3.class,
// MainTest.Task4.class,
// MainTest.Task5.class,
// MainTest.YourTests.class, // <-- add this if you want
})
You can easily write a test using the helper methods runCommands()
, assertContains()
and assertDoesNotContain()
.
(which are implemented by us—they are not standard JUnit).
First, with runCommands()
you specify the commands (or inputs) to be executed (separated by a comma). Then, with assertContains()
, you specify what is the text that you expect to see on the console after executing all the commands. For example, this test case checks that two new profiles are correctly created and added into the system:
Note that is a bit different from A1
, multiple inputs are separated by a space. Also notice the space before EASY
, It is needed as it is part of the same atomic command new-game EASY ODD
. A simple way to think about it is that every comma in runCommands
,
is when the user presses enter.
@Test
public void T1_03_play_ask_for_input() throws Exception {
runCommands(
NEW_GAME + " EASY EVEN",
"Valerio", PLAY,
"1");
assertContains(START_ROUND.getMessage("1"));
assertContains(ASK_INPUT.getMessage());
}
Sometimes it is easier to follow the test case by forcing breaklines with //
at the end of each line. For example, the previous test case could be written as:
@Test
public void T1_03_play_ask_for_input() throws Exception {
runCommands(
NEW_GAME + " EASY EVEN",
"Valerio",
//
PLAY,
"1");
assertContains(START_ROUND.getMessage("1"));
assertContains(ASK_INPUT.getMessage());
}
This way, even if your IDE attempts to auto-format the code, it will not change the way the test case is layed out. It makes it easier in the second case to see we executed two commands (NEW_GAME
and PLAY
), and then we checked that the output contains the lines we would expect to see as a result of those commands executing.
While you can add as many tests as you want, we will not consider them when marking your assignment. Be aware that your code must still work with the original version of the MainTest.java
file, where we will reuse the test cases initially provided to you while also adding new test cases not visible to you.
Note: We also provide additional “hidden” files (those starting with “.
”). You would need to change the folder options to be able to see them. We provide a .gitignore
file that specifies intentionally-untracked files that Git should ignore, and a .mvn
folder containing the Maven wrapper. You should not change these files, and you should not delete them.
OOP Requirements
For this assignment, you should use the OOP concepts and the Design Patterns that we covered in class. As such, you should create appropriate classes and objects. We are giving you complete freedom on how to do the OO design. You will decide how many and which Java classes to create. However, to be sure that you are using design patterns, you are requested to do the following.
OOP requiriments
Your should use the Strategy design pattern to implement the two different AI’s strategies (Random and Top) and change them at runtime. Also you should use the Factory design pattern to create the different AI instances based on the difficulty level given by the player (EASY, MEDIUM, or HARD). For the Strategy design pattern make sure there is the method setStrategy
as we did in class (call the meothod exactly like this).
AND
You should use at least 1 interface and 1 abstract class or at least 2 abstract classes or at least 2 interfaces. This includes those interfaces/abstract classes that you will need to create to implement the design patterns.
Later sections of this page will provide more information. Note that you can choose to use either “interfaces” or “abstract classes”; it is up to you. You can choose the one that you think is more suitable for your implementation! In the lectures, we discussed several times how you should choose between them. Also, you have the freedom to use additional design patterns other than the ones mentioned above. However, when marking the assignment we will only consider the implementation of Strategy and Factory as described above. It is up to you if you want to use other design patterns, it will not affect your marks.
It goes without saying that just implementing the design patterns is not sufficient. Your code has to make use of the classes that implements the design patterns. This is also true for the abstract classes/interface requirement
The Commands
Before proceeding with the tasks, read the code provided to you and start to familiarise yourself with the command-line interface.
To run the application in VS Code in an interactive mode, run the Main class using the Maven wrapper through VS Code’s built-in terminal. If the terminal window is not open, you can open it by clicking on the Terminal
menu, then New Terminal
. Then type the following command:
./mvnw clean compile exec:java@run
for Unix/Mac OS or .\mvnw.cmd clean compile exec:java@run
for Windows
You should see the following output:
Now you can try some of the commands!
Note: The commands are not case sensitive. Also, you can use underscores or hypens interchangeably.
For example, the following are all correct and equivalent:
new-game
NEW_game
NEW_GAME
NeW-GaME
Try the HELP
command to see the list of available commands
You can also try the EXIT
command to exit the system:
281-odd-or-even>exit
You closed the terminal. Goodbye.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:
[INFO] Finished at:
[INFO] ------------------------------------------------------------------------
Only the HELP
and EXIT
commands are implemented for you. You will need to implement the rest of the commands.
Commands with no arguments
The following commands do not require any arguments:
PLAY [no args] Play a round
SHOW_STATS [no args] Show the current statistics
END_GAME [no args] End the game
HELP [no args] Print usage
EXIT [no args] Exit the application
This means you can just type them in the command line, press Enter/Return, and they will be executed.
Obviously, nothing got printed since you need to implement the logic. But notice that no error was reported, since you did not add arguments (as the command expects).
If you were to use the PLAY
command followed by some arguments, you would get an error message:
281-odd-or-even> play 1 2 hello
Error! Incorrect number of arguments provided. Expected 0 argument for the "PLAY" command
This is because the command expects no arguments, but you provided some (in this case, 1
, 2
, hello
).
Commands with arguments
The following command require arguments:
NEW_GAME [2 arguments] start a new game <DIFFICULTY_LEVEL> <ODD_OR_EVEN>
DIFFICULTY_LEVEL: EASY
MEDIUM
HARD
This means you must provide the required number of arguments before pressing Enter/Return for them to be executed. For example, if you use the NEW_GAME
command without arguments (or the wrong number of arguments) and press Enter/Return, you will get and ERROR.
To use it correctly, you need to provide the correct number of arguments:
The DIFFICULTY_LEVEL
and what the player chooses between ODD and EVEN.
It shows an error if you don’t put the correct difficulty level and either ODD or EVEN.
281-odd-or-even> new-game hello ODD
Error! Incorrect difficutly level. The possible difficulty leves are EASY, MEDIUM, H̉ARD```
281-odd-or-even> new-game HARD Hello
Error! You should choose between ODD or EVEN
The input check of new-game
is already implemented for you (you are welcome :)).
Obviously, nothing got printed after you executed the command NEW_GAME
since you need to implement the logic. But notice that no error was reported, since you provided two arguments (as the command expects).
AI Strategies
Before delving into the assignment tasks, let’s explore the AI strategies you’ll need to implement. These strategies will dictate the number of fingers the AI plays each round, ranging from 0 to 5. The primary objective of the AI is to secure victory in the game. It’s worth noting that at the beginning of the game, the human player selects either ODD or EVEN. If the player opts for ODD, the AI aims to win by achieving an EVEN sum of fingers, and vice versa.
Random Strategy
This strategy selects the fingers to play randomly between 0
and 5
.
Top Strategy
This strategy involves monitoring how frequently the human player has chosen evens and odds. Based on this data, the strategy predicts that the player will likely continue favoring the most frequently chosen type of number (ODD or EVEN) and adapts its own approach accordingly. For example, if the player has predominantly selected ODD numbers, the AI assumes they will likely choose an ODD number in the current round. Therefore, if the AI needs an ODD number to win, it will display an EVEN number randomly chosen from 0
, 2
, or 4
(recall that ODD + EVEN = ODD). Conversely, if the AI needs an EVEN number to win, it will opt to show an ODD number randomly chosen from 1
, 3
, or 5
(since ODD + ODD = EVEN). A similar rationale applies if the player has predominantly selected EVEN numbers.
In the scenario where the player has played an equal number of ODD and EVEN numbers, the AI will resort to a random selection between 0
and 5
.
Clearly, the AI cannot get the value played by the human in the current round, only the values of the previous rounds (otherwise is cheating)
Tasks
To guide you through the assignment, we have divided it into five tasks
For each task, we provide a number of test cases (in MainTest.java
) that you can use to test your code.
Task 1
Initial test results
As soon as you compile and run the tests, you will notice that all 10 test cases of Task 1 fail.
With the Maven wrapper:
./mvnw clean compile test
for Unix/Mac OS or .\mvnw.cmd clean compile test
for Windows:
With the Test Runner for Java extension in VS Code:
From the left side of VS Code, click on the Testing icon:
You will then see all the test cases. You might need to expand to see them all:
We recommend you use the Test Runner for Java extension in VS Code. It is a very useful tool that will help you run the tests. It will give you control to run all tests at the same time (as in the example above), or run a single test at a time.
TIP: If you have trouble running tests in Test Runner…
If you attempt to run the tests via the Test Runner, and it gives you some problems (e.g., there’s some weird error, or the tests don’t actually appear to run), then try running the tests via the command line first:
./mvnw clean compile test
for Unix/Mac OS or .\mvnw.cmd clean compile test
for Windows
This should then allow you to run the tests via the Test Runner as expected.
In either case, the examples above are telling you that 10 test cases were run, none of them passed, and all of them failed. In the output, you will find more details on which particular tests failed.
Hint: Look at the numbering of the test cases to guide you in the recommended order to tackle them, in this case the first test case is T1_01_new_game()
.
The important message to read is:
[ERROR] Failures:
[ERROR] MainTest$Task1.T1_01_welcome_message:68->CliTest.assertContains:152 The test is expecting the following output in the console, but it was not there:
"Welcome Valerio!"
This means that the test is expecting the output Welcome Valerio!
to be printed in the console, but it was not there. This is because you have not implemented the logic for the NEW_GAME
command yet.
Let’s try something. Go to the public void newGame(Difficulty difficulty, Choice choice, String[] options) {
method inside Game.java
, and add the following code:
public void newGame(Difficulty difficulty, Choice choice, String[] options) {
MessageCli.WELCOME_PLAYER.printMessage(options[0]);
}
From the terminal, we see that now only 9 of the 10 tests are failing:
[ERROR] Tests run: 10, Failures: 9, Errors: 0, Skipped: 0
We correctly print the Welcome message! For example,
281-odd-or-even> new-game EASY ODD
What is your name?: Bob
Welcome Bob!
Task 1 will require you to implement (some of) the logic for the PLAY
command and NEW_GAME
command:
-
printing of the welcome message of the given name of the human player when a new game starts
-
after the player invoked
NEW_GAME
, the commandPLAY
will show the current number of round, the first time it will be 1, the second timePLAY
is invoked within the same game, the number of round will be 2, then 3, and so on
281-odd-or-even>play
Start Round #1:
- then the game will ask the Human player for
fingers
, which the Human player will provide via command line. The game has to ask that by printing the following message:
281-odd-or-even>play
Start Round #1:
Give <fingers> and press enter
-
The game now is expecting that the user will enter a positive integer and presses Enter. You have to use the following statement to read the input from console
String input = Utils.scanner.nextLine();
. -
The user has to give exaxctly one number such that
fingers
is between 0 and 5 (inclusive). If not, the game will give the error message (INVALID_INPUT
inMessageCli
) and ask again for the number. It will continue to asking until the user enters the number correctly. For example:
281-odd-or-even>play
Start Round #5:
Give <fingers> and press enter
34 5 6
Error! Invalid input, you should give one integer number between 0 and 5 (inclusive), please try again
Give <fingers> and press enter
8
Error! Invalid input, you should give one integer number between 0 and 5 (inclusive), please try again
- When the numbers satisfies the criteria, the game prints
Player <name>: fingers: <a>
where<name>
is the name of the Human player anda
is the number of fingers
281-odd-or-even>play
Start Round #3:
Give <fingers> and press enter
5
Player Valerio: fingers: 5
If all the test cases pass and you are confident that the program is correct, you can move to the next Task.
Task 2
In Task 2, you need to implement the EASY
level of the AI.
Go to the top of the MainTest.java
file, and uncomment the following line:
@RunWith(Suite.class)
@SuiteClasses({MainTest.Task1.class,
// MainTest.Task2.class, // <-- uncomment this line to get started on Task 2
// MainTest.Task3.class,
// MainTest.Task4.class,
// MainTest.Task5.class,
})
You will see 5 new test cases, all of which are failing. Follow the same process as Task 1 to get them all passing, and carefully read the requirements below.
-
The
EASY
level uses theRandom
strategy explained above, and it will never change the strategy for the rest of the game. -
The game also needs to print
Player <name>: fingers: <a>
for the AI with the played values. The AI is calledHAL-9000
, and will always beHAL-9000
even in the hidden test cases.
Start Round #3:
Give <fingers> and press enter
1
Player Valerio: fingers: 1
Player HAL-9000: fingers: 5
- then the game has to print the PRINT_OUTCOME_ROUND of the round, for example
The sum is : 6, is EVEN, player Valerio wins
(assuming that the human player selected EVEN at the beginning of the game)
Task 3
In Task 3 you need to implement the MEDIUM
level of the AI.
- For the first 3 rounds the
MEDIUM
level will use theRandom
strategy, for the fourth round onwards theMEDIUM
level will switch to the Top strategy and will keep that strategy until the current game ends.
Note that everytime the player runs NEW_GAME a new game will start, and the AI will forget all the fingers that the Human player played (and of course if level MEDIUM
is selected again, it will start from the Random
strategy). In other words, the number of played odds and evens numbers has to be calculated for only the history of the fingers played within the current game. If a new game start you need to reset the history.
Task 4
In Task 4, you need to implement the HARD
level of the AI.
-
For the first 3 rounds
HARD
will use theRandom
strategy, for the fourth round onwards theHARD
level AI will switch strategy if the strategy lost in the previous round, otherwise will keep using that strategy. -
When switching strategy
Top
strategy will consder the whole history of rounds from round 1
For example:
Round 1: Random (always) - Human wins
Round 2: Random (always) - AI wins
Round 3: Random (always) - AI wins
Round 4: Random (random stays because AI won the previous round) - Human wins
Round 5: Top (switch strategy because AI lost the previous round) - AI wins
Round 6: Top (top stays because AI won the previous round) - AI wins
Round 7: Top (top stays because AI won the previous round) - Human wins
Round 8: Random (switch strategy because AI lost the previous round) - AI wins
Same as above, everytime the player runs NEW_GAME a new game will start and the AI will forgot all the fingers that the Human player played.
Task 5
In Task 5, you need to implement the logic that terminates the game and executes the command SHOW_STATS
- first of all, the user cannot run the command
PLAY
before the game is started (it shows an error message):
281-odd-or-even>play
Error! Game not started yet. Please start a new game first
-
The player has the freedom to start a new game with
NEW_GAME
while the current game is not finished yet. In this case, everything must starts from a blank state. If a new game is made whilst another is in progress, end the current game without displaying the stats/winner and just immediately start a new game. -
You need to implement the
SHOW-STATS
command, which can only be executed when a game is running (otherwise the game shows an error message). The command shows for each player how many rounds they won and how many rounds they lost. -
The player has also the freedom to end the game with
END_GAME
command. In this case the game has to show the statistics and print the winner. -
Note that the game can and in a TIE!
For example:
281-odd-or-even> play
Error! Game not started yet. Please start a new game first
281-odd-or-even> show-stats
Error! Game not started yet. Please start a new game first
281-odd-or-even> end_game
Error! Game not started yet. Please start a new game first
281-odd-or-even> new-game HARD ODD
What is your name?: Valerio
Welcome Valerio!
281-odd-or-even> show-stats
Valerio won 0 rounds and lost 0 rounds
HAL-9000 won 0 rounds and lost 0 rounds
281-odd-or-even> play
Start Round #1:
Give <fingers> and press enter
4
Player Valerio: fingers: 4
Player HAL-9000: fingers: 3
The sum is : 7, is ODD, player Valerio wins!
281-odd-or-even> show-stats
Valerio won 1 rounds and lost 0 rounds
HAL-9000 won 0 rounds and lost 1 rounds
281-odd-or-even> end-game
Valerio won 1 rounds and lost 0 rounds
HAL-9000 won 0 rounds and lost 1 rounds
Player Valerio won the game!
281-odd-or-even> new-game
Error! Incorrect number of arguments provided. Expected 2 arguments for the "NEW_GAME" command
281-odd-or-even> new-game HARD EVEN
What is your name?: Valerio
Welcome Valerio!
281-odd-or-even> play
Start Round #1:
Give <fingers> and press enter
4
Player Valerio: fingers: 4
Player HAL-9000: fingers: 4
The sum is : 8, is EVEN, player Valerio wins!
281-odd-or-even> show-stats
Valerio won 1 rounds and lost 0 rounds
HAL-9000 won 0 rounds and lost 1 rounds
281-odd-or-even> play
Start Round #2:
Give <fingers> and press enter
0
Player Valerio: fingers: 0
Player HAL-9000: fingers: 1
The sum is : 1, is ODD, player HAL-9000 wins!
281-odd-or-even> play
Start Round #3:
Give <fingers> and press enter
0
Player Valerio: fingers: 0
Player HAL-9000: fingers: 3
The sum is : 3, is ODD, player HAL-9000 wins!
281-odd-or-even> play
Start Round #4:
Give <fingers> and press enter
4
Player Valerio: fingers: 4
Player HAL-9000: fingers: 2
The sum is : 6, is EVEN, player Valerio wins!
281-odd-or-even> show-stats
Valerio won 2 rounds and lost 2 rounds
HAL-9000 won 2 rounds and lost 2 rounds
281-odd-or-even> end-game
Valerio won 2 rounds and lost 2 rounds
HAL-9000 won 2 rounds and lost 2 rounds
Tie!
When all the test cases are passing, that’s a great sign! However, keep in mind that only half the test cases are provided (read the instructions below).
You will need to write your own test cases to ensure that your code is correct for other requirements mentioned above, where test cases were not provided.
Marking Scheme
Item | Value | Note |
---|---|---|
Task 1 | 1% | ❶ |
Task 2 | 0.5% | ❶ |
Task 3 | 2% | ❶ |
Task 4 | 1% | ❶ |
Task 5 | 0.5% | ❶ |
OO Design | 6% | ❷ |
Code Style | 3% | ❸ ❹ |
Git Etiquette | 1% | ❸ ❺ |
Total | 15% |
Important Instructions
Please read the following information carefully before you begin your assignment.
Does passing test cases mean I have completed the assignment?
You will see that we provide some test cases to help guide you. In most cases, these test cases are not comprehensive. They are not designed to test all possible inputs. They are designed to help you get started.
What’s more, you should make sure you do not hard code your logic to pass the specific test cases we provide. You should write your code in a way that it will work for any input.
For example, if we provide a test case that checks if the method checkIfIsEven
returns true
when the input is 2
:
@Test
public void testIsEven() {
checkIfIsEven(2);
assertContains("true");
}
You should not write your code like this:
public void checkIfIsEven(int number) {
if (number == 2) {
System.out.println("true");
} else {
System.out.println("false");
}
}
This is because in the actual marking, we will use different values for the test cases. For example, we may use the test case:
@Test
public void testIsEven() {
checkIfIsEven(280);
assertContains("true");
}
If you have hard coded your logic to pass the test case checkIfIsEven(2)
, then your code will not pass the test case checkIfIsEven(280)
and you will therefore not get the marks for that test case.
Code Style Tool
Note: You should have received an email (from “GradeStyle”) with your personal access token. If you didn’t, it’s most likely because you have not associated your GitHub username with your identity when you accepted one of the assignments. In that case, please email Nasser and let him know what GitHub username you used for Hello GitHub.
There will be marks allocated to your code style. Please see the Java Conventions and Best Practices page for more information on code style relevant to this course.
To provide you with feedback on your code style, we will be using a tool we have developed. This tool will check your code for common code style issues, and email you a report on your code style. This email report will let you know what you need to fix.
After the assignment deadline has passed, we will use the same tool to mark code style for your submission.
To benefit from this tool, you need to have your commits pushed to the remote GitHub repository. The tool will extract the code from there, analyse your code, and email you the report.
To use the tool, a codestyle.config
file is needed in to the root directory (where the pom.xml
file is). Inside it, you should include two things:
email: "student@aucklanduni.ac.nz"
accessToken: "token-that-was-emailed-to-you"
Note: You will notice that the codestyle.config
file is added to the .gitignore
file. It is good practice to never track credentials in a repository.
The access token will be emailed to you, and is unique for you.
In the assignment repo, you will find a codestyle_SAMPLE.config
for your convenience. You can copy-and-paste it, change the name (to codestyle.config
), and fill the email
and accessToken
values with your credentials.
To invoke the actual tool, you will run:
./mvnw clean compile exec:java@style
for Unix/Mac OS or .\mvnw.cmd clean compile exec:java@style
for Windows
You will receive an email with the feedback.
Some notes about running the tool:
- We limit the number of times you can run the tool (currently once per 30 minutes). With a large number of students, we cannot afford to run the tool on every commit. To make the most of the tool, we therefore recommend you start the assignment early on, and run the tool frequently. If you leave it too late, you will not be able to run the tool as many times as you might like.
- The tool runs on code you have pushed to the remote repository. It does not run on your local repository. Therefore, if you want to generate a new report on your latest code, you will need to do a
git commit
and agit push
to the remote repository. The tool will decline to run if you have not pushed your latest code to the remote repository. - Some of the code style aspects might require your code to compile. So, make sure you have a working code before running the tool. If you have a compilation error, the tool will not run (and it will still count as one of your runs). So, remember to do a
./mvnw clean compile
for Unix/Mac OS or.\mvnw.cmd clean compile
for Windows (or include theclean compile
in yourexec:java@style
command) before running the tool. - The tool will use the GitHub username that was registered in the first Hello GitHub assignment you completed. If you did not associate your name with a GitHub username in GitHub Classroom, you would not have received an email with the access token. If you have a GitHub username associated with your name in GitHub Classroom, but you did not receive an email with the access token, please contact us.
- If you are using a different GitHub username (compared to the one you used in the Hello GitHub assignment), then the tool will not be able to find your repo, and therefore will not be able to run. Try to re-accept the GitHub Classroom invitation link (for the assignment) using the same GitHub account you registered earlier.
Here’s an example of running the Code Style tool:
Academic Honesty
You MUST use the GitHub repository created from the GitHub Classroom invitation link provided.
NEVER use your own repository, or copy your code to another repository to work from.
Doing so means your assignment will not be accepted for marking.
- The work done on this assignment must be your own work. Think carefully about any problems you come across, and try to solve them yourself before you ask anyone for help (struggling a little with it will help you learn, especially if you end up solving it). If you still need help, check on Ed Discussion (if it is about interpreting the assignment specifications) or ask in the Drop-In help clinics (if you would like more personal help with Java). Under no circumstances should you take or pay for an electronic copy of someone else’s work.
- All submitted code will be checked using software similarity tools. Submissions with suspicious similarity will result in action taken following the University’s Guidelines for Academic Misconduct, and forwarded to the Disciplinary Committee.
- Penalties for copying will be severe. In most cases, this is ZERO for the assignment in question. To avoid being caught copying, don’t do it. Please note the same penalty applies to both the person who copied and the person who was copied from.
- The University has recently taken a much stricter stance on academic misconduct and streamlined the process for dealing with it. In a nutshell, it takes a non-negotiation approach — no longer requiring a thorough investigation. You will therefore simply be informed, and find the penalty applied to the assignment. This is why it’s important to not only copy from others, but also not to show your work to others.
- You must not attempt to tamper with your GitHub commits. This means all commits must be preserved, including the one that is automatically created by GitHub Classroom. Disregarding this will result in major penalties. See the section on Tampering with your Git commit history for more information.
- To ensure you are not identified for potential plagiarism, you should follow these points:
- Always do individual assignments by yourself.
- Never show or give another person your code.
- Make sure you are doing plenty of commits and pushes to GitHub. This will help you to track your progress and also to ensure that you have a backup of your work. It also makes it easier for us to see that you have not been copying from someone else.
- Do not share your GitHub account with anyone.
- Never put your code in a public place (e.g. Reddit, public GitHub repository, forums, your website, etc).
- Never leave your computer unattended. You are responsible for the security of your account.
- Ensure that you always remove your USB flash drive from any public computer before you log off from it.
- Frequently commit your code to GitHub. This provides a track record of your work and will allow the teaching team to follow your footsteps as you complete your assignment. If you do not frequently commit your code, it will look suspicious.
Git Etiquette
All the take-home programming assignments will require you to make good use of Git and GitHub.
There are marks associated with Git usage. But you could stand to lose more marks if there’s evidence of tampering with your Git commit history.
Make sure you are familiar with the expectations outlined in the Git Etiquette page.
Can I use Copilot and ChatGPT for this assignment?
As you progress through the course, mastering the underlying OOP concepts is essential. Throughout this process, Generative AI tools like Copilot and ChatGPT can be beneficial. They help generate code snippets and assist with programming tasks.
We do not frown upon using these tools. In fact, part of this course includes a task specifically designed to enhance your skills in using these tools critically.
You will notice how these tools can help you write code faster and more efficiently. They boost your productivity.
While these AI tools are valuable, relying too heavily on them can impede your learning. If you depend too much on their output, you may miss out on the opportunity to develop your programming skills. Our goal is to not only acquaint you with tools such as Copilot and ChatGPT but more importantly, to solidify your understanding of core programming concepts for effective application.
This course includes invigilated and practical tests that run without the aid of AI tools (or any other resource for that matter), to ensure you can independently apply what you’ve learned. Over-dependence on AI might make these tests more difficult and stressful.
The real benefit of Generative AI tools lies in understanding the logic of the code they produce, not just in using the code. This video below illustrates the importance of comprehending AI-generated code:
As highlighted in this video, Generative AI is great at filling in the small gaps in your knowledge. Just make sure you aren’t relying on them to fill in the big gaps in your knowledge—because they won’t.
Final Submission on GitHub
In this course, all your assignments will be automatically extracted from GitHub. There will be no separate submission on Canvas.
The following instructions are very important. Make sure you double check everything, otherwise your assignment will not be marked:
- You must use the GitHub Classroom link provided in the assignment instructions to create your GitHub repository.
- You must have frequent commits and pushes to GitHub. This will help you to track your progress and also to ensure that you have a backup of your work. It also makes it easier for us to see that you have not been copying from someone else.
- It is not enough that you were doing
git add
andgit commit
commands! This only tracks the changes on your local machine! - Unfortunately, it is not a good look for us to hack into your machine in order to take your local repo (even for the good intentions of marking it). Therefore, it is absolutely important you have (correctly) executed a
git push
so that all your commits and changes are sent to the remote GitHub repository. - To make sure you submitted your code, simply go to https://github.com and check the “commits” tab of your assignment repository. Do you see the latest changes there? If so, you are good. If no, something went wrong and you need to sort it out so that it appears in the remote repository before the deadline.
- As an extra (strongly recommended) precaution, you should clone your GitHub remote repo to your machine (e.g., to a temporary folder), and check it works correctly by compiling it and running it all over again (in a “fresh” directory). This is to protect you if you didn’t correctly include all the changed files (in which case, the assignment runs correctly on your local repo but you didn’t push everything to the remote repo).
- If you want to submit late, review the Late Submissions section to understand how it works with your GitHub repository.
If you don’t want zero…
It is your responsibility to make sure all your changes are correctly visible on your remote GitHub repository. Read all the submission instructions carefully. It is not enough that you did commits and they appear in your local repository. Even if you pushed them to the remote repository later on (with timestamps before the deadline), it is not enough! The changes must appear in the remote repository before the deadline to be considered for marking. No exceptions.
You must double check that you have uploaded the correct code for marking! There will be no exceptions if you accidentally submitted the wrong files, regardless of whether you can prove you did not modify them since the deadline. No exceptions. Get into the habit of downloading them again, and double-checking all is there.
Late Submissions
Late submissions are based on the GitHub server timestamp
If you intend to submit before the deadline (and not utilise the late penalty allowance), then make sure you have pushed all your commits to your remote GitHub repository before the deadline.
After the 2-day late penalty allowance, we will clone your remote repository. To determine if you have a late submission, we use the GitHub server timestamp. If the timestamp is after the deadline, then it is late.
Please note: We do NOT use the commit timestamps. This is because the commit timestamps are based on your local machine, and can be easily changed. We will therefore only use the GitHub server timestamp to determine if your submission is late or not. No exceptions. This is why it’s your responsibility to make sure you push your commits to the remote repository before the deadline.
If you would like more time and submit late (with penalties), then simply keep working on your assignment and make sure you push the latest commits to the remote repository either 24 hours late or 48 hours late. By looking at the last push timestamp, we will determine if your assignment is 24 hours late or 48 hours late.
After the 48-hour late period passes, your repository will become read-only — and you will not be able to push to it. You will get an error message when you attempt to push, that you do not have access to it. Again, it doesn’t matter if you did the commit within the 48 hours. What matters is that you do the push within the 48 hours.
Remember: your commits need to be pushed and in the remote repository within the 48 hours, not only timestamped!.
Late submissions will incur the following penalties:
- 15% penalty for 0 minutes < t <= 24 hours late (based on GitHub server timestamp of last push).
- 30% penalty for 24 hours < t <= 48 hours late (based on GitHub server timestamp of last push).
- 100% penalty for t > 48 hours late (GitHub repository becomes read-only, no more pushes possible).
It is up to you if you want to risk working on your assignment up until the deadline. If you don’t successfully push to the remote repository before the above deadlines, then it will be late. Don’t risk it.
We will stick by these clearly-specified rules. We have to be fair to everyone, and we will not be able to make exceptions to these rules due to mistakes or misunderstandings. If you are unsure about anything, please ask in Ed Discussion well ahead of the deadline.