骰子赔率:模拟掷骰子游戏Craps

10

我弟弟即将满21岁了,我和父母想带他去拉斯维加斯旅游。在我自己的21岁生日时,我带了200美元去赌场,最终从掷骰子游戏中赚了约450美元。这次旅行我打算再次带上200美元,并在出发前进行一些掷骰子模拟,以查看能否再次翻倍。

我从多个来源了解到,在掷骰子游戏中,当放置一个最大赔率的通过线下注时,庄家优势最小。按照我的记忆,并根据Wizard of Odds的调查,大多数沿着赌场大道的赌场都是3-4-5的赔率,最低下注额为5美元。考虑到这些因素,以下是一个PHP掷骰子游戏(100次掷骰子)的模拟结果:

<?php

$stash = 200;
$bet = 5;

for($i=100; $i--;) {

    $dice1 = mt_rand(1, 6);
    $dice2 = mt_rand(1, 6);
    $total = $dice1 + $dice2;

    if(!$button) {
        if($total===7 || $total===11) {
            $stash += $bet;
        }
        elseif($total===2 || $total===3 || $total===12) {
            $stash -= $bet;
        }
        else {
            $button = $total;
            if($total===4 || $total===10) {
                $odds = $bet*3;
            }
            elseif($total===5 || $total===9) {
                $odds = $bet*4;
            }
            elseif($total===6 || $total===8) {
                $odds = $bet*5;
            }
        }
    }
    else {
        if($total===7) {
            $button = 0;
            $stash -= ($bet + $odds);
        }
        elseif($total===$button) {
            $button = 0;
            $stash += $bet;
            if($total===4 || $total===10) {
                $stash += $odds*2/1;
            }
            elseif($total===5 || $total===9) {
                $stash += $odds*3/2;
            }
            elseif($total===6 || $total===8) {
                $stash += $odds*6/5;
            }
        }
    }

    echo 'Stash: $'.$stash.'<br/>';

}

?>

我的数学有什么问题吗?虽然在每个会话期间都会出现高峰和低谷,但这个模拟更经常在破产之前使其资金翻倍。考虑到在 Craps 游戏中庄家总是占优势,即使只有一小部分的百分比,我对此结果感到困惑。

3个回答

9

如果有任何一段代码试图“证明”在掷骰子(或者任何其他博彩游戏)中你破产之前更容易翻倍,请您小心。内华达州的拉斯维加斯市是一个广阔的沙漠城市,证明了两个事实:

  1. 最终,庄家总是赢的
  2. 人们不擅长数学

没有任何一个赌场会将既不利用第一个规则也不利用第二个规则的游戏放在他们的赌场上。如果你的代码与拉斯维加斯的结果不同,我会把我的钱投注在拉斯维加斯身上。

更新:

这里是我根据您提供的原始代码编写的C++代码。您发布的原始问题是,是否大多数情况下都能使自己在破产之前翻倍。我跟进了我编写的代码,并附上了一些结果。

#include <iostream>

int die_roll()
{
    return std::rand() % 6 + 1;
}

int win_count_g(0);
int loss_count_g(0);

// return true when double our money.
// return false when we can't bet anymore.
bool test_loop(int cash)
{
    static const int bet_k(5);

    int goal(cash * 2);
    int button(0);

    while (true)
    {
        if (cash >= goal)
            return true;
        else if (cash < bet_k)
            return false;

        int roll(die_roll() + die_roll());
        int odds(0); // additional odds bet

        if (button == 0)
        {
            if (roll == 7 || roll == 11)
            {
                ++win_count_g;
                cash += bet_k;
            }
            else if (roll == 2 || roll == 3 || roll == 12)
            {
                ++loss_count_g;
                cash -= bet_k;
            }
            else
            {
                button = roll;

                if (roll == 4 || roll == 10)
                {
                    odds = std::min(cash - bet_k, bet_k * 3);
                }
                else if (roll == 5 || roll == 9)
                {
                    odds = std::min(cash - bet_k, bet_k * 4);
                }
                else // if (roll == 6 || roll == 8)
                {
                    odds = std::min(cash - bet_k, bet_k * 5);
                }
            }
        }
        else
        {
            if (roll == 7)
            {
                ++loss_count_g;
                button = 0;
                cash -= bet_k + odds;
            }
            else if (roll == button)
            {
                ++win_count_g;
                button = 0;
                cash += bet_k;

                if (roll == 4 || roll == 10)
                {
                    cash += odds * 2;
                }
                else if (roll == 5 || roll == 9)
                {
                    cash += odds * 3 / 2;
                }
                else // if (roll == 6 || roll == 8)
                {
                    cash += odds * 6 / 5;
                }
            }
        }
    }
}

void test(int cash)
{
    win_count_g = 0;
    loss_count_g = 0;

    int doubled(0);
    int broke(0);

    for (int i(0); i < 10000; ++i)
        if (test_loop(cash))
            ++doubled;
        else
            ++broke;

    float win_percentage(static_cast<float>(doubled) / (doubled + broke) * 100.0);

    std::cout << "starting cash: $" << cash
              << "; doubled: " << doubled
              << "; broke: " << broke
              << " (" << win_percentage << "% win)"
              << "; loop wins: " << win_count_g
              << "; loop losses: " << loss_count_g
              << std::endl;
}

int main ()
{
    static const int cash_set_k[] =
    {
        5,
        10,
        20,
        50,
        100,
        200,
        400,
        800,
        1000
    };
    static const int cash_set_size_k(sizeof(cash_set_k) / sizeof(cash_set_k[0]));

    std::for_each(&cash_set_k[0], &cash_set_k[cash_set_size_k], &test);

    return 0;
}

结果:

starting cash: $5; doubled: 4944; broke: 5056 (49.44% win); loop wins: 4944; loop losses: 5056
starting cash: $10; doubled: 4862; broke: 5138 (48.62% win); loop wins: 19706; loop losses: 20258
starting cash: $20; doubled: 4755; broke: 5245 (47.55% win); loop wins: 78360; loop losses: 80320
starting cash: $50; doubled: 4345; broke: 5655 (43.45% win); loop wins: 489406; loop losses: 502506
starting cash: $100; doubled: 3553; broke: 6447 (35.53% win); loop wins: 1914393; loop losses: 1972273
starting cash: $200; doubled: 2468; broke: 7532 (24.68% win); loop wins: 7172464; loop losses: 7375024
starting cash: $400; doubled: 861; broke: 9139 (8.61% win); loop wins: 22615369; loop losses: 23277609
starting cash: $800; doubled: 112; broke: 9888 (1.12% win); loop wins: 54556881; loop losses: 56121041
starting cash: $1000; doubled: 31; broke: 9969 (0.31% win); loop wins: 69308617; loop losses: 71296217

2
你的代码看起来和我想到的差不多,只是在计算赔率时需要考虑初始赌注。例如:odds = std::min( cash - bet_k, bet_k * 3); 而不是 odds = std::min(cash, bet_k * 3); - ghoppe
1
谢谢,已更新;有趣的是,我没有看到那个更改对结果产生任何影响。这将成为从维加斯拉动的有趣内容:按赔率下注,维加斯会给你一个最低下注额度! - fbrereto

5

首先,我看到在简单的7或11赢的情况下,你犯了一个错误:你应该赢得你的赌注,而不是两倍的赌注。

编辑:我认为赔率赌注的支付与实际概率相称。你掷出7(输掉你的赔率)的可能性是掷出10的两倍,所以当你在4或10上获胜时,你应该获得2:1的赔付;而只有在6或8上获胜时才获得6:5的赔付。


1
我修改了源代码 - 现在看起来怎么样?赔率的获胜需不需要调整,或者模拟是否正确? - Kevin
1
@Kevin:我认为你现在已经完全正确地理解了crap的所有支付方式。然而,其他人给出的答案包含了改进和扩展模拟的方法。 - John Y

4
您没有检查自己的赌注储备是否足够以下注所需的赔率。事实上,您根本没有检查自己的储备规模。如果您能够在储备规模为负数的情况下下注,那么这个模拟将更容易击败庄家,这一点并不令人意外。
顺便说一下,我运行了50000次您的100次掷骰子模拟(我的修改是剩余赌注的最大下注额),得出以下结果:
胜利次数:23807
失败次数:25465
平局(您带着200美元离开):728
平均赢钱数:109.07美元

2
我刚意识到的另一件事是,你的模拟投掷骰子100次后就离开了,而不考虑桌子上还剩多少钱,因此平均赢利和获胜次数应该会稍微低一些。 - ghoppe
1
所以我运行了这个修改后的脚本(50,000次迭代),并额外加上了“不留下任何赌资”的条件,进行了十次测试,得出以下胜率:48.6%,48.1%,48.2%,48.0%,47.7%,48.4%,48.0%,48.2%,48.2%,47.7%。简而言之:不,你无法击败拉斯维加斯。 :) - ghoppe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接