24 点游戏

作者:Filip Sergot

24 点游戏可以测试一个人的心算能力。

编写一个程序,随机选择并显示四个数字,每个数字从一到九,允许重复。程序应该提示玩家使用这四个数字输入一个等式。程序应该检查并计算表达式。目标是让玩家输入一个计算结果为 24 的表达式。

只允许使用乘法、除法、加法和减法运算符/函数。除法应该使用浮点数或有理数运算等来保留余数。如果使用中缀表达式求值器,则允许使用括号。

不允许从提供的数字中形成多位数。(因此,当给出 1、2、2 和 1 时,答案 12+12 是错误的)。

给出数字的顺序不必保留。

注意

不要求使用特定类型的表达式求值器。例如,RPN 求值器也是可以接受的。

任务不是让程序生成表达式,也不是测试表达式是否可行。

更多

http://rosettacode.org/wiki/24_game#Raku

有什么有趣的?

  • 语法

  • 求值

  • 提示

  • 滚动

  • 强制转换

源代码:24-game.pl

use v6;

use MONKEY-SEE-NO-EVAL;  # we use EVAL to process user input

grammar Exp24 {
    token TOP { ^ <exp> $ }
    token exp { <term> [ <op> <term> ]* }
    token term { '(' <exp> ')' | \d }
    token op { '+' | '-' | '*' | '/' }
}

my @default-digits = roll 4, 1..9;  # to a gamer, that's a "4d9" roll

sub MAIN ($digits = Nil){
    my @digits = $digits.split(/\s+/);
    @digits = @digits.elems == 4 ?? @digits !! @default-digits;
    say "Here are your digits: {@digits}";

    while my $exp = prompt "\n24-Exp? " {
        unless is-valid($exp, @digits) {
            say "Sorry, your expression is not valid!";
            next;
        }

        my $value = EVAL $exp;
        say "$exp = $value";
        if $value == 24 {
            say "You win!";
            last;
        }
        say "Sorry, your expression doesn't evaluate to 24!";
    }
}

sub is-valid($exp, @digits) {
    unless ?Exp24.parse($exp) {
        say "Expression doesn't match rules!";
        return False;
    }

    unless $exp.comb(/\d/).sort.join == @digits.sort.join {
        say "Expression must contain digits {@digits} only!";
        return False;
    }

    return True;
}