読者です 読者をやめる 読者になる 読者になる

ゴトーのブログ

プログラミングを学習したり、スポーツやゲームや漫画などの三度の飯より好きなことを語ったりするブログです。

プログラミング学習日記10日目 ~コンピューターが弱すぎるJavaScript製マルバツゲーム~

JavaScript プログラミング
広告

どうも、ゴトーだ。

f:id:hogehoge223:20161111111638p:plain

今はPHPとJavaScriptを並行して学習している。
PHPの方は掲示板以上のものになるとなかなかアウトプット出しづらいので、JavaScriptで学習したものを少しずつ出していきたいと思う。

2日前にストップウォッチとタイマーを作ったので、今回は簡単なゲームを作りたいということで、マルバツゲームにしてみた。
一応コンピューター対戦という名目になっているが、余りにも弱すぎて負けるのが難しいので「コンピューターが弱すぎるマルバツゲーム」というタイトルにした。

f:id:hogehoge223:20161109221042p:plain

10日目の成果物: コンピューターが弱すぎるマルバツゲーム

f:id:hogehoge223:20161111112455p:plain

個人的にゲームで育ってきただけあってゲームっぽい何かを作りたいんだが、いかんせんHTMLとJavaScriptでは高度なグラフィックができないし、そもそも本格的なゲームが作れるなんて最初から思っていないので、最も簡単そうに作れそうで定番のマルバツゲームにしてみた。

幸い検索してみたらサンプルコードがいろいろみつかったので、それを参考に作ってみた。
jQueryは勉強中だが今回はjQueryを使わずにやってみた。今の所doucment.querySelectorとdocument.getElementByIdだけで何とかなっているので、特にjQueryの必要性は感じなかった。

作り方、実装方法

盤面の表示

最初にハマったのはどうやって盤面を表示するかということで、こちらのブログや質問などを参考にさせてもらった。

そんで結局試行錯誤した末に、盤面を配列で0~8まで確保しておいて、その配列の値に応じて、盤面を表示するということにした。
具体的にはマスが3×3で9マスあるのだが、左上から0, 1, 2, 3…というふうにみなして、それぞれのマスに当たる配列の値が1なら◯、-1なら✕とした。

そしてユーザーやコンピューターがあるマスに打った時に、そのマスに該当する配列の値を設定して、新しい値に応じて盤面を更新するということを行っている。

あくまで実態は配列の値にあるから、配列の値を見ればどちらが勝ったかを判定することができるし、それをもとに盤面をいつでも更新できるというメリットがある。

それぞれのマス目はHTMLのdata属性を使って、クリックしたマス目がどの配列に属しているかを設定している。
この場合、盤面の配列は「boardState」という変数にしていて、「boardState[0]」の値が1なら自分が打った場所ということで、◯が表示されることになる。

ターン

自分のターンを1、相手のターンを-1として、どちらかが打つ度にターンを入れ替えるという仕組み。

打つまでの動作

まずそれぞれのマス目にクリックイベントを設定する。

少してこずったのが、複数のHTML要素にイベントを設定する時には、querySelectorAllによって配列を取得してから、その配列をループで回して、それぞれにイベントを設定しなければならないということ。
「このクラスを持っているもの全て」みたいなイベントの設定ができなかったのが面倒に感じた。

そしてクリックされたら、そのマス目が持つ値を取得する。
この場合は「getAttribute('data-sequence')」によって認識できる。

そうしたらdata-sequenceにあたるマスが既に○か✕が置かれていないかチェックして、置かれていたらアラートを表示する。

f:id:hogehoge223:20161111114433p:plain

さらにこれは終了判定を実装した後のことだが、ゲームが終了していてもアラートを表示する。

f:id:hogehoge223:20161111114512p:plain

このような感じで、打とうとしたマスが実際に打てるかを判別して、打てるのならばマスの状態を管理している配列に値をいれる。
値を入れた時に、終了判定を行い、ターンを入れ替えて、盤面を更新するということを繰り返し行う。

コンピューターの動作

自分が打ったら、コンピューターのターンに移る。

コンピューターは単に空いているマスの中からランダムで一つのマスに打つだけ。
相手がリーチをかけていてもお構いなしに好きなように打ってくるので非常に弱い。

相手のリーチを察知してそこを未然に防ぐようなプログラムを書けばいくらかマシになる気がする。

一応臨場感を出すために、0.5秒間待機してから打ってくるが、本当は一瞬で打ってくる。

終了判定

ここが最後まで正しい実装方法がわからなかった。
マルバツゲームは8パターンの終了条件があるのだが、その8パターンを全てif文で書くというみっともない書き方をしてしまった。

それとハマったところとしては、3つのマスが同じ値かどうかを判定するために、

a == b == c

という書き方をしたのだが、JavaScriptはこれだと上手く判定してくれないらしい。
結局やり方がわからず、英語で検索して見つかったものをそのままコピペしてしまったが、原理がわからないので気持ちが悪いところでもある。

stackoverflow.com

学習した感想

値を保持してから、それを盤面に表示するということで、少しプログラミングっぽいことを初めて行った気がする。
アルゴリズムなんて立派なものでもないけど、ゲームの進行を管理することで、プログラミングの基礎な部分を学習できた。

それと当たり前だけど、終了条件なんかは上手く書けなかったので、まだまだ未熟だと感じるところでもあった。

ただ総じて言えば、最終的にそれっぽいものはできたのでJavaScriptで初めて達成感があった。
PHPと比べてクセが強いというか、なんか馴染まない感じが未だにあって、まだまだ苦戦してばかりだが。

次回はマルバツゲームを更に改良するか、PHPと連動して戦績を保存したりすることにも挑戦したい。