ミニゲーム制作をとおして学ぶJavaScript 第1回 コードを書き始める前に必要なこと
ほんのちょっぴりの知識しかないピクセルグリオ君が、エンジニアの先生にJavaScriptの手ほどきを受けます。いきなりプログラムを書くのかと思いきや、第1回にコードは出てきません。さて、先生は何を教えてくれたのでしょう。待望の超入門シリーズです。
- カテゴリー
- JavaScript >
- JavaScriptの実践
発行
はじめに
このシリーズは、JavaScript入門者が、High/Lowゲーム制作をとおして、プログラミングの基本や考え方が学んでいくものです。登場人物は次の2人です。
先生
このシリーズにおけるJavaScriptの達人の先生。実務では、クライアントにとってちょうどいいエンジニアリングを日々探求しているエンジニア。学ぶ意欲を大切にし、やる気のない生徒にはやや冷たい。愛用のエディタソフトはVim。グリオ君
プログラミング入門者。JavaScriptは学んでいるのでコードは少し書けるし、ググることで構文を探してくることはできる。しかし、それらを一つの「アプリ」としてまとめるのはまだ難しいと思っている。
もしあなたがプログラミング入門者なら、グリオ君といっしょに考えてみてください。もしすでにある程度コードを書けるなら、このシリーズは自分が入門者に教えるときに、どんなふうに進めるかということのヒントになるかもしれません。
それでは、はじまり、はじまり。
記事中に登場する先生とグリオ君はフィクションです。また、記事中、コード表記など、不統一や乱れがありますが、シリーズ後半で整えられます。
ゲームを「案件定義」してみよう
先生:プログラミングの学習では、なにか作るときに「TODOアプリを作る」ということが多いんですけど、そこまで簡単かと言われると、そうでもないんですよね。ですから、今回はもう少し簡単なものからやってみましょう。次のうち、どれを作ってみたいですか?
- ブラックジャック
- High/Lowゲーム
- 三目並べ
グリオ君:そうですね……High/Lowゲームかな!
先生:わかりました。High/Lowゲームを作ってみましょう。自分が作りたいと思うものを作ることが大切ですよ。
High/Lowゲームは、次のようなゲームですね。
High/Lowゲームのルール
まず、出題者が決められた範囲の数字から一つ選んでおく。回答者はその数字を知らない。そして、回答者が適当な数字を言って、それより高いか低いかだけを出題者は答えていく。決められた手数以内に当てられたら回答者の勝ち、当てられなかったら負けというゲーム。
それでは、これをJavaScriptで作ってみます。
さて、まずはHigh/Lowゲームとは何かを文章で書いてみましょう。いわゆる「仕様」ですね。今私が言ったルールを、細かく考えていきますよ。
グリオ君:えーっと、こんなかんじでしょうか。
High/Lowゲームの仕様
1. 出題者がある範囲の中から数字一つ選ぶ
2. 回答者が一つ数字を答える
3. 出題者はその数字が自分の提示した数字より大きいか(high)、小さいか(low)答える
4. 回答者は出題者のhigh/lowを受けて、数字を出し直す
5. 3.と4.を数回(規定数)繰り返す
6. 規定数内に回答者がぴったりな数字を提示できたら、回答者の勝ち。できなかったら出題者の勝ち
7. なんかするとリセットされて、新しいゲームが始められる
要件定義を見直す
先生:ふむふむ。でも、この書いた仕様はもっと具体的に書けるところがないかな? 上から見直してみましょう。
グリオ君:はい……まず1つ目の「ある範囲」は「どの範囲」か。
先生:そうですね、それが深められますね。
グリオ君:じゃあ、ここは0〜10までの整数にします。
先生:あと、3番目の手順にもう一つパターンがありませんか。Highじゃなくて、Lowじゃなくて……?
グリオ君:うーん…あ! 「同じ」か。
先生:そうです。一発で当たった場合ですね。答えが当たっていたら、回答者の勝ちで終了ですね。
5つ目の「規定数」をどうしましょうね? 当たるまで永遠にもできます。でもまあ、答えとなる数字が0〜10しかないので、3手くらいで絶対当たるでしょうね。
グリオ君:とりあえず最初は当たるまでにします。
先生:そうすると、7番目の前が……。
グリオ君:「当たったら終了」ですね!
先生:そうですね、まとめると、こんなかんじでしょうか。
High/Lowゲームの仕様(アップデート版)
1. 出題者がある範囲の中から数字一つ選ぶ
- ある範囲:0〜10の整数
2. 回答者が一つ数字を答える
3. 出題者はその数字が自分の提示した数字より大きいか(high)、小さいか(low)、同じ(same)か答える→sameなら6へ
4. sameでなければ、回答者は出題者のhigh/lowを受けて、数字を出し直す
5. 3と4を数回(当たるまで)繰り返す
6. 当たったら終了
7. なんかするとリセットされて、新しいゲームが始められる
先生:今やってきた作業のことを、「要件定義」と呼んだりしますね。なにか作ろう! となったら、まずこういうふうに何を作ろうとしているのか、どう作ろうとしているのかを明文化することが必要です。最初のうちは、いきなりコードを書き始めようとしてはいけません。
今回のような簡単なものでさえ、最初に考えた仕様には、ぽんぽん穴が見つかりましたね。これが実際の案件だったら、もっとあり得ます。
「モデリング」でなにが必要か考えよう
先生:作りたいものが決まって仕様も考えられたので、コードを書いていきたいところです。ですがその前に、どんなふうにコードを書いていけばいいかも、先に書き出しておきたいですね。なにが必要そうですかね?
グリオ君:「なに」とは、なんでしょう?
先生:どういうデータを用意して、どういうデータに対してコードを加えたらこうなってほしい、という仕組みを考えることです。これは、「モデリング」という作業です。
グリオ君:なるほど、「データをどう取り回すか」ですか。全体の仕組みというか、流れ、ですね。
先生:そうそう。そう考えると、なにが必要でしょうか。
グリオ君:えーと、まず、出題者が数字を選べる。あとは、数字を提示する回答者も必要ですよね。そうしたら、出題者と回答者の数字を比較するわけだから……
登場人物
答えを持った出題者
数字を提示する回答者
先生:そうですね、基本的にはこの2つがやり取りするわけですね。でもこの2つが、勝手にやり取りしてくれるわけではありません。だから、コードを書く人が「出題者はこれして、回答者はこれして」という指示をしないといけないですね。この「枠組み」も考えましょう。要件定義の7番目にヒントがありますよ。
グリオ君:うーん……「ゲーム」?
先生:そう、「ゲーム」という枠組みが必要ですね。出題者も回答者も、そのゲームに属していますよね。リセットされると前の出題者と前の回答者はどっか行きますよね? なので「ゲーム」という世界に「出題者」と「回答者」がいる、ということですね。
グリオ君:なるほど。たいてい、この「ゲーム」にあたるものってあるんですよね?
先生:「アプリ」とか「ページ」とかが、それにあたりますかね。
さて、そうしたら、次のように、それぞれの機能を考えていきましょう。
機能の構造化
- ゲームが持つ機能
- 出題者が持つ機能
- 回答者が持つ機能
グリオ君:はい。出題者が持つ機能としては、選んだ数字を持つ。それから、回答者も数字を選ぶ。
先生:はい、選んだ数字を持っていなくてはいけないですね。どちらもこれは同じですね。では、さっき要件で出した「数字の、ある範囲」というのは、どこに持たせましょう? 少なくとも、出題者はある範囲を知らないと数字を選べないですよね。
グリオ君:でも知らなければ、誰かに聞いてくればいいというのもありますよね?
先生:そうですね、聞くという手もありますね!
グリオ君:どっちがいいんだろう。ゲームが知っていて出題者が聞くという方法と、出題者が範囲を知っているのは、どっちがシンプルかな?
先生:では、こう考えてみましょう。ゲームが数字の範囲を知っている場合、回答者もそれを知ることができますよね。
グリオ君:そうです。
先生:でも、回答者がそれを知る必要はどうでしょうか。知ってる必要はないけれども、知っていたらお得と言えばお得ですよね? だって「0から10」という数字の範囲を知らなかったら、「100」と回答することもありえるわけです。
そう考えると、知っていたほうが親切であろうということであればゲームに持たせた方が良いということになりますね。
グリオ君:なるほど。わかりました。選べる数字の範囲はゲームが持つことにします。
先生:あとゲームの仕事は何でしょうね。
グリオ君:ゲームの仕事は……場の提供? ゲームを始める?
先生:そうです!
グリオ君:それから、回答者が数字を選んだら、highかlowか出すし、もしsameだったら終了になるわけですよね。そいう分岐はどうやって整理すればいいのでしょう?
先生:それもゲーム(枠組み)で判断させてもよいですが、今回はそういうコードを「私」が書けばOKということにしましょうか。つまり「神である私」が必要ですね。
まず「ゲーム」という場を机の上にぼんと置きますよね。そこに出題者と回答者がいるわけです。で、「よしスタート!」と、スタートボタンをポチッと「私」が押す。そうすると出題者が数字を出して、回答者としての私もしくは違う誰かが代わりに回答すると両者の数字が出揃います。それを「私」または出題者が、もう一周続けるか、終了するか判断する。
というのが、コードを書く「私」です。私は絶対そこにいるので、あえてここで定義したりしなくてよいですね。
グリオ君:なるほど。わかりました。
先生:後はリセットできる機能だけ足りないですね。
グリオ君:そうか、リセットか。当たってゲームが終わりになって、もう一度やりたい場合ですよね。ゲームのところに「ゲームを始める」が入っているから、リセットはゲームを呼べばいい?
先生:そうですね、始めるとはつまりやり直すこと。とりあえず、ゲームの途中でリセットするのはブラウザをリロードする、ということでいいのではないですかね。ここまでの話をまとめると、どうなるかな?
グリオ君:こんなかんじです。
モデル
- 私
- 出題者と回答者の数字を比較する
- 比較した結果を表示する
- 再度回答者に提示を促す
- 終了を知らせる
- リセットする
- ゲーム
- 新規にゲームを始める
- 選べる数字の範囲
- 答えを持った出題者
- 選んだ数字を持つ
- 回答者が選んだ数字を判定する
- 数字を提示する回答者
- 選んだ数字を持つ
先生:ざっとこんなものですかね。これも大事なステップです。何を作ろうと思っているのかという下調べのことですね。
「こういうものを作りたい」というのが、言葉にできなければプログラムに表現することは絶対できないのですよ。こうやって書き出しておくと、他の人とも、「あと、こういう機能も入るんじゃない?」という話ができますよね。これらをそのままコードに落とし込めなかったとしても、機能の実装漏れなどはなくすことができるはずです。
グリオ君:そうですよね。次はゲームの画面を考えるのかな? HTMLを用意するとか?
先生:ちょっと考えてもらいたいのですが、このゲームは画面がなくても作れますよね?
グリオ君:え!?
「ワイヤーフレーム」を考えよう
先生:コンソールログを使ってゲームを作ることもできるし、ターミナルでもできる。なにが言いたいかというと、あらゆるもののUIは、基本的に後付ということです。画面なくても作れるというのを知らないがゆえに、いきなり画面から作り始めちゃう人が多い。そうすると、書かれたコードは画面べったりになりやすいんですよね。
というわけで、なにごとも画面なしでまずロジックを考えて、それを画面から動かせるようにするというのが、入門者にはわかりやすいですね。それに気付かずに書き始めちゃって、余計なところでつまずいちゃう人も多いです。
今までの作業を思い返してもらいたいのですが、今までのところビュー(見た目)に関するものは一切登場していないですよ。中で入力されたデータをどういうふうに取り回すか、というところしか考えていないですよね。
グリオ君:はい。
先生:もちろん、どういう画面にしたいかによって実はこういう機能が必要だったということにもなる。だから同時並行でやるのが一番いい。でも、ここでいきなりHTMLを書き始めたり、すばらしいデザインを作ったりするのは一番ダメ。どういう画面にするかも決まっていないのに手を動かし始めるというのはダメです。
グリオ君:はー……。
先生:だから、まずはそのへんの紙に手書きしたり、レイアウトソフトを使ったりして、こういう画面にしたいというイメージを書いてみましょう。きれいなデザインになっていなくていいんです。これが、「ワイヤーフレーム」を作るという作業です。
グリオ君:実際の案件では、ワイヤーフレームはクライアントから支給されるものなんですか?
先生:それは案件によりますね。案件によっては、「それ、どうやって作るんですか!?」っていうようなトンデモ画面を提示されることもあったりとか……データベースにそんな値はないのに「こういう値を出して欲しい」みたいなことになっていたりとか……。まったく、ワイヤーフレームは、ちゃんとエンジニアが同席して決めて欲しいっつーの……。
グリオ君:せ、先生!?
先生:あっと、はいはい! 書けましたか?
グリオ君:ええっと、回答者の入力欄をボタンを並べて、数字を選んだらその結果が右側の枠に出ると……こんな感じかな。ビンゴだったら「Play Again」ボタンが出る。
先生:画面のイメージもできましたね。この画面によって、要件定義から漏れていた、新たに入れておかなきゃいけない機能はありませんよね?
グリオ君:……多分……ないですよね。
先生:じゃあ、設計が間違ってなくてよかったですね。
グリオ君:そうか、この画面を書いた時点で、「このときどうするんだっけ?」という問題が出てくることもあるんですね。
先生:そうです。出てきたならば、それを踏まえて再度要件を定義しないといけないですね。それぞれ、足りないものがないか、確認して、足りなかったら足していきます。
- 要件定義する
- モデリングする
- ワイヤーフレームを作る
今回はこの作業を行いました。
さあ、次はいよいよコードを書いていきましょう。