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;
}