【问题标题】:Issue with hold function in Yatzy botYatzy 机器人中的保持功能问题
【发布时间】:2012-10-04 07:54:00
【问题描述】:

在开发 Yatzy 机器人时,我遇到了“保持”功能。其他一切正常,但此功能的逻辑在某些情况下似乎失败了。基本上,这个想法是保留所有给定的数字,然后掷出与给定数字不匹配的骰子。

[00:04] @Dessimat0r: .roll
[00:04] YatzyBot: #1: dice: [2, 5, 3, 4, 1], scores: [ 1 2 3 4 5 6 1P 2P 3K 4K SS LS H Y C ]
[00:04] @Dessimat0r: .hold 2 1
[00:04] YatzyBot: #2: dice: [2, 5, 3, 4, 1], scores: [ 1 2 3 4 5 6 1P 2P 3K 4K SS LS H Y C ]
[00:04] @Dessimat0r: .hold 2 1
[00:04] YatzyBot: #3: dice: [2, 5, 3, 4, 1], scores: [ 1 2 3 4 5 6 1P 2P 3K 4K SS LS H Y C ]

可以看出,所有数字都被保留,而不仅仅是选定的少数数字(这不是掷骰子的巧合)。代码如下:

} else if (event.getMessage().startsWith(".hold")) {
    if (y.getTurn() != null && event.getUser().getNick().equals(y.getTurn().getPlayer().getName())) {
        String[] tokens = event.getMessage().split(" ");
        if (tokens[0].equals(".hold")) {
            boolean failed = false;
            try {
                if (tokens.length == 1) {
                    bot.sendMessage(CHANNEL, "Must choose some dice to hold!");
                    return;
                }
                ArrayList<Integer> dice = new ArrayList<Integer>();
                ArrayList<Integer> holdnums = new ArrayList<Integer>();
                ArrayList<Integer> rollnums = new ArrayList<Integer>();

                for (Die d : y.getDice()) {
                    dice.add(d.getFaceValue());
                }

                // parse other numbers
                for (int i = 1; i < tokens.length; i++) {
                    int num = Integer.parseInt(tokens[i]);
                    holdnums.add(num);
                }
                ListIterator<Integer> diter = dice.listIterator();
                dice: while (diter.hasNext()) {
                    Integer d = diter.next();

                    if (holdnums.isEmpty()) {
                        rollnums.add(d);
                        diter.remove();
                        continue;
                    }
                    ListIterator<Integer> iter = holdnums.listIterator();
                    while (iter.hasNext()) {
                        int holdnum = iter.next().intValue();
                        if (holdnum == d) {
                            iter.remove();
                            diter.remove();
                            continue dice;
                        }
                    }

                }

                if (!holdnums.isEmpty()) {
                    bot.sendMessage(CHANNEL, "Hold nums not found: " + holdnums);
                    failed = true;
                }

                if (!failed) {
                    y.getTurn().rollNumbers(convertIntegers(rollnums));

                    Map<Scoring, Integer> scores = y.getRollScores();

                    Map<Scoring, Integer> unchosen = new EnumMap<Scoring, Integer>(Scoring.class);
                    Map<Scoring, Integer> chosen = new EnumMap<Scoring, Integer>(Scoring.class);

                    for (Entry<Scoring, Integer> entry : scores.entrySet()) {
                        if (y.getTurn().getPlayer().getTotals().get(entry.getKey()) == -1) {
                            unchosen.put(entry.getKey(), entry.getValue());
                        } else {
                            chosen.put(entry.getKey(), entry.getValue());
                        }
                    }
                    bot.sendMessage(CHANNEL, "#" + y.getTurn().getRolls() + ": dice: " + y.getDiceStr() + ", scores: " + getDiceStr(y.getTurn().getPlayer().getTotals(), scores));
                }
            } catch (TurnException e1) {
                bot.sendMessage(CHANNEL, e1.getMessage());
            } catch (RollException e2) {
                bot.sendMessage(CHANNEL, e2.getMessage());
            } catch (YahtzyException e3) {
                bot.sendMessage(CHANNEL, e3.getMessage());
            } catch (NumberFormatException e4) {
                bot.sendMessage(CHANNEL, e4.getMessage());
            }
        }
    }
}

编辑:全部修复。更新代码:

} else if (event.getMessage().startsWith(".hold")) {
    if (y.getTurn() != null && event.getUser().getNick().equals(y.getTurn().getPlayer().getName())) {
        String[] tokens = event.getMessage().split(" ");
        if (tokens[0].equals(".hold")) {
            boolean failed = false;
            try {
                if (tokens.length == 1) {
                    bot.sendMessage(channel, "Must choose some dice to hold!");
                    return;
                }
                ArrayList<Integer> holdnums = new ArrayList<Integer>();
                ArrayList<Integer> rollnums = new ArrayList<Integer>();

                // parse other numbers
                for (int i = 1; i < tokens.length; i++) {
                    int num = Integer.parseInt(tokens[i]);
                    holdnums.add(num);
                }
                for (int i = 0; i < y.getDice().length; i++) {
                    int d = y.getDice()[i].getFaceValue();

                    if (holdnums.isEmpty()) {
                        rollnums.add(d);
                        continue;
                    }

                    ListIterator<Integer> iter = holdnums.listIterator();

                    boolean found = false;
                    while (iter.hasNext()) {
                        int holdnum = iter.next().intValue();
                        if (holdnum == d) {
                            iter.remove();
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        rollnums.add(d);
                    }
                }

                if (!holdnums.isEmpty()) {
                    bot.sendMessage(channel, "Hold nums not found: " + holdnums);
                    failed = true;
                }

                if (!failed) {
                    boolean[] rolled = y.getTurn().rollNumbers(convertIntegers(rollnums));

                    Map<Scoring, Integer> scores = y.getRollScores();

                    Map<Scoring, Integer> unchosen = new EnumMap<Scoring, Integer>(Scoring.class);
                    Map<Scoring, Integer> chosen = new EnumMap<Scoring, Integer>(Scoring.class);

                    for (Entry<Scoring, Integer> entry : scores.entrySet()) {
                        if (y.getTurn().getPlayer().getTotals().get(entry.getKey()) == -1) {
                            unchosen.put(entry.getKey(), entry.getValue());
                        } else {
                            chosen.put(entry.getKey(), entry.getValue());
                        }
                    }
                    bot.sendMessage(channel, "#" + y.getTurn().getRolls() + ": dice: " + diceToString(rolled) + ", scores: " + getDiceStr(y.getTurn().getPlayer().getTotals(), scores));
                }
            } catch (TurnException e1) {
                bot.sendMessage(channel, e1.getMessage());
            } catch (RollException e2) {
                bot.sendMessage(channel, e2.getMessage());
            } catch (YahtzyException e3) {
                bot.sendMessage(channel, e3.getMessage());
            } catch (NumberFormatException e4) {
                bot.sendMessage(channel, e4.getMessage());
            }
        }
    }
}

【问题讨论】:

    标签: java algorithm irc dice


    【解决方案1】:

    一切看起来都不错,但是对holdnum 的检查不在正确的位置:

        if (absent) {
          bot.sendMessage(CHANNEL, "Hold num not found: " + holdnum);
          failed = true;
          break dice;
        }
    

    现在说给定的保持号是对还是错还为时过早,所以最好删除这段代码。要检查 holdnums 的有效性,您可以在“骰子”循环完成后查看此列表:如果 holdnums 不为空,则它包含一些未找到的项目。


    更新问题:

    我看到一个问题:rollnums.add(d) 不应该在嵌套的while 中调用以避免多次添加相同的值。相反,它应该在此循环完成后调用一次。

    【讨论】:

    • 谢谢。这不完全是问题,但无论如何它都有帮助。骰子再次被迭代,所以我把它们放到另一个列表中,一旦处理就删除。这似乎奏效了。我将更新上面的代码以反映修复。如果您有任何优化建议,欢迎您:)
    • @ChrisDennett:我已经更新了答案。至于优化,据我所知,Yatzy 中只有 5 个骰子,所以优化这部分代码不太可能产生任何效果。您可以对 diceholdnums 列表进行排序,然后在一个循环中迭代两者,推进具有较小值的迭代器。
    • 我在测试时发现了一些其他问题,如果可能,请更新答案:D
    • @ChrisDennett:问题仍然存在于rollnums.add(d)。您已将其从嵌套循环中删除,但没有按照我的建议将其添加到循环之后。
    • 我看不出这怎么可能,因为rollnums.add(d) 正在从循环中获取骰子面值? dice: while (diter.hasNext()) { Integer d = diter.next(); ... }。请澄清:D
    猜你喜欢
    • 2020-07-21
    • 2016-12-05
    • 2019-09-11
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    • 2021-01-17
    • 1970-01-01
    • 2020-08-09
    相关资源
    最近更新 更多