lunlumo #6414(2008/06/03 09:29 GMT) [ FORTRAN ] Rating0/0=0.00
Wikipediaの完勝手順を参考に,以下の形で実装してみました。 1. 3マス揃う場合には揃える 2. 敵方にリーチが掛かっている場合には阻止する 3. ダブルリーチが掛けられる場合には掛ける 4. 敵方がダブルリーチを掛けられる場合には,以下の方法で阻止する 4-1. 敵方のダブルリーチを阻止できる形でリーチを掛けられる場合にはリーチを掛ける 4-2. 4-1以外の場合は,直接的にダブルリーチを阻止する 5. 中央が開いていれば中央に置く 6. 敵方の角の反対が空いていれば,その角に置く 7. 角が空いていれば角に置く 8. 1~7のいずれにも該当しない場合には,空いているマスに置く 以下実行結果です。 1> c(tic_tac_toe). {ok,tic_tac_toe} 2> tic_tac_toe:start(). first:0,second:8762,draw:1238 ok 3> tic_tac_toe:start({fun tic_tac_toe:clever_choice/2,fun tic_tac_toe:random_choice/2}). first:9573,second:0,draw:427 ok 4> tic_tac_toe:start({fun tic_tac_toe:clever_choice/2,fun tic_tac_toe:clever_choice/2}). first:0,second:0,draw:10000 ok
see: Wikipedia
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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
-module(tic_tac_toe). -import(io). -import(lists). -import(random). -export([start/0,start/1,random_choice/2,clever_choice/2]). create_board() -> lists:map(fun(_) -> 0 end,lists:seq(1,9,1)). enemy(P) -> P rem 2 + 1. move(B,1,{C,_}) -> move(B,1,C); move(B,2,{_,C}) -> move(B,2,C); move(B,P,C) -> PS = C(B,P), lists:sublist(B,PS - 1) ++ [P|lists:sublist(B,PS + 1,length(B) - PS)]. check_pattern() -> lists:map(fun(X) -> lists:seq(X,X+6,3) end, lists:seq(1,3,1)) ++ lists:map(fun(X) -> lists:seq(X,X+2,1) end, lists:seq(1,7,3)) ++ [lists:seq(1,9,4),lists:seq(3,7,2)]. check(B,P) -> lists:any( fun(PT) -> lists:all( fun(ST) -> ST == P end, lists:map(fun(X) -> lists:nth(X,B) end, PT) ) end, check_pattern() ). process(B,P,C) -> BN = move(B,P,C), R = check(BN,P), D = lists:all(fun(ST) -> ST /= 0 end, BN), if R -> P; D -> 0; true -> process(BN, enemy(P), C) end. process(C) -> process(create_board(),1,C). random_choice(B,_) -> S = lists:map(fun({PS,_}) -> PS end, lists:filter(fun({_,X}) -> X == 0 end, lists:zip(lists:seq(1,length(B),1),B))), lists:nth(random:uniform(length(S)),S). will_complete(B,P,PL) -> lists:filter( fun(SL) -> (length(lists:filter(fun({_,S}) -> S == P end, SL)) == 2) and (length(lists:filter(fun({_,S}) -> S == 0 end, SL)) == 1) end, lists:map( fun(PP) -> lists:map(fun(PS) -> {PS,lists:nth(PS,B)} end, PP) end, PL ) ). proposed_complete(B,P,PL) -> lists:map( fun(SL) -> {PS,_} = lists:nth(1, lists:filter(fun({_,S}) -> S == 0 end, SL)), PS end, will_complete(B,P,PL) ). check_fork(B,P) -> length(will_complete(B,P,check_pattern())) >= 2. lookahead(F,B,P) -> lists:filter( F, lists:map( fun({PT,_}) ->{PT,lists:sublist(B,PT - 1)++[P|lists:sublist(B,PT + 1,length(B) - PT)]} end, lists:filter(fun({_,S}) -> S == 0 end, lists:zip(lists:seq(1,9,1),B)) ) ). proposed_fork(B,P,_) -> lists:map( fun({PS,_}) -> PS end, lookahead(fun({_,BP}) -> check_fork(BP,P) end,B,P) ). proposed_block_fork(B,P,PL) -> FL = proposed_fork(B,enemy(P),PL), F = length(FL), if F == 0 -> []; true -> lists:map( fun({PS,_}) -> PS end, lookahead( fun({_,BP}) -> (length(lists:subtract(proposed_complete(BP,P,check_pattern()),FL)) > 0) or (length(proposed_fork(BP,enemy(P),[])) == 0) end, B, P ) ) end. proposed_opposite(B,P,PL) -> lists:filter( fun(PS) -> lists:nth(PS,B) == 0 end, lists:map( fun({EP,_}) -> {_,OP} = lists:nth(1, lists:filter( fun({CP,_}) -> CP == EP end, lists:zip(PL,lists:map(fun(X) -> 10 -X end, PL)) ) ), OP end, lists:filter( fun({_,S}) -> S == enemy(P) end, lists:zip(PL,lists:map(fun(PT) -> lists:nth(PT,B) end, PL)) ) ) ). proposed_space(B,_,PL) -> lists:filter(fun(PS) -> lists:nth(PS,B) == 0 end, PL). clever_choice(B,P) -> lists:nth( 1, lists:append( lists:map( fun({F,PP,PL}) -> F(B,PP,PL) end, [ {fun proposed_complete/3,P,check_pattern()}, {fun proposed_complete/3,enemy(P),check_pattern()}, {fun proposed_fork/3,P,[]}, {fun proposed_block_fork/3,P,[]}, {fun proposed_space/3,0,[5]}, {fun proposed_opposite/3,P,[1,3,7,9]}, {fun proposed_space/3,0,[1,3,7,9]}, {fun proposed_space/3,0,[2,4,6,8]} ] ) ) ). start(C) -> R = lists:map(fun(_) -> process(C) end,lists:seq(1,10000,1)), io:format("first:~w,second:~w,draw:~w~n",lists:map(fun(P) -> length(lists:filter(fun(X) -> X == P end, R)) end,[1,2,0])). start() -> start({fun random_choice/2,fun clever_choice/2}).
Rating0/0=0.00-0+
1 reply [ reply ]
lunlumo #6416(2008/06/03 09:37 GMT) Rating0/0=0.00
[ reply ]
lunlumo #6414() [ FORTRAN ] Rating0/0=0.00
Wikipediaの完勝手順を参考に,以下の形で実装してみました。 1. 3マス揃う場合には揃える 2. 敵方にリーチが掛かっている場合には阻止する 3. ダブルリーチが掛けられる場合には掛ける 4. 敵方がダブルリーチを掛けられる場合には,以下の方法で阻止する 4-1. 敵方のダブルリーチを阻止できる形でリーチを掛けられる場合にはリーチを掛ける 4-2. 4-1以外の場合は,直接的にダブルリーチを阻止する 5. 中央が開いていれば中央に置く 6. 敵方の角の反対が空いていれば,その角に置く 7. 角が空いていれば角に置く 8. 1~7のいずれにも該当しない場合には,空いているマスに置く 以下実行結果です。 1> c(tic_tac_toe). {ok,tic_tac_toe} 2> tic_tac_toe:start(). first:0,second:8762,draw:1238 ok 3> tic_tac_toe:start({fun tic_tac_toe:clever_choice/2,fun tic_tac_toe:random_choice/2}). first:9573,second:0,draw:427 ok 4> tic_tac_toe:start({fun tic_tac_toe:clever_choice/2,fun tic_tac_toe:clever_choice/2}). first:0,second:0,draw:10000 oksee: Wikipedia
-module(tic_tac_toe). -import(io). -import(lists). -import(random). -export([start/0,start/1,random_choice/2,clever_choice/2]). create_board() -> lists:map(fun(_) -> 0 end,lists:seq(1,9,1)). enemy(P) -> P rem 2 + 1. move(B,1,{C,_}) -> move(B,1,C); move(B,2,{_,C}) -> move(B,2,C); move(B,P,C) -> PS = C(B,P), lists:sublist(B,PS - 1) ++ [P|lists:sublist(B,PS + 1,length(B) - PS)]. check_pattern() -> lists:map(fun(X) -> lists:seq(X,X+6,3) end, lists:seq(1,3,1)) ++ lists:map(fun(X) -> lists:seq(X,X+2,1) end, lists:seq(1,7,3)) ++ [lists:seq(1,9,4),lists:seq(3,7,2)]. check(B,P) -> lists:any( fun(PT) -> lists:all( fun(ST) -> ST == P end, lists:map(fun(X) -> lists:nth(X,B) end, PT) ) end, check_pattern() ). process(B,P,C) -> BN = move(B,P,C), R = check(BN,P), D = lists:all(fun(ST) -> ST /= 0 end, BN), if R -> P; D -> 0; true -> process(BN, enemy(P), C) end. process(C) -> process(create_board(),1,C). random_choice(B,_) -> S = lists:map(fun({PS,_}) -> PS end, lists:filter(fun({_,X}) -> X == 0 end, lists:zip(lists:seq(1,length(B),1),B))), lists:nth(random:uniform(length(S)),S). will_complete(B,P,PL) -> lists:filter( fun(SL) -> (length(lists:filter(fun({_,S}) -> S == P end, SL)) == 2) and (length(lists:filter(fun({_,S}) -> S == 0 end, SL)) == 1) end, lists:map( fun(PP) -> lists:map(fun(PS) -> {PS,lists:nth(PS,B)} end, PP) end, PL ) ). proposed_complete(B,P,PL) -> lists:map( fun(SL) -> {PS,_} = lists:nth(1, lists:filter(fun({_,S}) -> S == 0 end, SL)), PS end, will_complete(B,P,PL) ). check_fork(B,P) -> length(will_complete(B,P,check_pattern())) >= 2. lookahead(F,B,P) -> lists:filter( F, lists:map( fun({PT,_}) ->{PT,lists:sublist(B,PT - 1)++[P|lists:sublist(B,PT + 1,length(B) - PT)]} end, lists:filter(fun({_,S}) -> S == 0 end, lists:zip(lists:seq(1,9,1),B)) ) ). proposed_fork(B,P,_) -> lists:map( fun({PS,_}) -> PS end, lookahead(fun({_,BP}) -> check_fork(BP,P) end,B,P) ). proposed_block_fork(B,P,PL) -> FL = proposed_fork(B,enemy(P),PL), F = length(FL), if F == 0 -> []; true -> lists:map( fun({PS,_}) -> PS end, lookahead( fun({_,BP}) -> (length(lists:subtract(proposed_complete(BP,P,check_pattern()),FL)) > 0) or (length(proposed_fork(BP,enemy(P),[])) == 0) end, B, P ) ) end. proposed_opposite(B,P,PL) -> lists:filter( fun(PS) -> lists:nth(PS,B) == 0 end, lists:map( fun({EP,_}) -> {_,OP} = lists:nth(1, lists:filter( fun({CP,_}) -> CP == EP end, lists:zip(PL,lists:map(fun(X) -> 10 -X end, PL)) ) ), OP end, lists:filter( fun({_,S}) -> S == enemy(P) end, lists:zip(PL,lists:map(fun(PT) -> lists:nth(PT,B) end, PL)) ) ) ). proposed_space(B,_,PL) -> lists:filter(fun(PS) -> lists:nth(PS,B) == 0 end, PL). clever_choice(B,P) -> lists:nth( 1, lists:append( lists:map( fun({F,PP,PL}) -> F(B,PP,PL) end, [ {fun proposed_complete/3,P,check_pattern()}, {fun proposed_complete/3,enemy(P),check_pattern()}, {fun proposed_fork/3,P,[]}, {fun proposed_block_fork/3,P,[]}, {fun proposed_space/3,0,[5]}, {fun proposed_opposite/3,P,[1,3,7,9]}, {fun proposed_space/3,0,[1,3,7,9]}, {fun proposed_space/3,0,[2,4,6,8]} ] ) ) ). start(C) -> R = lists:map(fun(_) -> process(C) end,lists:seq(1,10000,1)), io:format("first:~w,second:~w,draw:~w~n",lists:map(fun(P) -> length(lists:filter(fun(X) -> X == P end, R)) end,[1,2,0])). start() -> start({fun random_choice/2,fun clever_choice/2}).Rating0/0=0.00-0+
1 reply [ reply ]