I'm trying to implement a monopoly-style game in java as part of a school project but I've run into an issue that I cant resolve or seem to find an answer to the question that I have. The problem is that I'm getting a classCastException in my code, I think I've figured out why I'm getting it (i was originally trying to cast type Property onto the newPosition variable below)but now I need to find a way to implement the code so that I can avoid it.
The issue is i have a superclass Square which has 3 possible subclasses Property, Go and FreeParking. I'm storing my board as an ArrayList but I need to access the methods pertaining to Property objects to calculate rent etc. How can I access these methods if when I access the property from the ArrayList it it of type Square.
Apologies in advance if this doesn't make too much sense.
public abstract class Square {
private String name;
private boolean isAvailable;
private Player owner;
//getters and setters
}
public class Property extends Square{
private String colour;
private int buyHouset;
private int rent1House;
private int rent2House;
private int rent3House;
private int rentHotel;
private int numHouses;
private int rent;
private int price;
//getters and setters
}
public static void takeTurn(Player player, Dice die, ArrayList<Square> board) {
System.out.println(player.getGamertag() + "'s turn");
//get value from roll of die
int move = askToRoll();
String gamertag = player.getGamertag();
//if player does not quit continue with turn
if(move > 0) {
//get player current position and add roll of die
int newSpaceIndex = player.getPosition() + move;
//if players new position exceeds the array of squares, return to 0 index and add remainder
//add credits for passing Go
//else update position
if (newSpaceIndex > 11) {
player.setPosition(newSpaceIndex - 12);
Go.passGoAction(player);
}else {
player.setPosition(newSpaceIndex);
}
if(player.getPosition() == 1) {
Square newPosition = board.get(player.getPosition());
System.out.println(gamertag + " new position " + newPosition.getName());
}else if(player.getPosition() == 6) {
FreeParking.freeParkingAction();
} else {
Square newPosition = board.get(player.getPosition());
System.out.println("____________________");
System.out.println("Land on " + newPosition.getName());
if(newPosition.getOwner() != null) {
Player owner = newPosition.getOwner();
/* *****THIS IS WHERE THE ERROR IS STEMING FROM*****
*THE newPosition.getRent() method can not be accessed as newPosition
*is defines as Square
*/
System.out.println(owner.getGamertag() + " demands you pay " + newPosition.getRent() + " credits!");
}else {
System.out.println("What would you like to do now? ...\n"
+ "1. Buy property\n"
+ "2. End turn");
int input = in.nextInt();
boolean valid = false;
do {
switch(input) {
case 1:
System.out.println("You now own controlling stock of " + newPosition.getName());
player.setOwnsProperty(newPosition);
newPosition.setOwner(player);
valid = true;
break;
case 2:
System.out.println("Ending turn");
valid=true;
break;
default:
System.out.println("Invalid input, please select one of the options 1-2");
valid = false;
break;
}
}while(!valid);
}
}
}
System.out.println("END TURN: " + player);
System.out.println();
}
If you know that a particular Square is a Property, cast it and assign it to the appropriate type.
Property newPosition = (Property)board.get(player.getPosition());
Edit: In future, you might also want to consider putting the logic that goes with a particular type of Square into a subclass. In other words, something like square.process(player), where Property, Go, and FreeParking each implements the process(player) method with appropriate logic. That goes into more detailed concepts around object-oriented design, and may not be relevant to you right now.
I hope that this snippet helps you to understand the concept
public static void main(String[] args) {
Square newPosition = new Property();
if (newPosition instanceof Property) {
System.out.println("newPosition cast as Property");
Property newPositionAsProperty = ((Property) newPosition);
int newRent = newPositionAsProperty.getRent();
// or
newRent = ((Property) newPosition).getRent();
}
// To understand better
if (newPosition instanceof Square) {
System.out.println("newPosition instanceof Square");
((Square)newPosition).getName();
}
if (Square.class.isAssignableFrom(Property.class)) {
System.out.println("Square.class.isAssignableFrom(Property.class)");
((Square)newPosition).getName();
}
if (Property.class.isInstance(newPosition)) {
System.out.println("Property.class.isInstance(newPosition)");
((Property)newPosition).getName();
}
if (Square.class.isInstance(newPosition)) {
System.out.println("Square.class.isInstance(newPosition)");
((Square)newPosition).getName();
}
}
Result:
newPosition cast as Property
newPosition instanceof Square
Square.class.isAssignableFrom(Property.class)
Property.class.isInstance(newPosition)
Square.class.isInstance(newPosition)
Related
So as the title says im struggling to add a value to an integer and then pass it to another class that uses it, then this class will pass it to the next and then that one will pass it over to the main class. Its an integer that changes the stat template of the enemies in my small game im writing.
I have tried to make constructors in two of my classes as I thought that was the problem, Ive tried to see if they work by passing some messages in them.
The problem seems to be that when I save something in the "private int l" It dosnt actually change the value of that int and I cant figure out why that is.
Here is my code, its probably not very pretty so if you have any suggestions to structure changes that I might wanna do please feel free too let me know!
Thanks in advance!
import java.util.Scanner;
public class Stor {
public static void main(String[] args) {
Scanner user_Input = new Scanner(System.in);
Menu user = new Menu();
EnemyValue monster = new EnemyValue();
user.namn();
user.AnvNamn = user_Input.next();
user.introMeny();
user.difficulty();
System.out.println(“Your enemy has " + monster.HP + " HP and " +
monster.DMG + " Damage" );
user_Input.close();
}
}
class Menu {
Scanner user_Input = new Scanner(System.in);
String AnvNamn;
String difficultySvar;
String nivåSvar;
int svar;
private int i; /
private int l;
public int getL() {
return l;
}
boolean difficultyLoop = true;
boolean felLoop = true;
void introMeny() {
System.out.println(“Welcome " + AnvNamn + "!");
}
void namn() {
System.out.print(“Pick a name: “);
}
void difficulty() {
do {
System.out.println("\nWhat level do you want ?\n1 = Easy.\n2 =
Medium.\n3 = Hard.”);
svar = user_Input.nextInt();
if (svar == 1) {
System.out.println(“Your not very brave are you ? Are you sure
this is how you wanna play ?”);
difficultySvar = user_Input.next();
if (difficultySvar.equalsIgnoreCase(“Yes”)) {
difficultyLoop = false;
l = 1;
} // If ja 1
else if (difficultySvar.equalsIgnoreCase(“Nej”)) {
System.out.println(“Ahh good! I figuerd you would change
your mind.”);
}
else
System.out.println(“I don’t understand….”);
} // if 1
else if (svar == 2) {
System.out.println(“Not to hard or to easy, a good choice! But
maybe you want to go for something harder ? Or maybe easier ?");
difficultySvar = user_Input.next();
if (difficultySvar.equalsIgnoreCase(“Yes”)) {
difficultyLoop = false;
l = 2;
} // if ja 2
else if (difficultySvar.equalsIgnoreCase(“No”)) {
System.out.println(“I sure hope you don’t pick the easy
way…..”);
}
else
System.out.println("I don’t understand….");
} // Else if 2
else if (svar == 3) {
System.out.println(“Damn! We have a big player here! Are you
sure you can handle this ?");
difficultySvar = user_Input.next();
if (difficultySvar.equalsIgnoreCase(“Yes”)) {
difficultyLoop = false;
l = 3;
} // If ja 3
else if (difficultySvar.equalsIgnoreCase(“No”)) {
System.out.println(“Wuss.”);
}
else
System.out.println(“I don’t understand….”);
} // Else if 3
else {
if (i == 0) {
System.out.println(“Ha you thought you could fool the system?!
The system fools you!”);
System.out.println(“Nah but seriously, you can only choose
between 1-3…..“);
i++;
} // if i 0
else if (i == 1) {
System.out.println(“Alright I get that its hard but
COMEON!”);
i++;
} // if i 1
else if (i == 2) {
System.out.println(“OKEY YOU GET ONE LAST CHANCE!!”);
i++;
} // if i 2
else if (i == 3) {
System.out.println(“Alright thats it…. GET OUT!”);
System.exit(0);
} // if i 3
} // Else
} // do while loop
while(difficultyLoop == true);
} //Difficulty metod.
} // Menu class.
class Nivå {
//Menu level = new Menu();
//int levelChoice = level.getL();
int levelChoice;
private int enemyLife;
public int getenemyLife() {
return enemyLife;
}
private int enemyDMG;
public int getenemyDMG() {
return enemyDMG;
}
Nivå(){
Menu level = new Menu();
levelChoice = level.getL();
System.out.println("testNivå");
}
void fiendeLiv() {
if (levelChoice == 1)
enemyLife = 100;
else if (levelChoice == 2)
enemyLife = 150;
else if (levelChoice == 3)
enemyLife = 200;
} // fiendeliv method
void fiendeDMG() {
if (levelChoice == 1)
enemyDMG = 5;
else if (levelChoice == 2)
enemyDMG = 10;
else if (levelChoice == 3)
enemyDMG = 15;
} // fiendeDMG method
} // Nivå class
class EnemyValue {
public int HP;
public int DMG;
int maxLife;
int maxDMG;
EnemyValue(){
Nivå stats = new Nivå();
maxLife = stats.getenemyLife();
maxDMG = stats.getenemyDMG();
System.out.println("TestEnemyValue");
}
void rank1() {
HP = maxLife;
DMG = maxDMG;
} // rank1 easy method
} // EnemyValue class
You say that when you save something in l (poor choice of a variable name, by the way) it does not save the value. How do you know that? Where in the code do you check whether the value is saved?
In the constructor for class Nivå you create a new Menu and then call getL() on that menu before you have ever set the value of that variable.
Everything runs at the start of your public static void main(String[] args) method, and nothing will run if its instructions are not in there. For example, you are not actually creating any Niva objects in the main method, so the Niva constructor is never called. That is one issue. The other is your constructors are creating new instances of objects and then getting their values; this gives you empty values from a brand new object:
Nivå(){
Menu level = new Menu(); // Don't do this. This is an empty menu
levelChoice = level.getL(); // Getting the blank L value from the empty menu
System.out.println("testNivå");
}
Instead, you need to define constructors with parameters to pass the values into the class like this:
Nivå(int level){ // add an int parameter
levelChoice = level; // Direct assignment
fiendeDMG(); // Call this in the constructor to set up your last value
System.out.println("testNivå");
}
Then, when you call the constructor (which you must if you want it to exist), include the parameter. Inside the Stor class:
public static void main(String[] args) {
Scanner user_Input = new Scanner(System.in);
Menu user = new Menu();
user.namn();
user.AnvNamn = user_Input.next();
user.introMeny();
user.difficulty(); // Run this before creating the other classes; you need the l value
Nivå niva = new Nivå(user.getL()); // Creates new Niva while also assigning l to the levelChoice and then getting DMG
EnemyValue monster = new EnemyValue(/*add some parameters for life and dmg*/);
}
There is still more that needs to be done, like modifying the constructor of the EnemyLevel. Just remember that methods are never called unless they connect to something running from main and use parameters in functions and constructors to pass on data to other objects. Hope this helps.
The purpose of this project is to make a pokedex that adds and holds all the pokemon passed in by user input. When the user inputs a pokemon that is already stored in the pokedex the word "duplicate" is supposed to be printed to the console. The word duplicate is printed even though there are no actual duplicates within the object array. Here is my output from the console :
Welcome to your new PokeDex!
How many Pokemon are in your region?: 3
Your new Pokedex can hold 3 Pokemon. Let's start using it!
List Pokemon
Add Pokemon
Check a Pokemon's Stats
Sort Pokemon
Exit
What would you like to do? 2
Please enter the Pokemon's Species: red
Duplicate
Now here is all the code used that could possibly be making this error
import java.util.Scanner;
public class Project4 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Welcome to your new PokeDex!");
System.out.print("How many Pokemon are in your region?: ");
int size = input.nextInt();
Pokedex pokedex = new Pokedex(size);
System.out.println("\nYour new Pokedex can hold " + size + " Pokemon. Let's start using it!");
int choice = 0;
boolean done = false;
while (!done) {
System.out.println("\n1. List Pokemon\n2. Add Pokemon\n3. Check a Pokemon's Stats" + "\n4. Sort Pokemon\n5. Exit");
System.out.print("\nWhat would you like to do? ");
choice = input.nextInt();
switch (choice) {
case 1:
String[] pokemonList = pokedex.listPokemon();
if (pokemonList == null)
System.out.println("Empty");
else
for (int i = 0; i < pokemonList.length; i++) {
System.out.println((i + 1) + ". " + pokemonList[i]);
}
break;
case 2:
System.out.print("\nPlease enter the Pokemon's Species: ");
String species = input.next();
pokedex.addPokemon(species);
break;
}
}
}
}
In the following class I have the actual method that adds the pokemon and the constructor for Pokedex
public class Pokedex {
Pokemon[] pokedex;
String pokeArray[];
public Pokedex(int size) {
pokedex = new Pokemon[size];
pokeArray = new String[size];
}
public boolean addPokemon(String species) {
Pokemon stuff = new Pokemon(species);
for (int i = 0; i < pokedex.length; i++) {
if (pokedex[i] == null) {
pokedex[i] = stuff;
}
else if (i < pokedex.length && pokedex[i] != null) {
System.out.println("Max");
}
if (pokedex[i].getSpecies().equalsIgnoreCase(species)) {
System.out.print("Duplicate");
break;
}
}
return false;
}
}
Sorry for the mass amounts of code I just need help tracing where this unexpected result is coming from.
The reason it's doing that is because of this bit of code here:
public boolean addPokemon(String species)
{
Pokemon stuff = new Pokemon(species);
for (int i = 0; i < pokedex.length; i++)
{
if (pokedex[i] == null)
pokedex[i] = stuff;
else if (i < pokedex.length && pokedex[i] !=null)
System.out.println("Max");
if(pokedex[i].getSpecies().equalsIgnoreCase(species))
{
System.out.print("Duplicate");
break;
}
}
return false;
}
The problem is just a little bit of syntax missing. In your for loop, you check to see if
A) there are any empty spots in the array
B) if every element in the array up to the user inputted size is full
and C) if any element in the array matches the one we're trying to add.
The problem you're encountering is because your C is an if instead of an else if. Because A sees the index is null, it assigns the new Pokemon to the Pokedex. Then because C is an if instead of an else if, it runs after you assign the new Pokemon and sees the Pokemon we just added and says it's a duplicate. Changing it to an else if would fix this.
Also, since there was no break; in A, it would assign every element of the array to the first one entered, causing any further additions to call Max. I edited the code and this is what I had that worked for me:
public boolean addPokemon(String species)
{
Pokemon stuff = new Pokemon(species);
for (int i = 0; i < pokedex.length; i++)
{
if(pokedex[i] !=null && pokedex[i].getSpecies().equalsIgnoreCase(species))
{
System.out.println("Duplicate");
break;
}
else if (pokedex[i] == null)
{
pokedex[i] = stuff;
break;
}
else if(i + 1 == pokedex.length)
{
System.out.println("Max");
break;
}
}
return false;
}
Also, out of curiosity, why is the addPokemon() function a boolean? You return a value (albeit arbitrarily) and then never do anything with that value. You could just make it a void, have it return nothing, and it would work just as fine.
We are trying to use the array to store the locations and then call them in the if else statements in the first class. We want to be able to call the grid locations so we do not have to type the description of the room in the if else statements.
package ProjectTwo;
import java.util.Scanner;
public class ProjectTwo {
// ----------------------------------------
// Main method, calls location (loc) method, which controls navigation
// ----------------------------------------
public static void main(String[] args){
loc();
}
// This method allows the user to view a list of actions that are used throughout the game
public static void help() {
System.out.println("Enter the letter 'n' to move north, the letter 's' to move south, or type the word 'quit' to end the game. Also, you can enter the letter 'm' to see an image of the map.");
}
// -------------------------------------
// Loc method
// Prints on-load message (intro)
// Defines global variables
// -------------------------------------
public static void loc() {
location.locMove();
int location = 0;
System.out.println("The Search" + "\n" + "\n" + "You have awoken in a laboratory. There is a door to your north and a door to your south." + "/n+" + "Enter 'n' and 's' to navigate, or type 'quit' to end the game. Also, enter the letter 'h'.");
String userInput = new String();
boolean stillPlaying = true;
// ------------------------------------
// Moves player while user is still playing
// Tells user his/her location
// ------------------------------------
while (stillPlaying) {
Scanner scan = new Scanner(System.in);
userInput = scan.nextLine();
if (location == 0){
if (userInput.equals("n")) {
System.out.println("You entered the dungeon.");
location = 1; // Moves user from location 0 to 1
}
else if (userInput.equals("s")) {
System.out.println("You cannot move south.");
location = 0; // Keeps user at location 0
} else if (userInput.equals("quit")){
System.out.println("Thanks for playing");
stillPlaying = false;
}
else if (userInput.equals("h")) {
help(); // calls the help method
}
else if (userInput.equals("m")) {
map(); // calls the map method
}
else {
System.out.println("Command not understood.");
}
} else if (location == 1) {
if (userInput.equals("n")) {
System.out.println("You have escaped out the back door of the dungeon.");
location = 2; // Moves user from location 1 to location 2
}
else if(userInput.equals("s")) {
System.out.println("You're back in the laboratory.");
location = 0; // Moves user from location 1 to location 0
} else if (userInput.equals("quit")){
System.out.println("Thanks for playing");
stillPlaying = false;
}
else if (userInput.equals("h")) {
help(); // calls the help method
}
else if (userInput.equals("m")) {
map(); // calls the map method
}
else {
System.out.println("Command not understood");
}
}
else if (location == 2) {
if (userInput.equals("n")) {
System.out.println("You cannot go that way...yet!");
location = 2; // Lets the user know that they cannot go that way
}
else if (userInput.equals("s")) {
System.out.println("You're back in the dungeon");
location = 1; // Mover from location 2 to location 1
}
else if (userInput.equals("quit")){
System.out.println("Thanks for playing");
stillPlaying = false;
}
else if (userInput.equals("h")) {
help(); // calls help method
}
else if (userInput.equals("m")) {
map(); // calls map method
}
else {
System.out.println("Command not understood.");
}
}
}
}
}
//This is our main class
-------------------------------------------------------------------------
// This is our class with the 2d array
package ProjectTwo;
public class location {
public int location;
public String name;
public static String message;
public location(String name, int location, String message){
this.name = name;
this.location = location;
this.message = message;
System.out.println(message);
}
public static void locMove() {
location [][] grid = new location[4][4];
{
grid [1][0] = new location("LABORATORY", 0, "You're in the lab.");
grid [2][0] = new location("DUNGEON", 1, "You entered the dungeon.");
grid [3][0] = new location("COURTYARD ENTRANCE",2,"You have left the dungeon out the backdoor. Either head east and search the courtyard maze, or travel north back to the dungeon");
grid [3][1] = new location("FIRST PATH", 3,"You have now entered the courtyard, either continue east or move north.");
grid [3][2] = new location("DEADEND", 4,"You have reached a deadend that has a Magic Shop. Go inside and explore it.");
grid [3][3] = new location ("MAGIC SHOP", 5, "Search around the Magic Shop and see what there is. When you're done searching continue through the maze.");
grid [2][1] = new location("SECOND PATH",6,"Search the surroundings for items that will help you get into the locked room, then keep moving.");
grid [2][2] = new location("END MAZE", 7, "You've made it to the end of the courtyard. There seems to be a cave in the distance; go check it out.");
grid [1][2] = new location("CAVE",8,"Explore the cave to find the remaining items that will lead to your freedom.");
grid [0][0] = new location("EXIT",9,"This room will lead to your freedom, but you need the three essential items that will open this door.");
}
while (grid.equals(0)) {
System.out.println(message.toString());
}
}
}
There are many ways to do what you say but look your code, think this is really fits your code without changing much but just my opinion:
"try using, Location not location to name classes but not nesesario"
package ProjectTwo;
public class location {
In Your Class location:
//Your other code
public static location [][] locMove() { // <--- change void for location [][]
location [][] grid = new location[4][4];
{
grid [1][0] = new location("LABORATORY", 0, "You're in the lab.");
grid [2][0] = new location("DUNGEON", 1, "You entered the dungeon.");
grid [3][0] = new location("COURTYARD ENTRANCE",2,"You have left the dungeon out the backdoor. Either head east and search the courtyard maze, or travel north back to the dungeon");
grid [3][1] = new location("FIRST PATH", 3,"You have now entered the courtyard, either continue east or move north.");
grid [3][2] = new location("DEADEND", 4,"You have reached a deadend that has a Magic Shop. Go inside and explore it.");
grid [3][3] = new location ("MAGIC SHOP", 5, "Search around the Magic Shop and see what there is. When you're done searching continue through the maze.");
grid [2][1] = new location("SECOND PATH",6,"Search the surroundings for items that will help you get into the locked room, then keep moving.");
grid [2][2] = new location("END MAZE", 7, "You've made it to the end of the courtyard. There seems to be a cave in the distance; go check it out.");
grid [1][2] = new location("CAVE",8,"Explore the cave to find the remaining items that will lead to your freedom.");
grid [0][0] = new location("EXIT",9,"This room will lead to your freedom, but you need the three essential items that will open this door.");
}
while (grid.equals(0)) {
System.out.println(message.toString());
}
return grid;
}
//Your other code
In your other class:
package ProjectTwo;
public class ProjectTwo {
//your other code
location [][] testGrid = null; //<--- add variable
//your other code
public static void main(String[] args){
loc();
}
//your other code
public static void loc() {
testGrid = location.locMove();
//testGrid <-- this your array
//your other code
I have not test, but I think it can work, but not the way I usually do, I hope you can help.
P.S: You could look at this, if you want https://stackoverflow.com/tour
I definitely agree with the comments about code style and formatting. Anyway here are the suggestions how you can refactor your code.
Probably the simplest way to avoid writing lots of if-else construction is to use switches. You loc() code might look something like that (I would also move duplicated h/m/quit commands to a single place):
Solution 1:
...
while (stillPlaying) {
Scanner scan = new Scanner(System.in);
userInput = scan.nextLine();
switch (userInput) {
case "quit":
System.out.println("Thanks for playing");
stillPlaying = false;
break;
case "h":
help(); // calls the help method
break;
case "m":
map(); // calls the map method
break;
case "n":
case "s":
switch (location) {
case 0:
switch (userInput) {
case "n":
System.out.println("You entered the dungeon.");
location = 1; // Moves user from location 0 to 1
break;
case "s":
System.out.println("You cannot move south.");
location = 0; // Keeps user at location 0
break;
}
break;
case 1:
switch (userInput) {
case "n":
System.out.println("You have escaped out the back door of the dungeon.");
location = 2; // Moves user from location 1 to location 2
break;
case "s":
System.out.println("You're back in the laboratory.");
location = 0; // Moves user from location 1 to location 0
break;
}
break;
case 2:
switch (userInput) {
case "n":
System.out.println("You cannot go that way...yet!");
location = 2; // Lets the user know that they cannot go that way
break;
case "s":
System.out.println("You're back in the dungeon");
location = 1; // Mover from location 2 to location 1
break;
}
break;
default:
System.out.println("no such location");
}
break;
default:
System.out.println("Command not understood.");
}
}
...
However the better way is to try to encapsulate the locations-commands-actions stuff to a different classes. That how it might look:
Solution 2:
public static interface Action {
// return the next location or an error
int action();
}
public static class LocationsMap {
public Map<Integer, Map<String, Action>> locations = new HashMap<>();
public void registerAction(int location, String userInput, Action action) {
Map<String, Action> actionsMap = locations.get(location);
if (actionsMap == null) {
actionsMap = new HashMap<>();
locations.put(location, actionsMap);
}
actionsMap.put(userInput, action);
}
public int executeAction(int location, String userInput) {
Map<String, Action> currentLocation = locations.get(location);
if (currentLocation == null) {
return -1;
}
Action currentAction = currentLocation.get(userInput);
if (currentAction == null) {
return -2;
}
return currentAction.action(); // move to next location
}
}
then you can define your actions (per location and user input) like that:
...
public static LocationsMap locationsMap = new LocationsMap();
static {
// location 0
locationsMap.registerAction(0, "n", new Action() {
#Override
public int action() {
System.out.println("You entered the dungeon.");
return 1; // Moves user from location 0 to 1
}
});
locationsMap.registerAction(0, "s", new Action() {
#Override
public int action() {
System.out.println("You cannot move south.");
return 0; // Keeps user at location 0
}
});
// location 1
locationsMap.registerAction(1, "n", new Action() {
#Override
public int action() {
System.out.println("You have escaped out the back door of the dungeon.");
return 2; // Moves user from location 1 to location 2
}
});
locationsMap.registerAction(1, "s", new Action() {
#Override
public int action() {
System.out.println("You're back in the laboratory.");
return 0; // Moves user from location 1 to location 0
}
});
// location 2
locationsMap.registerAction(2, "n", new Action() {
#Override
public int action() {
System.out.println("You cannot go that way...yet!");
return 2; // Lets the user know that they cannot go that way
}
});
locationsMap.registerAction(2, "s", new Action() {
#Override
public int action() {
System.out.println("You're back in the dungeon");
return 1; // Mover from location 2 to location 1
}
});
}
...
and then the code in the loc() function will look like that:
...
while (stillPlaying) {
Scanner scan = new Scanner(System.in);
userInput = scan.nextLine();
switch (userInput) {
case "quit":
System.out.println("Thanks for playing");
stillPlaying = false;
break;
case "h":
help(); // calls the help method
break;
case "m":
map(); // calls the map method
break;
default:
int actionResult = locationsMap.executeAction(location, userInput);
if (actionResult == -1) {
System.out.println("no such location");
break;
}
if (actionResult == -2) {
System.out.println("Command not understood.");
break;
}
location = actionResult; // move to next location
}
}
...
That is not the best solution, but it is much better and readable.
I would also define an enum for locations instead of using ints.
Also you can think about storing this locations-inputs-actions information in some file, parse it and then use in the app/game, but that will be more complicated to implement.
What would be the best way for me to code the the actual attack / defend between the two characters and how would I store the health value so that re attacks could be stored until either player health or enemy health reached 0, and then declare the victor. This is my first ever attempt at any kind programming after self teaching from various sources, please also give me feed back on any improvement I could make, I'm sure there will be many.
Thank you in advance.
:-)
package test;
public class BattleClass {
public static void main(String[] args) {
PlayerStats ps = new PlayerStats();
EnemyStats es = new EnemyStats();
int eh = es.getEnemyHealth();
int ph = ps.getPlayerHealth();
ps.PlayerAttackDefend();
es.AttackDefend();
System.out.println("You chose to " + ps.getpInput() + " and rolled "
+ ps.getPlayerRoll());
System.out.println("The enemy chose to " + es.getEaod()
+ " and rolled " + es.getEnemyRoll() + ".");
if (ps.getpInput().equals("Attack")) {
if (es.getEaod().equals("Attack")) {
System.out
.println("YOUR SWORDS BOUNCE OFF EACHOUTHERS... TRY AGAIN!");
System.exit(0);
}
if (es.getEaod().equals("Defend")) {
if (ps.getPlayerRoll() > es.getEnemyRoll())
eh -= ps.getPlayerRoll() - es.getEnemyRoll();
System.out.println("Enemy Health is " + eh);
}
}
if (ps.getpInput().equals("Defend")) {
if (es.getEaod().equals("Defend")) {
System.out
.println("YOUR SHIELDS BOUNCE OFF EACHOTHERS... TRY AGAIN!");
System.exit(0);
}
}
if (es.getEaod().equals("Attack")) {
if (es.getEnemyRoll() > ps.getPlayerRoll())
ph -= es.getEnemyRoll() - ps.getPlayerRoll();
System.out.println("Your Health is " + ph);
}
}
}
package test;
import java.util.Random;
import java.util.Scanner;
public class PlayerStats {
static Scanner paod = new Scanner(System.in);
//Players initial health value.
private int playerHealth = 10;
//RNG for attack value / defence value using dice as object.
private int playerRoll = new Random().nextInt(6) + 1;
private String pInput;
//Method for selecting Attack or Defence.
public void PlayerAttackDefend() {
System.out.println("Do you want to Attack or Defend?");
System.out.println("a = Attack / d = Defend");
//Player selects attack or defend.
String userInput = paod.nextLine();
if (userInput.equals("a")) {
pInput = "Attack";
}
if (userInput.equals("d")) {
pInput = "Defend";
}
}
public static Scanner getPaod() {
return paod;
}
public int getPlayerHealth() {
return playerHealth;
}
public int getPlayerRoll() {
return playerRoll;
}
public String getpInput() {
return pInput;
}
public static void setPaod(Scanner paod) {
PlayerStats.paod = paod;
}
public void setPlayerHealth(int playerHealth) {
this.playerHealth = playerHealth;
}
public void setPlayerRoll(int playerRoll) {
this.playerRoll = playerRoll;
}
public void setpInput(String pInput) {
this.pInput = pInput;
}
}
package test;
import java.util.Random;
public class EnemyStats {
//Enemy initial health value.
private int enemyHealth = 10;
//RNG for attack value / defence value using dice as object.
private static int enemyRoll = new Random().nextInt(6) + 1;
//RNG for enemy decision to Attack or Defend.
private static int eAttackDefend = new Random().nextInt(2) + 1;
//Used for returning attack or defend string.
private static String eaod;
//Attack or Defend method.
public void AttackDefend() {
if (eAttackDefend == 1) {
eaod = "Attack";
} else {
eaod = "Defend";
}
}
public int getEnemyHealth() {
return enemyHealth;
}
public int getEnemyRoll() {
return enemyRoll;
}
public int geteAttackDefend() {
return eAttackDefend;
}
public String getEaod() {
return eaod;
}
public void setEnemyHealth(int enemyHealth) {
this.enemyHealth = enemyHealth;
}
public void setEnemyRoll(int enemyRoll) {
EnemyStats.enemyRoll = enemyRoll;
}
public void seteAttackDefend(int eAttackDefend) {
EnemyStats.eAttackDefend = eAttackDefend;
}
public void setEaod(String eaod) {
EnemyStats.eaod = eaod;
}
}
An easy way would to be to set maxHp and actualHp values, if you want to be able to "heal".
If you just decrease until one is dead, you can just decrease the actual health variable you already have.
You might wanna take a look at Inheritance in general, as you have a lot of duplicate code.
In general, just make a loop
while(ps.getHealth() > 0 && es.getHealth() > 0) {
// your battle code
}
you might want to remove the System.exit(0) calls, as they terminate the program.
Add to the player/enemy a dealDamage(int damage) method to actually be able to reduce their health
The health values should be in the objects, and you should not need to store them in your BattleClass.
I could give you the short answer but I guess you get more out of a detailed explanation :-)
You want to run your code "until either player health or enemy health reached 0" so you need a loop.
In java you have 3 kinds of loops:
The for loop
for(int i=1;i<=3;i++) System.out.println("Hello Musketeer Nr. "+i);
The most elaborate loop, the for loop consists of three parts, the initialization, the condition, and the afterthought. While the for loop can be used differently, it is mostly is used in the fashion shown here, that is, you have a counter variable whose value you need somehow.
If you don't need the counter variable value, you can use the short form with collections and arrays:
for(Person p: persons) System.out.println("Hello, "+person.getName()+"!");
The while loop
The second most commonly used (at least by me) loop, it has an initial condition and iterates, as long as it is true.
while(ph>0&&eh>0)
{
...
}
As you see, it fits your problem very well. For completeness, I will however describe the third loop which is the
do-while loop
do
{
...
}
while(ph>0&&eh>0)
You use this loop like the while loop but if you want to have at least one run through.
Other Remarks
Why have two classes PlayerStats and EnemyStats in combat system (they both seem to have the same actions and values) ? You could just have:
Stats playerStats=new Stats();
Stats enemyStats=new Stats();
im working on a card pair game that generates two random value from an array of strings.. what i want to know is how to get the sum of two random values from the array of strings to determine the winner. here are the codes
import java.util.*;
public class Cards {
private String suit;
private String face;
private String[] cardSuits;
private String[] cardFaces;
private Random ran;
public Cards() {
ran = new Random();
cardSuits = new String[] { "of Spade", "of Hearts", "of Diamonds",
"of Clubs" };
cardFaces = new String[] { "Ace", "2", "3", "4", "5", "6", "7", "8", "9",
"10", "Jack", "Queen", "King" };
}
public String setPlayerCardSuit() {
suit = cardSuits[ran.nextInt(4)];
return suit;
}
public String setPlayerCardFace() {
face = cardFaces[ran.nextInt(13)];
return face;
}
public String setPlayerCardSuit2() {
suit = cardSuits[ran.nextInt(4)];
return suit;
}
public String setPlayerCardFace2() {
face = cardFaces[ran.nextInt(13)];
return face;
}
public String setCompCardSuit() {
suit = cardSuits[ran.nextInt(4)];
return suit;
}
public String setCompCardFace() {
face = cardFaces[ran.nextInt(13)];
return face;
}
public String setCompCardSuit2() {
suit = cardSuits[ran.nextInt(4)];
return suit;
}
public String setCompCardFace2() {
face = cardFaces[ran.nextInt(13)];
return face;
}
public void getResults() {
System.out.println("Here are your cards: " + setPlayerCardFace() + " "
+ setPlayerCardSuit() + " and " + setPlayerCardFace2() + " "
+ setPlayerCardSuit2());
}
public void getCompCard() {
System.out.println("Here's the computer's cards: " + setCompCardFace()
+ " " + setCompCardSuit() + " and " + setCompCardFace2() + " "
+ setCompCardSuit2());
}
}
and here is the code to test the Cards Class:
import javax.swing.JOptionPane;
public class TestCards {
public static void main(String[] args) {
Cards playerCards = new Cards();
Cards computerCards = new Cards();
int confirm, x = 1;
while (x == 1) {
JOptionPane.showMessageDialog(null,
"Random Card game \nPlease press OK to Start Game",
"Card Pair Game", JOptionPane.INFORMATION_MESSAGE);
JOptionPane.showMessageDialog(
null,
"Here are your Cards: " + playerCards.setPlayerCardFace()
+ " " + playerCards.setPlayerCardSuit() + " and "
+ playerCards.setPlayerCardFace2() + " "
+ playerCards.setPlayerCardSuit2()
+ "\nThe Computer's Cards are: "
+ computerCards.setCompCardFace() + " "
+ computerCards.setCompCardSuit() + " and "
+ computerCards.setCompCardFace2() + " "
+ computerCards.setCompCardSuit2());
confirm = JOptionPane.showConfirmDialog(null, "Game Ends. Again?",
"Game Over", JOptionPane.YES_NO_OPTION);
if (confirm != JOptionPane.YES_OPTION) {
x = 2;
}
}
}
}
what lacks now is the code to determine the winner.
PS: im a beginner in java programming.. so please bear with me if u see an unusual use of codes :)
i have tried Dylan's suggestion but i can't seem to make it work.. instead used his idea and added this code to Cards class.
public int playerValues(){
int temp = 0;
if(face != cardFaces[0] && face != cardFaces[10] && face != cardFaces[11] && face != cardFaces[12]){
temp = Integer.parseInt(face);
}else if(face == cardFaces[0]){
temp = 1;
}else if(face == cardFaces[10]){
temp = 11;
}else if(face == cardFaces[11]){
temp = 12;
}else if(face == cardFaces[12]){
temp = 13;
}
return temp;
}
public int computerValues(){
int temp = 0;
if(face != cardFaces[0] && face != cardFaces[10] && face != cardFaces[11] && face != cardFaces[12]){
temp = Integer.parseInt(face);
}else if(face == cardFaces[0]){
temp = 1;
}else if(face == cardFaces[10]){
temp = 11;
}else if(face == cardFaces[11]){
temp = 12;
}else if(face == cardFaces[12]){
temp = 13;
}
return temp;
}
You have a problem that not all the cards are unique. Two players can have the same cards. They could all be the same card even.
Instead you should generate a list of all the possible cards. I suggest using a Card class. Use Collections.shuffle to shuffle them. This way all the players will have different cards.
You need rules for comparing a set of cards. Define them in English first, and then translate them into code.
You shouldn't use an array of Strings to hold the card faces, but an array of CardFace, having a name (for display), and a value (to compute the sum of the faces). And since there are only 13 values, it should be an enum:
public enum CardFace {
ACE("Ace, 1),
TWO("2", 2),
...
KINK("King", 13);
private String face;
private int value;
private CardFace(String face, int value) {
this.face = face;
this.value = value;
}
public String getFace() {
return this.face;
}
public int getValue() {
return this.value;
}
}
I would really suggest that your Card be a class or at least an enum. Then summing them will make sense.
Also, please explain these two
public String setCompCardFace()
public String setCompCardFace2() //identical
Pretty much what you need is for each player to have an instance of Cards much like you started
public class Cards extends ArrayList<Card>
but somewhere along the way you got lost and mixed up these two into one class that does nothing really.
so in your Card you put these
public class Card
{
private String suit;
private String face;
public Card(String face, String color)
{
suit = color; this.face = face;
}
#Override
public int compareTo(Card otherCard); //implement this yourself
}
Using the String.parseInt() method will return the number within a string. But, youll have issues with the ace,kind,queen,jack since they arent a number. i would Recommend creating a statement like:
if(!cardFaces[x].equals("Ace")&&!cardFaces[x].equals("Queen")&&!cardFaces[x].equals("King")&&!cardFaces[x].equals("Jack"))
{
int temp = cardFaces[x].parseInt();
}
else if(cardFaces[x].equals("Ace")
{
int temp = 1;
}
else if(cardFaces[x].equals("King") || cardFaces[x].equals("Queen") || cardFaces[x].equals("Jack"))
{
int temp = 10;
It seems that no one has talked about getting combinations, so I'll talk about it here. If there's anything you don't understand, feel free to comment here.
Straight flush - you need a for loop.
First, you should sort an array of the player's cards with ascending (1, 2, 3, 4, 5 etc.). Now, check from the first entry, the lowest.
Note that the array cards stores only the values of the hand in integer.
// Variables to store the current and previous cards.
int previous = 0;
int current = 0;
cards = Arrays.sort(cards); // Sort cards into ascending order
boolean straightFlush = false;
for (i = 0; i < cards.length; i++) {
current = cards[i];
if (!current == cards[0]) { // If current is not the first card, execute the rest. You don't want random errors popping up, do you? :)
// Check if it is the last card - a straight flush would then be present
if (current == cards[cards.length - 1]) {
straightFlush = true;
break;
}
// Checks if current - 1 != previous or the current card is not consecutive to the previous card
if (current - 1 != previous) {
break;
}
}
...
How to compare the hands then? Find the highest value among the cards if it is a straight flush.
I'll post more about this soon.
I have managed to determine the winner by modifying the TestCard class instead of showing two random values from the array of strings. I changed it so that it shows only one value from the array. With that I managed to determine who the winner is.