文字を使用してあみだくじを自動生成するコードを書いてみました.
サンプル: amida.html
実行時の画像:
余談ですが,漢字だと「阿弥陀籤」と書いて,昔は放射状に描かれていたことから,それが後光に似ている言われたのが名前の由来だそうです(Wikipedia).
あみだくじを作成する部分
// あみだくじを作成するよ! function makeAmida(num, len){ // ①〜⑳まで if(num > 20) alert("20人以下でお願いします.") // 縦の長さ var amida = new Array(len); for(i=0; i<len; i++) { // 縦のループ // 横の長さ amida[i] = new Array(2*num-1); for(j=0; j<2*num-1; j++) { // 横のループ // 横の位置:偶数番目 if (j%2) { if(amida[i][j-1] == "┣") { amida[i][j] = "━"; // 左が┣だったら━ } else { amida[i][j] = " "; // それ以外(┫┃)だったら空白 } } // 横の位置:奇数番目 else { if(amida[i][j-1] == "━") { amida[i][j] = "┫"; // 左が━だったら┫ } else { if(j==2*(num-1)) { amida[i][j] = "┃"; // 右端は┃のみ } else { // その他の位置では1/2で┃か┣ (**ランダムなアミダを作る箇所**) amida[i][j] = (Math.floor(Math.random()*2)) ? "┃" : "┣"; } } } } // for i } // for j return amida; // 作成したアミダを返す }
偶数番目/奇数番目でありえる記号をamidaに代入していきます.例えば,偶数番目なら「━」か空白「 」し有り得ず,奇数番目なら「┫」か「┃」か「┣」しか有り得ないわけです.左から順に描いていくので,左が「┣」だったら絶対に「━」を取る,とか左が「━」だったら絶対に「┫」を取る,とかを考えながら場合わけをします.「┃」か「┣」の部分だけ1/2でどちらかを選択するようにコードを書けば,ランダムなアミダが生成できます.
アミダを描く
// 作成したアミダを描くよ! function writeAmida(matrix) { // ○付番号 var nums = new Array("①","②","③","④","⑤","⑥","⑦","⑧","⑨","⑩","⑪","⑫","⑬","⑭","⑮","⑯","⑰","⑱","⑲","⑳"); // 頭の番号 for(i=0; i<(matrix[0].length-1)/2; i++) { document.write('<span class="amida" id="top_num' + i + '">'); document.write(nums[i]); document.write(' </span>'); } document.write("<br />"); // アミダくじを描く for(i=0; i<matrix.length; i++) { // 横 for(j=0; j<matrix[0].length; j++) { document.write('<span class="amida" id="amida' + i + "l" + j + '">'); document.write(matrix[i][j]); document.write('</span>'); } document.write("<br />"); } // 下の番号 for(i=0; i<(matrix[0].length-1)/2; i++) { document.write('<span class="amida" id="bottom_num' + i + '">'); document.write(nums[i]); document.write(' </span>'); } }
得られたアミダを描きます.後でトレース出来るように適当なidを各要素に持たせておきます.
アミダをトレースする
// アミダをトレースするよ! // matrix: アミダ // i, j : 現在位置(i: 縦 j: 横) // i2, j2 : 1個前の位置 // 再帰回数 function traceAmida(matrix,i,i2,j,j2,step) { // 前のポジションを記憶 pre_i = i; pre_j = j; // 一番初めの時 if(step==0) { i = i2 = 0; pre_i = -1; j = j2 = 0; pre_j = 0; // 最初の開始位置はランダム(偶数位置) j = 2*Math.floor(Math.random()*(matrix[0].length+1)/2); } // 通常時 else { // 現在位置の記号で場合わけ if(matrix[i][j] == "━") { j += (j - j2); // そのままの速度で横方向へ移動 } else if (matrix[i][j] == "┫") { if (i-i2) { // 下向きに速度を持っていたら j--; // 左へ移動 } else { // 横向きだったら i++; // 下へ移動 } } else if(matrix[i][j] == "┣") { if (i-i2) { // 下向きに速度を持っていたら j++; // 右へ移動 } else { // 横向きだったら i++; // 下へ移動 } } else { // ┃であった場合 i++; // 下へ移動 } } // 最終段に達していないとき(道中の時) if (!(i==matrix.length)) { if (step == 0) { // 開始箇所は黄色にする document.getElementById("top_num" + (j/2)).style.color = "#ff0"; document.getElementById("amida" + i + "l" + j).style.color = "#ff0"; } else { // 通常時は赤色でトレース document.getElementById("amida" + i + "l" + j).style.color = "#f00"; } // 50ms後に再度実行 step++; setTimeout(function(){ traceAmida(matrix, i, pre_i, j, pre_j, step) }, 50); } // 最終段の場合 else { document.getElementById("bottom_num" + (j/2)).style.color = "#00f"; } }
前の位置を記憶して,現在位置と前の位置から,現在左に進んでいるか,右に進んでいるか,それとも下に進んでいるかを判断して,妥当な方向にiとjを進める,ということをしています.
通しで実行
// アミダくじを実行 function amida(num, len){ var amida = makeAmida(num, len); writeAmida(amida); traceAmida(amida,0,0,0,0,0); } // 人数を求めるプロンプトを出し,アミダを実行 function askNum() { var num = prompt("人数を入力してください.決定するとスタートします.","5"); amida(num, 30) }
askNumを実行すれば動作します.
おわりに
シンプルに書くにはどうすればいいんですかね?個人的に速度で調べる部分がちょっと微妙な感じがするのですが,巧い実装方法があったら教えてください.