state: Added initial state, island, player, coord object types

This commit is contained in:
Nathan Woodburn 2023-04-24 13:59:25 +10:00
parent 82a8dbccda
commit 7ed595dced
Signed by: nathanwoodburn
GPG Key ID: 203B000478AD0EF1
6 changed files with 705 additions and 0 deletions

View File

@ -0,0 +1,70 @@
package comp1110.ass2;
/**
* Object to store coordinates
* This stores the x and y coordinates of a point
*/
public class Coord {
private int x;
private int y;
/**
* Constructor for the Coord object
* @param x x coordinate
* @param y y coordinate
*/
public Coord(int x, int y) {
this.x = x;
this.y = y;
}
/**
* Get the x coordinate
* @return int x coordinate
*/
public int getX() {
return x;
}
/**
* Get the y coordinate
* @return int y coordinate
*/
public int getY() {
return y;
}
/**
* Set the x coordinate
* @param x int x coordinate
*/
public void setX(int x) {
this.x = x;
}
/**
* Set the y coordinate
* @param y int y coordinate
*/
public void setY(int y) {
this.y = y;
}
/**
* Check if two coordinates are equal
* @param coord Coord object to compare to
* @return boolean true if equal, false otherwise
*/
public boolean equals(Coord coord) {
return (this.x == coord.x && this.y == coord.y);
}
/**
* Get a string representation of the coordinate
* @return String representation of the coordinate
*/
@Override
public String toString() {
return "(" + x + ", " + y + ")";
}
}

View File

@ -0,0 +1,82 @@
package comp1110.ass2;
/**
* Island class
* This class is used to store the information of an island
*/
public class Island {
final int bonus;
private Coord[] coords;
/**
* Constructor for Island class
* This creates an island with a bonus and an empty array of coordinates
* @param bonus the bonus of the island
*/
public Island(int bonus) {
this.bonus = bonus;
this.coords = new Coord[0];
}
/**
* Get the bonus of the island
* @return int bonus of the island
*/
public int getBonus() {
return bonus;
}
/**
* Get the coordinates of the island
* @return Coord[] coordinates of the island
*/
public Coord[] getCoords() {
return coords;
}
/**
* Check if the island contains a coordinate
* @param coord the coordinate to be checked
* @return boolean true if the island contains the coordinate
*/
public boolean containsCoord(Coord coord) {
for (Coord c : this.coords) {
if (c.equals(coord)) {
return true;
}
}
return false;
}
/**
* Add a coordinate to the island
* @param coord the coordinate to be added
*/
public void addCoord(Coord coord) {
if (this.containsCoord(coord)) {
return;
}
Coord[] newCoords = new Coord[this.coords.length + 1];
for (int i = 0; i < this.coords.length; i++) {
newCoords[i] = this.coords[i];
}
newCoords[this.coords.length] = coord;
this.coords = newCoords;
}
/**
* Check if island is equal to another island
* @param island the island to be compared to
* @return boolean true if the island is equal to the other island
*/
public boolean equals(Island island) {
if (this.bonus != island.bonus) return false;
if (this.coords.length != island.coords.length) return false;
for (int i = 0; i < this.coords.length; i++) {
if (!this.containsCoord(island.coords[i])) return false;
}
return true;
}
}

View File

@ -0,0 +1,203 @@
package comp1110.ass2;
/**
* Player class
* This class is used to store the information of a player
* This includes the player's ID, score, resources, settlers and villages
*/
public class Player {
final int playerID;
private int score;
private int numCoconuts;
private int numBamboo;
private int numWater;
private int numPreciousStones;
private int numStatuette;
private Coord[] settlers;
private Coord[] villages;
/**
* Constructor for Player class
* This creates a player with a player ID and initialises the player's score, resources, settlers and villages
* @param playerID int player ID
*/
public Player(int playerID) {
this.playerID = playerID;
this.score = 0;
this.numCoconuts = 0;
this.numBamboo = 0;
this.numWater = 0;
this.numPreciousStones = 0;
this.numStatuette = 0;
this.settlers = new Coord[0];
this.villages = new Coord[0];
}
/**
* Get the player's ID
* @return int player ID
*/
public int getPlayerID() {
return playerID;
}
/**
* Get the player's score
* @return int player score
*/
public int getScore() {
return score;
}
/**
* Add a score to the player's score
* @param score int score to be added
*/
public void addScore(int score) {
this.score += score;
}
/**
* Get the number of a resource the player has of a type
* @param resourceType char resource type
* @return int number of the resource the player has
*/
public int getNumResource(char resourceType) {
switch (resourceType) {
case 'C':
return numCoconuts;
case 'B':
return numBamboo;
case 'W':
return numWater;
case 'P':
return numPreciousStones;
case 'S':
return numStatuette;
default:
return 0;
}
}
/**
* Add a resource to the player's resources
* @param numResource int number of the resource to be added
* @param resourceType char resource type
*/
public void addResource(int numResource, char resourceType) {
switch (resourceType) {
case 'C':
numCoconuts += numResource;
break;
case 'B':
numBamboo += numResource;
break;
case 'W':
numWater += numResource;
break;
case 'P':
numPreciousStones += numResource;
break;
case 'S':
numStatuette += numResource;
break;
}
}
/**
* Remove a resource from the player's resources
* @param numResource int number of the resource to be removed
* @param resourceType char resource type
*/
public void removeResource(int numResource, char resourceType) {
switch (resourceType) {
case 'C':
numCoconuts -= numResource;
break;
case 'B':
numBamboo -= numResource;
break;
case 'W':
numWater -= numResource;
break;
case 'P':
numPreciousStones -= numResource;
break;
case 'S':
numStatuette -= numResource;
break;
}
}
/**
* Get the player's settlers
* @return Coord[] list of the player's settlers coords
*/
public Coord[] getSettlers() {
return settlers;
}
/**
* Get the player's villages
* @return Coord[] list of the player's villages coords
*/
public Coord[] getVillages() {
return villages;
}
/**
* Add settlers to the player's settlers
* @param coord Coord coord of the settler to be added
*/
public void addSettler(Coord coord) {
Coord[] newSettlers = new Coord[settlers.length + 1];
for (int i = 0; i < settlers.length; i++) {
newSettlers[i] = settlers[i];
}
newSettlers[settlers.length] = coord;
settlers = newSettlers;
}
/**
* Add a village to the player's villages
* @param coord Coord coord of the village to be added
*/
public void addVillage(Coord coord) {
// Check if the player already has the maximum number of villages
if (villages.length >= 5) {
return;
}
Coord[] newVillages = new Coord[villages.length + 1];
for (int i = 0; i < villages.length; i++) {
newVillages[i] = villages[i];
}
newVillages[villages.length] = coord;
villages = newVillages;
}
/**
* Check if player is equal to another player
* @param player Player player to be compared to
* @return true if the players are equal, false otherwise
*/
public boolean equals(Player player) {
if (player.getPlayerID() != playerID) return false;
if (player.getScore() != score) return false;
if (player.getNumResource('C') != numCoconuts) return false;
if (player.getNumResource('B') != numBamboo) return false;
if (player.getNumResource('W') != numWater) return false;
if (player.getNumResource('P') != numPreciousStones) return false;
if (player.getNumResource('S') != numStatuette) return false;
if (player.getSettlers().length != settlers.length) return false;
if (player.getVillages().length != villages.length) return false;
for (int i = 0; i < settlers.length; i++) {
if (!player.getSettlers()[i].equals(settlers[i])) return false;
}
for (int i = 0; i < villages.length; i++) {
if (!player.getVillages()[i].equals(villages[i])) return false;
}
return true;
}
}

View File

@ -0,0 +1,64 @@
package comp1110.ass2;
/**
* Resource class
* This class is used to store the information of a resource
* This stores the type and the coordinate of the resource
*/
public class Resource {
private char type;
private Coord coord;
/**
* Constructor for Resource class
* This creates a resource with a type and a coordinate
* @param type the type of the resource
* @param coord the coordinate of the resource
*/
public Resource(char type, Coord coord) {
this.type = type;
this.coord = coord;
}
/**
* Get the type of the resource
* @return char type of the resource
*/
public char getType() {
return type;
}
/**
* Get the coordinate of the resource
* @return Coord coordinate of the resource
*/
public Coord getCoord() {
return coord;
}
/**
* Set the type of the resource
* @param type char type of the resource
*/
public void setType(char type) {
this.type = type;
}
/**
* Set the coordinate of the resource
* @param coord Coord coordinate of the resource
*/
public void setCoord(Coord coord) {
this.coord = coord;
}
/**
* Check if the resource is equal to another resource
* @param resource Resource resource to be compared
* @return boolean true if the resources are equal
*/
public boolean equals(Resource resource) {
return (this.type == resource.type && this.coord.equals(resource.coord));
}
}

View File

@ -0,0 +1,234 @@
package comp1110.ass2;
/**
* Object to store the game state
* This stores the state of the game in a way that is easy to access and modify
* It stores the board height, number of players, current player, current phase, islands, stones,
* unclaimed resources and players (with their data)
*
*/
public class State {
final int boardHeight;
private int numPlayers;
private int currentPlayer;
private int currentPhase; // 0 for exploration, 1 for settlement
private Island[] islands;
private Coord[] stonesCoords;
private Resource[] unclaimedResources;
private Player[] players;
/**
* Constructor for the state object
* This takes a string containing the state of the game and initialises the object
* @param stateString String containing the state of the game
*/
public State(String stateString) {
// Split the state string into its components
String[] components = stateString.split(";");
// For the game initialisation part
String[] gameInitComponents = components[0].trim().split(" ");
boardHeight = Integer.parseInt(gameInitComponents[1]);
numPlayers = Integer.parseInt(gameInitComponents[2]);
// Current state part
String[] currentStateComponents = components[1].trim().split(" ");
currentPlayer = Integer.parseInt(currentStateComponents[1]);
if (currentStateComponents[2].equals("E")) currentPhase = 0;
else currentPhase = 1;
// Islands part
int islandcount = 0;
for (int i=2; i< components.length; i++)
{
// Split island part
String[] islandComponents = components[i].trim().split(" ");
// Check if the component is still an island
if (!islandComponents[0].equals("i")) break;
Island tmpIsland = new Island(Integer.parseInt(islandComponents[1]));
// Add each coord
for (int j=2; j<islandComponents.length; j++)
{
String[] coordComponents = islandComponents[j].split(",");
tmpIsland.addCoord(new Coord(Integer.parseInt(coordComponents[0]), Integer.parseInt(coordComponents[1])));
}
islandcount++;
// Add the island to the array
Island[] tmpislands = new Island[islandcount];
for (int j=0; j<tmpislands.length-1; j++)
{
tmpislands[j] = islands[j];
}
tmpislands[islandcount-1] = tmpIsland;
islands = tmpislands;
}
// Stones part
String[] stonesComponents = components[2+islandcount].trim().split(" ");
stonesCoords = new Coord[stonesComponents.length-1];
for (int i=1; i<stonesComponents.length; i++)
{
String[] coordComponents = stonesComponents[i].split(",");
stonesCoords[i-1] = new Coord(Integer.parseInt(coordComponents[0]), Integer.parseInt(coordComponents[1]));
}
// Unclaimed resources part
String[] unclaimedResourcesComponents = components[3+islandcount].trim().split(" ");
unclaimedResources = new Resource[unclaimedResourcesComponents.length-1];
int currentResource = 0;
char type = 'C';
for (int i=1; i<unclaimedResourcesComponents.length; i++)
{
if (unclaimedResourcesComponents[i].matches("[CBWPS]")){
currentResource++;
type = unclaimedResourcesComponents[i].charAt(0);
continue;
}
String[] coordComponents = unclaimedResourcesComponents[i].split(",");
Coord tmpCoord = new Coord(Integer.parseInt(coordComponents[0]), Integer.parseInt(coordComponents[1]));
unclaimedResources[i-1-currentResource] = new Resource(type, tmpCoord);
}
// Players part
players = new Player[numPlayers];
for (int i=0; i<numPlayers; i++)
{
String[] playerComponents = components[4+islandcount+i].trim().split(" ");
players[i] = new Player(Integer.parseInt(playerComponents[1]));
players[i].addScore(Integer.parseInt(playerComponents[2]));
players[i].addResource(Integer.parseInt(playerComponents[3]),'C');
players[i].addResource(Integer.parseInt(playerComponents[4]),'B');
players[i].addResource(Integer.parseInt(playerComponents[5]),'W');
players[i].addResource(Integer.parseInt(playerComponents[6]),'P');
players[i].addResource(Integer.parseInt(playerComponents[7]),'S');
int pieceType = 0;
for (int j=8; j<playerComponents.length; j++)
{
if (playerComponents[j].matches("[ST]")){
pieceType++;
continue;
}
if (pieceType == 1) {
String[] coordComponents = playerComponents[j].split(",");
players[i].addSettler(new Coord(Integer.parseInt(coordComponents[0]), Integer.parseInt(coordComponents[1])));
}
else if (pieceType == 2) {
String[] coordComponents = playerComponents[j].split(",");
players[i].addVillage(new Coord(Integer.parseInt(coordComponents[0]), Integer.parseInt(coordComponents[1])));
}
}
}
}
/**
* Get the board height
* @return int board height
*/
public int getBoardHeight() {
return boardHeight;
}
/**
* Get the number of players
* @return int number of players
*/
public int getNumPlayers() {
return numPlayers;
}
/**
* Get the current player
* @return int current player
*/
public int getCurrentPlayer() {
return currentPlayer;
}
/**
* Get the current phase
* @return char current phase
*/
public char getCurrentPhase() {
if (currentPhase == 0) return 'E';
else return 'S';
}
/**
* Get the islands
* @return Island[] islands
*/
public Island[] getIslands() {
return islands;
}
/**
* Get one island (by 0 index)
* @return Island island
*/
public Island getIsland(int i) {
return islands[i];
}
/**
* Get the stones
* @return Coord[] stones
*/
public Coord[] getStones() {
return stonesCoords;
}
/**
* Check if a stone is at a given coordinate
* @param coord Coord coordinate to check
* @return boolean true if stone is at coordinate
*/
public boolean isStone(Coord coord) {
for (Coord stone : stonesCoords) {
if (stone.equals(coord)) return true;
}
return false;
}
public Player getPlayer(int i) {
return players[i];
}
/**
* Get the unclaimed resources
* @return Resource[] unclaimed resources
*/
public Resource[] getUnclaimedResources() {
return unclaimedResources;
}
/**
* Get the unclaimed resources of a given type
* @param type char type of resource
* @return Resource[] unclaimed resources of type
*/
public Resource[] getUnclaimedResources(char type) {
Resource[] tmpResources = new Resource[unclaimedResources.length];
int i = 0;
for (Resource resource : unclaimedResources) {
if (resource.getType() == type){
tmpResources[i] = resource;
i++;
}
}
Resource[] resources = new Resource[i];
for (int j=0; j<i; j++) {
resources[j] = tmpResources[j];
}
return resources;
}
}

View File

@ -4,6 +4,7 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.sql.SQLOutput;
import java.util.Arrays;
/**
* This class is used to test BlueLagoon methods/functions.
@ -103,6 +104,57 @@ public class D2DTests {
System.out.println("Test 7 passed");
System.out.println("All Tests passed");
}
@Test
public void testStateObject(){
String DEFAULT_GAME = "a 13 2; c 0 E; i 6 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 1,4 2,0 2,1; i 6 0,5 0,6 0,7 1,6 1,7 1,8 2,6 2,7 2,8 3,7 3,8; i 6 7,12 8,11 9,11 9,12 10,10 10,11 11,10 11,11 11,12 12,10 12,11; i 8 0,9 0,10 0,11 1,10 1,11 1,12 2,10 2,11 3,10 3,11 3,12 4,10 4,11 5,11 5,12; i 8 4,0 5,0 5,1 6,0 6,1 7,0 7,1 7,2 8,0 8,1 8,2 9,0 9,1 9,2; i 8 10,3 10,4 11,0 11,1 11,2 11,3 11,4 11,5 12,0 12,1 12,2 12,3 12,4 12,5; i 10 3,3 3,4 3,5 4,2 4,3 4,4 4,5 5,3 5,4 5,5 5,6 6,3 6,4 6,5 6,6 7,4 7,5 7,6 8,4 8,5; i 10 5,8 5,9 6,8 6,9 7,8 7,9 7,10 8,7 8,8 8,9 9,7 9,8 9,9 10,6 10,7 10,8 11,7 11,8 12,7 12,8; s 0,0 0,5 0,9 1,4 1,8 1,12 2,1 3,5 3,7 3,10 3,12 4,0 4,2 5,9 5,11 6,3 6,6 7,0 7,8 7,12 8,2 8,5 9,0 9,9 10,3 10,6 10,10 11,0 11,5 12,2 12,8 12,11; r C B W P S; p 0 0 0 0 0 0 0 S T; p 1 0 0 0 0 0 0 S T;";
State state = new State(DEFAULT_GAME);
Assertions.assertEquals(13, state.getBoardHeight(), "The test failed because the board length is not 13");
Assertions.assertEquals(2, state.getNumPlayers(), "The test failed because the number of players is not 2");
Assertions.assertEquals(0, state.getCurrentPlayer(), "The test failed because the current player is not 0");
Assertions.assertEquals('E', state.getCurrentPhase(), "The test failed because the current phase is not E");
// Creating test island for the string
// i 6 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 1,4 2,0 2,1;
Island island = new Island(6);
island.addCoord(new Coord(0,0));
island.addCoord(new Coord(0,1));
island.addCoord(new Coord(0,2));
island.addCoord(new Coord(0,3));
island.addCoord(new Coord(1,0));
island.addCoord(new Coord(1,1));
island.addCoord(new Coord(1,2));
island.addCoord(new Coord(1,3));
island.addCoord(new Coord(1,4));
island.addCoord(new Coord(2,0));
island.addCoord(new Coord(2,1));
Assertions.assertTrue(island.equals(state.getIsland(0)), "The test failed because the island at index 0 is not the same as the island created above");
island.addCoord(new Coord(2,2));
Assertions.assertFalse(island.equals(state.getIsland(0)), "The test failed because the island at index 0 is the same as the island created above even though it should not be because the island created above has 11 coords while the island at index 0 has 12 coords");
Assertions.assertTrue(state.isStone(new Coord(0,0)), "The test failed because the stone at (0,0) is not a stone");
Assertions.assertFalse(state.isStone(new Coord(0,1)), "The test failed because the stone at (0,5) is a stone even though it should not be because there is no stone at that location");
// Creating a test player for the string
// p 0 0 0 0 0 0 0 S T;
Player player = new Player(0);
Assertions.assertTrue(player.equals(state.getPlayer(0)), "The test failed because the player at index 0 is not the same as the player created above");
player.addScore(1);
Assertions.assertFalse(player.equals(state.getPlayer(0)), "The test failed because the player at index 0 is the same as the player created above even though it should not be because the player created above has a score of 1 while the player at index 0 has a score of 0");
player = new Player(0);
player.addVillage(new Coord(0,0));
Assertions.assertFalse(player.equals(state.getPlayer(0)), "The test failed because the player at index 0 is the same as the player created above even though it should not be because the player created above has a village at (0,0) while the player at index 0 has no villages");
player = new Player(0);
player.addResource(1,'C');
Assertions.assertFalse(player.equals(state.getPlayer(0)), "The test failed because the player at index 0 is the same as the player created above even though it should not be because the player created above has a resource of 1 for C while the player at index 0 has a resource of 0 for C");
}
}