ホームページ制作に使われるJavaScriptというコンピュータ言語は、色々な面白いことができます。
皆さんご存知の定番ゲーム、15パズルをJavaScriptで作ってみました。
ちなみに、ウィキペディアによると、15パズルは、日本では明治40年(1907年)に書かれた書物「世界遊戯法大全」に「十五置き換え遊び」の名で紹介されているということで、歴史の古い遊びなのです。
HTML部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<link rel="stylesheet" href="https://liveinhope.biz/wp-content/uploads/2017/06/15puzzle.css"> <div id="startdiv"> <button id="start">start</button> </div> <table id="puzzle"> <tr> <td id="cell_0"><button>1</button></td> <td id="cell_1"><button>2</button></td> <td id="cell_2"><button>3</button></td> <td id="cell_3"><button>4</button></td> </tr> <tr> <td id="cell_4"><button>5</button></td> <td id="cell_5"><button>6</button></td> <td id="cell_6"><button>7</button></td> <td id="cell_7"><button>8</button></td> </tr> <tr> <td id="cell_8"><button>9</button></td> <td id="cell_9"><button>10</button></td> <td id="cell_10"><button>11</button></td> <td id="cell_11"><button>12</button></td> </tr> <tr> <td id="cell_12"><button>13</button></td> <td id="cell_13"><button>14</button></td> <td id="cell_14"><button>15</button></td> <td id="cell_15"><br></td> </tr> </table> <div id="finish"></div> <script type="text/javascript" src="https://liveinhope.biz/wp-content/uploads/2017/06/15puzzle.js"></script> |
CSS部分
Google Fontsを使っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
@import url('https://fonts.googleapis.com/css?family=Frijole'); #startdiv{ text-align: center; } #start{ font-family: 'Frijole', cursive; font-size: 40px; } #puzzle{ margin: 20px auto; } #puzzle button{ font-family: 'Frijole', cursive; font-size: 40px; width: 80px; height: 80px; text-align: center; } #finish{ font-family: 'Frijole', cursive; font-size: 40px; text-align: center; } |
JavaScript部分
配列をランダムにして、それが解ける問題か否かを判定するロジックを自力で考えつくのは難しいです。
「15パズル 偶置換」で検索すると色々出てきますので、色々と参考にさせてもらいました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
(function () { //シャッフル関数はこちらを参照 https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array function shuffle(array) { var currentIndex = array.length, temporaryValue, randomIndex; while (0 !== currentIndex) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; temporaryValue = array[currentIndex]; array[currentIndex] = array[randomIndex]; array[randomIndex] = temporaryValue; } return array; } //駒配列 //keyがセル //valueが数字 var komaArr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; //ゼロのkeyを覚える変数 var zero; //最初に駒を並べる関数 function lineUp(arr) { //駒配列の長さをループ for (var i = 0; i < 16; i++) { //配列のvalueが0でなかったら if (arr[i]) { //HTMLを変更 document.getElementById("cell_" + i).innerHTML = "<button>" + arr[i] + "</button>"; //駒にイベント登録 //tdにidをつけているので //tdのfirstElementChild=最初の子要素のbuttonにイベントを追加する document.getElementById("cell_" + i).firstElementChild.addEventListener('click', move, false); } else { //配列のvalueが0なら //ゼロのkeyを覚える zero = i; //HTMLを変更 document.getElementById("cell_" + i).innerHTML = "<br>"; } } } //解けるパズルかどうかチェックする関数 //参照 http://y-uti.hatenablog.jp/entry/2015/04/29/103422 function check(arr) { //0のkey var z; //新しい配列を作る var a = new Array(); //新しい配列の添字 var i = 0; //0は何番目に出現? var j = 0; //コピー元の配列をループ for (var v in arr) { //valueが0でない時だけ if (arr[v]) { //新しい配列に追加 a[i] = arr[v]; i++; } else { //0は何番目か記憶する z = j; } j++; } //合計に使う変数 var count; //0が何行目にあるか /* * 1 2 3 4 * 5 6 7 8 * 9 10 11 12 * 13 14 15 0 * この場合0は4行目にある * */ if (z >= 0 && z <= 3) { count = 1; } else if (4 >= 0 && z <= 7) { count = 2; } else if (8 >= 0 && z <= 11) { count = 3; } else if (12 >= 0 && z <= 15) { count = 4; } //配列がなくなるまでループ while (a[0] !== undefined) { //配列の先頭を取得 var lead = a[0]; //配列の先頭を削除 a.shift(); //配列をループ for (var num in a) { if (lead > a[num]) { count++; } } } //偶数なら解ける if (count % 2 === 0) { return true; } else { return false; } } //ゲームオーバー判定 function finish() { //完成図 var complete = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0]; //完成図と比較 if (complete.toString() === komaArr.toString()) { return true; } else { return false; } } //駒移動の関数 function move(e) { //クリックしたbuttonのあるtdのid var id = e.target.parentNode.id; //配列のkeyをidから取得 var key = Number(id.replace("cell_", "")); //クリックした駒の上下左右のvalueの配列 /* * 1 2 3 4 * 5 6 7 8 * 9 10 11 12 * 13 14 15 0 * * 4×4のマス目があり、クリックされた駒の * 上下左右を見て、もし0があれば移動できる * */ var jgsy = new Array(4); //上 jgsy[0] = komaArr[key - 4]; //下 jgsy[1] = komaArr[key + 4]; //左 jgsy[2] = key % 4 !== 0 ? komaArr[key - 1] : undefined; //右 jgsy[3] = (key + 1) % 4 !== 0 ? komaArr[key + 1] : undefined; //上下左右のvalueの配列をループ for (var num in jgsy) { //上下左右に0があれば移動できる if (jgsy[num] === 0) { //0のid var zeroId = "cell_" + zero; //配列変更 //0のvalueにクリックしたvalueを代入 var henkou = komaArr[zero] = komaArr[key]; //クリックしたvalueに0を代入 komaArr[key] = 0; //ゼロのkeyを覚える zero = key; //HTMLを変更 document.getElementById(zeroId).innerHTML = "<button>" + henkou + "</button>"; //駒にイベント登録 document.getElementById(zeroId).firstElementChild.addEventListener('click', move, false); //HTMLを変更 document.getElementById(id).innerHTML = "<br>"; //ループを抜ける break; } } //ゲームオーバー判定 if (finish()) { document.getElementById("finish").innerHTML = "finished"; } else { document.getElementById("finish").innerHTML = ""; } } //ボタンを押したらスタート function start() { document.getElementById("finish").innerHTML = ""; //無限ループ while (true) { //シャッフルする komaArr = shuffle(komaArr); //解けるパズルならループを抜ける if (check(komaArr)) { break; } } //駒を並べる lineUp(komaArr); } //スタートボタンにイベント登録 document.getElementById('start').addEventListener('click', start, false); }()); |