Home > database >  How can I create an array of random integers without having the random numbers to generate duplicate
How can I create an array of random integers without having the random numbers to generate duplicate

Time:06-23

I have been only coding for a couple of months and I am trying to create a very simple guessing game. The game consists of a 5x5 square grid where the user will need to click on the square buttons and hope/pray that it is one of the correct squares. Now when I say correct squares they are randomly generated and stored in an array. However, whenever a set amount of random integers are generated, a few of them will generate duplicate numbers (this is no good or else it will be impossible to win my game). I am so close to finishing my code but my very last step is to find a way to solve this question.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.Random;

public class Display implements ActionListener {

    int lives = 10;
    int correct_counter = 0;

    Random random_int = new Random();
    int[] correct_squares = new int[10];

    JFrame frame = new JFrame();
    JPanel tile_panel = new JPanel();
    JButton[] button = new JButton[25];
    JButton reset_button = new JButton();
    JTextField title = new JTextField();
    JTextField motto = new JTextField();
    JTextField failure = new JTextField();
    JTextField success = new JTextField();
    JTextField life_label = new JTextField();
    JLabel life_counter = new JLabel();
   

    public Display(){

      for (int i = 0; i < correct_squares.length; i  ){
        correct_squares[i] = random_int.nextInt(25);
      }
      Collections.shuffle(Arrays.asList(correct_squares));
      System.out.println(Arrays.toString(correct_squares));

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600,700);
        frame.getContentPane().setBackground(Color.GRAY);
        frame.setLayout(null);

        title.setBounds(0,0,600,50);
        title.setBackground(Color.GRAY);
        title.setForeground(Color.GREEN);
        title.setFont(new Font("Ink Free", Font.BOLD, 50));
        title.setEditable(false);
        title.setHorizontalAlignment(JTextField.CENTER);
        title.setBorder(null);
        title.setText("Guessing Game");

        motto.setBounds(0,50,600,75);
        motto.setBackground(Color.GRAY);
        motto.setForeground(Color.GREEN);
        motto.setFont(new Font("Ink Free", Font.BOLD, 25));
        motto.setEditable(false);
        motto.setHorizontalAlignment(JTextField.CENTER);
        motto.setBorder(null);
        motto.setText("Test your luck!");

        life_label.setBounds(480,260,100,25);
        life_label.setBackground(Color.GRAY);
        life_label.setForeground(Color.GREEN);
        life_label.setFont(new Font("Ink Free",Font.PLAIN,25));
        life_label.setText("Lives: ");
        life_label.setBorder(null);
        life_label.setEditable(false);

        life_counter.setBounds(500,300,100,25);
        life_counter.setForeground(Color.GREEN);
        life_counter.setFont(new Font("Ink Free",Font.PLAIN,25));
        life_counter.setText(String.valueOf(lives));

        tile_panel.setBounds(25,120,400,400);
        tile_panel.setBackground(Color.GRAY);
        tile_panel.setLayout(new GridLayout(5,5, 1,1));

        for (int i = 0; i < button.length; i  ){
            button[i] = new JButton();
            button[i].setBackground(Color.WHITE);
            button[i].setSize(80,80);
            button[i].addActionListener(this);

            tile_panel.add(button[i]);
        }

        // Create Reset Button
        reset_button.setBounds(480,400,75,25);
        reset_button.addActionListener(this);
        reset_button.setBackground(Color.WHITE);
        reset_button.setForeground(Color.GREEN);
        reset_button.setFont(new Font("Times New Roman", Font.PLAIN,25));
        reset_button.setBorder(BorderFactory.createLineBorder(Color.GREEN, 2));
        reset_button.setText("Restart");

        frame.add(motto);
        frame.add(reset_button);
        frame.add(tile_panel);
        frame.add(life_label);
        frame.add(life_counter);
        frame.add(title);
        frame.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        boolean correctanswer = false;

        if (e.getSource() == reset_button){
          
          if(lives == 0){
            failure.setVisible(false);
            frame.remove(failure);
          }
          else if(correct_counter == correct_squares.length){
            success.setVisible(false);
            frame.remove(success);
          }

          for (int i = 0; i < correct_squares.length; i  ){
            correct_squares[i] = random_int.nextInt(26);
          }
          Collections.shuffle(Arrays.asList(correct_squares));
          System.out.println(Arrays.toString(correct_squares));

          for(int i = 0; i < button.length; i  ){
            button[i].setBackground(Color.WHITE);
            button[i].setEnabled(true);
          }          

          correct_counter = 0;
          lives = 10;
          life_counter.setText(String.valueOf(lives));
    
        }

        for(int i = 0; i < button.length; i  ){
            if (e.getSource() == button[i]){
                for (int k = 0; k < correct_squares.length; k  ){
                    if (correct_squares[k] == i){
                      button[i].setBackground(Color.GREEN);
                      button[i].setEnabled(false);
                      correctanswer = true;
                      k = correct_squares.length;
                      correct_counter  ;
                    } 
                }
                if (correctanswer == false){
                    button[i].setBackground(Color.RED);
                    button[i].setEnabled(false);
                    lives--;
                    life_counter.setText(String.valueOf(lives));
                    i = button.length;
                }
                else if (correct_counter == correct_squares.length){
                  i = button.length;
                }
            }
        }
        
        gameOver();

    }

    public void gameOver(){

      if(lives == 0){

        for(int i = 0; i < button.length; i  ){
          button[i].setEnabled(false);
          button[i].setBackground(Color.RED);
        }

        // Create Game Over Label
        failure.setBounds(100,550,250,50);
        failure.setBackground(Color.BLACK);
        failure.setForeground(Color.RED);
        failure.setFont(new Font("Times New Roman",Font.PLAIN,50));
        failure.setBorder(null);
        failure.setEditable(false);
        failure.setText("YOU DIED");
        failure.setVisible(true);

        frame.add(failure);

      }
      else if (correct_counter == correct_squares.length){

        for(int i = 0; i < button.length; i  ){
          button[i].setEnabled(false);
          button[i].setBackground(Color.GREEN);
        }

        success.setBounds(100,550,250,50);
        success.setBackground(Color.WHITE);
        success.setForeground(Color.GREEN);
        success.setFont(new Font("Free Ink",Font.PLAIN,50));
        success.setBorder(null);
        success.setEditable(false);
        success.setText("YOU WON");
        success.setVisible(true);

        frame.add(success);
      }
    }
} 

Now if you can find where I generated the random numbers, you may also find a Collection.shuffle() method being called. Other post similar to what my question was told to do this Fisher–Yates shuffle. However, it doesn't seem to work and I don't understand how that shuffle method helps let alone what it does (other than shuffle numbers).

public class Main {
  public static void main(String[] args){
      new Display();
  }
}

CodePudding user response:

To generate a pseudorandom permutation without keeping all items in a data structure you can build a block cipher of appropriate block size (e.g. 16bits for values in the 0 - (216-1) range) and operate it counter mode. For non-power-of-two ranges you can use rejection sampling.

This is primarily for very long sequences where the memory overhead would be significant. For short sequences shuffling a collection is easier to implement.

CodePudding user response:

I suggest you separate the matrix generator code from the code that displays your matrix.

This small method can generate a matrix with the given size:

private List<Integer>[] generateMatrix(int size) {
    List<Integer>[] matrix = new List[size];
    IntStream.range(0, matrix.length).forEach(i -> {
        matrix[i] = IntStream.rangeClosed(1, size).boxed().collect(Collectors.toList());
        Collections.shuffle(matrix[i]);
    });
    return matrix;
}

It creates an array (your matrix) with the proper size, fills in the matrix items with ordered numbers, and shuffles that sequence.

Then this way you can show your generated matrix:

for (List l : generateMatrix(5)) {
   System.out.println(l);
}

Hope that this can help you.

Result:

[5, 1, 4, 2, 3]
[1, 5, 2, 4, 3]
[4, 3, 2, 1, 5]
[4, 1, 3, 5, 2]
[5, 4, 2, 3, 1]

CodePudding user response:

/**
 * @param count how many random numbers you want to generate
 * @implNote if you don't care about extreme performance or something like that, this implementation just works
 * */
static int[] genRandomNumbers(int count)
{
    var rand = new Random();
    var set = new HashSet<Integer>(); // use hash set to store unique numbers
    while(set.size() < count) // fill the set with random numbers
        set.add(rand.nextInt());

    // move numbers into array
    var ret = new int[count];
    var step = 0;
    for(var number : set)
    {
        ret[step] = number;
        step  ;
    }
    return ret;
}
  •  Tags:  
  • java
  • Related