Comment detail
マルバツゲーム (Nested Flatten)1行ミスってました。コピペはいけませんね・・・。あらためて
player1 won: 5826
player2 won: 2857
draw : 1317
という感じです。
1 2 3 4 5 6 7 8 9 | @@ -4,7 +4,7 @@
protected val field = new Array[Array[char]](size,size)
val len = size*size
val lines = _stline((v,v2) => (v,v2))++_stline((v,v2) => (v2,v))++
- List(((size-1).until(-1,-1)).map(v=>(v,v))) ++
+ List(((size-1).until(-1,-1)).map(v=> (v,(size-1-v)))) ++
List((0 until size).map(v=>(v,v)))
def _stline(f:(int,int) => Pair[int,int]) =
|
出題者です。統計的には試行回数が多いほど誤差が小さくなるので、試しに100万×5回ほどやってみました。
その結果、
先攻勝ち:先攻負け:引き分け ≒ 58.5:28.8:12.7
と出ました。 そこらへんの数字の人は正解と思われます。
乱数は素直につかえば問題ないのですが、変なロジックをとおした結果、かたよりが出たりすると怖いです。 処理系によって乱数の癖が見れたりしたら面白かったかも??
全局面を探索したところ、 先攻:51.4%、後攻:30.4%、引き分け18.1% が正解のようですね。
syatさんの結果でいいのではないでしょうか。 全局面の意味がよくわかりませんが、 途中で終わったりもするので、 すべての局面が等確率で出現するわけではありません。
結果の検証用に打ち筋をすべてたどってみました。 先攻勝ち:131184(51.4%) 後攻勝ち:77904(30.5%) 引き分け:46080(18.1%) の255168通りでした。 乱数で勝負させたものは確かにsyatさんの数字に近くなったんですが・・・。
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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | #include <stdio.h>
#include <stdlib.h>
typedef struct {
int data;
int turn;
} CELL;
/*
[0][1][2]
[3][4][5]
[6][7][8]
cell
data cellの内容
0:空白
1:o
2:x
turn 打たれたターン数
*/
//勝敗チェック
// 0 :決着まだ
// not 0:勝負あり
int check(CELL a[],int w){
int i;
//縦横
for(i=0;i<3;i++){
if((a[i*3].data==w)&&(a[i*3+1].data==w)&&(a[i*3+2].data==w)||
(a[i].data==w)&&(a[i+3].data==w)&&(a[i+6].data==w)) return -1;
}
//斜め
if((a[0].data==w)&&(a[4].data==w)&&(a[8].data==w)||
(a[2].data==w)&&(a[4].data==w)&&(a[6].data==w)) return -1;
return 0;
}
int result[3];
int analyze(CELL a[],int t,int turn){
int i;
if(turn==10){
//引き分け
result[0]++;
return -1;
}
//進行
for(i=0;i<9;i++){
if(a[i].data==0){
//置けるなら置く
a[i].data=t;
a[i].turn=turn;
//勝負判定
if(check(a,t)){
//決着
result[t]++;
}else{
//続行
analyze(a,3-t,turn+1);
}
//一手戻す
a[i].data=0;
a[i].turn=0;
}
}
return 0;
}
int main(){
int i;
CELL a[9];
//盤面初期化
for(i=0;i<9;i++){
a[i].data=0;
a[i].turn=0;
}
for(i=0;i<3;i++){
result[i]=0;
}
analyze(a,1,1);
i=result[0]+result[1]+result[2];
printf("o win:%d(%2.1f%%) x win:%d(%2.1f%%) draw:%d(%2.1f%%)\n",
result[1],100.0*result[1]/i,
result[2],100.0*result[2]/i,
result[0],100.0*result[0]/i);
return 0;
}
|
ちと違うみたいです。 58行目、 result[t]+=weight(9-turn); に直して下記コードを追加 で、 o win:212256(58.5%) x win:104544(28.8%) draw:46080(12.7%) だと思います。
1 2 3 4 | int weight(int i) {
if (i<=1) return 1;
return i*weight(i-1);
}
|
なるほど・・・ ようやく理解しました。







yuin
#6191()
[
Scala
]
Rating0/0=0.00
お昼休みにさくっとやってみました。
Playerクラスを継承したクラスをつくることでPlayerを差し替えることができます。
10000回を3回ほどやってみて
というかんじでした。
import java.util.Random class TicTacToe(val size:int, val players:List[Player]) { protected val field = new Array[Array[char]](size,size) val len = size*size val lines = _stline((v,v2) => (v,v2))++_stline((v,v2) => (v2,v))++ List(((size-1).until(-1,-1)).map(v=>(v,v))) ++ List((0 until size).map(v=>(v,v))) def _stline(f:(int,int) => Pair[int,int]) = (0 until size).map(v => (0 until size).map(v2 => f(v,v2))) override def toString = { val sep = List.make(size*4+1, "-").mkString("\n", "", "\n") field.map{_.mkString("| ", " | ", " |")}.mkString(sep,sep,sep) } def start:Option[Player] = { for(val i<-(0 until size); val j<-(0 until size)) { field(i)(j) = ' '} Stream.const(players).flatMap(v=>v).take(len).find {player => val p = player.put(this) if(!available_?(p)) error("Oops!") field(p._1)(p._2) = player.mark judge } } def judge = lines.exists(l => l.forall(!available_?(_)) && l.forall(v => field(l(0)._1)(l(0)._2) == field(v._1)(v._2))) def available_?(pos:Pair[int,int]) = field(pos._1)(pos._2) equals ' ' } abstract class Player{ val mark:char val name:String def put(ttt:TicTacToe):Pair[int,int] } class RandomPlayer(override val mark:char, override val name:String) extends Player{ val rnd = new Random override def put(ttt:TicTacToe) = { def _n = (rnd.nextInt(ttt.size), rnd.nextInt(ttt.size)) def next(v:Pair[int,int]):Stream[Pair[int,int]] = Stream.cons(v, next(_n)) next(_n).find(ttt.available_?).get } } object Main extends Application{ val ttt = new TicTacToe(3, List(new RandomPlayer('○', "1"), new RandomPlayer('×', "2"))) val result = Array.make(3,0) (1 to 10000) foreach { i => ttt.start match { case Some(p) if p.name equals "1" => result(0) += 1 case Some(p) if p.name equals "2" => result(1) += 1 case _ => result(2) += 1 } } println("player1 won:\t"+result(0)+"\n"+"player2 won:\t"+result(1)+"\n"+"draw :\t"+result(2)) }Rating0/0=0.00-0+
1 reply [ reply ]