マルバツゲーム
Posted feedbacks - Other
ちょっと力業でしょうか。
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 59 60 61 62 63 64 65 66 67 68 69 | (use srfi-1)
(use srfi-27)
(use util.list)
(random-source-randomize! default-random-source)
;; board: (0 1 0 0 0 0 0 0 0)
;; board -> board
(define (player-random board self)
(define (okeru)
(length (filter zero? board)))
(let loop ((board board)
(next (random-integer (okeru))))
(if (null? board)
()
(cons (if (= next 0)
self
(car board))
(loop (cdr board)
(if (= (car board) 0)
(- next 1)
next
))))))
(define (play p1 p2)
(define (finish? board)
(or (> (judge board) 0)
(not (find zero? board))))
(let loop ((board (make-list 9 0))
(phase 1))
(if (finish? board)
board
(if (= phase 1)
(loop (p1 board 1) 2)
(loop (p2 board 2) 1)))))
(define (judge board)
(define line-points-list
'((0 1 2)
(3 4 5)
(6 7 8)
(0 3 6)
(1 4 7)
(2 5 8)
(0 4 8)
(2 4 6)))
(define (judge-4-player n)
(find (lambda (line-points)
(every (lambda (j)
(= (ref board j) n))
line-points))
line-points-list))
(cond ((judge-4-player 1) 1)
((judge-4-player 2) 2)
(else 0)))
(define (marubatsu p1 p2)
(define (one-play)
(judge (play p1 p2)))
(define hash (make-hash-table))
(dotimes (counter 10000)
(hash-table-update! hash (one-play) (cut + 1 <>) 0))
(write (hash-table->alist hash)))
|
drawを先に判定しちゃダメじゃん...
というわけで、100万回試行の結果がちゃんと
player 1 won : 585255(0.585255) player 2 won : 287878(0.287878) draw : 126867(0.126867)
になりました。
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 | int
board_checker::operator()(board& b)
const
{
if ( int id = b(1,1) )
if ((b(0,0) == id && b(2,2) == id ) ||
(b(0,2) == id && b(2,0) == id) ||
(b(0,1) == id && b(2,1) == id) ||
(b(1,0) == id && b(1,2) == id) )
return id;
if ( int id = b(0,0) )
if ((b(0,1) == id && b(0,2) == id) ||
(b(1,0) == id && b(2,0) == id) )
return id;
if ( int id = b(2,2) )
if ((b(1,2) == id && b(0,2) == id) ||
(b(2,1) == id && b(2,0) == id) )
return id;
bool draw=true;
for (int x = 0; draw && x < 3; ++x )
for (int y = 0; draw && y < 3; ++y )
draw = b(x,y) != 0;
if ( draw )
return -1;
// not finish
return 0;
}
|



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