Search code examples
javaarraysclassobjectmethods

How come I'm running into an error after all the enemies are defeated, shouldn't it have ended?


I'm making a program using java, and the particular issue I ran into was in the battle method, where the program runs into an error after all the enemies are defeated. I tried to alter it a couple time already, but unable to come up with a proper solution. The terminal states that the error is in the calculation of **dmg = (skill[i][0] * charList.get(i).getSTR()) / enemyList.get(0).getDEF();**

I would apricate any ideas or suggestions anyone can provide.

Below is the method of my java code I'm having trouble with.

public static void battle(ArrayList<Characters> charList, String[] name, String[][] skillname, int[][] MPCost, double[][] skill,double[][] HPnMP, int enemynum, double[] enemyStats){
        Scanner scanN = new Scanner (System.in);
        DecimalFormat df = new DecimalFormat("0.0");
        ArrayList<Enemies> enemyList = new ArrayList<>();
        
        int battlechoice;
        double dmg;
        double EnemyHP;
        
        for(int j = 0; j < enemynum; j++){
            enemyList.add(new Enemies(enemyStats[0], enemyStats[1], enemyStats[2], enemyStats[3]));
        }
        
        System.out.println("Battle Start:");
        while(!enemyList.isEmpty()){
            for(int i = 0; i < charList.size(); i++){//for the characters turn so that they all go and then the enemies can go

                if(HPnMP[i][0] <= 0) {
                    System.out.println(name[i] + " has been defeated!");
                    continue; // Skip turn for defeated character, and I found it on the following site: https://www.w3schools.com/java/java_break.asp
                }
                
                System.out.println("The current characters status is below. ");
                
                DragonForce(charList, name, HPnMP, i);
                
                System.out.println("Character: " + name[i]);
                System.out.println("HP: " + df.format(HPnMP[i][0]) + "/" + charList.get(i).getHP());
                System.out.println("MP: " + df.format(HPnMP[i][1]) + "/" + charList.get(i).getMP());
                System.out.println("STR: " + charList.get(i).getSTR());
                System.out.println("DEF: " + charList.get(i).getDEF());
                
                System.out.println("1) Do a basic attack");
                System.out.println("2) Use a skill");
                System.out.println("3) Rest (recovers mana)");
                battlechoice = scanN.nextInt();
                
                switch(battlechoice){//switch used instead of for loop because its easier when its using int values and needs differing ouputs for each of them
                    case 1://this is a basic attack choice, simply dealing damage based on the strength value of the character and prints a corresponding message
                        dmg = charList.get(i).getSTR() - enemyList.get(0).getDEF();
                        EnemyHP = enemyList.get(0).getHP() - dmg;
                        if (dmg < 0) {
                            dmg = 0;
                        } 
                        
                        if(EnemyHP<=0){
                            enemyList.remove(0);
                            System.out.println("One enemy defeated!");
                        }
                        else{
                            System.out.println(name[i] + " dealt " + df.format(dmg) + " damage. The enemy has " +df.format(EnemyHP) + " HP left.");
                            enemyList.get(0).setHP(EnemyHP);
                        }
                        
                        break;
                    case 2:
                        System.out.println("Select skill:");
                        System.out.println("1. " + skillname[i][0]);
                        System.out.println("2. " + skillname[i][1]);
                        int choice = scanN.nextInt();
                        if(choice == 1){
                            double MP = HPnMP[i][1] - MPCost[i][0];
                            
                            if(MP >= 0){//if statement checks if there is enough mp to use the skill
                                HPnMP[i][1] = MP;//changes their mp value so they lost the amount used for their skill

                                dmg = (skill[i][0] * charList.get(i).getSTR()) / enemyList.get(0).getDEF();
                                
                                if (dmg < 0) {
                                    dmg = 0;
                                } 
                                EnemyHP = enemyList.get(0).getHP() - dmg;//the index of 0 is used for the enemy so that there is always an enemy there, instead of putting in an index where there is no enemy object
                                
                                CharHeal(charList, skill, HPnMP, i);//calls a method to heal a character if Wendy's healing gets used
                                
                                if(EnemyHP<=0){//detects if an enemy had been killed 
                                    enemyList.remove(0);
                                    System.out.println("One enemy defeated!");
                                }
                                else{//if an enemy is still alive, it displays an output of their current state
                                    System.out.println(name[i] + " dealt " + df.format(dmg) + " damage. The enemy has " + df.format(EnemyHP) + " HP left.");
                                    enemyList.get(0).setHP(EnemyHP);
                                }
                            }
                            else{//if they ran out of mana to use their skill
                                System.out.println(name[i] + " ran out of mana to use their skill.");
                            }
                        }
                        else{
                            double MP = HPnMP[i][1] - MPCost[i][1];
                            
                            if(MP >= 0){//if statement checks if there is enough mp to use the skill
                                HPnMP[i][1] = MP;//changes their mp value so they lost the amount used for their skill

                                dmg = (skill[i][1] * charList.get(i).getSTR()) / enemyList.get(0).getDEF();
                                if(dmg<0){//in the case the def of the enemy is higher than the characters attack
                                    dmg = 0;
                                }
                                EnemyHP = enemyList.get(0).getHP() - dmg;//the index of 0 is used for the enemy so that there is always an enemy there, instead of putting in an index where there is no enemy object
                                
                                if(EnemyHP<=0){//detects if an enemy had been killed 
                                    enemyList.remove(0);
                                    System.out.println("One enemy defeated!");
                                }
                                else{//if an enemy is still alive, it displays an output of their current state
                                    System.out.println(name[i] + " dealt " + df.format(dmg) + " damage. The enemy has " + df.format(EnemyHP) + " HP left.");
                                    enemyList.get(0).setHP(EnemyHP);
                                }
                            }
                            
                            else{//if they ran out of mana to use their skill
                                System.out.println(name[i] + " ran out of mana to use their skill.");
                            }
                        }
                        break;
                    case 3://recovers the characters mana
                        HPnMP[i][1] = (charList.get(i).getMP() * 0.2) + HPnMP[i][1];
                        if(HPnMP[i][1] > charList.get(i).getMP()){
                            HPnMP[i][1] = charList.get(i).getMP();
                        }
                        System.out.println(name[i] + " has rested and as a result, their MP has increased to " + df.format(HPnMP[i][1]));
                        break;
                    default:
                        System.out.println("Not a valid option. The turn will be skipped.");
                }
            }
            for (int i = 0; i < enemyList.size(); i++) {//the enemy's turn and the damage they deal
                int charnum = (int)Math.floor(Math.random() * (charList.size() - 1 + 0) + 0);//randomly selects a character for the attack to target
                dmg = enemyList.get(i).getSTR() - charList.get(charnum).getDEF();
                if(dmg<0){
                    dmg = 0;
                }
                HPnMP[charnum][0] = charList.get(charnum).getHP() - dmg;
                if(HPnMP[charnum][0]<= 0){
                    System.out.println(name[charnum] + " has been knocked out!");
                }
                else{
                    System.out.println("The enemy has dealt " + df.format(dmg) + " to " + name[charnum]);
                    System.out.println(name[charnum] + " now has " + df.format(HPnMP[charnum][0]) + " HP left.");
                }
            }
        }
    }

Solution

  • The problem arises if you have more than one player and the first player defeats all enemies. The loop over all the players still continues, but for the second player there is no enemy left which results in an exception when trying to access enemyList.get(0).

    You need to change the loop over the players from

    for(int i = 0; i < charList.size(); i++) {
        //...
    } 
    

    to

    for(int i = 0; i < charList.size() && !enemyList.isEmpty(); i++) {
        //...
    } 
    

    so that it terminates if there are no enemies left.