ここでは配列にまつわるプログラムとしてトランプを題材にいろいろなプログラムを作ってみます。
将来的には何らかのトランプゲームになる予定ですが、いろいろなアルゴリズムを実装しながら寄り道します。
準備
HTMLとCSSを準備します。
これまで作ってきたプログラムをForkしても良いですし、一から作成しても良いでしょう。
HTML
<html>
<body>
<form name="form1">
<br>
<INPUT TYPE="button" NAME="cmdCalc" value="開始" onclick="start()">
</form>
<div id="disp">
</div>
</body>
</html>
ポイントはonclickでstart()が起動できるようにすること。
divタグを書いて出力用の領域を置くことです。
CSS
body { background-color: #DDDDDD; font: 30px sans-serif; }
なくてもなんとかなりますが、font: 30px ぐらいで字の大きさを調整します。
構造体の作り方
構造体を作りますが、厳密に言うとクラスを作成しています。
ここでは、アルゴリズムの習得に特化するために構造体として利用します。
構造体とは、いくつかの変数を1つにまとめた構造をもつ変数です。
これからトランプのカードを表す構造体を作成します。
function Card(mark,num)
{
this.mark=mark;
this.num=num;
}
トランプにはマーク(スペードとかハート)と数字(A~K)がありますので、その二つをペアで格納するための構造体です。
JavaScriptでは関数を作成する function命令を利用して構造体を作成します。
構造体を作成するときに、markとnumの二つの値を受け取り格納しています。
配列の作り方
それでは、実際にカードを格納するプログラムを書いてみます。
カードはたくさんあるので配列として確保します。
いくつかパターンはありますが、以下のように配列宣言します。この配列変数はこれから作るプログラムで共通に使いますので、先頭に記述します。
var cards=[];
これで、cardsという配列変数の使用を宣言できます。
cards[0]やcards[1]としてカードの情報を取り出すことができます。
カードを作って格納する部分はinitCardという関数を用意して、以下のようにします。
function initCard() {
x=0;
for(i=1;i<=13;i++) {
cards[x]=new Card(0,i);
x++;
cards[x]=new Card(1,i);
x++;
cards[x]=new Card(2,i);
x++;
cards[x]=new Card(3,i);
x++;
}
}
for( ) は繰り返す命令です。
for( 初期値 ; 繰り返し条件 ; 増分 ) {
}
という構文で使います。
上のプログラムでは、i=1でスタートして、13以下の間、iを1ずつ増やしながら繰り返す、という意味です。
カードの種類を表すために 0,1,2,3 という数値を使います。直接ハート、スペード等と入れることも可能ですが、一般的には数値を利用した方がプログラムが書きやすく(比較しやすく)なります。
また、同じ理由でA,J,Q,K等の絵札は数値で1,11,12,13で表すことにしています。
マークは ♠=0,♣=1,♥=2,♦=3として表すことにすると、上記のプログラムで作成した配列cardsは、
♠A |
♣A |
♥A |
♦A |
♠2 |
♣2 |
♥2 |
♦2 |
……… |
♠K |
♣K |
♥K |
♦K |
という配列を作成していることになります。
構造体の生成で new というキーワードを使うのは、本当はクラスだからです。
ここではあまり気にしない事にしましょう。とにかく構造体の実体を作っています。
次に、確かに上記のような配列が格納されているのか確認するための表示用プログラムを作りましょう。
表示用のプログラム(関数)の名前はdispCardにします。
function dispCard()
{
この中にプログラムを書く。
}
構造体の配列の内部は全て数値で扱っていますから表示用の配列を作っておきます。
var markimg = ["♠","♣","♥","♦"];
var numimg = ["","A","2","3","4","5","6","7","8","9","10","J","Q","K"];
それぞれ
と
|
A |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
J |
Q |
K |
という配列を表しています。
numimgの最初には空白を入れています。使用しないので無駄に感じるかもしれませんが、配列の添字と内容を合わせておくと分かりやすいのでダミーとして入れています。
こうすると、numimg[1]は"A"、numimg[2]は"2"を表すので間違いが発生しにくくなります。
出力用の文字列用変数を初期化しておきます。
var tempHtml = "";
さらに以下の構文でマークと数値を連結しながら追記していきます。カードの枚数は(13×マークの数)枚なので、13*4回繰り返しています。
for(i=0;i<13*4;i++) {
tempHtml = tempHtml+ markimg[cards[i].mark] + ":" + numimg[cards[i].num] +" ";
}
次は「肥満度判定機」でも使った書き方です。
ループが完了したら<BR>タグで改行を追加してから、HTMLのdispという名前のdivタグの位置に出力しています。
tempHtml += "<BR>";
document.getElementById("disp").innerHTML = tempHtml;
HTMLで作成したボタンは、start()という関数を呼び出すように書きました。start()関数を書きましょう。
function start()
{
initCard();
dispCard();
}
これで、完成です。HTMLボタンを押して全てのカードが表示されるか確認してみましょう。
完成版のプログラムを以下に示します。
シャッフル
繰り返しと乱数を用いて、トランプのシャッフルをするプログラムを作ります。
基本的なアルゴリズムを図に示します。
基準を最初のカードから最後までずらしながら(繰り返し)
乱数で決めたカードの位置のカードを交換します。
常に交換でカードを混ぜていくので、プログラムミスによるカードの紛失が発生しないので私はこのアルゴリズムを良く使います。
もしも混ぜる回数が足りないのではないかと不安になるのであれば、一通り終わったあとに再度数回繰り返すと良いでしょう。
交換のアルゴリズムも定番で良く出てきます。
AとBを交換する場合、基本的には交換する2つ以外の領域wを一つ用意して
- W ← A (AをWに退避)
- A ← B (Aは既に退避したのでBをAに入れる)
- B ← W (Bは既に移動を終えたので、退避したAをBに戻す)
この3ステップで交換完了です。
shuffleCard()という関数を作ります。
function shuffleCard()
{
この中にシャッフルのプログラムを書く
}
繰り返しはカードの枚数なので、13*4枚分繰り返す。
for(i=0;i<13*4;i++) {
この中に繰り返したい内容を書く
}
交換相手となるカードを指定する乱数を発生します。
r = Math.floor(Math.random()*13*4);
Math.random()は0〜1までの乱数値を発生します。その数に13*4を掛けて 0〜13*4 つまりカードの枚数分の乱数が発生します。
Math.floor()は切り捨てをします。計算機の時に使いましたね。
これで0〜13*4未満の整数値の乱数を取得することができます。
交換相手が決まれば、あとは交換します。
基準のカードは i 番目で、交換相手は r 番目の配列の内容を交換するには、
w = cards[i];
cards[i]=cards[r];
cards[r]=w;
この3行で交換完了です。
ボタンを押した時のstart()関数でカードの初期化が終わった後にshuffleCard()の呼び出しを挿入して、カードが混ぜられたか確認してみましょう。
function start()
{
initCard();
shuffleCard();
dispCard();
}
完成版を以下に示します。
練習
- initCard関数の内部ではさらに繰り返し(for)を使うことが出来る場所があります。繰り返しを使って同じ動作をするように書き換えてください。
- dispCardではHTMLタグを使って表示する文字の色を変更することができます。<font color='red'> とするとその後が赤になります。その色を終了する場合は</font>タグで閉じます。黒にする場合は<font color='black'>です。♥と♦を赤文字で、♠と♣を黒文字で表示するように改良してください。
- ヒント:色の開始<font color>はmarkimgの配列中で指定する。色の終わりの</font>は共通なのでプログラム中で追加する。
実行結果
最終更新:2012年11月27日 02:35