1

I'm doing my homework for Data Structures and I'm having trouble with 2D Array. Here's what I have to do:

"Suppose you are designing a multiplayer game that has n≥1000 players, numbered 1 to n, interacting in an enchanted forest. The winner of this game is the first player who can meet all the other players at least once (ties are allowed). Assuming that there is a method meet(i, j), which is called each time a player i meets a player j (with i ̸= j), describe a way to keep track of the pairs of meeting players and who is the winner."

I can't compile because of this error:

Multiplayer.java:51: error: constant expression required

for this line:

case meet: sb.append("1");

I'm a beginner so I really appreciate any help. Thank you in advance!

/* Suppose you are designing a multiplayer game that has n≥1000
   players, numbered 1 to n, interacting in an enchanted forest. The winner
   of this game is the first player who can meet all the other players at 
   least once (ties are allowed). Assuming that there is a method meet(i,
   j), which is called each time a player i meets a player j (with i ̸=
   j), describe a way to keep track of the pairs of meeting players and 
   who is the winner. */

public class Multiplayer {
    int n; // number of players
    int map[][] = new int[n][n]; // create a 2D array
    int meet = 1;
    int notMeet = 0;
    int[] count; // an array to keep the count, player wins when it reaches n

    public Multiplayer() {
        clearMap();
    } // initiate a new game

    public void clearMap() { // clear the 2d array
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                map[i][j] = notMeet; // clearing the map
                count[i] = 0; // turn every value of count[] into 0
                if (i == j)
                    map[i][j] = map[j][i] = meet; // when i == j give the tile the value of 1
            }
        }
    }

    public void meet(int i, int j) {
        // when player i meets player j, add 1 to the count[] of each player
        count[i] = count[i] + 1;
        count[j] = count[j] + 1;
    }

    public int isWin() {
        for (int i = 0; i < n; i++) {
            if (count[i] == n)
                return i; // player at the index i wins
        }
        return -1; // no player won yet
    }

    public String toString() {
        // display the map in string
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                switch (map[i][j]) {
                case meet:
                    sb.append("1"); // if player i and j meets, put 1 in the map //this line causes error
                default:
                    sb.append("0"); // if they haven't met, put the 0 as default
                }
                if (j < n - 1)
                    sb.append("|");
            }
            if (i < n - 1)
                sb.append("\n-----\n");
        }
        return sb.toString();
    }
}

class MultiplayerTest {
    public static void main(String[] args) {
        Multiplayer newGame = new Multiplayer();
        newGame.n = 5; // test for a small number of players
        // test for player 1 to meet all other players
        for (int i = 2; i <= 5; i++) {
            newGame.meet(1, i);
        }
        // print test to see if player 1 wins the game
        System.out.println(newGame.toString());
        System.out.println(newGame.isWin());

    }
}
rghome
  • 8,529
  • 8
  • 43
  • 62
chocolatte
  • 352
  • 4
  • 15
  • 2
    You cannot use a variable for `case` statements, it has to be a constant expression so you can't use `meet` here. Either use a literal or a `final` variable. – BackSlash Feb 11 '19 at 09:17
  • @BackSlash Thank you! Is there any better way to write it without the case statements? – chocolatte Feb 11 '19 at 09:21
  • Since you have just `case meet` and `default`, `switch` is not the proper statement to use. You should use an `if/else` instead. `if(map[i][kj] == meet) { ["case meet" here] } else { "default" here }` – BackSlash Feb 11 '19 at 09:23
  • I edited the code and it has this error: Exception in thread "main" java.lang.NullPointerException at Multiplayer.meet(Multiplayer.java:29) at MultiplayerTest.main(Multiplayer.java:64) I also edited the post. Thank you so much for your help! – chocolatte Feb 11 '19 at 09:44
  • Exception in thread "main" java.lang.NullPointerException I googled and they said this error is due to an inappropriate main but the solution doesn't seem to apply to my code... Could you help me please? I really appreciate it! – chocolatte Feb 11 '19 at 09:52
  • Sorry, but you cannot edit the title of your question as you debug your code to related to the next but that you have found. Edits may not change the meaning of the question. One question per bug. If you have a new problem, then you need to start a new question. But this is not a code debugging service. – rghome Feb 11 '19 at 15:12
  • I'm very sorry! I'm new to the site and I didn't know that I can't change the title. Sorry to you and anyone to whom I'm being disrespectful. I hope you understand that I do not have that intention. I'll be mindful next time when I ask a question. Have a nice day! – chocolatte Feb 11 '19 at 16:09
  • No problem and good luck with your project. Please remember to upvote any answers that have been helpful to you and accept an answer that best resolved your problem (if there is one). – rghome Feb 12 '19 at 08:39

6 Answers6

0

You can't use variables as the labels in a switch statement.

If you want to have a constant value in your program, the usual method is to create a static final member:

public static final int MEET = 1;

However, in this case if you only have two values then you are better using a boolean array and just checking for true and false. There is no need for a switch statement.

boolean map[][] = new boolean[n][n];

...

if (map[i][j]) {
    ...

In this case, it is better to rename the array met, so you code reads like this:

if (met[i][j]) {
    ...
rghome
  • 8,529
  • 8
  • 43
  • 62
  • Thank you so much! I edited the code and don't encounter the previous error, but a new error (Exception in thread "main" java.lang.NullPointerException). I edited the new error in the post. Thank you so much for your help! – chocolatte Feb 11 '19 at 09:49
  • It is unofficial stack overflow policy not to fix people's NullPointerException errors in their code, but to point to how to fix it. Please see here: [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – rghome Feb 11 '19 at 10:00
0

In the below snippet:

switch (map[i][j]) {
    case meet:
        sb.append("1"); // if player i and j meets, put 1 in the map //this line causes error
    default:
        sb.append("0"); // if they haven't met, put the 0 as default
}

Please note that there is no break; statement and hence, as per fall through logic, it will append 0 anyway.

If you just have one case, you should rather use if, e.g.:

if(map[i][j] == meet) {
    sb.append("1");
}else {
    sb.append("0");
}

update

Regarding the NullPointerException, you are getting that exception because count array is not initialised and you are trying to access the element.

Change the declaration to the following:

int[] count = new int[n];
Darshan Mehta
  • 30,102
  • 11
  • 68
  • 102
  • Thank you so much! I edited the code and don't encounter the previous error, but a new error (Exception in thread "main" java.lang.NullPointerException). I edited the new error in the post. Thank you so much for your help! – chocolatte Feb 11 '19 at 09:47
  • @HangNguyen what have you got at this line : `Multiplayer.java:29`? – Darshan Mehta Feb 11 '19 at 09:50
  • better still to write `sb.append(map[i][j] == meet ? "1" : "0")` – rghome Feb 11 '19 at 10:14
  • Hi, I posted a comment with the edited code. Thank you so much! I still have an ArrayIndexOutOfBound error though, but that's so much better than my previous code :) – chocolatte Feb 11 '19 at 10:42
0

You need to initialize your count array, like

public void initializeArray(int n) {
    this.n = n;
    count = new int[n];
    for (int i = 0; i < n; i++) count[i] = 0;
}

and then, instead of

newGame.n = 5;

you will need to do:

initializeArray(5);
Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
0

I can't see where you actually create the array count. Your code: boolean met[][] = new boolean[n][n]; //edited int[] count; // an array to keep the count, player wins when it reaches n creates the array met (... = new boolean[n][n]), but there is no such statement for the array count. Hence, references to count[i] fail.

HAig
  • 21
  • 1
  • 2
0

So I fixed the code like you guys suggested. Thank you all so much! This code below still has an error, but it's a lot better than my original one. Anyone knows about ArraysIndexOutOfBound error?

import java.util.Arrays;
public class Multiplayer {


    int n; //number of players
    boolean met[][] = new boolean [n][n];
    int[] count; //an array to keep the count, player wins when it reaches n

    public Multiplayer() {clearMap(); } //initiate a new game

    public void clearMap() {
        for (int i = 0; i < n; i ++) {
            for (int j = 0; j < n; j++) {
                met [i][j] = false; //clearing the map
                count [i] = 0;  //turn every value of count[] into 0
                if (i == j)
                    met[i][j] = met[j][i] = true;
            }
        }
    }

    public int[] meet(int i, int j){
        //when player i meets player j, add 1 to the count[] of each player
        if (i != j) {
            count [i] = count[i] + 1; 
            count [j] = count [j] + 1;
            met [i][j] = met[j][i] = true;

        }
        //System.out.println(Arrays.toString(count));
        return count;
    }

    public void initializeArray(int n) {
        this.n = n;
        count = new int[n];
        for (int i = 0; i < n; i++) count[i] = 0;
    }

    public int isWin () {
        for (int i = 0; i < n ; i++){
            if (count[i] == n-1) //if player i meets all the other players 
                return i; //player at the index i wins
        }
        System.out.println(Arrays.toString(count));
        return -1;
    }

    public String toString() {
        //display the map
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j <n; j++) {
                if (met [i][j]) {sb.append("true");} //this line causes error ArrayIndexOutofBound
                else {sb.append("false");}
                if (j<n-1) sb.append ("|");
            }
            if (i<n-1) sb.append("\n-----\n");
        }
        return sb.toString();   
    }
}


class MultiplayerTest {
    public static void main (String[] args) {
        Multiplayer newGame = new Multiplayer ();
        newGame.initializeArray(5); //test for a small number of players
        //test for player 1 to meet all other players
        for (int k = 0; k < 5; k++) {newGame.meet (1,k); }
        //print test to see if player 1 wins the game
        System.out.println(newGame.isWin());
        //System.out.println(newGame.toString()); I tried printing the 2D array output into String but encountered an error and don't know how to fix it, but the other methods are fine.

    }
}
chocolatte
  • 352
  • 4
  • 15
0

The 'constant expression required' suggests that the labels in switch case requires a constant. And as suggested by other answers, its better to use if and use boolean 2d array.
ArraysIndexOutOfBound error is actually due to because you need to create an array using the new operator in the constructor method and then pass the reference to map asmap = new boolean[n][n];

I've tried here:

public class Multiplayer {
  int n; //number of players
  boolean[][] map; //not initializing here but in constructor
  int[] count; //an array to keep the count, player wins when it reaches n

  public Multiplayer(int num){
    n=num;
    map = new boolean[n][n];
    count = new int[n];
    //No need to use clearMap as all instance variables are assigned the default value of 0 or false or null;
    for(int i=0;i<n;i++){ //self-meeting
      count[i]=1;
      map[i][i]=true; 
    }
  }

  public void meet(int i,int j){
    if(i==j) return;
    //player number 1 is at index number 0
    //Hence player i is at index number i-1
    i--;j--;
    count[i]+=1;
    count[j]+=1;
    map[i][j]=map[j][i]=true;
  }

  public int isWin(){
    for(int i =0;i<n;i++)
      if(count[i]==n)
          return i; // player at the index i wins
    return -1; // no player won yet
  }

  public String toString(){
    String s = "";
    for(int i=0;i<n;i++){
      for(int j=0;j<n;j++){
        if(map[i][j])  s+="1";
        else           s+="0";
        if(j<n-1)      s+="|";
      }
      s+="\n";
      for(int k=0;k<n && i<n-1;k++)
        s+="--";
      s+="\n";
    }
    return s;
  }
}

public class MultiplayerTest {
  public static void main(String[] args) {
    int numberOfPlayers = 5;
    Multiplayer newGame = new Multiplayer(numberOfPlayers);
    // test for player 1 to meet all other players
    for (int i = 2; i <=5; i++) {
      newGame.meet(1, i);
    }
    // print test to see if player 1 wins the game
    System.out.println(newGame.toString());
    System.out.println(newGame.isWin());
  }
}
peru
  • 1
  • 4