じゃんけん用に「janken.html」を作成して、保存します。
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>じゃんけん</title> </head> <body> <h3>じゃんけん</h3> <hr> </body> </html>
まずは表示用のテーブルを作成します。
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>じゃんけん</title> </head> <body> <h3>じゃんけん</h3> <hr> <table border="0" align="center"> <tr> <th><div id="ahand"></div></th> <th>VS</th> <th><div id="bhand"></div></th> </tr> <tr> <th>相手</th> <td> </td> <th>自分</th> </tr> <tr> <th colspan="3"> </th> </tr> <tr> <th colspan="3"></th> </tr> </table> </body> </html>
テーブルは全体の枠を表示しないように「border="0"」にして、画面の中央に置くために「align="center"」と指示します。(ブラウザによってはalignは機能しません)
表示用テーブルは、次のように4段で作っておきます。
マス(列)は<td>を使わず、全て<th>にしています。
1段目は手の画像を表示する部分になります。
横に3マスあり、<div>タグを使って相手の手を表示する「ahand」、「VS」の文字、<div>タグで自分の手を表示する「bhand」となっています。
2段目は説明用の言葉を入れます。「相手」、空欄、「自分」となっています。
空欄には「 」という文字が入っています。これは半角のスペースを意味しています。なくても実害はありませんが、ソースを見たときにこれがあることで空白があるということが判りやすくなります。
今回はテーブル枠が消えているので判りませんが、枠の中が本当の空欄だと枠線が消える現象が起こります。ただ、ブラウザによって表現が違いますので、自分は見えていても、他の人は見えないということが起こりますので、それを統一する意味でも、「 」をしておくと間違いはありません。
3段目は全て空欄です。これは下のテーブルとの距離を開けるためで、デザイン的な調節の役割を果たしています。
3つにマスを分ける必要がないので、「colspan」を使って1つにまとめています。
4段目には操作ボタンなどが入る予定なので、空欄にしてあります。
テーブルは、全体を表す<table>タグ、行を表す<tr>タグ、マス(列)を表す<td>または<th>の3つが揃わないと正しく表示できません。
タグ | 上位のタグ | タグの意味 | 属性の種類 |
---|---|---|---|
<table></table> | <body> | テーブル全体を表すタグ | border、cellspacing、cellpadding、bgcolor、bordercolor、width、height、align |
<caption></caption> | <table> | テーブルのタイトル | align、valign |
<tr></tr> | <table> | テーブルの行を表すタグ | bgcolor、bordercolor、width、height、align、valign、nowrap |
<td></td> | <tr> | テーブルの1マスを表すタグ | colspan、rowspan、bgcolor、bordercolor、width、height、align、valign、nowrap |
<th></th> | <tr> | テーブルの1マスで、ヘッダを表すタグ | colspan、rowspan、bgcolor、bordercolor、width、height、align、valign |
属性には共通のものもあります。各タグで同じ属性を使った場合、優先順位は<td>と<th>、<tr>、<table>の順です。しかし、幅や高さを%で示した場合は、逆順に外側から適用されます。また、画面の大きさや画像・文字の大きさと量に応じて、幅や高さが広がることがあります。
【主な属性の意味と書き方】
基本的な書式は、<tag option="xxx">という形です。optionに属性名が入ります。値は「=」の後に「""」で囲んで書きます。値がない場合もあります。
属性名 | 属性の意味 | 例 |
---|---|---|
border | テーブル枠の幅です。数値で指定します。 | デフォルト(標準値)は「0」または「2」で、ブラウザによって異なります。 |
bgcolor | 枠線の色です。色番号で指定します。 | 赤なら#FF0000、緑なら#00FF00、青なら#0000FF。 |
width | テーブルまたは列の幅です。値はドット数または%で指定します。%とは、テーブルの場合、ウインドウに対する割合で、列の場合、テーブルに対する割合となります。 | 半分に幅にしたいときは、width="50%"。 |
height | テーブルまたは行の幅です。値はドット数または%で指定します。%の対応はwidthと同様です。 | |
align | テーブルまたは内容の水平位置です。 | 「center」なら中央、「left」なら左、「right」なら右に寄せられます。テーブルの場合、「left」「right」を指定すると、続く文字などに回り込みが発生します。 |
valign | 内容の垂直位置です。 | 「middle」なら中央、「top」なら上、「bottom」なら下に寄せられます。 |
colspan | <td><th>内で使用し、複数の枠を横に繋ぎます。繋ぎたい枠の個数を値に指定します。 | colspan="3"の場合、3つの枠が1つになります。他の行と比べると3つ分の幅に1つの枠があることになります。1枠にした分、同じ行内に2枠分のタグがなくなることに注意が必要です。 |
rowspan | <td><th>内で使用し、複数の枠を縦に繋ぎます。繋ぎたい枠の個数を値に指定します。 | rowspan="3"の場合、下の2行にまたがった1つの枠ができます。その分、下の2行から1つ枠ずつのタグがなくなります。 |
【使用例】
<table width="100" border="2" align="center" cellpadding="5" cellspacing="2" bgcolor="#FFFF99">
<tr><th colspan="2">A</th><th bgcolor="#FFCCFF">1</th></tr>
<tr bgcolor="#CCFFFF"><td align="right">2</td><td rowspan="2" valign="bottom">B</td><td height="50" bgcolor="#FFCCFF">3</td></tr>
<tr><td>4</td><td bgcolor="#FFCCFF">5</td></tr>
</table>
上をコピーして、どんなテーブルができるか試してみてください。
操作用ボタンをテーブルを使ってレイアウトします。
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>じゃんけん</title> </head> <body> <h3>じゃんけん</h3> <hr> <table border="0" align="center"> <tr> <th><div id="ahand"></div></th> <th>VS</th> <th><div id="bhand"></div></th> </tr> <tr> <th>相手</th> <td> </td> <th>自分</th> </tr> <tr> <th colspan="3"> </th> </tr> <tr> <th colspan="3"><form name="janken"> <table border="0" align="center"> <tr> <td colspan="3">なにをだそうかな?</td> </tr> <tr> <th><input type="button" value="グー"></th> <th><input type="button" value="チョキ"></th> <th><input type="button" value="パー"></th> </tr> </table> </form></th> </tr> </table> </body> </html>
<form>タグには「janken」という名前を付けておきましょう。
テーブルにはメッセージ用と、ボタンを並べる部分と、2つの行があります。
テーブルは単に表を作るというだけでなく、透明にすることで物の配置を決めるレイアウト作りに活用できます。
マスの大きさや、余白の分量、上下左右の位置指定などを使い、細やかにレイアウトを指定することができます。
ボタンを押したらじゃんけんをしますので、ボタンからユーザー関数を呼び出せるようにしておきます。
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>じゃんけん</title> </head> <body> <h3>じゃんけん</h3> <hr> <table border="0" align="center"> <tr> <th><div id="ahand"></div></th> <th>VS</th> <th><div id="bhand"></div></th> </tr> <tr> <th>相手</th> <td> </td> <th>自分</th> </tr> <tr> <th colspan="3"> </th> </tr> <tr> <th colspan="3"><form name="janken"> <table border="0" align="center"> <tr> <td colspan="3">なにをだそうかな?</td> </tr> <tr> <th><input type="button" onClick="getbhand(0)" value="グー"></th> <th><input type="button" onClick="getbhand(1)" value="チョキ"></th> <th><input type="button" onClick="getbhand(2)" value="パー"></th> </tr> </table> </form></th> </tr> </table> </body> </html>
ユーザー関数「getbhand()」に対して、どの手を出したか判るように、3つのボタンそれぞれに異なる数値を送り出すようにしておきます。
じゃんけんの手を数値で判定するために、「グー」は「0」、「チョキ」は「1」、「パー」は「2」と統一することも決めておきます。こうしておけば、勝った負けたを調べるときにも、数値で比較することができます。
スクリプトを書き始めましょう。
ボタンを押したら自分の手を表示するだけでなく、相手の手も同時に表示するように作ります。
<script type="text/javascript"> hand = new Array("グー","チョキ","パー"); function getbhand(btn) { //手を出す r = Math.floor(Math.random() * 3); document.getElementById("ahand").innerHTML = hand[r]; document.getElementById("bhand").innerHTML = hand[btn]; } </script>
まずは初期設定として、配列変数handを使って3つの手を用意しておきす。これは表示用なので、後で画像に置き換えます。
次に、ボタンが押されたときの処理となるユーザー関数getbhand()を作りましょう。
「//」の部分はコメントアウトという注釈部分です。注意書きや覚え書きで、あとで見直すときのために書いておきます。
スクリプトは3行です。
1行目は乱数を発生させて0~2の3つの数字を取り出して、変数rに入れています。
2行目は、そのまま変数rを配列変数handのr番目の文字列を取ってきて、ahandに表示している。これが相手の出した手となります。
3行目は、押したボタンから引き継いだ変数btnを要素にして、配列変数のbtn番目の文字列を取り出して、bhandに表示しています。これは自分の手ですね。
これでじゃんけんゲームの原型ができました。
<img src="gu.png"> | <img src="ch.png"> | <img src="pa.png"> |
手の画像を3つ用意します。検索をしてみると、上のフリー素材が見つかりました。こちらから取ってきます。
保存は画像の上で、右クリックしてショートカットメニューを出し、「名前を付けて画像を保存」を選びます。
デジカメで自分の手を撮影して使っても面白いと思います。もちろん、絵や顔や足で表現しても良いですよ。
出した手の表示部分を文字から画像に変更します。
<script type="text/javascript"> hand = new Array("gu.png","ch.png","pa.png"); function getbhand(btn) { //手を出す r = Math.floor(Math.random() * 3); document.getElementById("ahand").innerHTML = "<img src='" + hand[r] + "'>"; document.getElementById("bhand").innerHTML = "<img src='" + hand[btn] + "'>"; } </script>
配列変数handの設定にファイル名を入れます。
表示の箇所でファイル名をタグの中に入れて出力させます。
配列変数を使わずに表記することも出来ます。
ファイル名をグーは「hand0.png」、チョキは「hand1.png」、パーは「hand2.png」と番号がついた共通の名前にしておきます。
document.getElementById("ahand").innerHTML ="<img src='hand" + btn + ".png'>";
そうすると上のように番号を使ってファイル名を作って表示させることができるのです。
ただし、画像を入れ換えたいときには、ファイル名をプログラムに合わせるか、プログラムをファイル名に合わせて変更する必要があります。
3つの手の画像の大きさが違うため、画像が切り替わる度にテーブルが画像のサイズに応じて動いてしまいますので、修正しましょう。
<table border="0" align="center"> <tr> <th width="200" height="200"><div id="ahand"></div></th> <th>VS</th> <th width="200" height="200"><div id="bhand"></div></th> </tr> <tr> <th>相手</th> <td> </td> <th>自分</th> </tr> <tr> <th colspan="3"> </th> </tr>
画像を表示する枠の大きさを画像より大きめに指定します。これでテーブルが動いて見にくくなるのを防ぎます。
画像を自分で作った場合は、その大きさに合わせて調整してください。
スロットのように3つの手を順番に表示して、何が出るのか?という期待感を表現したいと思います。
<table border="0" align="center">
<tr>
<td colspan="3">なにをだそうかな?</td>
</tr>
<tr>
<th><input type="button" onClick="getbhand(0)" value="グー"></th>
<th><input type="button" onClick="getbhand(1)" value="チョキ"></th>
<th><input type="button" onClick="getbhand(2)" value="パー"></th>
</tr>
<tr>
<th colspan="3"><input type="button" onClick="handreset()" value="リセット"></th>
</tr>
</table>
表示を動かすため、止める操作と、再び動かす操作も考えます。
自分が手を出したときに止まって相手の手が出ます。
次に再び動かすためには1つアクションが必要です。フォームに新しくリセットボタンを追加しましょう。
リセットボタンからユーザー関数handreset()を呼び出すことにします。
手の絵がスロットのように入れ替わり表示される部分のスクリプトを作ります。
<script type="text/javascript"> hand = new Array("gu.png","ch.png","pa.png"); timer = 0; count = 0; getahand(); function getbhand(btn) { //手を出す r = Math.floor(Math.random() * 3); document.getElementById("ahand").innerHTML = "<img src='" + hand[r] + "'>"; document.getElementById("bhand").innerHTML = "<img src='" + hand[btn] + "'>"; } function getahand() { //手を順番に表示 document.getElementById("ahand").innerHTML = "<img src='" + hand[count] + "'>"; document.getElementById("bhand").innerHTML = "<img src='" + hand[count] + "'>"; count++; if (count > 2) count = 0; timer = setTimeout("getahand()",500); } </script>
まず、2つの変数を用意します。
1つは、タイマーの制御用の変数timerです。タイマーを起動したときにそのID番号を記録しておけば、タイマーを止めることができます。
変数countはどの手が出ているのか記録するものです。順番に手が切り替わるようにするために使います。
for文を使って繰り返し処理をするときは、その中で変数を指定します。
しかし、今回はタイマーを使いますので、1つのユーザー関数の中で処理が終わらず、次へと継続して同じ関数を使う必要があります。
そのために、スクリプト全体でどこでも使える変数を用意しておくのです。
ユーザー関数getahand()を繰り返し呼び出すことで、絵が順次切り替わります。
最初の2行で、相手(ahand)も自分(bhand)も同じ手を表示します。1回目は「count = 0」なので「グー」が表示されます。
3行目で、変数countに「1」を足し、「count = 1」になって、次に「チョキ」を出す準備ができたことになります。このようにしてここで手を替えているのです。
しかし、繰り返しの後、「count = 2」になり、次に「count = 3」になったとき、エラーが発生します。配列変数にhand[3]がないからです。
そこで、4行目でif文を使って変数countが2を超えたとき(3になったとき)、「count = 0」に戻しています。これで何度繰り返しても正常に「グー」「チョキ」「パー」が繰り返されます。
5行目で、次の繰り返しの準備しています。ユーザー関数getahand()を0.5秒(500/1000秒)後に呼び出して、繰り返し処理を行います。
タイマーの起動の行は、今回変数timerへの代入式となっています。
右辺だけでも動作はしますが、後で動きを止めるため、ここではタイマーIDを記録するために変数timerが必要なのです。
これで3つの手が回転するように次々と現れます。
次に、手の回転を止めるスクリプトを追加します。
<script type="text/javascript"> hand = new Array("gu.png","ch.png","pa.png"); timer = 0; count = 0; getahand(); function getbhand(btn) { //タイマーを止める clearTimeout(timer); //手を出す r = Math.floor(Math.random() * 3); document.getElementById("ahand").innerHTML = "<img src='" + hand[r] + "'>"; document.getElementById("bhand").innerHTML = "<img src='" + hand[btn] + "'>"; } function handreset() { //初期状態に戻す getahand(); } function getahand() { //手を順番に表示 document.getElementById("ahand").innerHTML = "<img src='" + hand[count] + "'>"; document.getElementById("bhand").innerHTML = "<img src='" + hand[count] + "'>"; count++; if (count > 2) count = 0; timer = setTimeout("getahand()",500); } </script>
ユーザー関数getbhand()でお互いの手を出す直前に「clearTimeout()」を使ってタイマーを止めます。
setTimeoutを使った時点で変数timerに制御用のID番号が入っています。
止まった手を動かすのは、リセットボタンが押された後です。
リセットボタンから呼び出されるユーザー関数「handreset()」を作ります。
handreset()の中からgetahand()を呼び出して、手の回転がまたスタートします。
リセットボタンから直接getahand()を呼び出しても良いように見えますが、もう1つhandreset()でやりたいことがあるので、繰り返しの部分だけ分けてあるのです。
現在は連続でじゃんけんできる状態です。これでは、手が回転する意味がありません。
そこで、リセットボタンを使ってもらうために、じゃんけんをするとボタンを使えなくしてしまいます。
リセットボタンを押すとまたボタンが使えるようにします。
function getbhand(btn) { //タイマーを止める clearTimeout(timer); //手を出す r = Math.floor(Math.random() * 3); document.getElementById("ahand").innerHTML = "<img src='" + hand[r] + "'>"; document.getElementById("bhand").innerHTML = "<img src='" + hand[btn] + "'>"; //ボタンを使えなくする document.janken.elements[0].disabled = true; document.janken.elements[1].disabled = true; document.janken.elements[2].disabled = true; } function handreset() { //初期状態に戻す document.janken.elements[0].disabled = false; document.janken.elements[1].disabled = false; document.janken.elements[2].disabled = false; getahand(); }
ユーザー関数getbhand()に、じゃんけんボタンを使えなくするプログラムを追加します。
ユーザー関数handreset()には、ボタンを使える状態に戻すプログラムを書きます。
じゃんけんの結果を判りやすくするためにメッセージを表示しましょう。
<table border="0" align="center">
<tr>
<td colspan="3"><div id="message"></div></td>
</tr>
<tr>
<th><input type="button" onClick="getbhand(0)" value="グー"></th>
<th><input type="button" onClick="getbhand(1)" value="チョキ"></th>
<th><input type="button" onClick="getbhand(2)" value="パー"></th>
</tr>
<tr>
<th colspan="3"><input type="button" onClick="handreset()" value="リセット"></th>
</tr>
</table>
まずはテーブルの「なにをだそうかな?」と書かれた部分を<div>タグで置き換え、メッセージを表示できるようにしておきます。
次にスクリプトでメッセージを準備して、表示するまでを作りましょう。
<script type="text/javascript"> hand = new Array("gu.png","ch.png","pa.png"); msg = new Array("なにをだそうかな?","かった~!!","まけちゃったよ","あいこだよ"); timer = 0; count = 0;getahand();handreset(); (省略) function handreset() { //初期状態に戻す document.janken.elements[0].disabled = false; document.janken.elements[1].disabled = false; document.janken.elements[2].disabled = false; document.getElementById("message").innerHTML = msg[0]; getahand(); }
初期設定に配列変数msgを追加して、4つのメッセージを準備しておきます。
文章は自由に考えても良いのですが、順番や役割は変えないようにしましょう。順番に、最初の言葉、勝ったときの言葉、負けたときの言葉、あいこのときの言葉、とします。
初期設定の最後にユーザー関数getahand()を呼び出していましたが、これをユーザー関数handreset()に変更します。
ユーザー関数handreset()の最後でユーザー関数getahand()が呼び出されています。
そして、ユーザー関数handreset()の中で、先に用意したメッセージを表示させます。
初回は「message」という場所に、配列変数msgの0番目の文字列を出力しますので、変更前と同じ表示になっています。
次にユーザー関数getbhand()の中で、勝ったとき、負けたとき、あいこの時の3つのパターンでメッセージ表示をしましょう。
function getbhand(btn) { //タイマーを止める clearTimeout(timer); //手を出す r = Math.floor(Math.random() * 3); document.getElementById("ahand").innerHTML = "<img src='" + hand[r] + "'>"; document.getElementById("bhand").innerHTML = "<img src='" + hand[btn] + "'>"; //ボタンを使えなくする document.janken.elements[0].disabled = true; document.janken.elements[1].disabled = true; document.janken.elements[2].disabled = true; //あいこ var num = 3; //グー if (btn == 0 && r == 1) num = 1; if (btn == 0 && r == 2) num = 2; //チョキ if (btn == 1 && r == 0) num = 2; if (btn == 1 && r == 2) num = 1; //パー if (btn == 2 && r == 0) num = 1; if (btn == 2 && r == 1) num = 2; //表示 document.getElementById("message").innerHTML = msg[num]; }
勝った場合は「1」、負けた場合は「2」、あいこの場合は「3」を変数numに入れることにします。
勝ちのパターンは3つ、負けのパターンも3つ。そして、あいこのパターンが3つになります。
それぞれをif文で判断して、変数numの値を変更します。
じゃんけんのような三つどもえの場合、数値の大小だけで勝ち負けを判断することができません。
そのため、1つ1つの組み合わせをif文で書くことになります。
まず、最初に変数numを「あいこ」の場合に設定します。
あいこのパターンは3つあります。if文で書くと「if (btn == r)」と1つにまとめられす。しかし、ここではif文がありません。この段階では必要ないからです。勝ち負けと同列に判断しなくても、最初にあいこの場合を想定し、後は勝ちのとき負けのときに変数numを変更するため、そのどちらでもない場合は変数numに変化はありません。残るのはあいこだからです。
後の勝ち負けのパターンは、それぞれ自分が何を出すかによって分けて見ましょう。
改めて確認すると、「グー」は「0」、「チョキ」は「1」、「パー」は「2」でした。
自分が「グー」を出した場合、変数btnは0です。相手の手である変数rが1なら勝ち、2なら負けです。
それぞれにif文を作ります。
これに続いてチョキの場合とグーの場合を作ります。
勝負の結果の判定が終わったら、最後にメッセージを表示します。
ここでは変数numに勝負の結果が入っているので、これを配列変数msgの要素にしています。
さて、普通に使っていると気づかない問題点があります。
リセットボタンを何度も続けて押すと、新しいタイマーがいくつも起動してしまい、いつまで経っても手の回転が止まりません。
そこで今度は、回転が止まったときだけリセットボタンを使えるようにします。
function getbhand(btn) { //タイマーを止める clearTimeout(timer); //手を出す r = Math.floor(Math.random() * 3); document.getElementById("ahand").innerHTML = "<img src='" + hand[r] + "'>"; document.getElementById("bhand").innerHTML = "<img src='" + hand[btn] + "'>"; //ボタンを使えなくする document.janken.elements[0].disabled = true; document.janken.elements[1].disabled = true; document.janken.elements[2].disabled = true; //リセットボタンを元に戻す document.janken.elements[3].disabled = false; //あいこ num = 3; //グー if (btn == 0 && r == 1) num = 1; if (btn == 0 && r == 2) num = 2; //チョキ if (btn == 1 && r == 0) num = 2; if (btn == 1 && r == 2) num = 1; //パー if (btn == 2 && r == 0) num = 1; if (btn == 2 && r == 1) num = 2; //表示 document.getElementById("message").innerHTML = msg[num]; } function handreset() { //初期状態に戻す document.janken.elements[0].disabled = false; document.janken.elements[1].disabled = false; document.janken.elements[2].disabled = false; //リセットボタンを使えなくする document.janken.elements[3].disabled = true; document.getElementById("message").innerHTML = msg[0]; getahand(); }
ユーザー関数handreset()の中で、初期状態はリセットボタンが使えないようにします。
ユーザー関数getbhand()の中では、じゃんけんをしたらリセットボタンを使えるようにします。
メッセージ部分を見やすいようにテーブル内のデザインを変更してみましょう。
<table border="0" align="center" cellpadding="5" cellspacing="5"> <tr bgcolor="#000000"> <td colspan="3" align="center"><font color="#FFFFFF"><div id="message"></div></font></td> </tr> <tr> <th><input type="button" onClick="getbhand(0)" value="グー"></th> <th><input type="button" onClick="getbhand(1)" value="チョキ"></th> <th><input type="button" onClick="getbhand(2)" value="パー"></th> </tr> <tr> <th colspan="3"><input type="button" onClick="handreset()" value="リセット"></th> </tr> </table>
まず、背景を黒くして、文字を白くします。
<tr>に「bgcolor」属性を使い背景色を付けます。これは<td>に書いても同じです。
次の<td>内に「align」属性で、メッセージがマスの中央に寄るようにしています。
<td>を<th>に変更しても、文字は中央に寄せられますが、同時に太文字になってしまいます。
<div>タグを囲うように<font>タグを使って文字に色が着くようにします。
このままだと、メッセージやボタンが余裕なくひっついています。
デザインのバランスを考えると、それぞれの部分を離して余裕をもたせる方が落ち着いて見えます。
<table>タグに「cellpadding」と「cellspacing」の2つの属性を付けてマス内の余白とマス同士の隙間を作ります。
「cellpadding」と「cellspacing」の違いはテーブル枠を表示して数値を変更してみると判ります。
borderやこれらの属性にはデフォルト(標準)の数値があって、ブラウザによって若干の違いがあります。そのような違いをなくすためには、使わないとしても何か数値をしていしておけば、どのブラウザで見ても同じ幅に揃えることができます。
とりあえず、これで完成です。
この後も改良をするとすれば、履歴を残したり、勝敗を「○勝○敗」と表示したり、名前を入力できるようにしたり、手の画像を自分で描くか、自分の手を写真に撮って使うことなど考えられます。
なにかにチャレンジしてみてください。