Yatzy bot中的hold函数问题

时间:2012-10-13 21:11:23

标签: java algorithm irc dice

在开发Yatzy机器人时,我坚持使用'hold'功能。其他一切都有效,但在某些情况下,这个功能的逻辑似乎失败了。基本上,这个想法是保留给定的所有数字,然后滚动与给定数字不匹配的骰子。

[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());
            }
        }
    }
}

1 个答案:

答案 0 :(得分:2)

一切看起来都不错,但对holdnum的检查不在正确的地方:

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

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


有关更新的问题:

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