dude
dude

Reputation: 39

How to fill a matrix with random integers without repeating them?

Noob to programming. I am attempting to code a Bingo game, I have encountered two hard challenges (for me) that I don't know how to deal with. - How to fill my 2d arrays with non repeating integers. - How to leave a blank space right in the middle of the bingo card (matrix). That's the way it's supposed to be.

This is the function I use to fill the values of the matrix

public static void fillBoard(int [][] pBoard){

      Random rand = new Random();
       for (int[] pBoard1 : pBoard) {
           for (int j = 0; j < pBoard1.length; j++) {
               pBoard1[j] = rand.nextInt(100);
           }
       }


   }

This is how I initialize the matrices

public static int [] [] defineBoard(){

        int [] [] board = {{1,2,3,4,5},{1,2,3,4,5},{1,2,3,4,5},{1,2,3,4,5},
            {1,2,3,4,5},};

        return board;

    }

And I print it this way

public static void printBoard(int [][] pBoard){

       for(int [] rows : pBoard) 
        {
            for(int column : rows) 
            {
                System.out.print("| " + column + " ");
            }
                System.out.println("|");
        }
}

Here is an example of my output

| 34 | 43 | 6 | 22 | 61 |
| 18 | 95 | 43 | 75 | 53 |
| 40 | 10 | 34 | 38 | 66 |
| 43 | 74 | 77 | 77 | 34 |
| 95 | 69 | 48 | 29 | 38 |

Once again my issues are: I have no idea how to leave a blank space in the middle (3d row, 3d column) and I can't get the values to be non repeating. Thank you!

Upvotes: 0

Views: 599

Answers (2)

scottb
scottb

Reputation: 10084

There are classes in the Java Platform that will make the completion of this task simpler. As GBloggett has pointed out, the HashSet class in the Java Collections Framework is defined so that the set may not contain duplicate values. Attempting to add an existing value to a HashSet results in the set being unmodified. Exploiting this contract, you can generate 25 unique random numbers this way:

Set<Integer> grid = new HashSet<Integer>();
Random rand = new Random();

while (grid.size() < 25) {
    Integer val = rand.nextInt(100);
    grid.add(val);
}

Note that the Java Collections Frameworks classes are generic types. The declaration new HashSet<Integer>() simply informs the compiler that your Set instance may contain only Integer instances.

Printing out the grid does not require a matrix. You can get a linear array directly from the HashSet instance and then exploit a little logic: namely that the grid row is equal to (array_index / 5) and that the grid column is equal to (array_index % 5). It is also true for your use case that the 'middle' of the grid is always (row, column) = (2, 2), so you can exploit this to make a hard coded solution for getting an empty space in the middle:

Integer[] gridInts = grid.toArray(new Integer[0]);
StringBuilder output = new StringBuilder();

for (int index = 0; index < gridInts.length; index++) {
   int row = index / 5;
   int col = index % 5;

   String cell = (row == 2 && col == 2) ? "--" : gridInts[index].toString();
   output.append(" | ").append(cell);
   if (col == 4) output.append(" |" + "\\n");  // causes a new line to start
                                               // after the last column in the grid
}

String result = output.toString();             // gets String from StringBuilder
System.out.println(result);                    // sends grid to standard output

These code snippets should address your needs. Note that the ternary operator is used to determine whether to generate a blank spot in the output. This is simply an in-line if-then-else expression. Note also that a StringBuilder instance is used to hold the output while it is being constructed. It isn't strictly necessary and the string concatenation operator could be used instead (and it might be more readable)

Upvotes: 1

user9519354
user9519354

Reputation:

REPEATING NUMBERS:

I think you should create an int[] that stores all of your previously used numbers and then make a while() loop where you keep repeating until the random number has not been used, like this: (in pseudocode)

int[] usedNumbers = new int[24];
for(int i=0; i<24; i++) {
    boolean isNotRepeated = false;
    int numberToFill = rand.nextInt(100);
    while(!isNotRepeated) {
        for(int n=0; n<usedNumbers.length; n++) {
            if(usedNumbers[n] == numberToFill)
                numberToFill = rand.nextInt(100)
            if(n==23 && usedNumbers[n] != numberToFill)
                isNotRepeated = true;
        }
    usedNumbers[i] = numberToFill;
}

THE EMPTY SPOT:

Using this int[] print out the following: (pseudocode)

for(int i=0; i<usedNumbers.length+1; i++) {
    if(i==13 /** the middle */) {
        System.out.println("| " + "  " + " ");
    } else if(i<13) { // before the middle
        System.out.println("| " + usedNumbers[i] + " ");
    } else if(i>13) { // after the middle
        System.out.println("| " + usedNumbers[i-1] + " ");
    }
}

I haven't tested this, but it should work.

It is a different style than you did your other code, but it should work and it is simple enough.

EDIT:

I noticed that your '6' value (and any other value that is single-digit) looks like: | x | while the others look like | xx |, so I advise you to make an if((number-10)<0) { print: "| x | **OR** | x | }; pseudocode (neither are centered in this way).

Upvotes: 0

Related Questions