简体   繁体   中英

How to display randomly selected strings from an array in java without repetitions

I'm trying to create a Bingo game using NetBeans IDE 6.9.1 (I'm a noob at coding). Right now I'm stuck at trying to create the bingo card. For the 5x5 card's boxes I used jButtons. I can't randomize the "B" bingo balls down the "B" column. I have a code that "works" for randomizing which "B" ball goes in which "B" jButton, but my method will not work for the jLabel I'm using to output the randomly drawn bingo ball. Here's my "random B-ball code:"

String[] Bball1 = {"B5", "B6", "B11"};
String Brandom1 = (Bball1[new Random().nextInt(Bball1.length)]);
String[] Bball2 = {"B1", "B8", "B15"};
String Brandom2 = (Bball2[new Random().nextInt(Bball2.length)]);
String[] Bball3 = {"B3", "B10", "B13"};
String Brandom3 = (Bball3[new Random().nextInt(Bball3.length)]);
String[] Bball4 = {"B2", "B9", "B14"};
String Brandom4 = (Bball4[new Random().nextInt(Bball4.length)]);
String[] Bball5 = {"B4", "B7", "B12"};
String Brandom5 = (Bball5[new Random().nextInt(Bball5.length)]);

Here is the code for when the user clicks the submit button when they pick a bingo pattern and the card would be generated (incomplete):

    btnSubmit.setEnabled(false);
    cboPattern.setEnabled(false);
    btn1B.setText(Brandom1);
    btn2B.setText(Brandom2);
    btn3B.setText(Brandom3);
    btn4B.setText(Brandom4);
    btn5B.setText(Brandom5);

Yes, this is repetitive, and not overly random, but I did some research on Arrays, as I have not learned them in my Computer Science class, and got this:

    public static void main(String[] Bballs) {
    String[] Bball;
    Bball = new String[2];
    Bball[0] = "B1";
    Bball[1] = "B2";
    Bball[2] = "B3";

    int num = (int) (Math.random() * 2);
    System.out.println(Bball[num]);
}

This is just a test code, and as you can see I could still get B1 more than one time which isn't what I want for the bingo card and the randomly picked bingo balls (which I haven't started yet). Plus, whenever I run my program it doesn't print out the last line. I need this done by the end of Wednesday :/ (It's a late ISU project, and no I did not start it late). Thanks for your time.

I hope this is not too far ahead of where you are, but the easiest way to pull M elements from a bag of N items (balls) without repetition, is to simply add all the elements to a List and shuffle() it, then take the first M values using subList() .

Here is a generic method for doing that:

private static List<String> draw(String ballPrefix, int noOfBalls, int noToDraw) {
    List<String> balls = new ArrayList<>();
    for (int ballNo = 1; ballNo <= noOfBalls; ballNo++)
        balls.add(ballPrefix + ballNo);
    Collections.shuffle(balls);
    return balls.subList(0, noToDraw);
}

Test

System.out.println(draw("B", 15, 5));

Sample output

[B9, B5, B3, B2, B15]

UPDATE

Ok, in the interest of teaching a bit, a List is somewhat similar to an array, but much more powerful. It contains a sequence of values, like an array, and the values are indexed starting at 0 , also like an array.

Unlike an array, where you get the length using arr.length , for a list you call list.size() . Instead of retrieving a value using arr[2] , you call list.get(2) .

Instead of assigning a value using arr[2] = 7 , you can call list.set(2, 7) but that is unusual. This is because, unlike an array that is allocated using new String[5] , which allocates a fixed-size array of 5 values, a list is allocated using new ArrayList() , and it will grow in size as needed when calling add() , like the method above does.

After that super short introduction, here is how you use the method above:

List<String> balls = draw("B", 15, 5);
btn1B.setText(balls.get(0));
btn2B.setText(balls.get(1));
btn3B.setText(balls.get(2));
btn4B.setText(balls.get(3));
btn5B.setText(balls.get(4));

If you want to get a random number, you can use Math.random() or Random , which don't matter your problem. Your problem is what you want to show. One way is get random from a special Max num, and the Max is not changed. I guess this is what you now use. Another way, when you get a random from special Max num ,and then remove the random, ensure every number(from Min to Max) will be used. Java has a Collections.java tool, which has shuffle function, it can make the whole list random. Below is example test code for you. If you want every num(from Min to Max) come out with equal rate, you can use averageRandom_1 or averageRandom_2 .

 import java.util.*;
public class Main {

    public static void main(String[] args) {
        System.out.println("Hello World!");
        String[] src = new String[]{"B1", "B2", "B3", "B4", "B5"};
        List<String> srcList = Arrays.asList(src);

   /*     for(int i = 0; i < srcList.size(); i++){
            System.out.print(" random = " + getRandom_2(0, srcList.size()));
        }*/

        averageRandom_2(srcList);
    }

 /**
 * @param min
 * @param max
 * @return [min, max), note it can't return max
 */
public static int getRandom_1(int min, int max){
    return (int)(min + Math.random()*(max-min));
}

/**
 * @param min
 * @param max
 * @return [min, max), note it can't return max
 */
public static int getRandom_2(int min, int max){
    Random random = new Random();
    return random.nextInt(max-min) + min;
}

    public static void averageRandom_1(List<String> data){
        List<String> dataCopy = new ArrayList<>();
        dataCopy.addAll(data);
        Collections.shuffle(dataCopy);
        for(String item : dataCopy){
            System.out.println("--" + item + "--");
        }
    }

    public static void averageRandom_2(List<String> data){
        List<String> dataCopy = new ArrayList<String>(data);
        while(dataCopy.size() > 0) {
            int random = getRandom_2(0, dataCopy.size());
            System.out.println("random = " + random + "--" + dataCopy.get(random) + "--");
            dataCopy.remove(random);
        }
    }
}

Please remember random.nextInt(value) return 0 to (value - 1). Hope to help you.

You have to know that Math.random() gives a number within 0 and 1.

It never gives 1.

0 < Math.random() < 1
0 < Math.random() * 2 < 2
0 <= (int)(Math.random() * 2) <= 1

Notice the flooring logic, it makes you never get index 2.

Don't try to use Math.random you wont get an even distribution. Using List and Random.nextInt(int) you get a fairly simple solution like so.

Random rand = new Random();
List<String> inRandomOrder = new ArrayList<>();
List<String> items = new ArrayList<>();
items.add("blah1");
items.add("blah2");
items.add("blah3");

while (!items.isEmpty()) {
    String removed = items.remove(rand.nextInt(items.size()));
    inRandomOrder.add(removed)
}

Then you have a list of your items in some random order. It's not really random is only pseudo random if you needed truly random you would have to use SecureRandom. I am sure this is probably an easier way to do this functionally with Java 8 streams, but I haven't had a ton of time to mess with them so sorry if the answer is old fashioned.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM