という方、初学者向けの解説記事です。
この記事を読んでできること
・オセロの作り方を理解することができる
・簡単なCPUを実装することができる
対象読者様
②コードの意味・作り方を理解したい方
上記のような読者様を想定しております。
当記事では javascriptで初めて何かを作りたい方 を想定している為
4つのパートに分けて解説をしていきます。
今回は第4回(前回はこちら:リバーシの作り方を初学者向けに1行づつ解説!③)
CPUが自動で考えて、石を置いてくれるを解説していきます。
今回でついに最終回です。がんばっていきましょう!
概要説明
今回はついにCPUが自動で考えて、石を置いてくれるを実装していきます。
…といってもあまり身構えなくても大丈夫です。
ちょっとの追加と関数を3つ理解するだけで↓を完成させることができます。
◆ポイント
②keisanOmomiData()/copyData() → どのマスの点数が高いか判定する③cpuThinking() → ひっくり返せるマスをCPUが探して実行する
それを②の関数で補助しているような関係です。
順に解説していきます。
①配列とsetTimeoutを追加しよう!
//変数の宣言するところに追加する
let omomiData = [
[30, -12, 0, -1, -1, 0, -12, 30],
[-12, -15, -3, -3, -3, -3, -15, -12],
[0, -3, 0, -1, -1, 0, -3, 0],
[-1, -3, -1, -1, -1, -1, -3, -1],
[-1, -3, -1, -1, -1, -1, -3, -1],
[0, -3, 0, -1, -1, 0, -3, 0],
[-12, -15, -3, -3, -3, -3, -15, -12],
[30, -12, 0, -1, -1, 0, -12, 30]
];
//kousin()の最後に追加する
if (myTurn === false) {
setTimeout(cpuThinking, 1000);
}
まずは、関数以外のお話です。上記2点を追加します。
青色部分はなんとなくお分かりかと思います。
setTimeout(cpuThinking, 1000)
は
1秒(=1000ミリ秒)経過したら関数cpuThinkingを実行してねという関数です。
kousin()は自分のターンの処理が終わると発動し、画面を再描画するもの
setTimeoutを設定することがCPUが悩んでいるようになり、ゲームっぽくなります。
重みデーター とは
続いて配列についてです。
気づいた方もいらっしゃると思いますが、8×8のマスそれぞれに対応する数字になっています。具体的にはどのマスに置くと価値が高いかを表します。
・四隅の隣のマスが「-12」
・四隅の斜めのマスが「-15」
・それ以外は大体マイナス
オセロは4隅をとると大体勝てちゃいますよね。
それを数字で表したのがこの配列です。
一旦は「価値の高さをマスごとに数字で設定している」ことだけ分かれば大丈夫です。
②keisanOmomiData()/copyData()を理解しよう!
function keisanOmomiData(kariData) {
let score = 0;
for (let x = 0; x < 8; x++) {
for (let y = 0; y < 8; y++) {
if (kariData[x][y] === KURO) {
score += omomiData[x][y];
}
}
}
return score;
}
// 石テーブルデータをコピー;
function copyData() {
let kariData = [];
for (let x = 0; x < 8; x++) {
kariData[x] = [];
for (let y = 0; y < 8; y++) {
kariData[x][y] = data[x][y];
}
}
return kariData;
}
keisanOmomiData(kariData)
⇒return score
copyData()
⇒return kariData
kariData
はとてもシンプル
xを8回、yを8回まわした後にkariData[x][y] = data[x][y]
としているので
64個分の配列(kariData[0][0]、kariData[0][1]…kariData[7][7]) がreturnされます。
score って何を表しているの?
一方でscore
は合計した値です。
黒の置かれた場所の重み(omomiData)を合計した値です。
合計値が一番大きくなるマスを探して石を置くという処理をcpuThinkingで実装します。その判断基準がこの合計値です。
kariData[x][y] === KURO
、つまりCPU(黒)の石があるなら
score += omomiData[x][y]
でマス目に対応した数値(0,-30,15…)を加えてね
という処理になっています。
③cpuThinking()を理解しよう!
function cpuThinking() {
let highScore = -1000;
let px = -1;
let py = -1;
for (let x = 0; x < 8; x++) {
for (let y = 0; y < 8; y++) {
let kariData = copyData();
let cpuCanReverceMasu = canReverceMasu(x, y, KURO);
if (cpuCanReverceMasu.length > 0) {
for (let i = 0; i < cpuCanReverceMasu.length; i++) {
let p = cpuCanReverceMasu[i][0];
let q = cpuCanReverceMasu[i][1];
kariData[p][q] = KURO;
kariData[x][y] = KURO;
}
let score = keisanOmomiData(kariData);
if (score > highScore) {
highScore = score;
(px = x), (py = y);
}
}
}
}
if (px >= 0 && py >= 0) {
let cpuCanReverceMasu = canReverceMasu(px, py, KURO);
if (cpuCanReverceMasu.length > 0) {
for (let k = 0; k < cpuCanReverceMasu.length; k++) {
put(cpuCanReverceMasu[k][0], cpuCanReverceMasu[k][1], KURO);
}
}
put(px, py, KURO);
}
kousin();
}
ついに最後の関数までやってきました…!
処理の流れはこのようになります。①②③の順に解説します。
②置いた状況を再現
③②の状態で一番点数の合計値が高い座標を求める
④石を置く
①仮データー(kariData)を作成しよう
let kariData = copyData();
let cpuCanReverceMasu = canReverceMasu(x, y, KURO);
kariData
は64個分の配列(kariData[0][0]、kariData[0][1]…kariData[7][7])のこと
cpuCanReverceMasu
は黒をひっくり返すことができるマスのことです
どのマスをひっくり返せるかは前の章で説明した内容ですので、こちらをご参考いただければ幸いです。リバーシの作り方を初学者向けに1行づつ解説!③
②置いた状況を再現
if (cpuCanReverceMasu.length > 0) {
for (let i = 0; i < cpuCanReverceMasu.length; i++) {
let p = cpuCanReverceMasu[i][0];
let q = cpuCanReverceMasu[i][1];
kariData[p][q] = KURO;
kariData[x][y] = KURO;
}
cpuCanReverceMasu
はCPUの石をおける座標p
,q
としてkariData[p][q] = KURO
を設定します。
こうすると、KUROが置かれたと仮定した状況を作ることができます。
③②の状態で一番点数の合計値が高い座標を求める
let score = keisanOmomiData(kariData);
if (score > highScore) {
highScore = score;
(px = x), (py = y);
}
if (px >= 0 && py >= 0) {
//略
put(px, py, KURO)
//略
}
keisanOmomiData
はCPUの石を置いた時の合計点数これを1つ前のscore(highScore)と比較して優先度が高いならhighScoreを更新。
その座標をpx,pyに格納します。
これが
if (px >= 0 && py >= 0)
、両方0以上になる場合ならどこかに石を置けたことになります。しっかりゲームとして機能していることがわかりますね!
まとめ
ここまで4回にわたり、オセロの実装方法について解説致しました。
分かりづらかったところも多々あると思いますが、javascript学習の一助になれば幸いです。
お疲れさまでした!