見出し画像

JavaScriptで時間あてゲームを作ろう

質問はTwitterよりDMでお受けしています。

Java Scriptとは


JavaScript(以下、JSと呼びます)はWeb開発において必須の存在です。主にWebサイトのページ内に記述され、Webブラウザ上で、実行されるプログラム言語です。現在、「ライブラリ」という便利な機能を集めたものが多く開発され、世界中で利用されています。
例えば、有名なJSのライブラリやプラットフォームには「jQuery」や「React」、「Node.js」などがあります。

画像1


JSを別ファイルに書き出して、そのファイルをHTMLから読みむように構成します。VS Code(まだエディタをインストールされていない方とHTMLがわからない方は、まずこちらを参照してください)でindex.htmlというファイルをデスクトップに新規作成・保存してください。HTMLのテンプレートを挿入したら、<html lgang=”ja”>としてください。
そして<body></body>sの間で、script:と入力、tabを押します。そうすると、<script src=””></script>と出てきます。
“”にファイル名index.jsとしてください。

画像2

次にそのindex.jsというファイルを作成し、index.htmlと同じフォルダに保存します。
index.jsに次のように入力してみます。
document.write(‘1たす2は’);
document.write(1+2);
document.write(‘です’);

画像3


デスクトップに戻り、index.htmlのファイルをGoogle Chromeで開くとscript内で記述した処理の結果が表示されます。

画像4


次に、コンソールという画面に文字を出力(表示)します。
「console.log(“○○”);」というJSのコードを書くと、丸かっこの中の○○という文字がコンソールに出力されます。
console.log(  )は(  )内に入力された数値をコンソールに出力します。文字列を出力する場合はシングルクォーテーション(‘)かダブルクォーテーション(“)でその文字列を囲みます。

画像5


セミコロン
JSは文の最後はセミコロン(;)で終わります。セミコロンはなくても正常に動作する場合が多いですが、思わぬ不具合が生じる可能性があるので、忘れずにつけましょう。

検証ツールとコンソール

index.htmlをGoogle Chromeで開いた画面。ここで、右クリックをすると、検証が出てくるので、さらにクリックしてください。

画像6

画像7


デビロッパーツールが開きます。右の方にconsoleとありますね。ここがconsole画面です。先程console.logで出した「計算結果を表示しました」と出ています。

document.write()とconsole.log()


「document.write(‘こんにちは “);」と「console.log(‘こんにちは’);」、いずれの書き方でも計算結果や文字をブラウザに表示することができました。ここで、2つの違いについて説明しておきます。「document.write)」はHTMLの本文を書き込む命令です。このJavaScriptが埋め込まれたHTML を閲覧している人は、誰でもその内容を見ることができます。一方、「console.log()」はコンソールに文字列を表示する命令です。この JavaScriptが埋め込まれた HTML を閲覧している人は、デベロッパーツールでコンソールを開くまで、その文字列を見ることができません。デベロッパーツールはその名のとおり、開発者向けのツールです。そのため、「console.log()」は基本的には開発者が見るための表示、「document.write()」はページを閲覧する人全員が見るための表示と覚えておいてください。

今回の「計算結果を表示しました」というログは開発者(あなた)が確認するための途中経過であって、ページを閲覧している人向けのものではないため、「console.log()」を使っているのです。

掛け算「*」、割り算「/」


プログラミングでは、足し算・引き算以外の計算も可能です。
左の図のように、掛け算は「*」(アスタリスク)、割り算は「/」(スラッシュ)という記号を用いて計算することができます。これらの記号は数学で用いるものと少し違いますので、しっかり覚えましょう。

画像8

画像9

「%」記号を使うと、割ったときの余りを求めることができます。(プログラミングでは余りの計算を使う機会がよくありますので、しっかりと覚えておきましょう!)

JSの変数


プログラミングでは「変数」というものがしばしば用いられます。変数は、データ(値)の入れ物です。箱についている名前が「変数名」であり、箱の中に実際の値(文字列や数値など)が入っています


変数は「let 変数名 = 値」として定義します。プログラミングの「=」は「等しい」という意味ではなく、「右辺を左辺に代入する」という意味です。「let」は「これから変数を定義します」という宣言で、その後ろに変数名を書き、値を代入します。

画像10

画像11


変数の使い方は簡単です。左の図のように「”John”」という値が代入された変数nameを出力すると、図のように「”John”」という値が出力されます。

let name=”John”;
console.log(name);

>_コンソール
John

実際のプログラムの中には多くの値が登場します。プログラムを書く時は、それらの値を間違いのないように、そして値の変更に対応しやすいようにすることが求められます。それを助けるための1つの仕組みが変数です。変数には以下のようなメリットがあります。

1、同じ値を繰り返し使える
2、変更に対応しやすい
3、値の意味が分かりやすい

「number = number + 10」といった書き方には、省略した書き方もあります。 よく使いますので、ぜひ覚えましょう。
x=x+10→x+=10
x=x-10→x-=10
x=x*10→x*=10
x=x/10→x/=10
x=x%10→x%=10

変数とよく似たものに、定数があります。
定数はletの代わりにconstを用いて定義します。
定数のメリットは、「後から値を更新できない」ところにあります。これは一見不便に感じるかもしれません。ですが、予期せぬ更新を防ぐことができ、より安全なコードを書くことができます。これはコードの量が増えるにつれて徐々にメリットとして感じると思います。

ループで繰り返し処理を実行する


「1から100,000までの数を書き出す」プログラムを作るとき、ループという機能を使うことで、繰り返しの作業を簡単に書けます。

ループとは、プログラムにおいて繰り返しを行う処理のことをいいます。JavaScriptでループを行うときには、for文を使います。それではさっそくJavaScript で for文を書いてみましょう。100回繰り返し処理を行うfor文は、次のような内容になります。

for (let i = 0; i < 100; i++) {
// 100 回繰り返しを行いたい処理
}

このfor文がどのような意味なのかひとつひとつ見ていきましょう。

let i = 0

まずこの部分は、初期化式といって、ループを開始する前に実行される処理です。ここでは、変数iを宣言して0を代入しています。この処理は最初の1回だけ実行されます。

i<100

次にこの部分は、条件式といい、繰り返しの処理を実行するかどうかを判断する論理式を書きます。ここでは、「変数iが100より小さいときに繰り返しの処理を実行する」という意味の論理式を書いています。

i++

最後にこの部分は、変化式といって、ループの繰り返し処理を繰り返すごとに実行される処理です。この「i++」という書き方は、次の代入命令を簡略化して書いたもので、数値」を1だけ増やして再代入するという処理をします。

i = i+1

まとめると、for文の構造は次のようになります。

for (初期化式; 条件式; 変化式) {
// 繰り返しを行いたい処理
}

今回のプログラムは、変数iが0からはじまり(初期化式)、繰り返し処理を繰り返すごとに1ずつ数値が大きくなり(変化式)、100になると繰り返し処理を終了する(条件式)という意味になります。つまり、変数iが0から99になるまでの間の100回、処理を繰り返すわけです。

JSの条件分岐

プログラミングを学んでいると「ある条件が成り立つときだけある処理を行う」という場面が出てきます。このようなプログラムを条件分岐と言います。


if文を用いると「もし○○ならば●●を行う」という条件分岐が可能になります。ifの後ろに条件式を書き、それが「成り立つ」場合の処理を{ }の中に書きます。
下の図でif文の書き方のイメージを掴みましょう。

画像12

const number = 12;
if(number>10){
cpnsole.log(‘numberは10より大きいです。’)
}

>_コンソール

numberは10より大きいです。

関数とは


関数とは、ひとかたまりの処理に名前を付けて、再利用できるようにしたものです。実は、ここまでで紹介してきた「alert(‘警告 “);」のalert の部分、「console.log(‘ログ’);」のlogの部分、「document.write(‘HTML’);」のwriteの部分はそれぞれ関数の名前であり、上記はどれも関数を利用する記述でした。

これらの関数は「組み込み関数」といって、ブラウザで最初に使えるようにしてある関数です。つまり、すでにみなさんは関数を使っていたことになります。

これらの関数を自分で作ることもできます。次のコードは、現在の日時をコンソールに出力する処理をまとめたものです。まず最初に「関数」という意味の「function」という宣言を書き、その後に「logDate」という関数名を設定しています。関数名の後には、()を書いて、{ }の中に処理を書きます。

function logDate() {
console.log(new Date());
}

実際に関数を作って実行してみましょう。Chromeのデベロッパーツールの[Console] タブを開き、上のコードを入力します。最初の「」のあとの改行は、Shift] + Enterキーを押して入力する必要があります。というのも、コンソール上で普通に Enter]キーを押すと、その時点でプログラムが実行されてしまうためです。最後の「」のあとは、実行したいので Enterキーを押して構いません。

なお、

new Date()

という記述は、現在の日時を値として取得できる記述です。このような「new」を用いた記法も、一種の関数の呼び出しといえます。つまりlogDate関数では、現在の日時を値として取得し、それをコンソールに出力するという処理をまとめているわけです。関数の入力後は、次のように関数を呼び出すコードを入力して、Enterキーを押します。

logDate 関数を呼び出す

logDate();

「logDate();」と入力するたびに、次のような形式で、現在の日付と時間が表示されます。これが関数の基本的な使い方です。

関数に渡す値によって処理を変える
logDate関数は、「現在の日時を値として取得し、それをコンソールに出力する」という2つの処理をひとかたまりにしただけでした。ですが、これでは決まりきった処理しかできません。たとえば、数値を2乗する関数「square」を作るとしましょう。これまで学んできた方法だと、次のような関数になります。

5の2乗を求める関数
function square() {
console.log(5 * 5);
}

しかしこの関数では、5の2乗しか求めることができません。関数に渡した値を2乗して出力する柔なプログラムにするには、次のように記述します。

数値の2乗を求める関数

function square(n) {
console.log(n * n);
}

この例で()の中に入っている「n」は、引数(ひきすう)と呼ばれます。引数は、関数を呼び出すときに、関数に渡すデータのことです。関数を呼び出すときに()の中に値を入力することで、その値が関数の変数nに渡され、変数nを使って計算を実行してくれるというわけです。

Chromeのデベロッパーツールの[Console] タブを開いて、上の関数を入力したあと、次のコードを参考に関数を呼び出してみましょう。

関数に引数を与える

square(3);

( )の中に3を入力したときは「9」、12を入力したときは「144」と表示されるはずです。

関数の呼び出し元に値を戻す

プログラムを作っていると、関数の中で処理したデータを別のところで使いたいことも出てきます。このように関数の中で処理を完結するのではなく、関数の呼び出し元に処理したデータを戻したいときは、return文を使います。returnの後ろにデータを記述すると、そのデータが関数の呼び出し元に戻されます。先ほど作った関数 square を書き換えて、データを戻すように変更しましょう。コンソールに次のコードを入力して下さい。

値を返す関数

function square(n) {
return n * n;
}

2行目の「return n* n」は、「n*n」の結果を、この関数の結果として戻すという意味です。この関数の結果のことを、戻り値といいます。JavaScriptでは、戻り値を記述するためにreturn文を用います。

関数の入力後、次のように関数を呼び出すと、変数 result に関数の結果「144」が代入されていることが確認できます。

値を返す関数を呼び出す

var result = square(12);
console.log(result);

オブジェクトとは


オブジェクト (object) とは、JavaScript における値の1つです。オブジェクトは、プロパティという、名前と値のセットを複数持つことができます。学校の生徒を例に考えてみましょう。生徒は、氏名や年齢、クラスなどさまざまな特徴を持っています。これがプロパティです。そしてプロパティは、「氏名:太郎」「年齢:15歳」「クラス:B組」のように、名前と値のセットで成り立ちます。

ではさっそく、オブジェクトの書き方を見てみましょう。

生徒のオブジェクトを作る

let student = {
name: ‘太郎’,
age: 15
};

オブジェクトは、{ }で宣言し、その中にプロパティを「プロパティ名:値」の形式で宣言します。プロパティが複数ある場合には「,」(カンマ)で区切ります。

上記の例では、nameとageという2つのプロパティを持つオブジェクトを作り、studentという変数に代入しています。15歳の太郎さんという生徒を表したオブジェクトです。

このように、現実世界のものを単純化して表現したものをモデルといい、単純化して表現することをモデリングといいます。JavaScriptでは、オブジェクトを使ってモルを作ることができます。

オブジェクトのプロパティを取得する

プロパティの値は、取得して変数に代入したり、コンソールに出力したりすることができます。Chromeのデベロッパーツールで[Console] タブを開き、次の生徒オプジェクトのコードを入力してみましょう。コードの途中の改行は、キーを押して入力し、最後に Enter」キーを押すことで実行できます。

生徒オブジェクト

var student = {
name: ‘太郎’,
age: 15
};

次に、生徒オブジェクトのプロパティの値を取り出して、コンソールに出力します。

次のコードをコンソールに入力して下さい。

プロパティの値を取り出す

console.log(student.name);
console.log(student.age);

これらを入力すると、次のような結果が表示されます。

太郎
15

プロパティの値を取得しコンソールで確認

このように、オブジェクトのプロパティは、「オブジェクト名.プロパティ名」で取得できます。また、プロパティは変数と同じく、任意の値を代入・更新することができます。

プロパティの値を更新する

オブジェクトのプロパティは一定である必要はありません。プログラムを書いていると、クラスが変わった。年齢が上がったなどの理由で、オブジェクトのプロパティを更新したいシチュエーションも出てくるでしょう。

プロバティの値を更新する方法も覚えておきましょう。生徒オブジェクトのageプロバティ(年齢)を更新するには、コンソールに次のコードを入力します。

生徒オブジェクトのプロパティを更新する

student.age = 16;
console.log(student.age);

すると、「16」と更新されたプロパティの値が表示されます。

プロパティに関数を代入する

また、プロパティには関数を設定することもできます。次のコードは、printプロパティに関数を代入し、printプロパティを呼び出すと、number プロパティに保存した数値を出力するオブジェクトです。

counterオブジェクト

var counter = {
 number: 0,
   print: function() {
   counter.number++;
   console.log(counter.number);
 }
};

counterオブジェクトのプロパティ「print」に定義した関数を呼び出すには、「counter.print()」のようにオブジェクト名とプロパティ名をドット (.) でつなぎ、プロパティ名の後ろに半角の()を入力します。

実際にChromeのデベロッパーツールのコンソールに、counter オブジェクトのコー ドを入力してみましょう。なお、コードの途中の改行は、「Shift] + | Enter]キーを押して入力し、最後に Enterキーを押すことで実行できます。

オブジェクトの入力後、counter.print(); とコンソールに3回入力すると、次の結果が表示されます。

「counter.print();」を3回実行したときの結果

1
2
3

このコードでは print プロパティに、“number プロパティに代入されている数値を1だけ増やして、その数値をコンソールに表示する”関数が定義されています。counter.print)で関数を呼び出すたびに、counter.number に代入されている数値が1ずつ大きくなって、コンソールに表示されることになります。

時間あてゲームを作ってみよう


それでは、ここまで学んできた関数を活用して、ゲームをスタートしてから10秒ちょうどに時間を止めることを競う「時間あてゲーム」を作っていきましょう。動画も参考にすると理解が深まります。


最初に時間あてゲームの要件を考えてみましょう。要件とは、要求を実現するためにプログラムがどんな機能を持つべきかを表す事柄です。ここでは、次の4つの要件を設定します。ではこの機能を作っていきましょう。

・「OKを押して10秒だと思ったら何かキーを押して下さい」というダイアログを表示する

・ダイアログで[OK] ボタンをクリックすると、時間あてゲームがスタートする

・何かキーを押すと、時間あてゲームがストップする

・9.5秒から10.5秒の間なら「すごい」、そうでないなら「残念」と表示する

フォルダ内に以下のファイルを用意します。

• index.html

• index.js

まずはHTMLファイルを作ります。次のコードをindex.htmlに入力します。

<!DOCTYPE html>
<html lang=”ja”>
<html>
<head>
<meta charset=”UTF-8″>
<title>JavaScriptのオブジェクト</title>
</head>
<body>
<h1 id=”display-area”></script>
</body>
</html>

idというのはその名の通り名札の意味です。次にindex.jsを書いていきます。

ダイアログ(小さな子画面)を表示するプログラムを実装する
「OKを押して10秒だと思ったら何かキーを押してください」と表示させる要件を実装していきます。
index.jsに次のように入力します。

if(confirm( ‘OKを押して10秒だと思ったら何かキーを押してください’)){
console.log(‘スタートしました’);
}

「confirm()」は「alert()」と同様に、引数で渡した文字列をダイアログで表示する関数です。ただし、confirm() では alert() と違い、ボタンが[OK] と[キャンセル]の2つに増えます。さらに、confirm()では戻り値が意味を持ち、[OK]ボタンがクリックされると true、[キャンセル] ボタンがクリックされるとfalse が戻り値となります。「confirm()」は、英単語 confirm の「確認する」という意味のとおり、ユーザーが何かを操作するときの確認に使います。
この状態でChromeでindex.htmlを開いてみると、ダイアログが表示され、OKボタンを押すと、コンソールに

スタートしました

と表示されます。

ゲームをスタートするプログラムを実装する
次は、「ダイアログで[OK] ボタンをクリックすると、時間あてゲームがスタートする」という要件について考えてみましょう。まず、時間あてゲームでは、スタートからストップまでの時間を計る必要があります。スタートした時刻(ミリ秒)と、ストップした時刻(ミリ秒)があれば、その間の時間が計算できます。したがって、スタート時の処理としては、その瞬間の時刻(開始時刻)を記録しておけばよいことになります。

開始時刻を記録するの部分は、このように実装することができます。

index.js

let startTime = null;
function start() {
startTime = Date.now();
console.log(‘スタートしました ‘);
}
if (confirm(‘OK を押して 10 秒だと思ったら何かキーを押して下さい’)){
start();
}

nullは空っぽという意味になります。ゲーム開始時刻を変数として用意しています。

ゲームをストップするプログラムを実装する

続けて、「何かキーを押すと、時間あてゲームがストップする」という要件を実装てみましょう。この要件は、stop関数を追加で実装することで実現していきます。

index.js

let startTime = null;
function start() {
startTime = Date.now();
document.body.onkeydown=function() {
console.log(‘ストップしました’);
};console.log(‘スタートしました’);
}
if (confirm(“OK を押して 10 秒だと思ったら何かキーを押して下さい’)) {
start();
}

先ほどと変わった部分を見ていきましょう。

start関数には、
document.body.onkeydown = function() {
console.log(ストップしました’);
};
が追加されています。これは、「何かキーが押されたらコンソールに『ストップしました』と表示する」ということが書かれています。onkeydownプロパティには、キーボードのキーが押されたときの関数を指定します。
function() { } のように書いて名前のない関数を表現し、そのまま onkeydownプロパティに指定していますが、コードを見やすくするためにもstop関数として新たに宣言していきます。stop 関数の中身は、今はまだコンソールに「ストップしました」と出力するだけとなっています。

index.js

let startTime = null;
function start() {
startTime=Date.now();
document.body.onkeydown=stop;console.log(‘スタートしました ‘);
}
function stop() {
console.log(‘ストップしました’);
}
if (confirm(‘OK を押して 10 秒だと思ったら何かキーを押して下さい’)) {
start();
}

document.body.onkeydown=stop; これは「何かキーが押されたらstop 関数を実行する」というコードです。関数なのに stop() と書かず、stopと書くことに疑問を感じる人もいるのではないでしょうか。ここで stop()と書くと、キーが押されたときではなく、このファイルが読み込まれた時点で stop関数が実行されます。そして、その結果がonkeydownプロパティに代入されてしまいます。

「何かキーを押すと時間あてゲームが停止する」という要件を満たすには、onkeydownが発生するたびに実行されなければならないので、このような書き方になっています。

実際に実行してみると、キーを押すたびに、ストップしましたと表示されることが確認できます。

なお、一部のキーはこのプログラムでは認識されないので、スペースキーなどを押してみて下さい。動作させて問題なく動くのであれば、開発のために出していたコンソールへのログ出力のコードは消しましょう。

条件によって表示するメッセージを変える
「9.5秒から 10.5秒の間なら「すごい」、そうでないなら「残念」と表示する」という要件を実装していきましょう。実装するコードは、次のようになります。

index.js

let startTime = null;
let displayArea = document.getElementById(‘display-area’);
function start() {
startTime = Date.now();
document.body.onkeydown=stop;
}
function stop() {
let currentTime Date.now();
let seconds = (currentTime startTime) / 1000;
if (9.5 <= seconds && seconds <= 10.5) {
displayArea.innerText = seconds + ‘秒でした。すごい。’;
} else {
displayArea.innerText = seconds + ‘秒でした。残念。’;
}
}
if (confirm(‘OK を押して10秒だと思ったら何かキーを押して下さい’)) {
start();
}

追加・変更された部分を見ていきます。

let displayArea=document.getElementById(‘display-area’);

表示エリアを取得している部分です。HTMLで「display-area」と名前 (id) を付けていた要素を取得し、displayArea という変数に代入しました。
次に stop 関数では、ストップされた瞬間の現在時刻を変数 currentTime として取得し、開始時刻の変数startTime と引き算することで、かかった秒数を計算しています。

let currentTime = Date.now();
let seconds = (currentTime – startTime) / 1000;

current(カレント):現在の

「(currentTime – startTime) / 1000」がかかった秒数の計算です。現在の時刻のミリ秒から、開時刻のミリ秒を引き、1000で割って秒数を求めています。

if (9.5 <= seconds && seconds <= 10.5) {
displayArea.innerText = seconds + ‘秒でした。すごい。’;
} else {
displayArea.innerText = seconds + ‘秒でした。残念。’;
}
計算した秒数が9.5以上、かつ、10.5以下であれば、

○秒でした。すごい。

とHTML にテキストとして表示し、そうでなければ

○秒でした。残念。

と表示する処理です。

実際に動作確認してみましょう。Chromeでjs-object.htmlを開いてゲームをスタートすると、キーを押すごとに「○秒でした。すごい。」もしくは「○秒でした。残念。」というメッセージが表示されます。

ゲームオブジェクトで表現してみよう
4つ目の要件を実装する際、キーを押すまでにかかった秒数を計算するストップウォッチのような機能が出てきていました。最後に、この部分をオブジェクトとして表現することで、コードをわかりやすくしてみましょう。

let startTime = null; ;

let displayArea = document.getElementById(‘display-area’);

上のコードのように、すでにこの時間あてゲームには、

・開始時刻

・表示エリア

の2つの情報が保存されています。「game」というオブジェクトにまとめてみましょう。オブジェクトを使って、次のように置き換えてみます。

let game = {
startTime: null,
displayArea: document.getElementById(‘display-area’)
};

ほかの箇所もオブジェクトを使った形に置き換えると、次のようになります。

index.js

let game = {
startTime: null,
displayArea: document.getElementById(‘display-area’)
};
function start() {
game.startTime=Date.now();
document.body.onkeydown stop;
}
function stop() {
let currentTime = Date.now();
let seconds = (currentTime game – startTime) / 1000;
if (9.5 <= seconds && seconds <= 10.5) {
game.displayArea.innerText = seconds + ‘秒でした。すごい。’;
} else {
game.displayArea.innerText = seconds + ‘秒でした。残念。’;
}
}
if (confirm(“OK を押して 10 秒だと思ったら何かキーを押して下さい’)) {
start();
}

これで、時間あてゲームが完成しました。Chromeで index.html を開いてゲームをスタート


この記事が気に入ったらサポートをしてみませんか?