F#でブラックジャックを実装しました
はじめに
以下の2記事に触発されて自分でもシンプルなブラックジャックを実装してみました。
プログラミング入門者からの卒業試験は『ブラックジャック』を開発すべし
F# で“卒業試験”ことブラックジャック開発をやってみた
ソースコードはこちら。120行程度です。
https://github.com/msanou/BlackJackFsharp/blob/master/Program.fs
引いたカードの重複チェックについて
既に引いたカードの管理方法についてです。なるべくArrayなどのmutableなコレクションは使わずにやることを目指していたので、引いたカードをdeckとして引き渡しながら管理することにしました。
let rec pickCard hand deck =
let card = { PlayingCard.Number = rand.Next(1,13);
PlayingCard.Suit = rand.Next(1,4) |> enum<Suits> }
if isCardExist card deck then pickCard hand deck
else hand @ [card], deck @ [card]
はじめは山札を模したArrayを用意して……などと考えていましたが、今回のようなゲームだと山札を引き切るケースがまずないのでリストをシャッフルして要素を一つずつ減らしていくより記憶していく方がいいのかもしれない。
あと、かなりタプルを多用しましたが、もう少し冴えたやり方があるようにも思います。
スコアの計算
let calcScore hand =
let temp = hand |> List.sumBy(fun x -> if x.Number > 10 then 10 else x.Number)
hand |> List.fold (fun x y ->
if y.Number = 1 && x <= 11 then x + 10 else x) temp
let calcScore hand =
let temp = hand |> List.sumBy(fun x -> if x.Number > 10 then 10 else x.Number)
hand |> List.fold (fun x y ->
if y.Number = 1 && x <= 11 then x + 10 else x) temp
まず、J,Q,Kの点数を10点として手札の合計を計算します。そして、点数の合計が11を超えない場合に限り、エースのスコアを11として扱う(合計値に10足す)……という形なのですが、「点数の合計が11点以下の時、エースのカードが手札に一枚でも含まれる場合は10を加算する」で良かったですね。わざわざfold関数使わなくてよかった。
let calcScore hand =
let temp = hand |> List.sumBy(fun x -> if x.Number > 10 then 10 else x.Number)
if hand |> List.exists (fun x -> x.Number = 1) && temp <= 11 then temp+10 else temp
このように書き換えられました。
おわりに
メッセージの表示処理や入力の受付を記述する場所、判別共用体を手札とかに使ってバーストの判別をそのメンバにやらせるなど、色々他にも工夫の余地はあるように思います。
作って記事にでもしようと考えていましたが、思ったより何も書くことがない。
Author And Source
この問題について(F#でブラックジャックを実装しました), 我々は、より多くの情報をここで見つけました https://qiita.com/MinoruSanou/items/159aa5937907dce594fe著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .