マインスイーパーfor JavaScript全行解説

マップのイメージと配列の解説へ

<html>

<head>

<title>JavaScriptマインスイーパー</title>

<SCRIPT LANGUAGE="JavaScript">

<!--

// JavaScriptマインスイーパー  Programed by たこじゃらし

// このスクリプトは、商用目的でなければ、自由に使っていただいて結構です。

// 改造、配布も自由に行っていただいてかまいません。

// 作者への連絡も強要しません。

// ただし、この5行のコメントは消さないでください。

// 2006年2月13日改造  by  himawarinokage

// windowsのマインスイーパ風に右クリックで地雷をマークできるようにしました。

// 地雷のマークにミスがある場合、間違えた地雷の画像に×がつくようにしました。

// たこじゃらしさんのコメントの下の4行のコメントも消さないでください。

 

 

 

JavaScriptの始まり

<!--表示されない-->

// の後ろはJavaScriptの中で、コメントとしてコンピュータは無視する。

// --------------------------------

var bom_c;                           // 地雷の数。

// --------------------------------

map = new Array(100);                // 地雷の有無のマップ

op_map = new Array(100);    // あいているかどうか

op_mapx = new Array(10);    // あけるマップX

op_mapy = new Array(10);    // あけるマップY

mis = new Array(100);                // 右クリックし、地雷を表示されたかどうか

var game_over = 0;

 

変数bom_cの宣言

 

配列map、op_map、op_mapx、op_mapy,misの宣言括弧の中は要素の数

 

変数 game_overの値に0を代入(「=」意味は代入)

 

1のときゲームオーバー、0のときゲームオーバーではない。

function init_map()         // マップを作る

{

for( i=0;i<100; i++ ) {

         map[i] = 0;

         mis[i] = 0;                                // misも初期化

         op_map[i] = 0;

         document.images[i].src = "base.jpg";  // リセットしたときに置き直す

}

 

 

         // 地雷の数を決める

         bom_c = Math.round(Math.random() * 5)+10;

         document.ms.cnt.value=bom_c;         // テキストボックスに地雷の数を書き込む

         cnt = 0;

         while(1) {

                   r = Math.round(Math.random() * 100);

                   if( map[r] == 0 ) {

                            map[r] = 99;

                            cnt++;

                            if( cnt == bom_c ) break;

                   }

         }

 

         for( x=0;x<10;x++ ) {

                   for( y=0;y<10;y++ ) {

                            tnum = y*10+x;

                            if( map[tnum] != 99 ) {

                                     cnt = get_cnt(x,y);

                                     map[tnum] = cnt;

                            }

                   }

         }

 

         game_over = 0;

}

関数init_map()の宣言

mapの要素に地雷の位置を代入する

map[0]〜[99]に0を代入

mis[0]〜[99]に0を代入

op_map[0]〜[99]に0を代入

リセットした時に画像をbase.jpgに置きなおす

 

 

 

地雷の数を決めてbom_cに代入する。

Math.random()は0以上、1未満の乱数を発生させる。Math.round(Math.random()*5)は四捨五入して0から5の整数にする。

 

 

0以上、1未満の乱数を発生させ、100倍し四捨五入し、0〜99までの整数にし、地雷の数と同じ数になるまで、map[0]〜[99]に99(地雷)を代入する。

while(1)はbreakの条件(cntが地雷の数になるまで)間で繰り返す。Whileの引数1は真の間ということ

==」は「等しい」という意味。

 

 

 

tnumに

0×10+0,1×10+0,・・・,9×10+0

0×10+1,1×10+1,・・・,9×10+1

0×10+9,1×10+9,・・・,9×10+9

を代入し、map[0]〜[99]が99(地雷を配置)でないなら、関数get_cnt(x,y)を実行し、周りに何個地雷があるか(temp_cntの値)をcntに代入し、99に等しくないmap[0]〜[99]に、周りの地雷の数を代入する。

すでにゲームオーバーの場合もあるので、game_overに0を代入する。


// 何個回りにあるか

function get_cnt(x,y) {

         tmp_cnt = 0;

         if( x > 0 ) {                        // 左端でないなら(左端ならしない)

                   num = y * 10 + ( x - 1 );  // 左をチェック

                   if( map[num] == 99 ) tmp_cnt++;

                   if( y > 0 ) {              // 左上をチェック

                            num = ( y - 1 ) * 10 + x - 1;

                            if( map[num] == 99 ) tmp_cnt++;

                   }

                   if( y < 9 ) {              // 左下をチェック

                            num = ( y + 1 ) * 10 + x - 1;

                            if( map[num] == 99 ) tmp_cnt++;

                   }

         }

         if( x < 9 ) {                        // 右端でないなら(右端ならしない)

                   num = y * 10 + ( x + 1 );  // 右をチェック

                   if( map[num] == 99 ) tmp_cnt++;

                   if( y > 0 ) {              // 右上をチェック

                            num = ( y - 1 ) * 10 + x + 1;

                            if( map[num] == 99 ) tmp_cnt++;

                   }

                   if( y < 9 ) {              // 右下をチェック

                            num = ( y + 1 ) * 10 + x + 1;

                            if( map[num] == 99 ) tmp_cnt++;

                   }

         }

         if( y > 0 ) {      // 上端でないなら、真上をチェック(上端ならしない)

                   num = ( y - 1 ) * 10 + x;

                   if( map[num] == 99 ) tmp_cnt++;

         }

         if( y < 9 ) {      // 下端でないなら、真下をチェック(下端ならしない)

                   num = ( y + 1 ) * 10 + x;

                   if( map[num] == 99 ) tmp_cnt++;

         }

 

         return( tmp_cnt );

}

周りの地雷の数を求めて、int_map()に返す。

関数get_cnt()の宣言:x,yの値を受け取る

(y-1)×10+(x-1)

(y-1)×10+x

(y-1)×10+(x+1)

y×10+(x-1)

y×10+x

y×10+(x+1)

(y+1)×10+(x-1)

(y+1)×10+x

(y+1)×10+(x+1)

 

 

 

上下左右、斜め上下をチェックし、

map[num]が99(地雷がある)ならば、そのたびにtemp_cntに1を足す。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

関数get_cnt()の結果としてtemp_cntの値(地雷の数)をinit_map()のcntに返す。

function put(x,y)  // 置く

{

         if( game_over == 1 ) {

                   alert("リセットして、やり直してください!");

         }

 

         num = y*10+x;

         if( op_map[num] == 1 ) return;       // 開いてたら戻る

         open_map(x,y);              // マップを開く

 

 

 

 

         // 地雷を弾いちゃった時

         if( map[num] == 99 ) {

                   alert("どっかーん!!");

                   game_over = 1;

                   open_bom();

                   return;

         }

 

         // クリアチェック

         cnt = 0;

         for( i=0;i<100;i++ ) {

                   if( op_map[i] == 0 ) cnt++; // 開いてないマップの数をカウント

         }

         if( cnt == bom_c ) {                    // 地雷の数と一致したらクリア

                   alert("おめでとう!クリアです。");

                   game_over = 1;

                   open_bom();

                   return;

         }

 

}

関数put(x,y)の宣言

bodyのbase.jpgをクリックすると、put(x,y)が実行され、その座標xとyの値が代入される。

game_overの値が1に等しい時、アラートを実行し、ダイアログ・ボックスに「リセットして、やり直してください!」と表示。

numに、送られてきたy座標の値を10倍して、x座標の値を足したものを、代入

op_map[num]の値が1のとき(開いているとき)は何もしない

関数open_map(x,y)を実行し、op_mapの値を1にすると共に回りに地雷がいくつあるか書いた画像に変える。

map[num]の値が99のとき、アラートを実行し、ダイアログ・ボックスに「どっかーん」と表示。Game_overの値を1にしopen_bom()を実行し、地雷を開き、戻る。

 

 

 

 

cntに0を代入し、

op_map[0]〜[99]まで、0に等しいか調べ、0に等しい(開いていない)場合はcntの値を1ずつ増やす。

 

開いていないop_mapの数(cntの値)が地雷の数と等しくなったとき、アラートを実行し、ダイアログ・ボックスに「おめでとう!クリアです。」と表示。

 

 

 

Game_overの値を1、地雷を開き、戻る。

function open_bom()         // 地雷を開く

{

         for( i=0;i<100;i++ ) {

                   if( ( mis[i] == 1 ) && ( map[i] != 99 ) ){     // misが1かつmapが99でないとき

                            document.images[i].src = "100.jpg";  // 地雷×の画像に置き換える

                   }

                   if( map[i] == 99 ) {

                            document.images[i].src = "99.jpg";

                   }

         }

 

}

関数open_bom()の宣言

 

配列misの要素が1に等しく、かつ配列mapの要素が99以外のとき(地雷のマークが間違っている場合)、地雷に×の画像に変える

 

 

 

 

map[0]〜[99]を調べ、99に等しい場合、

画像を99.jpg(地雷の画像)にする。

 

function open_map(x,y)  // 選択されたもののopen_mapの値を1し、画像を変える

{

         op_cnt  = 0;

         op_cnt2 = 1;

 

         op_mapx[0] = x;

         op_mapy[0] = y;

 

         num = y*10+x;

 

         op_map[num] = 1;

         wdata = map[num]+".jpg";

         document.images[num].src = wdata;

 

         if( map[num] == 0 ) {

                   open_map2();

         }

}

関数open_map(x,y)の宣言

 

関数open_map2()で使う

op_cntに0、op_cnt2に1を代入

 

open_mapxの1番目の要素にx座標の値を代入

open_mapyの1番目の要素にy座標の値を代入

 

numに、送られてきたy座標の値を10倍して、x座標の値を足したものを、代入

op_map[num]に1(開いている)を代入

wdataにmap[num](周りの地雷の数)を代入

num番目の画像を周りの地雷の数の画像に置き換える(正確にはnum+1番目の画像)

map[num]が0に等しいとき(周りに地雷がないとき)

関数open_map2()を実行する

function open_map2(x,y)       // クリックしたmapの周りのマップに

// check()を実行させる

{

         while( 1 ) {

                   loop = op_cnt;

                   op_cnt = op_cnt2;

                  for( i=loop; i<op_cnt;i++ ) {

 

 

 

                            if( op_mapx[i] > 0 ) {      // 左をチェック

                                     check( op_mapx[i]-1,op_mapy[i] );

                            }

                            if( op_mapx[i] < 9 ) {      // 右をチェック

                                     check( op_mapx[i]+1,op_mapy[i] );

                            }

                            if( op_mapy[i] > 0 ) {      // 上をチェック

                                     check( op_mapx[i],op_mapy[i]-1 );

                            }

                            if( op_mapy[i] < 9 ) {      // 下をチェック

                                     check( op_mapx[i],op_mapy[i]+1 );

                            }

                   }

                   if( op_cnt == op_cnt2 ) break;

         }

}

関数open_map2()の宣言

連続してマップを開く

breakまで繰り返し、{  }の中身を実行

loopにop_cnt(初めの値は0)の値を代入、次に

op_cntにop_cnt2の値(初めの値は1)を代入。

iにloopの値(初めは0)を代入し、op_cntの値以下(この時点では1になっている)の間繰り返し、1回実行するとiに1を足す。

 

op_mapxの値が1以上(左端でない)のとき、

x座標が1小さいもの(左のマップ)に関数check(x,y)を実行

 

op_mapxの値が8以下(右端でない)のとき、

x座標が1大きいもの(右のマップ)に関数check(x,y)を実行

 

op_mapyの値が1以上(上端でない)のとき、

y座標が1小さいもの(上のマップ)に関数check(x,y)を実行

 

op_mapyの値が8以下(下端でない)のとき、

y座標が1大きいもの(下のマップ)に関数check(x,y)を実行

 

(関数check(x,y)の結果、チェックした座標の周りに地雷がない場合op_cnt2の値が1増える)

増えない場合、op_cnt=op_cnt2になり終了。増えた場合、繰り返す。

function check(x,y)         // 上下左右をチェックする

 

{

         num = y*10+x;

         if( op_map[num] == 1 ) return;

 

         if( map[num] == 0 ) {       // 0の時

                   op_mapx[op_cnt2]=x;

                   op_mapy[op_cnt2]=y;

                   op_cnt2++;                           // 取るところを増やす

         }

 

 

 

         // 0以外の時も開く。

         if( map[num] != 99 ) {

                   op_map[num] = 1;

                   wdata = map[num]+".jpg";

                   document.images[num].src = wdata;

         }

}

関数check(x,y)の宣言

x,yにはクリックしたマップの上下左右の座標が送られてくる。

numにy×10+xの値を代入

op_mapの値が1(開いている)なら関数終了

それ以外の場合

map[num]が0(周りに地雷がない)に等しいとき、

op_map[op_cnt2]にxの値を代入

op_map[op_cnt2]にyの値を代入

(open_map()に戻って、代入した座標のチェックを繰り返す。

op_cnt2に1を足す(while(1)がbreakしないで続く)

 

map[num]が99以外(地雷でない)のとき

op_map[num]に1(開いている)を代入

wdataにmap[num](周りの地雷の数)を代入

num番目の画像を周りの地雷の数の画像に置き換える(0から始まっているので正確にはnum+1番目の画像)

function change(x,y)   //右クリックしたとき、地雷を表示

{

         num = y*10+x;

         if(op_map[num]==1){                // すでに開いているとき

         return;                        // 中止

         }

         if(mis[num]==1){                     // 地雷を表示しているとき、

         document.images[num].src = "base.jpg"; // base.jpgを表示

         mis[num] = 0;

         return;

         }

         if(mis[num]==0){                     // 地雷を表示してないときは、

         document.images[num].src = "99.jpg"; // 地雷の画像を表示

         mis[num] = 1;

         }

}

関数change(x,y)の宣言

マップの上で右クリックしたとき実行される。

すでに開いているところを右クリックした場合、何もしないで関数を中止する

 

すでに地雷(99.gif)が表示されているときは、base.jpgに置き換える。

配列要素mis[num]の値を0(地雷が表示されてない)に戻す。

関数を終了。

 

地雷が表示されていないときは、

地雷(99.jpg)を表示し、

配列要素mis[num]の値を1(地雷を表示した)にする。

// -->

</SCRIPT>

javascriptの終了

</head>

headの終了

<BODY     BGCOLOR="#000000"

          TEXT="#ffffdd" LINK="#88ffff" VLINK="#88ffcc" ALINK="#88ffcc" onLoad=init_map()>

本文開始時に関数init_map()を実行

<div align="center">

<font size=7 color=#ff4466>

マインスイーパー</font><font size=5 color=#ffffff>for JavaScript</font>

<hr>

「マインスイーパー for JavaScript」の文字を表示

<!--- ゲームの枠 -->

<table border=2><tr><td>

 

ゲームの画像を並べる表の作成

<script language="JavaScript">

<!--

for(i=0;i<10;i++) {

         for(j=0;j<10;j++) {

                   document.write('<a href=JavaScript:put(',j,',',i,')><img src=base.jpg oncontextmenu="change(',j,',',i,');return false" border=0 width=32 height=32></a>');

         }

         document.write("<br>\n");

}

// -->

</script>

JavaScriptの始まり

10行、10列の画像base.jpgが並び、画像をクリックすると、xにjの値、yにiの値が代入され、関数 put(x,y)が実行される。

右クリックしたとき、関数change(x,y)を実行する

地雷を表示する

※ put(',j,',',i,') put('+j+','+i+')と書いても同じ。document.wirate('×××'+j+'・・・') ということです。シングルクォートがないとjやiが文字とみなされてしまいます。

1行に10個のbase.jpgを書いた後に改行を入れる。

 

</td></tr></table>

表の終了

<form name=ms>

地雷の数は<input type = text value="" alt="" name="cnt" size="5">個<br><br>

<input type = button value="リセット" onClick="init_map()">

</form>

フォームの作成(名前はms)

関数init_map()のbom_c(地雷の数)をテキストボックスに表示する

クリックすると関数init_map()を実行する、「リセット」と表示された、ボタンの作成

<br>

[<a href=http://www.bb.e-mansion.com/~okayama/j-tako/js/game/mines/mines_play.html>遊び方</a>]

</div>

<hr>

</body>

</html>

 

 

遊び方へのリンク