如何以随机顺序获取数组中的元素,且不重复读取相同的元素?

huangapple go评论59阅读模式
英文:

How to get elements of an array in a random order without reading the same element again?

问题

import java.util.Scanner;

public class MyClass {
    public static void main(String args[]) {
        Scanner input = new Scanner(System.in);

        System.out.println("欢迎来到牛津湾交通公司的新子弹头列车。");

        System.out.println("我们的新子弹头列车有20个座位,其中5个俱乐部座位和15个经济舱座位。");

        System.out.println("您想要预订吗?如果是,请输入true;如果不是,请输入false。");

        boolean wantToReserve = input.nextBoolean();

        while (!wantToReserve) {
            System.out.println("您输入了false。您想要预订吗?");

            wantToReserve = input.nextBoolean();

            if (!wantToReserve) {
                System.out.println("您可以关闭程序。");
            }
        }
        
        System.out.println("您想要预订多少个座位?");

        System.out.println("请注意我们只有20个座位,其中5个俱乐部座位和15个经济舱座位。");

        System.out.println("如果您想要预订超过20个座位,请多次执行程序。");

        int numberOfSeats = input.nextInt();

        while (numberOfSeats > 20 || numberOfSeats <= 0) {
            System.out.println("您输入了大于20或小于等于0的值。");

            System.out.println("您必须修改您想要预订的座位数,因为我们只有20个座位。");

            System.out.println("如果您想要预订超过20个座位,请多次执行程序。");

            numberOfSeats = input.nextInt();
        }

        boolean clubSeating[] = { false, false, false, false, false };

        boolean economySeating[] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false };

        System.out.println("您想要预订多少个俱乐部座位?");

        int numberOfClub = input.nextInt();

        System.out.println("您想要预订多少个经济舱座位?");

        int numberOfEconomy = input.nextInt();

        while (numberOfClub + numberOfEconomy != numberOfSeats || numberOfEconomy > 15 || numberOfClub > 5 || numberOfEconomy < 0 && numberOfClub < 0) {
            System.out.println("之前的输入中至少有一个不被允许。请注意我们有5个俱乐部座位和15个经济舱座位。请重新输入。");

            System.out.println("您想要预订多少个俱乐部座位?");

            numberOfClub = input.nextInt();

            System.out.println("您想要预订多少个经济舱座位?");

            numberOfEconomy = input.nextInt();
        }

        for (int j = 0; j < numberOfClub; j++) {

            int seatForClub1 = (int) (Math.random() * (numberOfClub));
            
            clubSeating[seatForClub1] = true;
            
            int seatForClub = (int) (Math.random() * (numberOfClub));

            if (!clubSeating[seatForClub]) {
                clubSeating[seatForClub] = true;
                System.out.println("登机牌:座位 " + seatForClub);
            }

            if (clubSeating[seatForClub]) {
                seatForClub = (int) (Math.random() * (numberOfClub));
                System.out.println("登机牌:座位 " + seatForClub);
            }
        }
    }
}
英文:

I'm given an assignment where the user enters the number of seats they would like to book for a trip. After, I set an array of the seats all to false, as they are empty. Then depending on the number of seats the user wants to reserve, the program will output a boarding pass with the seat number. And the output for the boarding passes cannot have the same seat numbers, as they are either empty or not.

My code is working great except for the little snippet you see below. As you see I set all the seats for the club and economy classes to false. Then I prompt the user to enter the seats they would like to reserve. The issue I'm having is at the bottom of the code, since there are 5 club seats, if I wanted to reserve 5 club seats, it should output the 5 boarding passes with the distinct seat numbers. But for some reason it doesn't output all 5 seats, for example, if I enter that I would like 5 seats, and that they are all club seats, my program outputs:

Club Pass: Seat 1
Club Pass: Seat 1
Club Pass: Seat 3
Club Pass: Seat 2
Club Pass: Seat 1

I'm new to arrays and I know that subscripts begins at 0, I was thinking that maybe I needed to subtract 1 from the Math.random line below. I understand the issue is most likely regarding the final snippet of the code and the Math.Random line but I'm not sure what is exactly causing this error.**

import java.util.Scanner;
public class MyClass
{
public static void main(String args[])
{
Scanner input = new Scanner (System.in);
System.out.println (&quot;Welcome to the new bullet train from Beefalo Bay Transportation Company.&quot;);
System.out.println (&quot;Our new bullet train has 20 seats, 5 club, and 15 economy seats.&quot;);
System.out.println (&quot;Would you like to make a booking? If so enter true, if not enter false.&quot;);
boolean wantToReserve = input.nextBoolean();
while (wantToReserve == false)
{
System.out.println (&quot;You entered false. Would you like to make a reservation?&quot;);
wantToReserve = input.nextBoolean();
if (wantToReserve == false)
{
System.out.println (&quot;You may close the program.&quot;);
}
}
System.out.println (&quot;How many seats would you like to book?&quot;);
System.out.println (&quot;Please note we only have 20 seats, 5 club and 15 economy.&quot;);
System.out.println (&quot;If you would like more than 20 seats, please execute the program multiple times.&quot;);
int numberOfSeats = input.nextInt();
while (numberOfSeats &gt; 20 | numberOfSeats &lt;= 0){
System.out.println (&quot;You entered a value greater than 20 or less than 0.&quot;);
System.out.println (&quot;You must modify the seats you would like to book, as we only have 20 seats.&quot;);
System.out.println (&quot;If you would like more than 20 seats, please execute the program multiple times.&quot;);
numberOfSeats = input.nextInt();
}
boolean clubSeating [] = {false, false, false, false, false};
boolean economySeating [] = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false};
System.out.println (&quot;How many club seats would you like?&quot;);
int numberOfClub = input.nextInt();
System.out.println (&quot;How many economy seats would you like?&quot;);
int numberOfEconomy = input.nextInt();
while (numberOfClub + numberOfEconomy != numberOfSeats || numberOfEconomy &gt; 15 || numberOfClub &gt; 5 || numberOfEconomy &lt; 0 &amp;&amp; numberOfClub &lt; 0 ){
System.out.println (&quot;At least one of the previous inputs were not allowed. Note that we have 5 club and 15 economy seats. Please re-enter.&quot;);
System.out.println (&quot;How many club seats would you like?&quot;);
numberOfClub = input.nextInt();
System.out.println (&quot;How many economy seats would you like?&quot;);
numberOfEconomy = input.nextInt();
}
for (int j = 0; j &lt; numberOfClub ; j++){
int seatForClub1 = (int) (Math.random()*(numberOfClub));
clubSeating [seatForClub1] = true;
int seatForClub = (int) (Math.random()*(numberOfClub));
if (clubSeating [seatForClub] == false){
clubSeating [seatForClub] = true;                       
System.out.println (&quot;Boarding Pass: Seat  &quot; + seatForClub);
}
if (clubSeating [seatForClub] == true){
seatForClub = (int) (Math.random()*(numberOfClub)); 
System.out.println (&quot;Boarding Pass: Seat  &quot; + seatForClub);
}
}
}        
}

答案1

得分: 0

你关于问题与Math.Random()的观点是正确的。
这只是返回一个随机数,但在四舍五入时可能会重复。因此,当您将其乘以座位数时,很可能会再次得到相同的值。

例如:一次调用Math.Random()可能会得到0.8,另一次可能会得到0.71。将这两者都乘以3(俱乐部座位数),结果将为2,因为强制转换为整数时会丢弃小数部分。

因此,如果您循环3次,而且不幸的是都得到了2,那么您只会预订一个座位。

一个解决方法是仅在预订座位时递增循环计数器。

for (int j = 0; j < numberOfClub; ) {
    int seatForClub = (int) (Math.random() * (numberOfClub));

    if (clubSeating[seatForClub] == false) {
        clubSeating[seatForClub] = true;
        System.out.println("Boarding Pass: Seat  " + seatForClub);
        j++;
    }
}

但是,获得相同座位号码的缺点仍然存在(如果Math.Random()给出的值在与俱乐部座位数相乘时不断返回2),因此您可能会循环多次,直到生成所有值为止。

存在一个边界情况。如果没有剩余的空座位,那么循环将无限运行。因此,我们还需要检查剩余的座位数。如果总共有10个俱乐部座位,并且用户请求12个座位。那么一旦这10个座位的数组全部变为true(即所有座位都被占用),循环仍然会继续运行,试图达到12个的数量(这是所请求的座位数)。一旦我们增加了对剩余座位数的检查,就不再需要担心无限循环。因此,基本上,如果在到达此代码段时所请求的座位数大于可用/剩余座位数,那么代码将失败。

int numberOfClubSeatsRemaining = totalNumberOfClubSeats; // 初始化为总座位数 

for (int j = 0; numberOfClubSeatsRemaining > 0 && j < numberOfClub; ) {
    int seatForClub = (int) (Math.random() * (numberOfClub));

    if (clubSeating[seatForClub] == false) {
        clubSeating[seatForClub] = true;
        System.out.println("Boarding Pass: Seat  " + seatForClub);
        j++;
        numberOfClubSeatsRemaining--;
    }
}

在Java中有更好的方法来获得随机值。您可以参考这个链接:https://stackoverflow.com/questions/363681/how-do-i-generate-random-integers-within-a-specific-range-in-java

您还可以使用Collections.shuffle()生成随机列表,并在其中迭代前n个元素(其中n将是此情况下的俱乐部座位数)。但是,如果这个特定练习的目标是让初学者理解算法,并在没有任何内置函数/集合框架的情况下完成,那么这种方法对您来说可能不合适。

英文:

You are right about the issue being about Math.Random().
This just returns a random number but it may be repeating when rounded off. So is highly likely that when you multiply this with the number of seats you may get the same value again.

For ex: One invocation of Math.Random() may result in 0.8 and another might result on 0.71. Both of these when multiplied by 3 ( number of club seats ) would return 2 Because when you typecast to an int, the decimal part is dropped.

So if you loop 3 times, and you are unfortunate enough to get all 2s, then you would have only booked one seat.

One workaround is to increment the loop counter only when the seat is booked.

       for (int j = 0; j &lt; numberOfClub; ) {
int seatForClub = (int) (Math.random() * (numberOfClub));
if (clubSeating[seatForClub] == false) {
clubSeating[seatForClub] = true;
System.out.println(&quot;Boarding Pass: Seat  &quot; + seatForClub);
j++;
}
} 

But the disadvantage of getting the same seat number remains ( if Math.Random() gives values that keep returning 2 when multiplied with number of club seats ) so you may end looping as many times as it takes to generate all the values.

There is an edge case. If there are no empty seats remaining then the loop would run indefinitely. So we need to check for the number of seats remaining as well. If there are 10 total club seats, and the user requests for 12. Then once the array of 10 seats all become true ( so all seats are occupied ), the loop would have still been running trying to reach the count of 12 ( this is the number of seats requested ). Once we add a check for number of seats remaining, we no longer have to worry about the indefinite loop. So basically, if the number of requested seats is greater than the number of available / remaining seats when we reach this code snippet then the code would fail.

        int numberOfClubSeatsRemaining = totalNumberOfClubSeats; // initialize to total number of seats 
for (int j = 0; numberOfClubSeatsRemaining &gt; 0 &amp;&amp; j &lt; numberOfClub; ) {
int seatForClub = (int) (Math.random() * (numberOfClub));
if (clubSeating[seatForClub] == false) {
clubSeating[seatForClub] = true;
System.out.println(&quot;Boarding Pass: Seat  &quot; + seatForClub);
j++;
numberOfClubSeatsRemaining--;
}
}

There are better ways to get a random value in Java. You can refer to this https://stackoverflow.com/questions/363681/how-do-i-generate-random-integers-within-a-specific-range-in-java

You can also generate a random list using Collections.shuffle() and iterate over the first n elements on this ( where n would be the number of club seats in this case ). But if the goal of this particular exercise is for beginners to understand the algorithm and to do it without any built in functions / Collections framework, then this approach wouldn't be right for you.

huangapple
  • 本文由 发表于 2020年9月5日 04:56:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/63747941.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定