作成日:2024年08月22日
三目並べを作ろう(7)

打ち手を判断するスクリプト(試作)
「ミニマックス法」が良さそうなので、こちらを使用して最善手を打つスクリプトを組んでみます
COMによる打ち手判定
スクリプト
# ################################################## # COMによる打ち手判定 # 作成日:2024年08月22日 # ################################################## 変数を設定 [$手番; 値: 一時記録::次の手番] 変数を設定 [$先手; 値: 一時記録::手順[1] & 一時記録::手順[3] & 一時記録::手順[5] & 一時記録::手順[7]] 変数を設定 [$後手; 値: 一時記録::手順[2] & 一時記録::手順[4] & 一時記録::手順[6] & 一時記録::手順[8]] 変数を設定 [$残; 値: Substitute ( "ABCDEFGHI"; [一時記録::手順[1]; ""]; [一時記録::手順[2]; ""]; [一時記録::手順[3]; ""]; [一時記録::手順[4]; ""]; [一時記録::手順[5]; ""]; [一時記録::手順[6]; ""]; [一時記録::手順[7]; ""]; [一時記録::手順[8]; ""]; [一時記録::手順[9]; ""] )] スクリプト実行 [指定: 一覧から; 「ミニマックス法判定」; 引数: JSONSetElement ( ""; ["手数"; $手数; JSONNumber]; ["手番"; $手番; JSONString]; ["先手"; $先手; JSONString]; ["後手"; $後手; JSONString]; ["残"; $残; JSONString] )] 変数を設定 [$param; 値: Get ( スクリプトの結果 )] 変数を設定 [$次手; 値: JSONGetElement ( $param; "次手" )] 変数を設定 [$i; 値: 1] Loop [フラッシュ: 延期] Exit Loop If [一時記録::手順[$i] = ""] 変数を設定 [$i; 値: $i + 1] End Loop フィールド設定 [一時記録::手順[$i]; $次手] フィールドを名前で設定 ["一時記録::盤面" & $次手; If ( 一時記録::次の手番 = "先手"; 画像保管::アイコン[1]; 画像保管::アイコン[2] )] スクリプト実行 [指定: 一覧から; 「勝敗判定」; 引数: ] If [一時記録::勝敗 = ""] フィールド設定 [一時記録::次の手番; If ( 一時記録::次の手番 = "先手"; "後手"; "先手" )] End If ウインドウ内容の再表示 []
ミニマックス法判定
スクリプト
# ################################################## # ミニマックス法判定 # 作成日:2024年08月22日 # ################################################## 変数を設定 [$param; 値: Get ( スクリプト引数 )] 変数を設定 [$手番; 値: JSONGetElement ( $param; "手番" )] 変数を設定 [$先手; 値: JSONGetElement ( $param; "先手" )] 変数を設定 [$後手; 値: JSONGetElement ( $param; "後手" )] 変数を設定 [$残; 値: JSONGetElement ( $param; "残" )] 変数を設定 [$次手; 値: ""] 変数を設定 [$判別値; 値: 0] 変数を設定 [$i; 値: 1] Loop [フラッシュ: 延期] Exit Loop If [$i > Length ( $残 )] 変数を設定 [$次手案; 値: Middle ( $残; $i; 1 )] 変数を設定 [$先手案; 値: $先手 & If ( $手番 = "先手"; $次手案; "" )] 変数を設定 [$後手案; 値: $後手 & If ( $手番 = "先手"; ""; $次手案 )] If [Length ( Filter ( $先手案; "ABC" ) ) = 3 or Length ( Filter ( $先手案; "DEF" ) ) = 3 or Length ( Filter ( $先手案; "GHI" ) ) = 3 or Length ( Filter ( $先手案; "ADG" ) ) = 3 or Length ( Filter ( $先手案; "BEH" ) ) = 3 or Length ( Filter ( $先手案; "CFI" ) ) = 3 or Length ( Filter ( $先手案; "AEI" ) ) = 3 or Length ( Filter ( $先手案; "CEG" ) ) = 3] 変数を設定 [$判定値案; 値: Case ( 一時記録::次の手番 = "先手"; 10; 一時記録::次の手番 = "後手"; -10; 0 )] Else If [Length ( Filter ( $後手案; "ABC" ) ) = 3 or Length ( Filter ( $後手案; "DEF" ) ) = 3 or Length ( Filter ( $後手案; "GHI" ) ) = 3 or Length ( Filter ( $後手案; "ADG" ) ) = 3 or Length ( Filter ( $後手案; "BEH" ) ) = 3 or Length ( Filter ( $後手案; "CFI" ) ) = 3 or Length ( Filter ( $後手案; "AEI" ) ) = 3 or Length ( Filter ( $後手案; "CEG" ) ) = 3] 変数を設定 [$判定値案; 値: Case ( 一時記録::次の手番 = "先手"; -10; 一時記録::次の手番 = "後手"; 10; 0 )] Else スクリプト実行 [指定: 一覧から; 「ミニマックス法判定」; 引数: JSONSetElement ( ""; ["手番"; If ( $手番 = "先手"; "後手"; "先手" ); JSONString]; ["先手"; $先手案; JSONString]; ["後手"; $後手案; JSONString]; ["残"; Substitute ( $残; $次手案; "" ); JSONString] )] 変数を設定 [$result; 値: JSONGetElement ( Get ( スクリプトの結果 ); "判定値" )] 変数を設定 [$判定値案; 値: Case ( $result > 0; $result - 1; $result < 0; $result + 1; $result )] End If If [$次手 = ""] 変数を設定 [$次手; 値: $次手案] 変数を設定 [$判定値; 値: $判定値案] Else If [一時記録::次の手番 = $手番 and $判定値案 > $判定値] 変数を設定 [$次手; 値: $次手案] 変数を設定 [$判定値; 値: $判定値案] Else If [一時記録::次の手番 = $手番 and $判定値案 = $判定値 and Random > .5] 変数を設定 [$次手; 値: $次手案] 変数を設定 [$判定値; 値: $判定値案] Else If [一時記録::次の手番 ≠ $手番 and $判定値案 < $判定値] 変数を設定 [$次手; 値: $次手案] 変数を設定 [$判定値; 値: $判定値案] Else If [一時記録::次の手番 ≠ $手番 and $判定値案 = $判定値 and Random > .5] 変数を設定 [$次手; 値: $次手案] 変数を設定 [$判定値; 値: $判定値案] End If 変数を設定 [$i; $i + 1] End Loop 現在のスクリプト終了 [テキスト結果: JSONSetElement ( ""; ["次手"; $次手; JSONString]; ["判定値"; $判定値; JSONNumber] )]
とりあえず記述できたので動作テストしてみたところ、(たぶん)最善手を打てているものの現実的ではない処理時間となっています
手数 | iPhone | Mac | Win |
---|---|---|---|
1手目 | 96241 | 71686 | 367983 |
2手目 | 9216 | 7904 | 39937 |
3手目 | 1211 | 1052 | 5047 |
4手目 | 261 | 161 | 646 |
5手目 | 111 | 53 | 203 |
6手目 | 61 | 24 | 81 |
7手目 | 61 | 16 | 41 |
8手目 | 61 | 12 | 36 |
9手目 | 70 | 30 | 58 |
何らかの手段で高速化し、私の持つ環境の中で最も遅いWindowsでも実用可能な時間で動くようにしたい所です
スクリプトの高速化
スクリプトの内容を改めて見てみますが、あまり大幅な改善が見込める改修案が思い当たりません
一応思いつく範囲で改修をいくつか試したものの、処理時間を計測しても若干早くなった程度の結果しか得られません
仕方がないので、最善手を事前判定させた結果を取得する方法で高速化する事にします
本来はテーブルにデータを持たせて参照する方が良いのでしょうが、今回はスクリプトに直接記述して対応します
COMによる打ち手判定
スクリプト
# ################################################## # COMによる打ち手判定 # 作成日:2024年08月22日 # ################################################## If [一時記録::手順[1] = ""] 変数を設定 [$次手; 値: Middle ( "ACEGI"; Int ( Random * 5 ) + 1; 1 )] Else If [一時記録::手順[2] = ""] 変数を設定 [$次手; 値: Case ( 一時記録::手順[1] = "A"; "E"; 一時記録::手順[1] = "C"; "E"; 一時記録::手順[1] = "G"; "E"; 一時記録::手順[1] = "I"; "E"; 一時記録::手順[1] = "B"; Middle ( "ACEH"; Int ( Random * 4 ) + 1; 1 ); 一時記録::手順[1] = "D"; Middle ( "AEFG"; Int ( Random * 4 ) + 1; 1 ); 一時記録::手順[1] = "F"; Middle ( "CDEI"; Int ( Random * 4 ) + 1; 1 ); 一時記録::手順[1] = "H"; Middle ( "BEGI"; Int ( Random * 4 ) + 1; 1 ); 一時記録::手順[1] = "E"; Middle ( "ACGI"; Int ( Random * 4 ) + 1; 1 ); "" )] Else If [一時記録::手順[3] = ""] 変数を設定 [$次手; 値: Case ( 一時記録::手順[1] = "A" and 一時記録::手順[2] = "B"; "G"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "C"; Middle ( "DGI"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "A" and 一時記録::手順[2] = "D"; "C"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "E"; "I"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "F"; "G"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "G"; Middle ( "BCI"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "A" and 一時記録::手順[2] = "H"; "C"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "I"; Middle ( "CG"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "B" and 一時記録::手順[2] = "A"; "D"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "C"; "F"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "D"; "A"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "E"; Middle ( "ACEFGI"; Int ( Random * 6 ) + 1; 1 ); 一時記録::手順[1] = "B" and 一時記録::手順[2] = "F"; "C"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "G"; "A"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "H"; Middle ( "ACEDFGI"; Int ( Random * 7 ) + 1; 1 ); 一時記録::手順[1] = "B" and 一時記録::手順[2] = "I"; "C"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "A"; Middle ( "FGI"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "C" and 一時記録::手順[2] = "B"; "I"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "D"; "I"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "E"; "G"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "F"; "A"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "G"; Middle ( "AI"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "C" and 一時記録::手順[2] = "H"; "A"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "I"; Middle ( "ABG"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "D" and 一時記録::手順[2] = "A"; "B"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "B"; "A"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "C"; "A"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "E"; Middle ( "ABCGHI"; Int ( Random * 6 ) + 1; 1 ); 一時記録::手順[1] = "D" and 一時記録::手順[2] = "F"; Middle ( "ABCEGHI"; Int ( Random * 7 ) + 1; 1 ); 一時記録::手順[1] = "D" and 一時記録::手順[2] = "G"; "H"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "H"; "G"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "I"; "G"; 一時記録::手順[1] = "E" and 一時記録::手順[2] = "A"; "I"; 一時記録::手順[1] = "E" and 一時記録::手順[2] = "B"; Middle ( "AC"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "E" and 一時記録::手順[2] = "C"; "G"; 一時記録::手順[1] = "E" and 一時記録::手順[2] = "D"; Middle ( "AG"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "E" and 一時記録::手順[2] = "F"; Middle ( "CI"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "E" and 一時記録::手順[2] = "G"; "C"; 一時記録::手順[1] = "E" and 一時記録::手順[2] = "H"; Middle ( "GI"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "E" and 一時記録::手順[2] = "I"; "A"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "A"; "C"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "B"; "C"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "C"; "B"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "D"; Middle ( "ABCEGHI"; Int ( Random * 7 ) + 1; 1 ); 一時記録::手順[1] = "F" and 一時記録::手順[2] = "E"; Middle ( "ABCGHI"; Int ( Random * 6 ) + 1; 1 ); 一時記録::手順[1] = "F" and 一時記録::手順[2] = "G"; "I"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "H"; "I"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "I"; "H"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "A"; Middle ( "CHI"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "G" and 一時記録::手順[2] = "B"; "I"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "C"; Middle ( "AI"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "G" and 一時記録::手順[2] = "D"; "I"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "E"; "C"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "F"; "A"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "H"; "A"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "I"; Middle ( "ACD"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "H" and 一時記録::手順[2] = "A"; "G"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "B"; Middle ( "ACDEFGI"; Int ( Random * 7 ) + 1; 1 ); 一時記録::手順[1] = "H" and 一時記録::手順[2] = "C"; "I"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "D"; "G"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "E"; Middle ( "ACDFGI"; Int ( Random * 6 ) + 1; 1 ); 一時記録::手順[1] = "H" and 一時記録::手順[2] = "F"; "I"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "G"; "D"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "I"; "F"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "A"; Middle ( "CG"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "I" and 一時記録::手順[2] = "B"; "G"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "C"; Middle ( "AGH"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "I" and 一時記録::手順[2] = "D"; "C"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "E"; "A"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "F"; "G"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "G"; Middle ( "ACF"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "I" and 一時記録::手順[2] = "H"; "C"; "" )] Else 変数を設定 [$手番; 値: 一時記録::次の手番] 変数を設定 [$先手; 値: 一時記録::手順[1] & 一時記録::手順[3] & 一時記録::手順[5] & 一時記録::手順[7]] 変数を設定 [$後手; 値: 一時記録::手順[2] & 一時記録::手順[4] & 一時記録::手順[6] & 一時記録::手順[8]] 変数を設定 [$残; 値: Substitute ( "ABCDEFGHI"; [一時記録::手順[1]; ""]; [一時記録::手順[2]; ""]; [一時記録::手順[3]; ""]; [一時記録::手順[4]; ""]; [一時記録::手順[5]; ""]; [一時記録::手順[6]; ""]; [一時記録::手順[7]; ""]; [一時記録::手順[8]; ""]; [一時記録::手順[9]; ""] )] スクリプト実行 [指定: 一覧から; 「ミニマックス法判定」; 引数: JSONSetElement ( ""; ["手数"; $手数; JSONNumber]; ["手番"; $手番; JSONString]; ["先手"; $先手; JSONString]; ["後手"; $後手; JSONString]; ["残"; $残; JSONString] )] 変数を設定 [$param; 値: Get ( スクリプトの結果 )] 変数を設定 [$次手; 値: JSONGetElement ( $param; "次手" )] End If 変数を設定 [$i; 値: 1] Loop [フラッシュ: 延期] Exit Loop If [一時記録::手順[$i] = ""] 変数を設定 [$i; 値: $i + 1] End Loop フィールド設定 [一時記録::手順[$i]; $次手] フィールドを名前で設定 ["一時記録::盤面" & $次手; If ( 一時記録::次の手番 = "先手"; 画像保管::アイコン[1]; 画像保管::アイコン[2] )] スクリプト実行 [指定: 一覧から; 「勝敗判定」; 引数: ] If [一時記録::勝敗 = ""] フィールド設定 [一時記録::次の手番; If ( 一時記録::次の手番 = "先手"; "後手"; "先手" )] End If ウインドウ内容の再表示 []
少々力業っぽいですが、「本気」モードはとりあえず実用的な速度になりました
接待モード
それでは接待モードです
あからさまに負けに行っては「接待」になりませんが、適度に勝たせられるくらいの難しさが望ましいです
とは言っても三目並べ程度の手数ではあまりできる事はありません
最善手を避ける様に設計してみます
COMによる打ち手判定
スクリプト
# ################################################## # COMによる打ち手判定 # 作成日:2024年08月22日 # ################################################## If [一時記録::手順[1] = ""] If [一時記録::難易度 = "本気"] 変数を設定 [$次手; 値: Middle ( "ACEGI"; Int ( Random * 5 ) + 1; 1 )] Else 変数を設定 [$次手; 値: Middle ( "BDEFH"; Int ( Random * 5 ) + 1; 1 )] End If Else If [一時記録::手順[2] = ""] If [一時記録::難易度 = "本気"] 変数を設定 [$次手; 値: Case ( 一時記録::手順[1] = "A"; "E"; 一時記録::手順[1] = "C"; "E"; 一時記録::手順[1] = "G"; "E"; 一時記録::手順[1] = "I"; "E"; 一時記録::手順[1] = "B"; Middle ( "ACEH"; Int ( Random * 4 ) + 1; 1 ); 一時記録::手順[1] = "D"; Middle ( "AEFG"; Int ( Random * 4 ) + 1; 1 ); 一時記録::手順[1] = "F"; Middle ( "CDEI"; Int ( Random * 4 ) + 1; 1 ); 一時記録::手順[1] = "H"; Middle ( "BEGI"; Int ( Random * 4 ) + 1; 1 ); 一時記録::手順[1] = "E"; Middle ( "ACGI"; Int ( Random * 4 ) + 1; 1 ); "" )] Else 変数を設定 [$次手; 値: Case ( 一時記録::手順[1] = "A"; Middle ( "BDFHI"; Int ( Random * 5 ) + 1; 1 ); 一時記録::手順[1] = "C"; Middle ( "BDFHI"; Int ( Random * 5 ) + 1; 1 ); 一時記録::手順[1] = "G"; Middle ( "BDFHI"; Int ( Random * 5 ) + 1; 1 ); 一時記録::手順[1] = "I"; Middle ( "BDFHI"; Int ( Random * 5 ) + 1; 1 ); 一時記録::手順[1] = "B"; Middle ( "DFGI"; Int ( Random * 4 ) + 1; 1 ); 一時記録::手順[1] = "D"; Middle ( "BCHI"; Int ( Random * 4 ) + 1; 1 ); 一時記録::手順[1] = "F"; Middle ( "ABGH"; Int ( Random * 4 ) + 1; 1 ); 一時記録::手順[1] = "H"; Middle ( "ACDF"; Int ( Random * 4 ) + 1; 1 ); 一時記録::手順[1] = "E"; Middle ( "BDFH"; Int ( Random * 4 ) + 1; 1 ); "" )] End If Else If [一時記録::手順[3] = ""] If [一時記録::難易度 = "本気"] 変数を設定 [$次手; 値: Case ( 一時記録::手順[1] = "A" and 一時記録::手順[2] = "B"; "G"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "C"; Middle ( "DGI"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "A" and 一時記録::手順[2] = "D"; "C"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "E"; "I"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "F"; "G"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "G"; Middle ( "BCI"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "A" and 一時記録::手順[2] = "H"; "C"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "I"; Middle ( "CG"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "B" and 一時記録::手順[2] = "A"; "D"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "C"; "F"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "D"; "A"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "E"; Middle ( "ACEFGI"; Int ( Random * 6 ) + 1; 1 ); 一時記録::手順[1] = "B" and 一時記録::手順[2] = "F"; "C"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "G"; "A"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "H"; Middle ( "ACEDFGI"; Int ( Random * 7 ) + 1; 1 ); 一時記録::手順[1] = "B" and 一時記録::手順[2] = "I"; "C"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "A"; Middle ( "FGI"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "C" and 一時記録::手順[2] = "B"; "I"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "D"; "I"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "E"; "G"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "F"; "A"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "G"; Middle ( "AI"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "C" and 一時記録::手順[2] = "H"; "A"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "I"; Middle ( "ABG"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "D" and 一時記録::手順[2] = "A"; "B"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "B"; "A"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "C"; "A"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "E"; Middle ( "ABCGHI"; Int ( Random * 6 ) + 1; 1 ); 一時記録::手順[1] = "D" and 一時記録::手順[2] = "F"; Middle ( "ABCEGHI"; Int ( Random * 7 ) + 1; 1 ); 一時記録::手順[1] = "D" and 一時記録::手順[2] = "G"; "H"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "H"; "G"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "I"; "G"; 一時記録::手順[1] = "E" and 一時記録::手順[2] = "A"; "I"; 一時記録::手順[1] = "E" and 一時記録::手順[2] = "B"; Middle ( "AC"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "E" and 一時記録::手順[2] = "C"; "G"; 一時記録::手順[1] = "E" and 一時記録::手順[2] = "D"; Middle ( "AG"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "E" and 一時記録::手順[2] = "F"; Middle ( "CI"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "E" and 一時記録::手順[2] = "G"; "C"; 一時記録::手順[1] = "E" and 一時記録::手順[2] = "H"; Middle ( "GI"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "E" and 一時記録::手順[2] = "I"; "A"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "A"; "C"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "B"; "C"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "C"; "B"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "D"; Middle ( "ABCEGHI"; Int ( Random * 7 ) + 1; 1 ); 一時記録::手順[1] = "F" and 一時記録::手順[2] = "E"; Middle ( "ABCGHI"; Int ( Random * 6 ) + 1; 1 ); 一時記録::手順[1] = "F" and 一時記録::手順[2] = "G"; "I"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "H"; "I"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "I"; "H"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "A"; Middle ( "CHI"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "G" and 一時記録::手順[2] = "B"; "I"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "C"; Middle ( "AI"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "G" and 一時記録::手順[2] = "D"; "I"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "E"; "C"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "F"; "A"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "H"; "A"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "I"; Middle ( "ACD"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "H" and 一時記録::手順[2] = "A"; "G"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "B"; Middle ( "ACDEFGI"; Int ( Random * 7 ) + 1; 1 ); 一時記録::手順[1] = "H" and 一時記録::手順[2] = "C"; "I"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "D"; "G"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "E"; Middle ( "ACDFGI"; Int ( Random * 6 ) + 1; 1 ); 一時記録::手順[1] = "H" and 一時記録::手順[2] = "F"; "I"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "G"; "D"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "I"; "F"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "A"; Middle ( "CG"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "I" and 一時記録::手順[2] = "B"; "G"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "C"; Middle ( "AGH"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "I" and 一時記録::手順[2] = "D"; "C"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "E"; "A"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "F"; "G"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "G"; Middle ( "ACF"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "I" and 一時記録::手順[2] = "H"; "C"; "" )] Else 変数を設定 [$次手; 値: Case ( 一時記録::手順[1] = "A" and 一時記録::手順[2] = "B"; "G"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "C"; Middle ( "DGI"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "A" and 一時記録::手順[2] = "D"; "C"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "E"; "I"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "F"; "G"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "G"; Middle ( "BCI"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "A" and 一時記録::手順[2] = "H"; "C"; 一時記録::手順[1] = "A" and 一時記録::手順[2] = "I"; Middle ( "CG"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "B" and 一時記録::手順[2] = "A"; "D"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "C"; "F"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "D"; "A"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "E"; Middle ( "ACEFGI"; Int ( Random * 6 ) + 1; 1 ); 一時記録::手順[1] = "B" and 一時記録::手順[2] = "F"; "C"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "G"; "A"; 一時記録::手順[1] = "B" and 一時記録::手順[2] = "H"; Middle ( "ACEDFGI"; Int ( Random * 7 ) + 1; 1 ); 一時記録::手順[1] = "B" and 一時記録::手順[2] = "I"; "C"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "A"; Middle ( "FGI"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "C" and 一時記録::手順[2] = "B"; "I"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "D"; "I"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "E"; "G"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "F"; "A"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "G"; Middle ( "AI"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "C" and 一時記録::手順[2] = "H"; "A"; 一時記録::手順[1] = "C" and 一時記録::手順[2] = "I"; Middle ( "ABG"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "D" and 一時記録::手順[2] = "A"; "B"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "B"; "A"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "C"; "A"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "E"; Middle ( "ABCGHI"; Int ( Random * 6 ) + 1; 1 ); 一時記録::手順[1] = "D" and 一時記録::手順[2] = "F"; Middle ( "ABCEGHI"; Int ( Random * 7 ) + 1; 1 ); 一時記録::手順[1] = "D" and 一時記録::手順[2] = "G"; "H"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "H"; "G"; 一時記録::手順[1] = "D" and 一時記録::手順[2] = "I"; "G"; 一時記録::手順[1] = "E" and 一時記録::手順[2] = "A"; "I"; 一時記録::手順[1] = "E" and 一時記録::手順[2] = "B"; Middle ( "AC"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "E" and 一時記録::手順[2] = "C"; "G"; 一時記録::手順[1] = "E" and 一時記録::手順[2] = "D"; Middle ( "AG"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "E" and 一時記録::手順[2] = "F"; Middle ( "CI"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "E" and 一時記録::手順[2] = "G"; "C"; 一時記録::手順[1] = "E" and 一時記録::手順[2] = "H"; Middle ( "GI"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "E" and 一時記録::手順[2] = "I"; "A"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "A"; "C"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "B"; "C"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "C"; "B"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "D"; Middle ( "ABCEGHI"; Int ( Random * 7 ) + 1; 1 ); 一時記録::手順[1] = "F" and 一時記録::手順[2] = "E"; Middle ( "ABCGHI"; Int ( Random * 6 ) + 1; 1 ); 一時記録::手順[1] = "F" and 一時記録::手順[2] = "G"; "I"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "H"; "I"; 一時記録::手順[1] = "F" and 一時記録::手順[2] = "I"; "H"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "A"; Middle ( "CHI"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "G" and 一時記録::手順[2] = "B"; "I"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "C"; Middle ( "AI"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "G" and 一時記録::手順[2] = "D"; "I"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "E"; "C"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "F"; "A"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "H"; "A"; 一時記録::手順[1] = "G" and 一時記録::手順[2] = "I"; Middle ( "ACD"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "H" and 一時記録::手順[2] = "A"; "G"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "B"; Middle ( "ACDEFGI"; Int ( Random * 7 ) + 1; 1 ); 一時記録::手順[1] = "H" and 一時記録::手順[2] = "C"; "I"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "D"; "G"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "E"; Middle ( "ACDFGI"; Int ( Random * 6 ) + 1; 1 ); 一時記録::手順[1] = "H" and 一時記録::手順[2] = "F"; "I"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "G"; "D"; 一時記録::手順[1] = "H" and 一時記録::手順[2] = "I"; "F"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "A"; Middle ( "CG"; Int ( Random * 2 ) + 1; 1 ); 一時記録::手順[1] = "I" and 一時記録::手順[2] = "B"; "G"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "C"; Middle ( "AGH"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "I" and 一時記録::手順[2] = "D"; "C"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "E"; "A"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "F"; "G"; 一時記録::手順[1] = "I" and 一時記録::手順[2] = "G"; Middle ( "ACF"; Int ( Random * 3 ) + 1; 1 ); 一時記録::手順[1] = "I" and 一時記録::手順[2] = "H"; "C"; "" )] End If Else 変数を設定 [$手番; 値: 一時記録::次の手番] 変数を設定 [$先手; 値: 一時記録::手順[1] & 一時記録::手順[3] & 一時記録::手順[5] & 一時記録::手順[7]] 変数を設定 [$後手; 値: 一時記録::手順[2] & 一時記録::手順[4] & 一時記録::手順[6] & 一時記録::手順[8]] 変数を設定 [$残; 値: Substitute ( "ABCDEFGHI"; [一時記録::手順[1]; ""]; [一時記録::手順[2]; ""]; [一時記録::手順[3]; ""]; [一時記録::手順[4]; ""]; [一時記録::手順[5]; ""]; [一時記録::手順[6]; ""]; [一時記録::手順[7]; ""]; [一時記録::手順[8]; ""]; [一時記録::手順[9]; ""] )] スクリプト実行 [指定: 一覧から; 「ミニマックス法判定」; 引数: JSONSetElement ( ""; ["手数"; $手数; JSONNumber]; ["手番"; $手番; JSONString]; ["先手"; $先手; JSONString]; ["後手"; $後手; JSONString]; ["残"; $残; JSONString] )] 変数を設定 [$param; 値: Get ( スクリプトの結果 )] 変数を設定 [$次手; 値: JSONGetElement ( $param; "次手" )] End If 変数を設定 [$i; 値: 1] Loop [フラッシュ: 延期] Exit Loop If [一時記録::手順[$i] = ""] 変数を設定 [$i; 値: $i + 1] End Loop フィールド設定 [一時記録::手順[$i]; $次手] フィールドを名前で設定 ["一時記録::盤面" & $次手; If ( 一時記録::次の手番 = "先手"; 画像保管::アイコン[1]; 画像保管::アイコン[2] )] スクリプト実行 [指定: 一覧から; 「勝敗判定」; 引数: ] If [一時記録::勝敗 = ""] フィールド設定 [一時記録::次の手番; If ( 一時記録::次の手番 = "先手"; "後手"; "先手" )] End If ウインドウ内容の再表示 []
ミニマックス法判定
スクリプト
# ################################################## # ミニマックス法判定 # 作成日:2024年08月22日 # ################################################## 変数を設定 [$param; 値: Get ( スクリプト引数 )] 変数を設定 [$手番; 値: JSONGetElement ( $param; "手番" )] 変数を設定 [$先手; 値: JSONGetElement ( $param; "先手" )] 変数を設定 [$後手; 値: JSONGetElement ( $param; "後手" )] 変数を設定 [$残; 値: JSONGetElement ( $param; "残" )] 変数を設定 [$次手; 値: ""] 変数を設定 [$判別値; 値: 0] 変数を設定 [$i; 値: 1] Loop [フラッシュ: 延期] Exit Loop If [$i > Length ( $残 )] 変数を設定 [$次手案; 値: Middle ( $残; $i; 1 )] 変数を設定 [$先手案; 値: $先手 & If ( $手番 = "先手"; $次手案; "" )] 変数を設定 [$後手案; 値: $後手 & If ( $手番 = "先手"; ""; $次手案 )] If [Length ( Filter ( $先手案; "ABC" ) ) = 3 or Length ( Filter ( $先手案; "DEF" ) ) = 3 or Length ( Filter ( $先手案; "GHI" ) ) = 3 or Length ( Filter ( $先手案; "ADG" ) ) = 3 or Length ( Filter ( $先手案; "BEH" ) ) = 3 or Length ( Filter ( $先手案; "CFI" ) ) = 3 or Length ( Filter ( $先手案; "AEI" ) ) = 3 or Length ( Filter ( $先手案; "CEG" ) ) = 3] 変数を設定 [$判定値案; 値: Case ( 一時記録::難易度 = "接待" and 一時記録::次の手番 = "先手"; -2; 一時記録::次の手番 = "先手"; 10; 一時記録::次の手番 = "後手"; -10; 0)] Else If [Length ( Filter ( $後手案; "ABC" ) ) = 3 or Length ( Filter ( $後手案; "DEF" ) ) = 3 or Length ( Filter ( $後手案; "GHI" ) ) = 3 or Length ( Filter ( $後手案; "ADG" ) ) = 3 or Length ( Filter ( $後手案; "BEH" ) ) = 3 or Length ( Filter ( $後手案; "CFI" ) ) = 3 or Length ( Filter ( $後手案; "AEI" ) ) = 3 or Length ( Filter ( $後手案; "CEG" ) ) = 3] 変数を設定 [$判定値案; 値: Case ( Case ( 一時記録::難易度 = "接待" and 一時記録::次の手番 = "後手"; -2; 一時記録::次の手番 = "先手"; -10; 一時記録::次の手番 = "後手"; 10; 0 )] Else スクリプト実行 [指定: 一覧から; 「ミニマックス法判定」; 引数: JSONSetElement ( ""; ["手番"; If ( $手番 = "先手"; "後手"; "先手" ); JSONString]; ["先手"; $先手案; JSONString]; ["後手"; $後手案; JSONString]; ["残"; Substitute ( $残; $次手案; "" ); JSONString] )] 変数を設定 [$result; 値: JSONGetElement ( Get ( スクリプトの結果 ); "判定値" )] 変数を設定 [$判定値案; 値: Case ( $result > 0; $result - 1; $result < 0; $result + 1; $result )] End If If [$次手 = ""] 変数を設定 [$次手; 値: $次手案] 変数を設定 [$判定値; 値: $判定値案] Else If [一時記録::次の手番 = $手番 and $判定値案 > $判定値] 変数を設定 [$次手; 値: $次手案] 変数を設定 [$判定値; 値: $判定値案] Else If [一時記録::次の手番 = $手番 and $判定値案 = $判定値 and Random > .5] 変数を設定 [$次手; 値: $次手案] 変数を設定 [$判定値; 値: $判定値案] Else If [一時記録::次の手番 ≠ $手番 and $判定値案 < $判定値] 変数を設定 [$次手; 値: $次手案] 変数を設定 [$判定値; 値: $判定値案] Else If [一時記録::次の手番 ≠ $手番 and $判定値案 = $判定値 and Random > .5] 変数を設定 [$次手; 値: $次手案] 変数を設定 [$判定値; 値: $判定値案] End If 変数を設定 [$i; $i + 1] End Loop 現在のスクリプト終了 [テキスト結果: JSONSetElement ( ""; ["次手"; $次手; JSONString]; ["判定値"; $判定値; JSONNumber] )]
下手を打てば負ける事もありますが、あまりあからさま過ぎずに勝ちを譲ってくれ様になったかと思います
ようやく三目並べアプリが完成しました
完成品はこちらからダウンロードできますので、ご興味がありましたらどうぞ

以上で今日のメモ書きは終了です
内容はいかがでしたか?
もしご意見やご要望、誤りの指摘などありましたら、下記フォームよりお気軽にご連絡ください