【问题标题】:Why won't this Java program terminate?为什么这个 Java 程序不会终止?
【发布时间】:2017-07-03 08:43:19
【问题描述】:

所以作为一项任务,我必须编写一个程序来模拟一次发五张牌,直到发皇家同花顺。它这样做了 10 次,然后取处理皇家同花顺的平均次数。我编写了一个运行良好的程序,但没有考虑到一副牌不会有两张牌的事实,因此处理皇家同花顺的次数超过 200,000。我想我修复了它,但现在我没有得到任何输出,因为程序没有终止。我是不是无意中放了一个无限循环?

import java.util.Random;

public class Problem1Version2 {

public static void main(String[] args) {

    // This program simulates the dealing of poker hands and returns the average
    // over 10 rounds of how many hands are dealt until a royal straight flush is received.

    // Initialize flush to false, which indicates that a royal straight flush has not
    // yet been dealt. Set the count variable, i, to 1.
    boolean flush = false;
    int i = 1;

    // Initialize the cards to 0 before any cards are dealt.
    int card1 = 0, card2 = 0, card3 = 0, card4 = 0, card5 = 0;

    // Initialize the total number of tries across all experiment rounds to 0.
    int totalTries = 0;

    // Repeat experiment for 10 seeds.
    for (int j = 0; j < 10; j++) {

        // The round number is the seed.
        Random r = new Random(j);

        // Deal hands of 5 until a royal straight flush is dealt.
        while (flush == false) {

            // To simulate the use of one deck, only one of each card can be dealt in a hand.
            while (card1 == card2 || card1 == card3 || card1 == card4 || card1 == card5 || 
                card2 == card3 || card2 == card4 || card2 == card5 || card3 == card4 
                || card3 == card5 || card4 == card5) {

                // Cards 1-13 are the hearts, 14-26 the spades, 27-39 the clubs, and 40-52 the diamonds.
                card1 = r.nextInt(52) + 1;
                card2 = r.nextInt(52) + 1;
                card3 = r.nextInt(52) + 1;
                card4 = r.nextInt(52) + 1;
                card5 = r.nextInt(52) + 1;
            }

            // Calculate the max and min of the cards.
            int max = Math.max(card1, Math.max(card2, Math.max(card3, Math.max(card4, card5))));
            int min = Math.min(card1, Math.min(card2, Math.min(card3, Math.min(card4, card5))));

            // Check if the hand dealt is a royal straight flush by confirming that 
            // they span 5 consecutive numbers (this is true if the difference between
            // the max and min is 4 since they are all different), and that they all come 
            // from the same suit (1-13, 14-26, 27-39, or 40-52).

            if (max - min == 4) {
                if ((1 <= min) && (13 >= max)) {
                    flush = true;
                }
                else if ((14 <= min) && (26 >= max)) {
                    flush = true;
                }       
                else if ((27 <= min) && (39 >= max)) {
                    flush = true;
                }       
                else if ((40 <= min) && (52 >= max)) {
                    flush = true;
                }
                else {
                    i++;    
                }
            }
            else {
                i++;
            }

        }

        // Add count from last round to total number of tries over the 10 rounds.
        totalTries += i;

        // Reset flush to false for the while loop.
        flush = false;
    }

    // Print the average number of required tries.
    System.out.println("The average number of hands it took was " + totalTries / 10.0);
}

}

【问题讨论】:

  • 调试,调试,再调试一次!
  • 我一行一行地走了,一切都按预期进行。我只是从来没有发现它达到皇家同花顺。
  • 考虑使用枚举来表示卡片和List&lt;Card&gt; deck,可以是Collection.shuffle(deck)。这应该会简化您的代码并有助于简化调试。
  • 感谢您的提示。不幸的是,我仅限于过去 3 周在课堂上学到的知识,但我相信这会对你有所帮助!

标签: java loops


【解决方案1】:

您不会在外部 while 循环中更改 card1、card2、card3、card4、card5 的值。基本上第一轮你要把它们设置为所有不同的东西(如你所愿),但在每次后续迭代中,它们不会用新的随机值更新,因为它们已经满足了它们都是不同的条件!

【讨论】:

  • 非常感谢!现在我明白了为什么其他程序也能正常工作 - 我没有那个 while 循环,因为我没有检查卡片是否相同!
  • @jillianjmb 你做了什么来尝试解决 d80 指出的问题?
  • @luk2302 我添加了 card1 = 0;卡2 = 0;卡3 = 0;卡4 = 0;卡5 = 0;刷新后 = 0;
  • @luk2302 如果这是唯一的原因,那真的不会让第 1-9 轮的计数值为 1 吗?它们最初具有刷新值,因此刷新将在第一次通过时设置为 true。
  • 这里的功能可以让您随机获得 5 张牌。用它替换内部的while循环,它应该会让事情变得更容易一些。 public static int [] randomHand() { ArrayList&lt;Integer&gt; allCards = new ArrayList&lt;Integer&gt;(); for (int i=1; i&lt;52; i++) { allCards.add(new Integer(i)); } Collections.shuffle(allCards); int [] hand = new int [5]; for(int i=0; i&lt;5; ++i){ hand[i] = allCards.get(i); } return hand; }
【解决方案2】:

您需要添加以下行

card1 = card2 = card3 = card4 = card5 = 0;

在以下地方:

while (flush == false) {

    // To simulate the use of one deck, only one of each card can be
    // dealt in a hand.
    while (card1 == card2 || card1 == card3 || card1 == card4 || card1 == card5
            || card2 == card3 || card2 == card4 || card2 == card5 || card3 == card4
            || card3 == card5 || card4 == card5) {

        // Cards 1-13 are the hearts, 14-26 the spades, 27-39 the
        // clubs, and 40-52 the diamonds.
        card1 = r.nextInt(52) + 1;
        card2 = r.nextInt(52) + 1;
        card3 = r.nextInt(52) + 1;
        card4 = r.nextInt(52) + 1;
        card5 = r.nextInt(52) + 1;
    }

    // Calculate the max and min of the cards.
    int max = Math.max(card1, Math.max(card2, Math.max(card3, Math.max(card4, card5))));
    int min = Math.min(card1, Math.min(card2, Math.min(card3, Math.min(card4, card5))));

    // Check if the hand dealt is a royal straight flush by
    // confirming that
    // they span 5 consecutive numbers (this is true if the
    // difference between
    // the max and min is 4 since they are all different), and that
    // they all come
    // from the same suit (1-13, 14-26, 27-39, or 40-52).

    if (max - min == 4) {
        if ((1 <= min) && (13 >= max)) {
            flush = true;
        } else if ((14 <= min) && (26 >= max)) {
            flush = true;
        } else if ((27 <= min) && (39 >= max)) {
            flush = true;
        } else if ((40 <= min) && (52 >= max)) {
            flush = true;
        } else {
            i++;
        }
    } else {
        i++;
    }
    card1 = card2 = card3 = card4 = card5;
}

输出:

平均手数为 177968.4

请注意,您目前只检查同花顺,没有皇家同花顺。对于皇家同花顺,你的内在逻辑应该是:

if (max - min == 4) {
    if ((13 == max) || (26 == max) || (39 == max) || (52 == max)) {
        flush = true;
    } else {
        i++;
    }
} else {
    i++;
}

输出

平均手数为 4944953.0

【讨论】:

  • 谢谢!您能否解释为什么在 for 循环中该行再往下一行时它不起作用?
  • @jillianjmb 因为您不想在 for 循环的每次迭代中处理新卡片,而是在内部 while 循环的迭代中处理。只需查看正确缩进的代码并考虑检查值的位置以进行重新计算。
  • 我明白了。我最初认为只有在flush = true时才需要重置卡片,但当然只要发生i++就必须重置它们。再次感谢您。
【解决方案3】:

您必须更改 flush 的值才能中断 while 循环。

【讨论】:

  • 正如 luk2302 在他的回答中提到的,您的代码只是选择了一次卡片,然后就进入了无限循环。你需要指定一些东西来打破循环,就像他写的 card1 = card2 = card3 = card4 = card5;这样每次都可以选择新的卡片。
【解决方案4】:

您的一个根本问题是您的随机数生成器。您是否想知道为什么每次运行您的所有卡时总是得到相同的精确值?这是因为 Random 类是基于您传入的初始种子的“伪随机”类。在您的代码中,您在每次运行时传入 1,导致您的卡片每次都具有相同的精确值。要获得更“随机”的值,请使用 System.currentTimeMillis() 作为初始种子。

【讨论】:

  • 也许他想要一个固定的种子,这样他就可以重现结果 - 无论如何,你的答案并没有接近实际解决 OP 面临的问题。
猜你喜欢
  • 2014-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-28
相关资源
最近更新 更多