マルバツゲーム
Posted feedbacks - OCaml
とりあえず愚直に。 player1:5803 player2:2916 draw:1281
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | type board = int list;;
type player = P1 | P2;;
type result = Won of player | Draw | Next of board;;
let rec mark board n =
let idx = Random.int 9 in
if List.nth board idx != 0 then mark board n
else
let _, board' = List.fold_left (fun (idx', res) n' ->
(idx' + 1, (if idx' == idx then res @ [n] else res @ [n']))
) (0, []) board in board'
let masks = [
[1; 1; 1; 0; 0; 0; 0; 0; 0];
[0; 0; 0; 1; 1; 1; 0; 0; 0];
[0; 0; 0; 0; 0; 0; 1; 1; 1];
[1; 0; 0; 1; 0; 0; 1; 0; 0];
[0; 1; 0; 0; 1; 0; 0; 1; 0];
[0; 0; 1; 0; 0; 1; 0; 0; 1];
[1; 0; 0; 0; 1; 0; 0; 0; 1];
[0; 0; 1; 0; 1; 0; 1; 0; 0];
];;
let judge board =
let judge' board =
List.exists (fun mask ->
mask = List.map (fun (a, b) -> a * b) (List.combine mask board)
) masks
in
if judge' board then Won P1
else if judge' (List.map (~-) board) then Won P2
else if List.mem 0 board then Next board else Draw
;;
let rec player1 board =
match judge (mark board 1) with
| Next board' -> player2 board'
| _ as x -> x
and player2 board =
match judge (mark board ~-1) with
| Next board' -> player1 board'
| _ as x -> x
;;
let rec play (p1, p2, draw) = function
| 0 -> (p1, p2, draw)
| _ as n ->
match player1 [0; 0; 0; 0; 0; 0; 0; 0; 0] with
| Won P1 -> play (p1 + 1, p2, draw) (n-1)
| Won P2 -> play (p1, p2 + 1, draw) (n-1)
| Draw -> play (p1, p2, draw + 1) (n-1)
| _ -> raise (Failure "unknown")
;;
let main =
Random.self_init ();
let p1, p2, draw = play (0, 0, 0) 10000 in
Printf.printf "player1:%d player2:%d draw:%d\n" p1 p2 draw
|

syat
#6190()
Rating5/5=1.00
マルバツゲームは3×3の格子に交互に○と×を書き込み、先に縦・横・斜めに記号をそろえたほうが勝ちというおなじみのゲームです。
「毎ターン乱数を使って手を決めるランダムプレイヤー同士を対戦させる」というのが今回のお題です。 1万回対戦させ、勝ち・負け・引き分けの数を表示してください。 そして先手が有利であることを確かめてください。
良い手を思考するプレイヤーについては別のお題にしようと思っています。 プレイヤーを簡単に差し換えることができる設計を目指してください。
[ reply ]