11. 変数と定数
このレッスンでは、計算結果を保存しておく変数について学びます。
変数を使う
前のレッスンでは、ダメージの計算Math.floor((186 - 97) / 2)を別々に2回行いました。
<!-- battle.html hidden -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>バトル</title>
<link rel="stylesheet" href="css/battle.css">
<script src="js/battle.js" defer></script>
</head>
<body>
<table id="status">
<tr>
<th>ゆうしゃ</th><th>せんし</th><th>そうりょ</th><th>まほうつかい</th>
</tr>
<tr><td>HP 153</td><td>HP 198</td><td>HP 101</td><td>HP 77</td></tr>
<tr><td>MP 25</td><td>MP 0</td><td>MP 35</td><td>MP 58</td></tr>
</table>
<div id="monster">
<img class="dark-knight" src="img/dark-knight.png">
<img class="dark-lord" src="img/dark-lord.png">
<img class="demon-priest" src="img/demon-priest.png">
</div>
<div id="message">
まおうがあらわれた。
</div>
</body>
</html>
/* battle.css hidden */
body {
background-color: rgb(34, 34, 34);
color: white;
font-family: sans-serif;
}
table#status {
border: solid 2px white;
border-collapse: collapse;
margin: 10px auto 0 auto;
width: 640px;
}
table#status tr:first-child {
border-bottom: solid 1px white;
}
table#status td {
text-align: center;
}
#monster {
text-align: center;
margin-top: 40px;
}
#monster .dark-lord {
width: 400px;
}
#monster .dark-knight {
width: 150px;
}
#monster .demon-priest {
width: 150px;
}
#message {
border: solid 2px white;
border-radius: 4px;
padding: 10px;
width: 720px;
margin: 30px auto;
}
// battle.js
document.getElementById("message").textContent = `ゆうしゃに${Math.floor((186 - 97) / 2)}のダメージ。`;
document.querySelector("#status tr:nth-child(2) td:nth-child(1)").textContent = `HP ${153 - Math.floor((186 - 97) / 2)}`;
同じ計算を2回書くのは無駄なので、ダメージの計算結果を取っておいて後から使えると便利です。それを実現するのが変数です。変数を使うと
// battle.js highlight:1-3
let damage = Math.floor((186 - 97) / 2);
document.getElementById("message").textContent = `ゆうしゃに${damage}のダメージ。`;
document.querySelector("#status tr:nth-child(2) td:nth-child(1)").textContent = `HP ${153 - damage}`;
変数は、値を入れておく箱のようなものです。letを使って変数を作ります。変数を作ることを、変数を宣言すると言います。
変数の値を変更する
変数の値は後から変更できます。
// highlight:4
let hp = 153;
console.log(hp);
hp = 109;
console.log(hp);
最初のconsole.log(hp)では153、次のconsole.log(hp)では109と表示されます。
hp = 109を実行すると、hpに新しい値109が入れられます。変数に値を入れることを代入すると言います。
変数を使って値にhpという名前を付けると、console.log(hp)は「HPを表示する」という意味だとわかりやすいです。
hpの値をdamageの分だけ減らす
hpの値をdamageの分だけ減らすにはどうすればいいでしょうか?ダメージを受けた後のHPはhp - damageと書けます。これをhpに代入するので、hp = hp - damageという式になります。
// highlight:4
let damage = Math.floor((186 - 97) / 2);
let hp = 153;
hp = hp - damage;
console.log(`HP ${hp}`);
HP 109
定数を使う
最大HPのように、変更されない値にはconstを使います。constで宣言された変数は定数とも呼ばれます。
最大HPを表す定数maxHpを作り、変数hpの初期値をmaxHPと同じにするには次のようにします。
const maxHp = 153;
let hp = maxHp;
constで宣言した変数は、後から値を変更しようとするとエラーになります。
// highlight:3
const maxHp = 153;
let hp = maxHp;
maxHp = 200; // ⛔️ エラー
変更されるべきでない値をconstにしておくと、うっかり変更してしまうミスを防げます。
それでは、battle.jsにmaxHpとhpを反映してみましょう。
// battle.js highlight:1-3,6
const maxHp = 153;
let hp = maxHp;
let damage = Math.floor((186 - 97) / 2);
hp = hp - damage;
document.getElementById("message").textContent = `ゆうしゃに${damage}のダメージ。`;
document.querySelector("#status tr:nth-child(2) td:nth-child(1)").textContent = `HP ${hp}`;
文字列を定数にする
変数や定数には数値だけでなく、文字列を代入することもできます。「ゆうしゃ」というキャラクター名も定数nameにしてみましょう。
// battle.js highlight:1,6
const name = "ゆうしゃ";
const maxHp = 153;
let hp = maxHp;
let damage = Math.floor((186 - 97) / 2);
hp = hp - damage;
document.getElementById("message").textContent = `${name}に${damage}のダメージ。`;
document.querySelector("#status tr:nth-child(2) td:nth-child(1)").textContent = `HP ${hp}`;
`${name}に${damage}のダメージ。`のように、メッセージボックスに表示するメッセージにもnameが使えます。
プログラムの中に直接ゆうしゃと書いてあると、名前を変更したいときに全部書き直さなければいけません。このように、名前のように変わらない値を定数にしておくと、名前を変更するときに定数の宣言部分を変えるだけで済みます。
ステータスを変数で管理する
攻撃力や防御力も変数で管理してみましょう。今はまだ使いませんが、「ゆうしゃ」の攻撃力や「まおう」のHPなどのステータスもまとめて宣言しておきます。
複数のキャラクターがいるので、変数名に番号をつけて区別します。
- ゆうしゃ(1番):
name1,maxHp1,hp1,attack1,defense1 - まおう(2番):
name2,maxHp2,hp2,attack2,defense2
// battle.js highlight:1-5,7-11,13-16
const name1 = "ゆうしゃ";
const maxHp1 = 153;
let hp1 = maxHp1;
const attack1 = 162;
const defense1 = 97;
const name2 = "まおう";
const maxHp2 = 999;
let hp2 = maxHp2;
const attack2 = 186;
const defense2 = 58;
let damage = Math.floor((attack2 - defense1) / 2);
hp1 = hp1 - damage;
document.getElementById("message").textContent = `${name1}に${damage}のダメージ。`;
document.querySelector("#status tr:nth-child(2) td:nth-child(1)").textContent = `HP ${hp1}`;
数値を直接書いていた部分が、変数名に置き換わりました。これでコードが読みやすくなり、値を変更するときも変数の宣言部分を変えるだけで済みます。
試してみよう
damageの値を変えて、HPがどう変わるか確認してみましょう- 他のキャラクターのステータスも変数で管理してみましょう
constで宣言した変数を変更しようとして、エラーメッセージを確認してみましょう
これまでの成果
<!-- battle.html folded -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>バトル</title>
<link rel="stylesheet" href="css/battle.css">
<script src="js/battle.js" defer></script>
</head>
<body>
<table id="status">
<tr>
<th>ゆうしゃ</th><th>せんし</th><th>そうりょ</th><th>まほうつかい</th>
</tr>
<tr><td>HP 153</td><td>HP 198</td><td>HP 101</td><td>HP 77</td></tr>
<tr><td>MP 25</td><td>MP 0</td><td>MP 35</td><td>MP 58</td></tr>
</table>
<div id="monster">
<img class="dark-knight" src="img/dark-knight.png">
<img class="dark-lord" src="img/dark-lord.png">
<img class="demon-priest" src="img/demon-priest.png">
</div>
<div id="message">
まおうがあらわれた。
</div>
</body>
</html>
/* battle.css folded */
body {
background-color: rgb(34, 34, 34);
color: white;
font-family: sans-serif;
}
table#status {
border: solid 2px white;
border-collapse: collapse;
margin: 10px auto 0 auto;
width: 640px;
}
table#status tr:first-child {
border-bottom: solid 1px white;
}
table#status td {
text-align: center;
}
#monster {
text-align: center;
margin-top: 40px;
}
#monster .dark-lord {
width: 400px;
}
#monster .dark-knight {
width: 150px;
}
#monster .demon-priest {
width: 150px;
}
#message {
border: solid 2px white;
border-radius: 4px;
padding: 10px;
width: 720px;
margin: 30px auto;
}
// battle.js
const name1 = "ゆうしゃ";
const maxHp1 = 153;
let hp1 = maxHp1;
const attack1 = 162;
const defense1 = 97;
const name2 = "まおう";
const maxHp2 = 999;
let hp2 = maxHp2;
const attack2 = 186;
const defense2 = 58;
let damage = Math.floor((attack2 - defense1) / 2);
hp1 = hp1 - damage;
document.getElementById("message").textContent = `${name1}に${damage}のダメージ。`;
document.querySelector("#status tr:nth-child(2) td:nth-child(1)").textContent = `HP ${hp1}`;