Craps 賭博遊戲

December 5, 2021

Craps 是個簡單的賭博遊戲,玩家擲兩個骰子,點數為 1 到 6,如果第一次點數和為 7 或 11,玩家勝,若點數和為 2、3 或 12,玩家輸,如果和為其他點數,記錄第一次的點數和,然後繼續擲骰,直至點數和等於第一次擲出的點數和,玩家勝,若在這之前擲出了點數和為 7,玩家輸。

解法思路

規則看來有些複雜,這是一個遊戲嗎?不!這是兩個遊戲,第一個遊戲規則是事先設定好輸贏點數,第二個遊戲規則是指定贏的點數(由玩家擲出),分別對這兩個遊戲的規則撰寫函式,就可避免看似複雜的條件判斷。

不過就流程來說,主要就是擲骰、使用規則判斷、顯示輸贏或繼續。規則判斷是一種策略,因此可使用回呼函式或物件傳入,遊戲流程就可當作可重用樣版了。

程式實作

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LOST 0
#define WON 1
#define CONTINUE 2

int dice();
int initialRoll(int);
int reRoll(int, int);

int main(void) {
    srand(time(0));
    
    int firstPoint = dice();
    printf("玩家點數:[%d]\n", firstPoint);
    
    int status = initialRoll(firstPoint);
    while(status == CONTINUE) {
        int point = dice();
        printf("玩家點數:%d\n", point);
        status = reRoll(firstPoint, point);
    } 

    puts(status == WON ? "玩家勝" : "玩家輸");

    return 0;
} 

int dice() { 
    return (rand() % 6) + (rand() % 6) + 2;
}

int initialRoll(int firstPoint) {
    switch(firstPoint) {
       case 7: case 11:         return WON;
       case 2: case 3: case 12: return LOST;
       default:                 return CONTINUE;
    }
}

int reRoll(int firstPoint, int point) {
    return firstPoint == point ? WON : (7 == point ? LOST : CONTINUE);
}
import static java.lang.Math.random;
import static java.lang.System.out;

enum Status { WON, LOST, CONTINUE }

public class Craps {
    public static int dice() { 
        return (int)(random() * 6) + (int)(random() * 6) + 2;
    }

    public static Status initialRoll(int firstPoint) {
        switch(firstPoint) {
            case 7: case 11:         return Status.WON;
            case 2: case 3: case 12: return Status.LOST;
            default:                 return Status.CONTINUE;
        }
    }

    public static Status reRoll(int firstPoint, int point) {
        return firstPoint == point ? Status.WON :
                   (7 == point ? Status.LOST : Status.CONTINUE);
    }
    
    public static void main(String[] args) {
        int firstPoint = dice();
        out.printf("玩家點數:[%d]%n", firstPoint);

        Status status = initialRoll(firstPoint);
 
        while(status == Status.CONTINUE) {
            int point = dice();
            out.printf("玩家點數:%d%n", point);
            status = reRoll(firstPoint, point);
        } 

        out.println(status == Status.WON ? "玩家勝" : "玩家輸");
    }
}
from random import randint

class Status:
    LOST = 0
    WON = 1
    CONTINUE = 2
    
def initialRoll(firstPoint):
    return Status.WON if firstPoint in [7, 11] else \
    (Status.LOST if firstPoint in [2, 3, 12] else Status.CONTINUE)

def reRoll(firstPoint, point):
    return Status.WON if firstPoint == point else \
    (Status.LOST if 7 == point else Status.CONTINUE)

def dice():
    return randint(1, 6) + randint(1, 6)

firstPoint = dice()
print("玩家點數:[%d]" % firstPoint)
status = initialRoll(firstPoint)

while status == Status.CONTINUE:
    point = dice()
    print("玩家點數:%d" % point)
    status = reRoll(firstPoint, point)

print("玩家勝" if status == Status.WON else "玩家輸")
import scala.util.Random

object Status extends Enumeration {
    val LOST, WON, CONTINUE = Value
}
    
def dice = {
    val r = new Random
    (r.nextDouble * 6).toInt + (r.nextDouble * 6).toInt + 2
}
    
def initialRoll(firstPoint: Int) = firstPoint match {
    case 7 | 11     => Status.WON
    case 2 | 3 | 12 => Status.LOST
    case _          => Status.CONTINUE
}

def reRoll(firstPoint: Int, point: Int) = {
    if(firstPoint == point) Status.WON else
    (if(7 == point) Status.LOST else Status.CONTINUE)
}

def doWhile(status: Status.Value) {
    if(status == Status.CONTINUE) {
        val point = dice
        printf("玩家點數:%d%n", point)
        doWhile(reRoll(firstPoint, point))
    }
}

val firstPoint = dice
printf("玩家點數:[%d]%n", firstPoint)
var status = initialRoll(firstPoint)

while(status == Status.CONTINUE) {
    val point = dice
    printf("玩家點數:%d%n", point)
    status = reRoll(firstPoint, point)
}

println(if(status == Status.WON) "玩家勝" else "玩家輸")
# encoding: UTF-8
class Status
    LOST = 0
    WON = 1
    CONTINUE = 2
end
    
def initialRoll(firstPoint)
    case firstPoint
        when 7, 11;     Status::WON
        when 2, 3, 12;  Status::LOST
        else;           Status::CONTINUE
    end
end

def reRoll(firstPoint, point)
    firstPoint == point ? Status::WON : 
    (7 == point ? Status::LOST : Status::CONTINUE)
end

def dice
    (rand * 6).to_i + (rand * 6).to_i + 2
end
    
firstPoint = dice
puts("玩家點數:[#{firstPoint}]")
status = initialRoll(firstPoint)

while status == Status::CONTINUE
    point = dice
    puts("玩家點數:#{point}")
    status = reRoll(firstPoint, point)
end

puts(status == Status::WON ? "玩家勝" : "玩家輸")
var Status = {
    LOST     : 0,
    WON      : 1,
    CONTINUE : 2
};

function dice() {
    return parseInt(Math.random() * 6) + parseInt(Math.random() * 6) + 2;
}

function initialRoll(firstPoint) {
    switch(firstPoint) {
        case 7: case 11:         return 0;
        case 2: case 3: case 12: return 1;
        default:                 return 2;
    }
    return 3;
}

function reRoll(firstPoint, point) {
    return firstPoint === point ? Status.WON :
           (7 === point ? Status.LOST : Status.CONTINUE);
}

var firstPoint = dice();
print("玩家點數:[" + firstPoint + "]");
var sts = initialRoll(firstPoint);

while(sts === Status.CONTINUE) {
    var point = dice();
    print("玩家點數:" + point);
    sts = reRoll(firstPoint, point);
} 

print(sts === Status.WON ? "玩家勝" : "玩家輸");
import Data.List
import System.Random

data Status = Won | Lost | Continue deriving (Eq)
    
initialRoll firstPoint =
    if firstPoint `elem` [7, 11] then Won 
    else if firstPoint `elem` [2, 3, 12] then Lost
         else Continue

reRoll firstPoint point =
    if firstPoint == point then Won
    else if 7 == point then Lost 
         else Continue
         
diceLt gen = randomRs (1, 6) gen::[Int]

craps roll firstPoint diceLt1 diceLt2 = do
    let point = (head diceLt1) + (head diceLt2)
        status = roll point
    putStrLn \$ "Point:" ++ show point
    if status == Continue then 
        craps r2 firstPoint (tail diceLt1) (tail diceLt2)
    else 
        putStrLn (if status == Won then "Won" else "Lost")
    where r2 = \point -> reRoll firstPoint point
    
main = do
    gen1 <- getStdGen
    gen2 <- newStdGen
    let diceLt1 = diceLt gen1
        diceLt2 = diceLt gen2
    craps r1 ((head diceLt1) + (head diceLt2)) diceLt1 diceLt2
    where r1 = \firstPoint -> initialRoll firstPoint