プログラムの中身を詳しくみてみよう
黒と白を交互に置いていくリバーシを作りましょう。
このプログラムでは実際の盤面の周りに1マス増やした仮想の盤面を使います。
一般的なリバーシの盤面は8×8マスであり、
このとき仮想の盤面は10×10マスになります。
1つのマスを表すスプライト(マス)をつくり、実際の盤面のマスの数(8×8=64)だけクローンを並べて実現します。
-
概要
-
用語の説明
概要
大まかな内容
をクリックして開始します。
開始時には盤面の中央の4つのマスに黒、白の石が2つずつ置かれます。
黒、白の順に交互にマスに石を置いていきます。 ただし、すでに置いている自分の石とこれから置く自分の石で 相手の石を挟むことができるマスにしか石を置くことはできません。
縦、横、斜めの8方向のどれか1つの方向で相手の石を挟むことができれば石を置くことができます。
置いた石とすでに置いてある自分の石で挟んでいる相手の石が裏返って自分の石になります。
例えばゲーム開始時であれば黒が置けるのは次の図の1~4のいずれかのマスだけです (この外側のマスもすべて置けません)。
1もしくは2に黒の石を置いたら左上の白の石が裏返って黒になります。 3もしくは4に黒の石を置いたら右下の白の石が裏返って黒になります。
このプログラムではそのターンで裏返した石がわかるように色を少し変えています。
- 次のターンの石(対戦相手の石)が置かれたら通常の色になります。
石が置けるマスがない時のみ、PASSボタンを押して石を置かずに相手のターンにします。 (このプログラムでは置ける場所があるかないかを判定する処理をしていないため、 置ける場所があった場合でもPASSボタンを押すと相手のターンになってしまいます)。
パスは何度でもすることができます。黒、白のどちらも置けるマスがなくなったら終了です。
RESULTボタンを押すと、黒、白のそれぞれの石の数を表示します。
もう一度RESULTボタンを押すと表示が消えます。ゲームの途中でも石の数を表示することができます。
マス
がクリックされたとき
-
- 説明
それぞれのマスを配置し、中央に4つの石を置いた状態にします。
- コードの詳細
盤面の設定を実行して1マスの幅や1辺のマスの数などを設定します。
初期化を実行して各変数、リストを初期の状態にします。
「Start」を受け取ったとき
-
- 説明
Startを受け取ったときに以下を実行します。
- コードの詳細
-
マスを並べるを実行して各マスを配置します。
石を中央に置くを実行して盤面の中央に黒を2つ、白を2つ石を置きます。
石更新を送ります。
盤面の設定
-
- 説明
1マスの幅や 1辺のマス数を設定し、 それをもとに基準とする左下のマスの座標などを計算します。
- コードの詳細
1マスの幅を40(px)にします。
1辺のマス数を8にします (これが実際に表示する盤面の1辺のマス数です)。
1辺のマス数(仮想)を( 1辺のマス数+2)にします
(これは仮想の盤面の1辺のマス数です。 実際の盤面のマスが8×8であれば仮想の盤面のマス数は10×10となります)。
盤面の中央の座標を0とし、 左下隅マスのx座標を計算します。
盤面の幅が「1マスの幅× 1辺のマス数」(40×8=320)であり、 左下隅マスのx座標は 「-(盤面の幅の半分-1マスの幅の半分)」となります。
左下隅マスのy座標の値は 左下隅マスのx座標の値と同じです。
左下隅マス(仮想)のx座標と y座標は 左下隅マスの座標から 1マスの幅分だけ外側になります。
初期化
-
- 説明
各変数、リストを初期化します。
- コードの詳細
オリジナルは表示しないため隠します。
クローン?をnoにします。
ターンを1(黒)にします。
コスチュームをなしにします。
マスリストの要素を一旦すべて削除します。
仮想の盤面のマスの数だけ マスリストに0を追加します。
マスリストの 各要素が各マスの状態を示します。 この時点ではすべてのマスが「なし」の状態となります。
マスを並べる
-
- 説明
実際の盤面のマスの数(1辺のマス数× 1辺のマス数)だけクローンを作成して配置します。
左下隅のマスから作り始め、右に並べていきます。マスを1行分並べたらその上にまた左からマスを並べます。
仮想の盤面のマス数(1辺のマス数(仮想)× 1辺のマス数(仮想))分の要素を持つ マスリストを用意し、 それぞれのマスの状態を管理します。
それぞれのマスの管理のしかたは 「仮想の盤面とそれぞれのマスの状態の管理」 で説明していますので、そちらを見てください。
- コードの詳細
マスの座標を左下隅マスの座標にします (仮想の盤面の左下隅ではなく実際の盤面の左下隅のマスです)。
番号を 1辺のマス数(仮想)+2にします (8×8の盤面であれば12です)。
まず以下のAの処理を 1辺のマス数(列数)回くり返し、 実際の盤面の一番下の行のマスを並べます。
- A :
自分自身のクローンを作ります。
クローン作成時の処理が進んでから次の処理に進むように念のため0秒待つブロックを置いています。
右隣の列に移動するためにx座標を1マスの幅だけ増やします。
番号を1増やします。 1行分並べ終わったらx座標を 左下隅マスのx座標に戻します。
上の行に移動するためにy座標を 1マスの幅だけ増やします。
右端と左端の仮想のマスを飛ばすために 番号を2増やします。
これを 1辺のマス数(行数)回くり返し、 1辺のマス数× 1辺のマス数(8×8)のマスを並べます。
クローンされたとき
-
- 説明
各マスがクローンされたときにそれぞれがおこなう処理です。
実際の盤面のマスの数が8×8=64であれば、64回実行されます。
- コードの詳細
表示します。
マス番号の値を 番号にします。
マス番号は このクローンが何番目のマス(どの位置のマス)であるかを示します。
x座標、 y座標を マスのx座標、 マスのy座標に保存しておきます。 これはゲーム中にマスを誤って移動させてしまった場合でも 石更新を受け取ったときに元の位置に戻せるようにするためです。
このマスが何行目、何列目であるかも マスの行、 マスの列に保存しておきます。 現在のプログラムでは使っていませんが、改造する場合に使う可能性があります。
マスリストの マス番号番目の値が このマスの状態を示します。
マスリストの マス番号番目の値が0の場合はコスチュームを なしにします。
0以外の場合、0より大きければ(1以上なら)コスチュームを黒にし、 そうでなければ(0より小さければ)コスチュームを白にします。
クローンされたときは0になっているはずですが、 念のため0以外だった場合にどうするのかも書いています。
石を中央に置く
-
- 説明
このゲームは盤面の中央のマスに黒と白の石を2ずつ置いた状態で開始します。
実際の盤面のマス数が8x8(仮想の盤面のマス数が10×10)であれば45番目、 46番目、55番目、56番目の4つのマスに石を置きます。
- コードの詳細
仮想の盤面の全マス数の2分の1から仮想の盤面の1辺のマス数の2分の1を引いた値を 番号にします。
これは中央の4つのうちの左下のマスの番号です。
マスリストの 番号番目の値を1(黒)にします。
次にその右隣のマスを白にします。
(マスリストの (番号+1)番目の値を-1(白)にします。
番号を (左下のマスの番号+仮想の盤面の1辺のマス数)にします。
これは中央の4つのうちの左上のマスの番号です。
マスリストの 番号番目の値を-1(白)にします。
次にその右隣のマスを黒にします
(マスリストの( 番号+1)番目の値を1(黒)にします。
石更新を受け取ったとき
-
- 説明
マスリストのそれぞれの要素の マスの状態 をもとに対応するマスのコスチュームを変更します。
誤って位置をずらしてしまったマスがあれば元の位置に戻します。
- コードの詳細
マスリストの マス番号番目の値 (マスの状態) によってコスチュームを変更します。
マスの状態が0の場合、0でない場合にわけ、0でなければ0より大きい場合、 0より小さい場合にわけるというようにしていますが、マスの状態=-2の場合、マスの状態=-1の場合、 マスの状態=0の場合、マスの状態=1の場合、 マスの状態=2の場合というように順番に確認していっても同じ結果となります。
マスの座標がずれてしまっている場合があるので、もとの座標に戻します。
このスプライトがクリックされたとき
-
- 説明
マスに石がなければ石を置けるかどうかを確認し、 置ける場合は石を置き、ターンを替えます。
すでにマスに石が置いてある場合はなにもせずに終了します。
クリックされたマス(クローン)でのみ実行されます。
- コードの詳細
このマスにすでに石が置いてある場合 (マスリストの マス番号番目の値が0以外の場合) は何もしないでこのスクリプトを終了します。
0の場合(石が置かれていない場合)は以降の処理をします。
裏返せる方向リストを空にします。
石を置ける?を実行します。 これはクリックしたマスの周囲の8方向の状態を調べ、このマスに石を置けるかどうかを確認する処理です。
相手の石を裏返すことができる方向が1つでもあれば石を置くことができます。 裏返すことができる方向は 裏返せる方向リストに追加されます。
裏返す方向があった場合( 裏返せる方向リスト の長さが1以上の場合)には石を置き、 自分の石で挟んだ相手の石を裏返してから相手のターンにします。
それは以下のAの処理でおこないます。
- A :
黒白(仮)→確定を実行します。
これは相手が前回のターンで裏返した石を確定して通常の状態にします。
マスリストの マス番号番目の値を ターンの値にします(自分の色の石を置きます)。
各方向を裏返すを実行します。 これは各方向の相手の石を裏返す処理です。 石を置けないマスだった場合は ポップの音を鳴らして終了します。
石を置ける?
-
- 説明
石を置きたいマスの左方向、右方向、左上方向、左下方向、上方向、下方向、右上方向、 右下方向の順に相手の石を裏返せるかどうかを判定します。
裏返せる方向が1つでもあればこのマスに石を置くことができます。
方向の値は次のようにします。
そのマスの番号に方向の 値を足すとその方向の1つ隣のマスの番号になります。
各方向ごとの判定はこの方向で裏返せる? で判定します。
- コードの詳細
確認結果 を0にします。
左方向(-1)に対してこの方向で裏返せる? を実行します。
右方向(+1)に対してこの方向で裏返せる? を実行します。
方向を 1辺のマス数(仮想)-1にします。 これは左上を指しています。
以下の処理を3回くり返し、6つの方向に対して判定します。
(左上、左下、上、下、右上、右下の順に判定しています)
- A :
方向に対して この方向で裏返せる?を実行します。(上の行の判定)
方向×(-1)に対して この方向で裏返せる?を実行します。(下の行の判定)
方向を1増やします。(方向を1つ右にずらします)
この方向で裏返せる?
-
- 説明
指定した方向に対して1マスずつ確認していき、 相手の石が1つ以上並び且つその先に自分の石があればその間にある相手の石を裏返すことができます。
石を置きたいマスのすぐ隣が自分の石であったり、自分の石にたどりつく前に石がないマスがあったり、 盤面の端まで相手の石が並んでいたりした場合はその方向では裏返すことができません。
- コードの詳細
隣のマスの番号をマス番号+方向にします。
隣のマスに石がなければ(隣のマスの状態が0なら) 確認結果を0にして終了します。
隣のマスに石があるなら(隣のマスの状態が0以外なら)Aの処理をします。
- A :
隣のマスにある石が相手の石である場合、Bの処理をします。
隣のマスにある石が相手の石でない場合(自分の石である場合)、Cの処理をします。 - B :
確認結果を1増やします。
「1ずつ変える」を使っていますが、このプログラムでは「1にする」を使用しても同じ結果となります。 「1ずつ変える」を使うと確認結果 の値と並んでいる相手の石の数が同じとなるので、 この方向に相手の石がいくつ並んでいるのかを確認することができます。 隣のマスの番号と方向を使って この方向で裏返せる?を実行します (同じ方向のさらに1つ先のマスに対して判定します)。 - C :
確認結果が0より大きければ 裏返せる方向リストにこの方向を追加します。
確認結果が0の場合は石を置きたいマスのすぐ隣が 自分の石ということなのでこの方向は裏返せないと判定し、リストへ追加しません。
確認結果が1以上の場合は途中に相手の石があったということなので、 この方向は裏返すことができると判定し、リストへ追加します。 このプロジェクトは仮想のマスを置くことで判定をしやすくしています。
もし仮想のマスを置かずに次の図のような状況で14のマスに黒の石を置けるかを判定するとします。
マスリストの15番目、 16番目とリストの番号を単純に1つずつ増やして調べていくと 17番目の黒の石で挟めると判定してしまいます。 それを防ぐためには端に到達したかのチェックも必要となり、やや複雑になります。
そこでこのプログラムでは石が置かれることがない仮想のマスを実際の盤面の外側に置くことで、 相手の石が続いたまま端に着いたか?という判定をしなくて済むようにしています。
27に黒の石を置けるかを判定する場合、 黒の石がある32のマスにたどり着く前に石がない30の仮想のマスがあるので 裏返すことができないという判定結果となります。
このように端のマスであっても端以外のマスと 同じ判定のしかたができるようにするために仮想のマスを置いています。
各方向を裏返す
-
- 説明
裏返せる方向リストに追加された方向ごとに 1方向を裏返すを実行し、 相手の石を裏返して自分の石にしていきます。
- コードの詳細
番号を1にし、 裏返せる方向リスト の長さの数だけAの処理をくり返します。
- A :
石を置きたいマスの番号と裏返せる方向リストの 番号番目の方向を渡して 1方向を裏返すを実行します。
番号を1増やします。 すべての方向を裏返したら石更新を送ります。
各方向を裏返すが実行された時点では マスリスト の中の値だけが更新されているだけで、 画面上のマスの状態は変わっていません。
石更新を 受け取ったときの処理の中で実際にマスのコスチュームを変更します。
1方向を裏返す
-
- 説明
隣のマスの石が自分の石であるか、もしくは石がない場合は何もせずに終了します。
隣のマスが相手の石である場合は自分の石に変更し、さらに隣のマスの番号を渡して 1方向を裏返すを実行します。
- コードの詳細
隣のマスの番号をマス番号+方向にします。
「ターン」×「マスリストの 隣のマスの番号番目の値」が 0未満(負の値)であれば隣のマスには相手の石があると判断します。
ターンは 黒なら1、白なら-1です。隣のマスに石がなければ「 ターン」×「マスリストの 隣のマスの番号番目の値」は必ず0になります。 ターンと隣のマスの石の色が同じである場合は同じ符号同士の かけ算であり黒×黒、白×白のどちらの場合も正の数(0より大きい)となります。
ターンと隣のマスの石の色が異なる場合は異なる符号同士の かけ算であり黒×白、白×黒のどちらの場合も負の数(0より小さい)となります。
隣のマスの石が相手の石なら「マスリストの 隣のマスの番号番目の値」をターン×2(2または-2)にし、 さらに隣のマスの番号を渡して 1方向を裏返すを実行します。
これは指定した方向に対して、 自分の色の石に当たるまで相手の石を裏返しています(石がないマスに当たった場合も この処理を止めるようにしていますが、実際 には裏返すことができる方向に対してのみ 実行するので石がないマスに当たることはありません)。
黒白(仮)→確定
-
- 説明
石を置いたら、その前のターンで裏返した石の状態を確定します(2から1へ、または-2から-1へ変更します)。
- コードの詳細
番号を1にし、 マスリストの長さの数だけAの処理をくり返します。
- A :
マスリストの 番号番目の値が1より大きい場合(2の場合)は
マスリストの 番号番目の値を1にします。
マスリストの 番号番目の値が-1より小さい場合(-2の場合)は
マスリストの 番号番目の値を-1にします。
番号を1増やします。 すべての2を1へ、-2を-1へ変更し終わったら 石更新を送ります。
ターン
がクリックされたとき
-
- 説明
コスチュームと座標を設定します。
- コードの詳細
コスチュームを黒にします。
x座標を-200、y座標を160にします。
石更新を受け取ったとき
-
- 説明
ターンの値によってコスチュームを黒、 白のどちらかに設定します。
- コードの詳細
ターンが0未満(-1)ならコスチュームを白、 そうでなければ(1なら)コスチュームを黒にします。
PASSボタン
がクリックされたとき
-
- 説明
座標を設定します。
- コードの詳細
x座標を-200、y座標を120にします。
このスプライトがクリックされたとき
-
- 説明
ターンを切り替えます。
- コードの詳細
ターンを ターン×(-1)にします。
(黒(1)なら白(-1)へ、白(-1)なら黒(1)にします)。 石更新を送ります。
RESULTボタン
がクリックされたとき
-
- 説明
座標を設定し、黒、 白を隠します。
- コードの詳細
x座標を-200、y座標を84にします。
結果表示を0にします。
黒を隠します。
白を隠します。
このスプライトがクリックされたとき
-
- 説明
黒の数と白の数の表示/非表示を切り替えます。
- コードの詳細
結果が表示されていない(結果表示=0)の場合、 黒と白の数を集計して表示します。
黒白集計を実行してそれぞれの数を集計します。
黒、白を表示します。
結果表示を1にします。結果が表示されている(結果表示=1)の場合、 黒、白を隠し、 結果表示を0にします。
石更新を受け取ったとき
-
- 説明
石更新を受け取ったら 黒、 白の数を集計しなおします。
- コードの詳細
結果が表示されている(結果表示=0)の場合のみ、 黒白集計を実行します。
黒白集計
-
- 説明
各マスの状態をチェックし、黒の数と白の数を集計します。
- コードの詳細
黒を0にします。
白を0にします。
マス番号を1にし、 マスリスト の長さの数だけ以下の処理をくり返します。
「マスリストの マス番号 番目の値」が0より大きい(1または2)場合は、 黒を1増やします。
「マスリストの マス番号 番目の値」が0より小さい(-1または-2)場合は、 白を1増やします。黒を1増やします。
用語の説明
マスの状態
(※)裏返したばかりの状態。
次のターンが終わったら確定して、通常の状態( )になります。
仮想の盤面とそれぞれのマスの状態の管理
- 実際の盤面(緑のマス)の周りに1マス増やしたものが仮想の盤面です。
実際の盤面を8×8マスとした場合、仮想の盤面は10×10マスとなります。
仮想の盤面のマス数(10×10マスであれば100)の要素を持つマスリストで それぞれのマスの状態を管理します。
仮想の盤面のマスとマスリストの各要素は次の図のように対応させます。
Start
主な動き
- がクリックされたらコスチュームをStartにして表示する。
- クリックされたら各スプライトへStartを送り、 非表示にする(各スプライト Startを受け取ってゲーム開始)。
がクリックされたとき
-
- 説明
- ゲームスタートの準備をする。
- 必要な処理
- 座標の初期化
Startの表示
マウスポインターが上に乗ったとき色を変える - コードの詳細
-
x座標(横の表示位置)を0、 y座標(縦の表示位置)を0にします。
コスチュームをStartにして表示します。 (ゲーム終了時は非表示になっているため)
マウスポインターがこのスプライトに触れているときは色を変え、 離れたら元の色に戻します。
このスプライトがクリックされたとき
-
- コードの詳細
-
コード「 がクリックされたとき」が動作しているので、止めます。
各スプライトにStartを送りゲームを開始します。