說明
一個簡單的賭博遊戲,遊戲規則如下:玩家擲兩個骰子,點數為1到6,如果第一次點數和為7或11,則玩家勝,如果點數和為2、3或12,則玩家輸,如果和 為其它點數,則記錄第一次的點數和,然後繼續擲骰,直至點數和等於第一次擲出的點數和,則玩家勝,如果在這之前擲出了點數和為7,則玩家輸。解法
規則看來有些複雜,這是一個遊戲嗎?不!這是兩個遊戲,第一個遊戲規則是事先設定好輸贏點數,第二個遊戲規則是要指定贏的點數(由玩家擲出),分別對這兩 個遊戲的規則撰寫函式,就可避免看似複雜的switch、if等條件判斷(如 C 到 JavaScript 的實作所示)。不過就流程來說,主要就是擲骰、使用規則判斷、顯示輸贏或繼續。規則判斷是一種策略,因此可使用回呼函式或物件傳入,遊戲流程就可當作可重用樣版了(如 Haskell 的實作所示)。
實作:C Java Python Scala Ruby JavaScript Haskell
#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: Big5
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