I am working on a text-based adventure game and need some help handling the IndexOutOfBounds exception on the getUserRoomChoice() function. I have an index of 3 on the menu so when the user enters a number > 3, it throws that exception. I tried using a try-catch on the line where it prompts the user to "Select a Number" but it is not catching it.
Here is my main class:
import java.util.Scanner;
public class Game {
private static Room library, throne, study, kitchen;
private static Room currentLocation;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
initialSetupGame();
String reply;
do {
printNextRooms();
int nextRoomIndex = getUserRoomChoice();
Room nextRoom = getNextRoom(nextRoomIndex);
updateRoom(nextRoom);
System.out.print("Would you like to continue? Yes/No: ");
reply = input.nextLine().toLowerCase();
} while ('y' == reply.charAt(0));
goodbye();
}
public static void initialSetupGame() {
// Instantiate room objects of type Room
library = new Room("Library");
throne = new Room("Throne");
study = new Room("Study");
kitchen = new Room("Kitchen");
// Connect the objects to each other
library.addConnectedRoom(throne);
library.addConnectedRoom(study);
library.addConnectedRoom(kitchen);
throne.addConnectedRoom(library);
throne.addConnectedRoom(study);
throne.addConnectedRoom(kitchen);
study.addConnectedRoom(library);
study.addConnectedRoom(throne);
study.addConnectedRoom(kitchen);
kitchen.addConnectedRoom(library);
kitchen.addConnectedRoom(study);
kitchen.addConnectedRoom(throne);
// Welcome message
System.out.println("Welcome to Aether Paradise, "
+ "a game where you can explore"
+ " the the majestic hidden rooms of Aether.");
// Prompt user for a name
Scanner input = new Scanner(System.in);
System.out.print("\nBefore we begin, what is your name? ");
String playerName = input.nextLine();
System.out.print("\n" + playerName +"? Ah yes. The Grand Warden told us"
+ " to expect you. Nice to meet you, " + playerName + "."
+ "\nMy name is King, a member of the Guardian Aethelorian 12"
+ " who protect the sacred rooms of Aether."
+ "\nAs you hold the Warden's signet ring, you have permission"
+ " to enter.\n\nAre you ready to enter? ");
String response = input.nextLine().toLowerCase();
if ('n' == response.charAt(0)) {
System.out.println("Very well then. Goodbye.");
System.exit(0);
}
if ('y' == response.charAt(0)) {
System.out.println("\nA shimmering blue portal appeared! You leap "
+ "inside it and your consciousness slowly fades...");
}
else {
System.out.println("Invalid input. Please try again.");
System.exit(1);
}
// Set the player to start in the library
currentLocation = library;
System.out.print("\nYou have spawned at the library.");
System.out.println(currentLocation.getDescription());
}
public static void printNextRooms() {
// Lists room objects as menu items
System.out.println("Where would you like to go next?");
currentLocation.printListOfNamesOfConnectedRooms();
}
// How to handle the exception when input > index?
public static int getUserRoomChoice() {
Scanner input = new Scanner(System.in);
System.out.print("(Select a number): ");
int choice = input.nextInt();
return choice - 1;
}
public static Room getNextRoom(int index) {
return currentLocation.getConnectedRoom(index);
}
public static void updateRoom(Room newRoom) {
currentLocation = newRoom;
System.out.println(currentLocation.getDescription());
}
public static void goodbye() {
System.out.println("You walk back to the spawn point and jump into"
+ "the portal... \n\nThank you for exploring the hidden rooms "
+ "of Aether Paradise. Until next time.");
}
}
Room Class
import java.util.ArrayList;
public class Room {
// Instance variables
private String name;
private String description;
private ArrayList<Room> connectedRooms;
// Overloaded Constructor
public Room(String roomName) {
this.name = roomName;
this.description = "";
connectedRooms = new ArrayList<>();
}
// Overloaded Constructor
public Room(String roomName, String roomDescription) {
this.name = roomName;
this.description = roomDescription;
connectedRooms = new ArrayList<>();
}
// Get room name
public String getName() {
return name;
}
// Get room description
public String getDescription() {
return description;
}
// Add connected room to the array list
public void addConnectedRoom(Room connectedRoom) {
connectedRooms.add(connectedRoom);
}
// Get the connected room from the linked array
public Room getConnectedRoom(int index) {
if (index > connectedRooms.size()) {
try {
return connectedRooms.get(index);
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
return connectedRooms.get(index);
}
// Get the number of rooms
public int getNumberOfConnectedRooms() {
return connectedRooms.size();
}
// Print the connected rooms to the console
public void printListOfNamesOfConnectedRooms() {
for(int index = 0; index < connectedRooms.size(); index++) {
Room r = connectedRooms.get(index);
String n = r.getName();
System.out.println((index + 1) + ". " + n);
}
}
}
You have to use try-catch in function call of getNextRoom().
Because getNextRoom(nextRoomIndex) is causing the exception. You have to put those two statements in try block.
Change this to
Room nextRoom = getNextRoom(nextRoomIndex);
updateRoom(nextRoom);
this
try{
Room nextRoom = getNextRoom(nextRoomIndex);
updateRoom(nextRoom);
} catch(Exception e){
System.out.println("print something");
}
You must have a closer look to the piece of code, where you try to access the list (or array). That is the part, where the exception is thrown, not when the user enters it. There you have to check, if the given index is larger than the size of your list.
if( index >= list.size()) {
// handle error / print message for user
} else {
// continue normaly
}
In your case, it would probably be in the method getConnectedRoom(int index) in class Room.
Where is your try/catch block for the specific part? anyway, you can use IndexOutOfBound or Custome Exception for it.
1.create a custom Exception Class
class RoomeNotFoundException extends RuntimeException
{
public RoomeNotFoundException(String msg)
{
super(msg);
}
}
add try/catch block for the specific part
public class Game
{
do {
printNextRooms();
int nextRoomIndex = getUserRoomChoice();
if(nextRoomeIndex>3)
{
throw new RoomNotFoundException("No Rooms Available");
}else{
Room nextRoom = getNextRoom(nextRoomIndex);
updateRoom(nextRoom);
System.out.print("Would you like to continue? Yes/No: ");
reply = input.nextLine().toLowerCase();
}
} while ('y' == reply.charAt(0));
}
Or you can use IndexOutOfBoundException instead of RoomNotFoundException
Related
I haven't been programming for long and I have spent hours trying to get this method to do what I need so help would be very much appreciated at this point. I am creating a board game which prompts players for the number of players playing, after which they are prompted for their names in turn, and those new players will be created and their names set/stored. I also want to make sure that two players cannot have the same name.
Here is part of my player class:
public class Player {
private String name;
private int currentPosition;
private int distance;
private boolean quit;
public Player() {
}
public Player(String name, int currentPosition, int distance, boolean quit) {
this.name = name;
this.currentPosition = currentPosition;
this.distance = distance;
this.quit = quit;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I have a setNumberOfPlayers method which is working fine and getting the correct number of players when getNumberOfPlayers() is called.
public class SetUpGame {
Scanner sc = new Scanner(System.in);
public void addPlayers() {
String playerName;
ArrayList<Player> players = new ArrayList<Player>();
System.out.println("What are the names of the " + this.numberOfPlayers + " players?\n");
for (int loop = 1; loop <= getNumberOfPlayers(); loop++) {
System.out.println("Player " + loop + " please enter your name");
boolean valid = false;
do {
playerName = sc.nextLine();
Player player = new Player();
for (Player play : players) {
if (players.isEmpty() || !play.getName().equalsIgnoreCase(playerName)) {
player.setName(playerName);
players.add(player);
System.out.println("success, your name is: " +playerName);
valid = true;
} else {
System.out.println("please enter another name");
valid = false;
}
}
} while (valid == false);
}
sc.close();
}
When the add players method is called from main, it gives this output:
What are the names of the 2 players?
Player 1 please enter your name
...and the user can input their name but the scanner never closes or loops around to ask the next player their name. I have messed around with the code so much that I've confused myself at this point. Can anyone help with this, and also how to validate/check that the players have been created and their names set? Thank you
Your inner for loop is iterating on players array, but it is empty.
Maybe try this instead:
do {
System.out.println("Please enter name:");
playerName = sc.nextLine();
if(playerName.length()!=0){
valid = true;
for(Player play : players)
if(play.getName().equalsIgnoreCase(playerName))
valid = false;
if(valid){
Player player = new Player();
player.setName(playerName);
players.add(player);
}
}
} while (!valid);
I think you might be having a hard time debugging because of how similar all your variable names are. ('players','player','play')
EDIT: updated to check if a duplicate
First, list of players is defined as a local variable in the method addPlayers, so when this method is done, all the players data are lost. So it is necessary to modify this method either to add the players to a field of SetupGame class or to return the list of players to the calling method. The latter way is a cleaner functional way of populating the player list.
Next, in order to efficiently detect duplicate names, it is recommended to create and use Set<String> playerNames.
And the last, if Scanner is open on System.in it must not be closed, because after that no user input can be entered.
That being said, the code of addPlayers may look as follows:
public List<Player> addPlayers() {
List<Player> players = new ArrayList<>();
Set<String> playerNames = new HashSet<>();
Scanner sc = new Scanner(System.in);
System.out.println("What are the names of the " + this.numberOfPlayers + " players?\n");
for (int loop = 1; loop <= this.numberOfPlayers; loop++) {
while (true) {
System.out.println("Player " + loop + " please enter your name");
String playerName = sc.nextLine();
if (playerNames.add(playerName)) {// Set.add returns true if name was added to it
Player p = new Player();
p.setName(playerName);
players.add(p);
break; // input new player
}
}
}
return players;
}
You missed some getters and setters in your Player class.
Player.java
public class Player {
private String name;
private int currentPosition;
private double distance;
private boolean quit;
public Player() {
// no-args constructor
}
public Player(String name, int currentPosition, double distance, boolean quit) {
this.name = name;
this.currentPosition = currentPosition;
this.distance = distance;
this.quit = quit;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCurrentPosition() {
return currentPosition;
}
public void setCurrentPosition(int currentPosition) {
this.currentPosition = currentPosition;
}
public double getDistance() {
return distance;
}
public void setDistance(double distance) {
this.distance = distance;
}
public boolean isQuit() {
return quit;
}
public void setQuit(boolean quit) {
this.quit = quit;
}
}
You can implement the SetUpGame class as follows.
No need to create the do-while loop.
SetUpGame.java
import java.util.ArrayList;
import java.util.Scanner;
public class SetUpGame {
Scanner sc = new Scanner(System.in);
ArrayList<Player> players = new ArrayList<Player>();
int numberOfPlayers;
public int getNumberOfPlayers() {
return numberOfPlayers;
}
public void setNumberOfPlayers(int numberOfPlayers) {
this.numberOfPlayers = numberOfPlayers;
}
public void addPlayers() {
System.out.print("Enter number of players: ");
numberOfPlayers = sc.nextInt();
System.out.println("What are the names of the " + numberOfPlayers + " players?");
for(int loop = 1; loop <= numberOfPlayers; loop++) {
Player player = new Player();
System.out.print("Enter name for player " + loop + ": ");
player.setName(sc.next());
System.out.print("Enter current position for player " + loop + ": ");
player.setCurrentPosition(sc.nextInt());
System.out.print("Enter distance for player " + loop + ": ");
player.setDistance(sc.nextDouble());
System.out.print("Enter validity for player " + loop + ": ");
player.setQuit(sc.nextBoolean());
players.add(player);
}
sc.close();
}
public void displayAllPlayers() {
System.out.println("Displaying all players...");
for(Player p : players) {
System.out.printf("%s %d %f %b", p.getName(), p.getCurrentPosition(), p.getDistance(), p.isQuit());
}
}
}
Finally you can test your SetUpGame class.
TestSetUpGame.java
public class TestSetUpGame {
public static void main(String[] args) {
SetUpGame game = new SetUpGame();
game.addPlayers();
game.displayAllPlayers();
}
}
My code creates a set of sport results using a scanner, the user enters input in this format "Home team : Away team : Home score : Away score" - each part is split into a string in the array. I want to create an error message if one part is missing for example "Error, Home team seems to be missing" for each corresponding section however;
I am a beginner and have been trying to put an else-if condition in the for loop to help make this error message however I am doing something wrong judging by the amount of errors I am getting (delete this token).
This code will help your program to validate the user-input as per the your requirements in your question, if any of the inputs is missed by the user it is reported to him:
import java.util.Scanner;
public class Test4 {
public static void ismissing(int i)
{
switch(i)
{
case 0:
System.out.println("Home team missing");
break;
case 1:
System.out.println("Away team missing");
break;
case 2:
System.out.println("Home score missing");
break;
case 3:
System.out.println("Away score missing");
break;
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Input as follows; ");
System.out.println("Home team : Away team : Home score : Away score");
String str=scanner.nextLine();
String array[]=str.split(":");
for(int i=0;i<array.length;i++)
{
if(array[i].equals(" "))
{
ismissing(i);
System.exit(0); //will exit program if something is missing
}
}
System.out.println("Correct Input");
}
}
If you are going to be creating numerous games, I would recommend you make a Game class as this will make it easier to manage a Game object as opposed to 2 Strings and 2 Integer values. With a Game object you can also output your desired string output using the toString method of your Game object. When getting the user input, the criteria I used is such that team names cannot be blank and team scores cannot be less than 0. If the user enters and empty string or an invalid integer, then we simply output a message indicating the invalid input and have the user try again until they get valid input. If you want to exit when this happens you could change this to accommodate a graceful exit of the program when the user enters invalid data.
I made two methods in the main, one to get a valid String team name, and another to get a valid Integer for the score. Again if the user inputs invalid data we will loop until the input is valid.
Game Class:
public class Game
{
String homeTeam = "";
String awayTeam = "";
int homeScore = -1;
int awayScore = -1;
public Game(String inHomeTeam, int inHomeScore, String inAwayTeam, int inAwayScore)
{
super();
this.homeTeam = inHomeTeam;
this.awayTeam = inAwayTeam;
this.homeScore = inHomeScore;
this.awayScore = inAwayScore;
}
#Override
public String toString()
{
return homeTeam + "[" + homeScore + "] | " + awayTeam + "[" + awayScore + "]";
}
public String getHomeTeam() {
return homeTeam;
}
public void setHomeTeam(String homeTeam) {
this.homeTeam = homeTeam;
}
public String getAwayTeam() {
return awayTeam;
}
public void setAwayTeam(String awayTeam) {
this.awayTeam = awayTeam;
}
public int getHomeScore() {
return homeScore;
}
public void setHomeScore(int homeScore) {
this.homeScore = homeScore;
}
public int getAwayScore() {
return awayScore;
}
public void setAwayScore(int awayScore) {
this.awayScore = awayScore;
}
}
Main
public class Main
{
static Scanner scanner = new Scanner(System.in);
static Game[] allGames;
static String homeTeam = "";
static String awayTeam = "";
static int homeScore = -1;
static int awayScore = -1;
static int numberOfGames = 0;
public static void main(String[] args)
{
numberOfGames = GetUserInt("How many games do you want to enter - 100 or less: ");
if (numberOfGames > 100)
numberOfGames = 100;
allGames = new Game[numberOfGames];
for (int i = 0; i < numberOfGames; i++) {
homeTeam = GetUserString("Enter the home team name: ");
homeScore = GetUserInt("Enter the home team score: ");
awayTeam = GetUserString("Enter the away team name: ");
awayScore = GetUserInt("Enter the away team score: ");
allGames[i] = new Game(homeTeam, homeScore, awayTeam, awayScore);
}
// output the users games
for(Game curGame : allGames)
{
if (curGame != null)
System.out.println(curGame.toString());
}
}
private static String GetUserString(String prompt)
{
String input = "";
while(true) {
System.out.print(prompt);
input = scanner.nextLine();
if (input.length() > 0)
return input;
else
System.out.println("Invalid input: Can not be empty string!");
}
}
private static int GetUserInt(String prompt)
{
String input = "";
while(true) {
System.out.print(prompt);
input = scanner.nextLine();
if (input.length() > 0) {
if (isValidInt(input)) {
int value = Integer.parseInt(input);
if (value >= 0) {
return value;
}
else {
System.out.println("Invalid input: Score can not be negative");
}
}
else {
System.out.println("Invalid input: Score must be a valid integer");
}
}
else {
System.out.println("Invalid input: Score can not be empty");
}
}
}
private static boolean isValidInt(String inString)
{
try {
Integer.parseInt(inString);
return true;
}
catch (NumberFormatException e) {
return false;
}
}
}
Hope this helps!
There are some things you can do, like checking the values with an if statement. You can say something like:
if(stringIsEmpty)
{
print ("Error");
}
else
{
/*Keep executing program*/
}
You could also use a try/catch block. This could help because if a string is null (empty), you can throw a null pointer exception and define it the way you want, like this:
try
{
/*blank string code*/
}catch(NullPointerException e)
{
System.out.println("Empty strings are not allowed");
}
I've implemented a boolean to a kennel system I'm developing in Java and I'm getting an InputMismatchError when loading the data from the file.
I've read through a few times and tried to work it out but the solutions I'm trying aren't working. So far I've:
restructured the read in method (initialise) to read the data in properly and in the correct order, then assign it the newPet (local variable) in the correct order.
I then read through the .txt file (below) and made sure everything corresponded the the correct data, strings are being read as strings, ints as ints etc and that hasn't helped.
Can anybody spot the problem that's through the InputMismatch here?
Here is the error:
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at java.util.Scanner.nextBoolean(Unknown Source)
at KennelDemo.initialise(KennelDemo.java:79)
at KennelDemo.main(KennelDemo.java:337)
with line 79 and 337 being:
boolean mutualBoolean = infile.nextBoolean(); //and
demo.initialise();
Main class (apologises for the length)
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Scanner;
public class KennelDemo {
private String filename; // holds the name of the file
private Kennel kennel; // holds the kennel
private Scanner scan; // so we can read from keyboard
private String tempFileName;
private String dogsFile = "dogs.txt";
private String catsFile = "cats.txt";
/*
* Notice how we can make this private, since we only call from main which
* is in this class. We don't want this class to be used by any other class.
*/
private KennelDemo() {
scan = new Scanner(System.in);
boolean fileCorrect = false;
do {
System.out.print("Which animal are you looking to check into the kennel?: " + "\n");
System.out.println("Dog");
System.out.println("Cat");
tempFileName = scan.next();
if(tempFileName.toLowerCase().equals("dog") || tempFileName.toLowerCase().equals("cat")) {
filename = tempFileName.toLowerCase().equals("dog") ? dogsFile : catsFile;
fileCorrect = true;
}
else {
System.out.println("That is not a valid filename, please enter either 'Dog' or 'cat' in lowercase.");
}
}
while(!fileCorrect);
}
/*
* initialise() method runs from the main and reads from a file
*/
private void initialise() {
kennel = new Kennel();
System.out.println("Using file " + filename);
// Using try-with-resource (see my slides from session 15)
try(FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);
Scanner infile = new Scanner(br)){
String kennelName = infile.nextLine();
int kennelSize = infile.nextInt();
infile.nextLine();
kennel.setCapacity(kennelSize);
int numPets = infile.nextInt();
infile.nextLine();
kennel.setName(kennelName);
for(int i=0; i < numPets; i++){
String PetName = infile.nextLine();
int numOwners = infile.nextInt();
infile.nextLine();
ArrayList<Owner> owners = new ArrayList<>();
for(int oCount=0; oCount < numOwners; oCount++){
String name = infile.nextLine();
String phone = infile.nextLine();
Owner owner = new Owner(name, phone);
owners.add(owner);
}
boolean mutualBoolean = infile.nextBoolean();
infile.nextLine();
String favFood = infile.nextLine();
infile.nextLine();
int feedsPerDay = infile.nextInt();
Pet Pet = new Pet(PetName, owners, mutualBoolean, favFood, feedsPerDay);
kennel.addPet(Pet);
}
} catch (FileNotFoundException e) {
System.err.println("The file: " + " does not exist. Assuming first use and an empty file." +
" If this is not the first use then have you accidentally deleted the file?");
} catch (IOException e) {
System.err.println("An unexpected error occurred when trying to open the file " + filename);
System.err.println(e.getMessage());
}
}
/*
* runMenu() method runs from the main and allows entry of data etc
*/
private void runMenu() {
String response;
do {
printMenu();
System.out.println("What would you like to do:");
scan = new Scanner(System.in);
response = scan.nextLine().toUpperCase();
switch (response) {
case "1":
admitPet();
break;
case "2":
changeKennelName();
break;
case "3":
printPetsWithBones();
break;
case "4":
searchForPet();
break;
case "5":
removePet();
break;
case "6":
setKennelCapacity();
break;
case "7":
printAll();
break;
case "Q":
break;
default:
System.out.println("Try again");
}
} while (!(response.equals("Q")));
}
private void setKennelCapacity() {
// set the boolean to check if the user REALLY wants to change the kennel size. We can never be too careful.
// boolean doContinue = false;
// Turns out the boolean does nothing, go figure.
// Still the error check works perfectly, now just a case of losing the temporary data if the program isn't closed through the menu.
// Kennel currently doesn't save until you use "q" at the menu to save the information. Possible solutions?
// Hello? Is this thing on?
int currentKennelCapacity = kennel.getCapacity();
System.out.println("The current kennel holds " + currentKennelCapacity + ", are you sure you want to change the current kennel size?");
String userWantsToContinue;
userWantsToContinue = scan.nextLine().toUpperCase();
if(userWantsToContinue.equals("Y")){
// doContinue = true;
System.out.print("Please enter the new size of the kennel you'd like: ");
int max = scan.nextInt();
scan.nextLine();
kennel.setCapacity(max);
System.out.println("The new kennel size is " + max + ", we'll now return you to the main menu. Please make sure the quit the program at the end of your session to save any changes. \n");
}
else System.out.println("No problem, we'll return you back to the main menu. \n");
//Duplicate code that caused an error when running through the conditions above, saved in case of future reference.
/* System.out.print("Enter max number of Pets: ");
int max = scan.nextInt();
scan.nextLine();
kennel.setCapacity(max);
*/
}
private void printPetsWithBones() {
Pet[] PetsWithBones = kennel.obtainDogsWhoLikeBones();
System.out.println("Pets with bones: ");
for (Pet d: PetsWithBones){
System.out.println("Pet name: " + d.getName());
}
}
/*
* printAll() method runs from the main and prints status
*/
private void printAll() {
Pet[] allPets = kennel.displayAllPets();
for (Pet p: allPets){
System.out.println("Animal name: " + p.getName());
System.out.println("Original owner(s): " + p.getOriginalOwners());
if(filename.equals(dogsFile)){
System.out.println("Do they like bones? " + Dog.getLikesBones());
}
else if(filename.equals(catsFile)){
System.out.println("Can they share a run? " + Cat.getShareRun());
}
System.out.println("Favourite food: " + p.getFavouriteFood());
System.out.println("Feeds per day: " + p.getFeedsPerDay());
System.out.println("====================================");
}
}
/*
* save() method runs from the main and writes back to file
*/
private void save() {
try(FileWriter fw = new FileWriter(filename);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter outfile = new PrintWriter(bw);){
outfile.println(kennel.getName());
outfile.println(kennel.getCapacity());
outfile.println(kennel.getNumOfPets());
Pet[] Pets = kennel.obtainAllPets();
for (Pet d: Pets){
outfile.println(d.getName());
Owner[] owners = d.getOriginalOwners();
outfile.println(owners.length);
for(Owner o: owners){
outfile.println(o.getName());
outfile.println(o.getPhone());
}
// TODO outfile.println(d.getLikesBones());
outfile.println(d.getFeedsPerDay());
outfile.println(d.getFavouriteFood());
}
} catch (IOException e) {
System.err.println("Problem when trying to write to file: " + filename);
}
}
private void removePet() {
System.out.println("which Pet do you want to remove");
String Pettoberemoved;
Pettoberemoved = scan.nextLine();
kennel.removePet(Pettoberemoved);
}
private void searchForPet() {
String allNames = kennel.getName();
System.out.println("Current pet in the kennel: " + allNames + "\n");
System.out.println("Which pet would you like to get the details for?");
String name = scan.nextLine();
Pet Pet = kennel.search(name);
if (Pet != null){
System.out.println(Pet.toString());
} else {
System.out.println("Could not find Pet: " + name);
}
}
private void changeKennelName() {
String name = scan.nextLine();
kennel.setName(name);
}
private void admitPet() {
boolean mutualBoolean = false;
if(filename.equals(dogsFile)){
System.out.println("enter on separate lines: name, owner-name, owner-phone, do they like bones?, favourite food, number of times fed");
}
else if(filename.equals(catsFile)){
System.out.println("enter on separate lines: name, owner-name, owner-phone, can they share a run?, favourite food, number of times fed");
}
String name = scan.nextLine();
ArrayList<Owner> owners = getOwners();
if(filename.equals(dogsFile)){
System.out.println("Does he like bones? (Y/N)");
}
else if(filename.equalsIgnoreCase(catsFile)){
System.out.println("Can the cat share a run? (Y/N)");
}
String booleanCheck;
booleanCheck = scan.nextLine().toUpperCase();
if (booleanCheck.equals("Y")) {
mutualBoolean = true;
}
System.out.println("What is his/her favourite food?");
String fav;
fav = scan.nextLine();
System.out.println("How many times is he/she fed a day? (as a number)");
int numTimes;
numTimes = scan.nextInt(); // This can be improved (InputMismatchException?)
numTimes = scan.nextInt();
Pet newPet = new Pet(name, owners, mutualBoolean, fav, numTimes);
kennel.addPet(newPet);
System.out.println("Pet " + newPet.getName() + " saved.");
// Save when you add new Pet in case the program isn't closed via the correct menu.
// Everything will still save when case "q" is used though.
save();
}
private ArrayList<Owner> getOwners() {
ArrayList<Owner> owners = new ArrayList<Owner>();
String answer;
do {
System.out
.println("Enter on separate lines: owner-name owner-phone");
String ownName = scan.nextLine();
String ownPhone = scan.nextLine();
Owner own = new Owner(ownName, ownPhone);
owners.add(own);
System.out.println("Another owner (Y/N)?");
answer = scan.nextLine().toUpperCase();
} while (!answer.equals("N"));
return owners;
}
private void printMenu() {
if(filename.equals(catsFile)) {
System.out.println("1 - add a new cat ");
System.out.println("2 - set up Kennel name");
System.out.println("4 - search for a cat");
System.out.println("5 - remove a cat");
System.out.println("6 - set kennel capacity");
System.out.println("7 - print all cats");
System.out.println("q - Quit");
}
else if(filename.equals(dogsFile)) {
System.out.println("1 - add a new dog ");
System.out.println("2 - set up Kennel name");
System.out.println("3 - print all dogs who like bones");
System.out.println("4 - search for a dog");
System.out.println("5 - remove a dog");
System.out.println("6 - set kennel capacity");
System.out.println("7 - print all dogs");
System.out.println("q - Quit");
}
}
// /////////////////////////////////////////////////
public static void main(String args[]) {
System.out.println("**********HELLO***********");
KennelDemo demo = new KennelDemo();
demo.initialise();
demo.runMenu();
demo.printAll();
demo.save();
System.out.println("***********GOODBYE**********");
}
}
and here is the .txt file being read from:
DogsRUs // kennel name
20 // capacity
3 // number of pets
Rover //pet name
2 // number of owners
Chris Loftus // first owner
1234 // phone number
Pete Hoskins // second owner
2222 // phone number
1 // boolean for mutualBoolean
biscuits // favourite food
// NOTE: for some reason favFood wasn't being added but it wasn't causing an error at all, it's the boolean that's throwing the input error. Structure above repeats for the data below.
Dinky
1
James Bond
007007
1
Gold fingers
catTest
1
Billy
456789
1
Curry
Clearly the problem is the boolean being read in but I really can't see the solution to it at all unfortunately. When mutualBoolean was likeBones (originally the program was only being used to check dogs in rather than dogs and cats) it was working fine.
Here is the code I've used to inherit for the mutualBoolean that's being used
import java.util.ArrayList;
public class Pet {
protected ArrayList<Owner> originalOwners;
protected boolean mutualBoolean;
protected String petName;
protected String favFood;
protected int foodPerDay;
public Pet(String name, ArrayList<Owner> owners, boolean mutualBoolean, String food, int mealsPerDay) {
petName = name;
this.favFood = food;
this.foodPerDay = mealsPerDay;
originalOwners = new ArrayList<Owner>();
for(Owner o: owners){
Owner copy = new Owner(o.getName(), o.getPhone());
originalOwners.add(copy);
}
this.mutualBoolean = mutualBoolean;
}
public String getName() {
return petName;
}
public void setName(String newName) {
petName = newName;
}
/*protected boolean mutualBoolean() {
return mutualBoolean;
}*/
/**
* Returns a copy of the original owners
* #return A copy of the original owners as an array
*/
public Owner[] getOriginalOwners(){
Owner[] result = new Owner[originalOwners.size()];
result = originalOwners.toArray(result);
return result;
}
/**
* How many times a day to feed the dog
* #param feeds The number of feeds per day
*/
public void setFeedsPerDay(int feeds){
foodPerDay = feeds;
}
/**
* The number of feeds per day the dog is fed
* #return The number of feeds per day
*/
public int getFeedsPerDay(){
return foodPerDay;
}
/**
* What's his favourite food?
* #param food The food he likes
*/
public void setFavouriteFood(String food){
favFood = food;
}
/**
* The food the dog likes to eat
* #return The food
*/
public String getFavouriteFood(){
return favFood;
}
/**
* Note that this only compares equality based on a
* dog's name.
* #param The other dog to compare against.
*/
#Override
public boolean equals(Object obj) { // Generated by Eclipse to be more robust
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dog other = (Dog) obj;
if (petName == null) {
if (other.petName != null)
return false;
} else if (!petName.equals(other.petName))
return false;
return true;
}
/**
* A basic implementation to just return all the data in string form
*/
public String toString() {
return "Dog name:" + petName + "Original Owner:" + originalOwners + "Favfood:" + favFood
+ "FoodPerDay:" + foodPerDay;
}
}
and the Dog class
import java.util.ArrayList;
public class Dog extends Pet {
public static boolean likesBones;
public Dog(String name, ArrayList<Owner> owners, String food, int mealsPerDay, boolean likeBones) {
super(name, owners, likeBones, food, mealsPerDay);
Dog.likesBones = likeBones;
}
/**
* Does the dog like bones?
* #return true if he does
*/
public static boolean getLikesBones() {
return likesBones;
}
}
I'm designing a shop system here, and it is mainly a media shop, containing items like video games, DVDs and CDs. The issue I am having is that I want to store different instances of the same object, in this case VideoGames, into a linked list. It seems to work, but when I output the List, it only outputs the last item entered into the list and repeats itself for the amount of objects which were supposed to be in the list.
I understand that it is a lot of code to look through, but any help would be greatly appreciaed.
Here is the code for the addVideoGame class:
import java.util.*;
import java.io.*;
public class addVideoGame extends VideoGames implements java.io.Serializable{
public static VideoGames game = new VideoGames();
public static VideoGames eGame = new VideoGames();
public static LinkedList <VideoGames> games = new LinkedList<>();
private static int vgChoice = 0;
public static int vgCount = 0;
public static int vgAmount = 0;
public static void vgMenu(){
IBIO.output("1: Add a new videogame to the list.");
IBIO.output("2: View the contents of the list.");
IBIO.output("3: Save the contents of the list to the local area.");
IBIO.output("4: Load in data from a local file.");
IBIO.output("5: Return to the main menu.");
vgChoice = IBIO.inputInt("Make your choice: ");
if(vgChoice == 1){
vgAmount = IBIO.inputInt("How many games would you like to add to the database?: ");
for(int x = 0; x < vgAmount; x = x + 1){
VideoGames vg = new VideoGames();
vg.setTitle(IBIO.inputString("Enter the title of the game: "));
vg.setPublisher(IBIO.inputString("Enter the publisher of the game: "));
vg.setDeveloper(IBIO.inputString("Enter the developer of the game: "));
vg.setAgeRating(IBIO.inputInt("Enter the age rating of the game: "));
vg.setGenre(IBIO.inputString("Enter the genre of the game: "));
vg.setQuantity(IBIO.inputInt("Enter the available quantity of the game: "));
game = vg;
games.add(vg);
IBIO.output(" ");
}
vgMenu();
} else if(vgChoice == 2){
IBIO.output("Current amount of games in the list: " + games.size());
System.out.println(Arrays.toString(games.toArray()));
vgMenu();
} else if(vgChoice == 3){
try{
FileOutputStream fileOut = new FileOutputStream("I:\\IB\\Computer Science\\TheStore\\games.txt");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(game);
out.close();
fileOut.close();
IBIO.output("Data has been saved to: I:\\IB\\Computer Science\\TheStore\\games.txt");
vgMenu();
} catch(IOException i){
i.printStackTrace();
}
} else if(vgChoice == 4){
eGame = null;
for(int x = 0; x < games.size(); x = x + 1){
try{
FileInputStream fileIn = new FileInputStream("I:\\IB\\Computer Science\\TheStore\\games.txt");
ObjectInputStream in = new ObjectInputStream(fileIn);
eGame = (VideoGames) in.readObject();
in.close();
fileIn.close();
} catch (IOException i){
i.printStackTrace();
return;
} catch(ClassNotFoundException c){
IBIO.output("VideoGames class not found");
c.printStackTrace();;
return;
}
IBIO.output("Object Details: " + eGame.toString());
vgMenu();
}
} else if(vgChoice == 5){
IBIO.output("Returning to main menu: ");
AccessMenus.adminMenu();
}
}
}
If anyone needs them, here are the two interface classes used to navigate the program:
public class TheStore {
static String password; //Variable created to hold and check the value of password against the correct value.
public static boolean privilege = false; //Variable created to distinguish the difference between a normal user and a user with administrator privileges.
public static void main(String[] args) {
IBIO.output("Welcome to The Store!");
IBIO.output("Please make sure that you enter the correct password for your given privileges.");
password = IBIO.inputString("Enter password: ");
if(password.equalsIgnoreCase("admin")){ //Checks the entered value against the correct value.
privilege = true; //Sets global boolean value to true, so that admin access is granted.
IBIO.output(" ");
AccessMenus.adminMenu();//If password is correct, loads admin menu.
} else if(password.equalsIgnoreCase("user")){
privilege = false; //Keeps admin access off, so that unauthorised changes cannot be made.
IBIO.output(" ");
AccessMenus.userMenu();//If correct, loads user menu.
} else {
IBIO.output("The password is incorrect. Exiting program.");
System.exit(1); //If an incorrect password is entered, the program will close.
} //close else
}//close main
}//close class TheStore
And the second one:
public class AccessMenus{
public static int choice;//Variable which will hold the value, which corresponds to an action depending on what value is entered.
public AccessMenus(){ //Null argument constructor, to set values to 0.
AccessMenus.choice = 0;
}
public AccessMenus(int c){ //Single argument constructor.
AccessMenus.choice = c;
}
public static void userMenu(){
IBIO.output("1: Sell a product.");
IBIO.output("2: Register a customer in the Loyalty programme.");
IBIO.output("3: Stock check.");
IBIO.output("4: Log out.");
IBIO.output(" ");
IBIO.output("Please make your choice: ");
choice = IBIO.inputInt();
if(choice == 1){
//Go to Sales class.
} else if(choice == 2){
//Go to CustomerRegister class.
} else if(choice == 3){
//Open the StockCheck class.
} else if(choice == 4){
IBIO.output("Logging out.");
System.exit(1);
} else {
IBIO.output("Invalid choice. Returning to menu.");
userMenu(); //If the value entered does not correspond to any action, the program will treat it as invalid and return to the menu.
}//close else
}//close userMenu
public static void adminMenu(){
IBIO.output("1: Sell a product.");
IBIO.output("2: Go to the specific object menus.");
IBIO.output("3: Stock check.");
IBIO.output("4: Order more stock.");
IBIO.output("5: Register a customer in the Loyalty programme.");
IBIO.output("6: Check Loyalty members.");
IBIO.output("7: Create databases.");
IBIO.output("8: Log out.");
IBIO.output(" ");
IBIO.output("Please make your choice: ");
choice = IBIO.inputInt();
if(choice == 1){
//Go to Sales class.
} else if(choice == 2){
int createChoice = 0;
IBIO.output("1: Video Games.");
IBIO.output("2: DVD.");
IBIO.output("3: CD.");
createChoice = IBIO.inputInt("Enter choice: ");
if(createChoice == 1){
addVideoGame.vgMenu();
} else if(createChoice == 2){
//Go to addDVD class.
} else if(createChoice == 3){
//Go to addCD class.
} else {
IBIO.output("Invalid input.");
adminMenu();
}
} else if(choice == 3){
//Go to StockCheck class.
} else if(choice == 4){
//Go to StockOrder class.
} else if(choice == 5){
//Go to CustomerRegister class.
} else if(choice == 6){
//Go to LoyaltyCheck class.
} else if(choice == 7){
//Go to DatabaseCreation class.
} else if(choice == 8){
IBIO.output("Logging out.");
System.exit(1);
} else {
IBIO.output("Invalid input. Returning to menu.");
adminMenu();
} //end else
}//close AdminMenu
}//close AccessMenus
Also, here is the VideoGames object class, containing things like the accessor and mutator methods and primary fields:
public class VideoGames implements java.io.Serializable {
//Instance variables
public static String title;
public static int ageRating;
public static String genre;
public static String publisher;
public static String developer;
public static int quantity;
public VideoGames(){ //null argument constructor
VideoGames.title = null;
VideoGames.ageRating = 0;
VideoGames.genre = null;
VideoGames.publisher = null;
VideoGames.developer = null;
VideoGames.quantity = 0;
}//end VideoGames null argument constructor
public VideoGames(String t, int aG, String g, String p, String d, int q){ //6-argument constructor
VideoGames.title = t;
VideoGames.ageRating = aG;
VideoGames.genre = g;
VideoGames.publisher = p;
VideoGames.developer = d;
VideoGames.quantity = q;
}//end VideoGames 6-arguement constructor
public VideoGames(VideoGames game){
game = new VideoGames();
}
#Override
public String toString(){
return "\nTitle: " + title + " " + "\nPublisher: " + publisher + " " + "\nDeveloper: " + developer + " " + "\nAge Rating: " + ageRating + " " + "\nGenre: " + genre + " " + "\nQuantity: " + quantity + "\n ";
}
//Accessor and Mutator methods
public static String getTitle(){
return title;
}
public static void setTitle(String t){
title = t;
}
public static int getAgeRating(){
return ageRating;
}
public static void setAgeRating(int ag){
ageRating = ag;
}
public static String getGenre(){
return genre;
}
public static void setGenre(String g){
genre = g;
}
public static String getPublisher(){
return publisher;
}
public static void setPublisher(String p){
publisher = p;
}
public static void setDeveloper(String d){
developer = d;
}
public static String getDeveloper(){
return developer;
}
public static void setQuantity(int q){
quantity = q;
}
public static int getQuantity(){
return quantity;
}//end method setDeveloper
}//end class VideoGames
Again, any help would be greatly appreciated.
There is too much code for me to properly go through but it sounds like (and a quick scan seemed to confirm) you are only creating one VideoGames object. Whenever you change any fields within that object it changes the field in that single object.
You then add that same VideoGames object multiple times to the list, but these are all separate references to the same object.
Instead VideoGames should be called VideoGame and contain the data for one game you should then create a new VideoGame() and set it up each time you add one to the list.
Remember the list only contains references to objects, not objects themselves.
Each VideoGames object is like a house on a street. At the moment you build one house and keep painting the door on that house different colours instead of building multiple houses and painting the door on each house a different colour.
Your list is just a list of addresses when you add the same house 4 times the list just repeats the same address.
So you were doing:
Build a house in plot 1
Paint house door blue
Write down plot 1 in a list
Paint house door green
Add plot 1 to the list again
Paint house door red
Add plot 1 to the list again
Now you go down the list, you see three entries - but when you go and look at the door colour they all say red.
The field of VideoGames class are all static. Static field belong to Class and only one memory space in method area of JVM. When you execute for loop:
VideoGames vg = new VideoGames();
you create one VideoGames instance, but when you execute set method:
vg.setTitle(IBIO.inputString("Enter the title of the game: "));
vg.setPublisher(IBIO.inputString("Enter the publisher of the game: "));
vg.setDeveloper(IBIO.inputString("Enter the developer of the game: "));
vg.setAgeRating(IBIO.inputInt("Enter the age rating of the game: "));
vg.setGenre(IBIO.inputString("Enter the genre of the game: "));
vg.setQuantity(IBIO.inputInt("Enter the available quantity of the game: "));
the data you receive will be set to the static field in method area. The value you set previous will be covered by the value you set following. When you print the value of list. You will get value from the static field in method area.
So,
but when I output the List, it only outputs the last item entered into the list and repeats itself for the amount of objects which were supposed to be in the list.
Hope to help you.
Sorry for my poor English.
You are using static members in your VideoGames -class.
The value of this affects all objects, e.g.
public class X {
public static int y;X() { }
public
}
X x1 = new X();
x1.y = 1;
X x2 = new X();
x2.y = 2;
System.out.println("x1.y" + x1.y); // 2
System.out.println("x2.y" + x2.y); // 2
I got some classes like UniversityDepartment & PolytechnicDepartment these 2 classes extends AcademicDepartment class. And the problem want me to do this. The AcademicDepartment can have pre-graduate program & after-graduate program. And the departments will be 2 University & Polytechnic. For a department to be polytechnic or University depending on the number of labs that have in pre-graduate program. So if we are in pre-graduate or after-graduate program i think the user must type it from keyboard and if we are in pre-graduate we also must be asked how many labs we got to see if we are in polytechnic or university. So how i will do this? I will give you an example of my code:
import java.io.*;
public class AcademicDepartment {
private String names;
private String labs;
private int teachers;
private int graduates;
// private boolean studies;
public void infostudies() throws IOException{
System.out.println("Enter the department you want."
+ "Press 1 for pre-graduate program or 2 for after-graduate program" );
String studies = "";
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
studies = br.readLine();
if (studies == 1){
System.out.println("You are in pre-graduate program");
System.out.println("Enter the number of labs");
String labs = "";
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
labs = br1.readLine();
if (labs > 5){
System.out.println("The department is polytechnic");
}
}
if (labs < 5 ){
System.out.println("The department is University");
}
else
{
System.out.println("Wrong number try again");
}
}
public AcademicDepartment(String names,String labs,int teachers,int graduates){
names = new String(names);
this.labs = labs;
this.teachers = teachers;
this.graduates = graduates;
}
public void printdepartmentinfo(){
System.out.println("The names are:" + names);
System.out.println("The labs are:" + labs);
System.out.println("The GRADUATES are:" + graduates);
System.out.println("The teachers are:" + teachers);
}
}
There are a couple of unfortunate things about the code.
One problem is that you're comparing String variables studies and labs with integer literals. That is not permitted by the compiler. Normally one would either compare a String variable (using String.equals) with a String literal, or else attempt to interpret the String variable using Integer.parseInt before comparing with an integer.
Another problem is that some variables local to method infostudies have the same names as fields of class AcademicDepartment. That's permitted, but it's needlessly confusing.
For an example, you'll deal with variable studies, but I'll show you what I mean with regard to variable labs.
Don't do this:
public class AcademicDepartment {
...
public void infostudies() throws IOException {
...
if (studies == 1) {
...
String labs = "";
...
if (labs > 5){ // Compare String with int? Won't compile!
...
}
...
}
if (labs < 5) { // Can't see the "labs" defined above!
...
}
...
}
}
Do this:
public class AcademicDepartment {
...
public void infostudies() throws IOException {
...
if (studies == 1) {
...
String labs = "";
...
try {
int labCount = Integer.parseInt(labs);
if (labCount > 5) {
System.out.println("The department is polytechnic");
} else {
System.out.println("The department is University");
}
} catch (NumberFormatException formatErr) {
System.out.println("Sorry, couldn't understand your number of labs.");
}
...
}
...
}
}