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.
Related
I'm currently working on an assignment that requires me to build a small database for an imaginary toy company. They sell four different types of toys, with all of their toy's data in a single text file. Different toys have varying attributes to them.
My job is to read every line of the text file, find out what toy it is based on it's serial number, create a new instance of that toy, and load it into an array list of Toys.
Here are some examples of a line in the .txt file for every type of toy.
Animal
2835360879;Cow;Game Assassin;19.52;3;7;Plastic;M
Puzzle
4353818087;Eight queens puzzle;Gamescape;15.69;5;6;C
Figure
1147205649;Ninja Turtles;Gamezoid;46.15;10;6;A
Board Game
7235647474;13 Dead End Drive;Game Assassin;55.18;10;9;1-8;Emeli Davis
The following method is in charge of parsing through the text file, to create new instances of Toy, and to add them into the Array List
public void loadData() {
try {
File dataFile = new File("res/toys.txt");
if (dataFile.createNewFile()) {
System.out.println("Data file created!");
}
else {
Scanner readData = new Scanner(dataFile);
readData.useDelimiter(";"); // sets semicolons as the delimiter
while(readData.hasNext()) {
sn = readData.nextDouble(); // reads the next double (serial number) on each line
category = categoryHandler(sn); // setting and returning value for category based on the serial number
nm = readData.next(); // initializes the name of the toy
brd = readData.next();
prc = readData.nextDouble();
availableCnt = readData.nextInt();
ageApp = readData.nextInt();
// creates a new object, dependant on the category
switch(category) {
case "Figures":
char classification = readData.next().charAt(0);
Figure figures = new Figure(sn, nm, brd, prc, availableCnt, ageApp, classification);
data.add(figures);
break;
case "Animals":
String material = readData.next();
char size = readData.next().charAt(0);
Animal animals = new Animal(sn, nm, brd, prc, availableCnt, ageApp, material, size);
data.add(animals);
break;
case "Puzzles":
char puzzleType = readData.next().charAt(0);
Puzzle puzzles = new Puzzle(sn, nm, brd, prc, availableCnt, ageApp, puzzleType);
data.add(puzzles);
break;
case "Board Games":
String playerCount = readData.next(); // holds the player count as a string
int minPlayers = Integer.parseInt(playerCount.substring(0, 1)); // holds the first integer
int maxPlayers = Integer.parseInt(playerCount.substring(playerCount.length() - 1, playerCount.length())); // holds the second integer
String designers = "";
BoardGame boardGames = new BoardGame(sn, nm, brd, prc, availableCnt, ageApp, minPlayers, maxPlayers, designers);
data.add(boardGames);
break;
default:
System.out.println("Invalid toy type selected!");
}
if (readData.hasNext()) {
readData.nextLine(); // skips to the next line if there's a line to skip to
}
}
readData.close();
}
}
catch (IOException e) {
System.out.println("An error occured.");
e.printStackTrace();
}
}
The following method is in charge of categorizing the toy type.
public String categoryHandler(double serialNumber) {
String serialNumCheck = Double.toString(serialNumber); // converting serial number to string to allow the first digit to be checked
double firstDigit;
// setting up the first digit, checking to see if it's zero.
if (serialNumCheck.length() == 12) {
firstDigit = 0;
}
else {
firstDigit = Double.parseDouble(Double.toString(serialNumber).substring(0, 1));
}
// conditionals
if (firstDigit == 0 || firstDigit == 1) {
category = "Figures";
}
else if (firstDigit == 2 || firstDigit == 3) {
category = "Animals";
}
else if (firstDigit == 4 || firstDigit == 5 || firstDigit == 6) {
category = "Puzzles";
}
else if (firstDigit == 7 || firstDigit == 8 || firstDigit == 9) {
category = "Board Games";
}
// this condition should not be possible to achieve, unless the first digit is negative. Still have it just in case.
else {
System.out.println("Invalid serial number created!");
category = "";
}
return category;
}
After running the loadData() method, my array list only contains 128 toys, instead of the expected 225. Almost all of them are categorized properly, but a few toys are not, at seemingly at random indices.
I suspect it has something to with readData.nextLine() at the end of the loadData() method. The problem is that when I remove the line, the program throws a NullPointerException as there nothing left to scan on the current line, so no Toy can be created.
At this point I'm fairly lost as to what is causing this bug.
Some guidance would be appreciated.
So I have this method here
while(oMenu == 1 || oMenu == 2){
oMeny = Kbd.readInt("\nClick 1 to make an account\nClick 2 to login\nClick 3 to exit the program");
if(oMeny == 1){
for(int i = 0; Account[i] != null; i++){
if(Account[i] == null){
pos = i;
}
}
Account[pos] = new Account();
}
if(oMeny == 2){
String s = Kbd.readString("Input your accountnumber: ");
for(int i = 0; Account[i] != null; i++){
if(Account[i] != null && s.equals(Account[i].getAccountNumber())){
System.out.println("Welcome!");
// Here is rest of my code , the "inner" menu that works menyMetod(iMeny,mMeny);
}
else{
System.out.println("There are no accounts with that given accountnumber!");
}
}
}
}
}
I want to understand why if I access the oMeny == 1 and make 2 accounts Why I can't seem to access the first one I make but rather the latest one? It seems that somehow my array "overwrites" the first empty position. Basically I want to find the first empty position in my array, so in the first case it's always index 0 and then the next time I make an account again, it should be Index 1 logically.
EDIT : Heres my code for the Account class
public class Account{
private int money, transactions;
private String AccountNumber;
public Account(){
money = Kbd.readInt("\nHow much money do you want to put in?");
AccountNumber = Kbd.readString("\nWhat account number do you want?");
}
The error is here:
for (int i = 0; accounts[i] != null; i++) {
if (accounts[i] == null)
The for loop repeats as long i points to a non-null entry. Therefore the if-condition is never true.
This becomes quickly obvious when you run the program line by line in a debugger.
Next time please provide a complete code example that can be compiled. Your code is full of error, It took me a lot of time to fix it before I was able to execute it.
Corrected code:
import java.util.Scanner;
class Main
{
static Scanner kbd = new Scanner(System.in);
static Account[] accounts = new Account[100];
static class Account
{
//public int money;
public String accountNumber;
public Account()
{
//System.out.println("\nHow much money do you want to put in?");
//money = Kbd.nextInt();
System.out.println("\nWhat account number do you want?");
accountNumber = kbd.next();
}
}
public static void main(String[] args)
{
int oMenu = 1;
int pos = 0;
while (oMenu == 1 || oMenu == 2)
{
System.out.println("\nClick 1 to make an account\nClick 2 to login\nClick 3 to exit the program");
oMenu = kbd.nextInt();
if (oMenu == 1)
{
for (int i = 0; i<accounts.length; i++)
{
if (accounts[i] == null)
{
accounts[i] = new Account();
break;
}
}
}
if (oMenu == 2)
{
System.out.println("Input your accountnumber: ");
String s = kbd.next();
Account found=null;
for (int i = 0; i<accounts.length; i++)
{
if (accounts[i] != null && s.equals(accounts[i].accountNumber))
{
found=accounts[i];
}
}
if (found!=null)
{
System.out.println("Welcome! nr. "+found.accountNumber);
}
else
{
System.out.println("There are no accounts with that given accountnumber!");
}
}
}
}
}
Notice how I also fixed the second for-loop.
You did not show the declaration or initialization of pos, so I think it is not working how you expect because you do not go into the for loop where Account[i] is null to set pos. Try this
if(oMenu == 1){
int pos = 0;
while (Account[pos] != null && pos < Account.length)
pos++;
if (pos < Account.length)
Account[pos] = new Account();
else{
//expand array and add account or throw error
}
}
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.
Hoping for some help - I've been asked to write a hotel room system using methods for uni. All has been going well until I try to order the array alphabetically.
I have managed to get it to order within the method but it updated the main array (hotel). I want it to keep it within the order method, if that makes sense?
I've included a cut down version below without all the functions.
Currently it will reorder the array hotel so if you view the rooms the array will print like 'e,e,e,etc, George, Peter, Robert' instead of keeping its original form 'e, Robert, Peter, e,e,etc, George'
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String roomName;
int roomNum = 0;
String[] hotelRef = new String[12];
String[] hotel = new String[12];
initialise(hotel); //initialise
while (roomNum < 13) {
System.out.println("Please select from the menu:");
System.out.println("V : View rooms");
System.out.println("O : Order Guests alphabetically");
String selection = input.next();
switch (selection) {
//There are more switch cases on the original version
case "O":
order(hotel);
break;
default:
System.out.println("");
}
}
}
private static void order(String[] hotelRef) {
int j;
boolean flag = true; //will determine when the sort is finished
String temp;
String[] order = new String[12];
order = hotelRef;
while (flag) {
flag = false;
for (j = 0; j < order.length - 1; j++) {
if (order[j].compareToIgnoreCase(order[j + 1]) > 0) {
//ascending sort
temp = order[j];
order[j] = order[j + 1]; // swapping
order[j + 1] = temp;
flag = true;
}
}
}
for (int y = 0; y < order.length; y++) {
if (!order[y].equals("e")) {
System.out.println("Room " + y + " is occupied by " + order[y]);
}
}
System.out.println("Ordering completed");
}
You should clone the hotelRef instead of assigning the reference like this order = hotelRef;
You could do the following while creating the order array :
String[] order = new String[hotelRef.length]; // to make sure that order has the right size.
and instead of order = hotelRef;
for (int i=0;i<order.length;i++)
order[i]=hotelRef[i]; // thereby cloning
or use System.arraycopy() or any other method to accomplish cloning the array.
You can make copy of hotel array in your order method:
String[] hotelCopy = new String[hotelRef.length];
System.arraycopy(hotelRef, 0, hotelCopy, 0, hotelRef.length);
And then just use hotelCopy inside your order method.
The problem lies with the following line
order = hotelRef;
Change it to
order = hotelRef.clone();
Though you are creating a new object, you have assigned the reference to outer object only. So whatever changes you make in the inner object it will be reflected to the outer object.
I'm working on a something like music player. I'm building playlist on HashMap, I have a problem with deleting specific setlist(case 5). It works but when I delete position in the middle of the list case 1 (showing all playlists) no longer works because I have empty space (1,2,3,deleted,5,6....). Now how do I make those positions after deleted one decrease index by one? Looks like x-- doesn't solve my problem. I hope you understand my problem, here is the code, if you need me to translate anything to English just ask. Thanks for help!
package PLAYLIST2;
import java.util.HashMap;
import java.util.Scanner;
public class Odtwarzacz {
// String lista;
// Odtwarzacz(Playlist) {
// lista = b;
// }
public static void main(String[] args) {
int nr;
int koniec = 0;
String nazwa11;
int x = 0;
HashMap<Integer, Playlist> Playlista = new HashMap<Integer, Playlist>();
Playlista.put(x, new Playlist("Rock"));
x++;
Playlista.get(0).dodajUtwor("Stockholm Syndrome", "Muse", 2004);
Playlista.get(0).dodajUtwor("Absolution", "Muse", 2004);
Playlista.put(x, new Playlist("Pop"));
x++;
Scanner odczyt = new Scanner(System.in);
// TODO Auto-generated method stub
while (koniec == 0) {
System.out.println("_________________________");
System.out.println("1.Wyświetl listę playlist");
System.out.println("2.Dodaj playlistę");
System.out.println("3.Wyświetl playlistę");
System.out.println("4.Posortuj playlistę");
System.out.println("5.Usuń playlistę");
nr = odczyt.nextInt();
switch (nr) {
case 1: {
System.out.println("Lista playlist: ");
for (int i = 0; i < x; i++) {
System.out.println(i + ". " + Playlista.get(i).Nazwa());
}
break;
}
case 2: {
System.out.print("Podaj nazwę nowej playlisty: ");
nazwa11 = odczyt.next();
Playlista.put(x, new Playlist(nazwa11));
System.out.println("Dodano playlistę: "
+ Playlista.get(x).Nazwa());
x++;
break;
}
case 3: {
System.out.print("Podaj numer playlisty:");
nr = odczyt.nextInt();
Playlista.get(nr).wyswietlListe();
break;
}
case 4: {
System.out.print("Podaj numer playlisty:");
nr = odczyt.nextInt();
Playlista.get(nr).sortuj();
break;
}
case 5: {
System.out.print("Podaj numer playlisty:");
nr = odczyt.nextInt();
System.out.println("Skasowano playlistę: "
+ Playlista.get(nr).Nazwa());
Playlista.remove(nr);
x--;
break;
}
}
}
}
}
You do not seem to need a HashMap.
A HashMap is just a key-value store that has no order.
In your case, a List seems like a better choice. It comes with an order since it is the main point of it.
You can specifically use a ArrayList:
List<Playlist> playlists = new ArrayList<>();
playlists.add(new Playlist("Rock"));
// ...
Playlist p = playlists.get(index);
If you want to safely remove and get correct keys after, you must iterate the Map
int count = 0;
boolean found = false;
Iterator<Map.Entry<Integer,String>> iter = TestMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Integer,String> entry = iter.next();
if("Sample".equalsIgnoreCase(entry.getValue())){
iter.remove();
found = true;
}
if (found) {
// set the new key using count...
}
count ++;
}
first let me see if i understand your problem correctly or not . you like to reoder playlist after any delete operation. 1,2,3,4,5 . you delete 3 , then it should be 1,2,4,5 and not 1,2, ,4,5.
if above is true , best is use linkedhashmap collection. also case1 you can rewrite as
case 1: {
System.out.println("Lista playlist: ");
for (Playlist pll:Playlista.values()) {
System.out.println(i + ". " + pll.Nazwa());
}
break;
}