Коэффициенты игры в кости: симуляция игры в кости - PullRequest
10 голосов
/ 22 февраля 2010

Моему брату через пару недель исполняется 21 год, и мы с родителями отвезем его в Лас-Вегас. 21-го я принес 200 долларов на игру в Вегасе и вернулся домой с 450 долларами, в основном из игры в крэпс. Я планирую снова принести 200 долларов за эту поездку, и перед отъездом я решил провести несколько симуляций игры в кости, чтобы посмотреть, смогу ли я снова удвоить свои деньги.

Я читал из нескольких источников, что дом имеет наименьшее преимущество в крэпс при размещении ставки на пасс с максимальной вероятностью. Насколько я помню, и как выяснил Wizard of Odds , большинство казино на Стрипе имеют 3-4-5 шансов с минимумом в 5 долларов. Принимая это во внимание, вот симуляция сеанса игры в кости (из 100 бросков костей) в PHP:

<?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/>';

}

?>

Что-то не так с моей математикой здесь? Несмотря на то, что на каждой сессии есть пики и спады, эта симуляция чаще всего удваивает деньги, прежде чем разориться. Учитывая, что дом всегда имеет преимущество в кости, даже если это всего лишь доля процента, я озадачен этим результатом.

Ответы [ 3 ]

9 голосов
/ 22 февраля 2010

Я буду осторожен с любым фрагментом кода, написанным, чтобы «доказать», что вы с большей вероятностью удвоите свои деньги в крэпс (или в любой другой азартной игре), прежде чем разориться. Лас-Вегас - это большой город в пустыне Невады, свидетельствующий о двух вещах:

  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
5 голосов
/ 22 февраля 2010

Ну, сразу, я вижу, что у вас есть ошибка в простом 7 или 11 выигрышном случае: вы должны выиграть свою ставку, а не в два раза больше.

Редактировать: Я считаю, что выплата по ставке на шансы соизмерима с реальной вероятностью. Вы в два раза чаще бросаете 7 (теряете свои шансы), чем 10, поэтому вам должны заплатить 2: 1, когда вы выигрываете 4 или 10; и выплачивается только 6: 5, когда вы выигрываете 6 или 8.

4 голосов
/ 22 февраля 2010

Вы не проверяете, достаточно ли у вас осталось в тайнике, чтобы сделать желаемую ставку на шансы. На самом деле, вы вообще не проверяете размер своего тайника. Неудивительно, что эта симуляция сможет побить дом чаще, если вы сможете делать ставки, даже если ваш размер тайника отрицательный.

Кстати, я выполнил 50000 итераций вашей симуляции 100 бросков костей (с моей модификацией максимальной ставки оставшегося тайника) и получил следующее:

побед: 23807

потери: 25465

толчок (вы уходите с 200 $): 728

ср. выигрыши: $ 109,07

...