1

I am building the object with the classical Nim game, and there are some methods dealing with the player data. I bumped into this problem when testing my code, and couldn't figure it out.

This problem appeared when I add a player in an array, removing it after. Then, adding a player again. It showed: Index 1 out of bounds for length 1. What I've tried is to filter the null position when I remove the player data.

Any help is highly appreciated. And thank you all for the patience and time solving it!

The code is a little bit longer, but related. Here is the related code from class Nimsys, main method.

public static void addPlayer(String [] name) {
    if (name != null && name.length == 3) {
        for (int i = 0; i < NimPlayer.getCounter(); i++) {
            String userCheck = NimPlayer.getPlayer()[i].getUserName();
            if (userCheck.contains(name[0])) {
                System.out.println("The player already exists.\n");// Test if player has been created
                return;
            }
        }
        NimPlayer.createPlayer(name[0], name[1], name[2]);
        System.out.println("The player has been created.");
        return;
    } 
    System.out.println("Not Valid! Please enter again!");   
}

public static void searchAndRemovePlayer(String user) {
    NimPlayer [] playerList = NimPlayer.getPlayer();
    for (int i = 0; i < playerList.length; i++) {
        String userName =playerList[i].getUserName().trim();
        if (userName.equals(user)) {
            playerList[i] = null;
            System.out.println("Remove successfully!");
            NimPlayer.setPlayerList(playerList);
            return;
        }
    }
    System.out.println("The player does not exist.\n");

}

public static void main(String[] args) {
    System.out.println("Welcome to Nim\n");

    //Scanner in = new Scanner(System.in);

    while (true) {
        System.out.print('$');
        String commandin = in.next();

        if (commandin.equals("addplayer")) {
            String inputName = in.nextLine();
            String[] name = splitName(inputName);
            addPlayer(name);
        }

        if (commandin.equals("removeplayer")) {
            String user = in.nextLine().trim();

            if (user.equals("")) {
                System.out.println("Are you sure you want to remove all players? (y/n)");

                commandin = in.next();
                if (commandin.equals("y")) {
                    NimPlayer [] playerList = NimPlayer.getPlayer();
                    for (int i = 0; i < playerList.length; i++) {
                        playerList[i] = null;
                        NimPlayer.setPlayerList(playerList);
                    }
                    System.out.println("Remove all the players\n");
                    Arrays.stream(NimPlayer.getPlayer()).filter(Objects::nonNull).toArray();
                }
            }
            if (!user.equals("")) {
                searchAndRemovePlayer(user);
                Arrays.stream(NimPlayer.getPlayer()).filter(Objects::nonNull).toArray();
            }
        }

Here is part of my NimPlayer class:

public class NimPlayer {
private String userName;
private String familyName;
private String givenName;
private int score;
private int gamePlayed;

private static int counter;
private static final int SIZE = 10;
private static NimPlayer[] playerList = new NimPlayer[SIZE]; // set an array here


//define NimPlayer data type
public NimPlayer(String userName, String surName, String givenName) {
    this.userName = userName;
    this.familyName = surName;
    this.givenName = givenName;

}
// create new data using NimPlayer data type
public static void createPlayer(String userName, String familyName, String givenName) {
    if (counter < SIZE) {
        playerList[counter++] = new NimPlayer(userName, familyName, givenName);
    } else {
        System.out.println("Cannot add more players.");
    }
}
public static int getCounter() {
    return counter;
}
public static NimPlayer [] getPlayer() {   
    NimPlayer[] nimPlayers = Arrays.stream(playerList).filter(Objects::nonNull).toArray(NimPlayer[]::new);
    counter = nimPlayers.length;  //update the counter
    return nimPlayers;
}
public static void setPlayerList(NimPlayer [] newplayerList) {
    NimPlayer.playerList = newplayerList;
Woden
  • 510
  • 3
  • 9
  • 2
    Does this answer your question? [Removing items from a list](https://stackoverflow.com/questions/17279519/removing-items-from-a-list) – relativelyPrime Apr 28 '20 at 16:34
  • removing items from a list is the same as removing items from an array? @relativelyPrime – Woden Apr 28 '20 at 16:55

3 Answers3

1

1. Replace

if (commandin.equals("removeplayer")) {
    String user = in.nextLine().trim();

    if (user.equals("")) {
        System.out.println("Are you sure you want to remove all players? (y/n)");

        commandin = in.next();
        if (commandin.equals("y")) {
            NimPlayer [] playerList = NimPlayer.getPlayer();
            for (int i = 0; i < playerList.length; i++) {
                playerList[i] = null;
                NimPlayer.setPlayerList(playerList);
            }
            System.out.println("Remove all the players\n");
            Arrays.stream(NimPlayer.getPlayer()).filter(Objects::nonNull).toArray();
        }
    }
    if (!user.equals("")) {
        searchAndRemovePlayer(user);
        Arrays.stream(NimPlayer.getPlayer()).filter(Objects::nonNull).toArray();
    }
}

with

if (commandin.equals("removeplayer")) {
    String user = in.nextLine().trim();    
    if (user.isEmpty()) {
        System.out.println("Are you sure you want to remove all players? (y/n)");    
        commandin = in.nextLine();
        if (commandin.equalsIgnoreCase("y")) {
            NimPlayer [] playerList = NimPlayer.getPlayer();
            for (int i = 0; i < playerList.length; i++) {
                NimPlayer.removePlayer(playerList[i]);
            }
            System.out.println("Removed all the players\n");
        }
    } else {
        searchAndRemovePlayer(user);
    }
}

2. Change the following methods as given below:

public static void searchAndRemovePlayer(String user) {
    NimPlayer[] playerList = NimPlayer.getPlayerList();
    for (int i = 0; i < playerList.length; i++) {
        String userName = playerList[i].getUserName().trim();
        if (userName.equals(user)) {
            NimPlayer.removePlayer(playerList[i]);
            System.out.println("The player, " + user + " removed successfully!");
            return;
        }
    }
    System.out.println("The player, " + user + "  does not exist.\n");
}

public static NimPlayer [] getPlayer() {       
    return Arrays.stream(playerList).filter(Objects::nonNull).toArray(NimPlayer[]::new);
}

2. Instead of exposing the playerList to be set from outside, you should remove its public setter and create public static void removePlayer similar to public static void createPlayer as follows:

public static void removePlayer(NimPlayer player) {
    int i;
    for (i = 0; i < playerList.length; i++) {
        if (playerList[i] != null && playerList[i].getUserName().equals(player.getUserName())) {
            break;
        }
    }
    for (int j = i; j < playerList.length - 1; j++) {
        playerList[j] = playerList[j + 1];
    }
    counter--;
}

Important note: Never put setting operation within getter, the way you have done in your method, getPlayer().

Arvind Kumar Avinash
  • 50,121
  • 5
  • 26
  • 72
  • 1
    It's really GLAD to meet you again, sir. @Arvind – Woden Apr 28 '20 at 17:11
  • How can I return the `nimPlayer` and the updated `counter`? It seems not right. – Woden Apr 28 '20 at 17:14
  • I see, but if I update the `playerList`, in the `getPlayer()` method, I should also return the `playerList`, right? Because in `getPlayer()`, there is a `nimPlayers`. – Woden Apr 28 '20 at 17:24
  • 1
    `nimPlayers` is nothing but `playerList` - right? I've reset the `playerList` in the method, `setPlayerList`. After resetting `playerList`, the value of `counter` will be the length of the updated `playerList`. Feel free to comment in case of any further doubt/issue. – Arvind Kumar Avinash Apr 28 '20 at 17:44
  • 1
    If you are struggling to understand the suggested changes, I recommend you make these changes and test your application and then try to understand it again. Do not hesitate to ask me in case of any doubt. – Arvind Kumar Avinash Apr 28 '20 at 17:52
  • After modification, it provokes the `NullPointerException` with other functions. I'll post another question. For example, `displayplayer` and `editplayer`. Thank you, sir, I need to take a rest. @Arvind – Woden Apr 28 '20 at 17:55
  • Sir, I've spotted the error, and why it happened. I couldn't figure out a way to solve it. Could you please review my code? https://stackoverflow.com/questions/61494092/how-to-add-object-again-after-filtering-array-with-non-null-object/61494237?noredirect=1#comment108780497_61494237 – Woden Apr 29 '20 at 05:10
  • good morning, sir. I appreciate again for your help. – Woden Apr 29 '20 at 09:06
0

You need to use Iterator and call remove() on iterator instead of assigning to null. Duplicate from: Removing items from a list

  • It's not a duplicate of the question you have pointed to. The question you have pointed to deal with a `List`, not an array. This question is based on an array. – Arvind Kumar Avinash Apr 28 '20 at 18:10
0

You shouldn't do a "playerList[i] = null;" for removing a player. Use an ArrayList instead and use the ArrayList's .remove method to remove a player. don't keep track of counter variables.

Lazy Bum
  • 499
  • 4
  • 19
  • I am assigned to use array only, that's why my code is longer... – Woden Apr 28 '20 at 16:52
  • In that case, you have to rearrange the players when you remove them. So if you want to remove a player, take the last player from the array using the counter and replace the player to be removed with the last player. then do a counter-- – Lazy Bum May 05 '20 at 20:20