概要
Javascript学習のスタートアップのために試作したもの。
内部に配列を持ち、世代交代の結果を文字ベースで表示し、setInterval()で更新している。
htmlのdiv要素内に文字ベースで表示している。
デモンストレーション
このアプリケーションは文字ベースなため、ブラウザやスタイルによって大変見にくい。別ページで用意したこのアプリケーションで、ブラウザによっては見やすくなる場合がある
パターン選択
実行
表示エリア
コード内容
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 |
<div> <h3>パターン選択</h3> 移動体 <input type="button" value="Grider" onclick="patternGrider()"> <input type="button" value="L-Spaceship" onclick="patternSpaceshipL()"> <input type="button" value="M-Spaceship" onclick="patternSpaceshipM()"> <input type="button" value="H-Spaceship" onclick="patternSpaceshipH()"> <br> 周期型 <input type="button" value="Octagon" onclick="patternOctagon()"> <input type="button" value="Nebula" onclick="patternNebula()"> <br> 長寿型 <input type="button" value="Die hard" onclick="patternDiehard()"> <br> ランダム <input type="button" value="Random" onclick="patternRandom()"> </div> <div> <h3>実行</h3> <input type="button" value="start/stop" onclick="startAndStop()"> </div> <div> <h3>表示エリア</h3> <div id="display_area"></div> <script src="./js/app_lifegame1.js"></script> |
JavaScript
グローバルな二次元配列にセルの情報を保持し、配列上で世代交代の処理をしたうえで、HTMLに書き出している。初期パターンの選択は、パターンごとの設定用関数を準備し、ボタンで呼び出している。主な処理ブロックは以下の通り。
- グローバル処理
- グローバル変数の宣言と初期値定義を行っている。
- 初期パターン選択
- 各パターンのボタンのクリックに応じて、パターンごとに準備された関数が呼び出され、初期pターンの設定と表示を行う。
- 起動・停止
- ボタンのクリックによって、一定時間間隔で世代交代関数を実行させ、停止させる。
- 世代交代
- ライフゲームのルールに従い、一世代後のパターンを決定し、表示する。
グローバル処理
- 共通して利用する変数の宣言/定義
- グリッドの初期化
- 初期状態のグリッドの表示
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 |
var isRunning = false; var timer; var rows = 20; var cols = 20; // エリアサイズ+2のグリッドを確保 var cell = new Array( rows + 2 ); for ( var i = 0; i <= rows + 1; i++ ) { cell[i] = new Array( cols + 2 ); } // 更新用のグリッドを確保 var newCell = new Array( rows + 2 ); for ( var i = 0; i <= rows + 1; i++ ) { newCell[i] = new Array( cols + 2 ); } initialize(); display(); function initialize() { for ( var i = 0; i <= rows + 1; i++ ) { for ( var j = 0; j <= cols + 1; j++ ) { cell[i][j] = 0; newCell[i][j] = 0; } } } function display() { var displayArea = document.getElementById( "display_area" ); displayArea.innerHTML = ""; for ( var i = 1; i <= rows; i++ ) { for ( var j = 1; j <= cols; j++ ) { displayArea.innerHTML += ( cell[i][j] == 0 ) ? "□" : "■"; } displayArea.innerHTML += "<br>"; } } |
初期パターン選択
ボタンで選択された初期パターンに対応した設定関数が呼び出される。設定関数はパターンごとに準備され、配列リテラルの内容を、グリッドの”ほぼ中央”にコピーする。
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 |
function patternGrider() { initialize(); var pattern = [ [1,1,1], [1,0,0], [0,1,0] ]; copyPattern( pattern ); display(); } function patternSpaceshipL() { initialize(); var pattern = [ [0,1,0,0,1], [1,0,0,0,0], [1,0,0,0,1], [1,1,1,1,0] ]; copyPattern( pattern ); display(); } function copyPattern( pattern ) { var patternRow = pattern.length; var patternCol = pattern[0].length; var startRow = Math.floor( rows / 2 ) - Math.floor( patternRow / 2 ); var startCol = Math.floor( cols / 2 ) - Math.floor( patternCol / 2 ); for ( var i = 0; i < patternRow; i++ ) { for ( var j = 0; j < patternCol; j++ ) { cell[startRow + i][startCol + j] = pattern[i][j]; } } } |
起動・停止
起動・停止のボタンが押されるたびに、稼働状態/停止状態がスイッチする。稼働時には、一定時間間隔で関数life()を呼び出している。life()関数内では、世代交代を施した後、表示をさせる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function startAndStop() { if ( isRunning ) { clearInterval( timer ); isRunning = false; } else { timer = setInterval( "life()", 500 ); isRunning = true; } } function life() { nextGeneration(); display(); } |
世代交代
あるセルの次世代の状態は、そのセル自身の状態と、その周囲8つのセルの数によって定められる。
存在 | 不在 | |
---|---|---|
0~1 | 死滅 | 不在 |
2 | 存在 | 不在 |
3 | 存在 | 誕生 |
4~ | 死滅 | 不在 |
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 |
function nextGeneration() { var n; for ( var i = 1; i <= rows; i++ ) { for ( var j = 1; j <= cols; j++ ) { n = numOfNeighbors( i, j ); if ( n <= 1 ) newCell[i][j] = 0; else if ( n == 2 ) newCell[i][j] = cell[i][j]; else if ( n == 3 ) newCell[i][j] = 1; else newCell[i][j] = 0; } } for ( var i = 0; i <= rows + 1; i++ ) { for ( var j = 0; j <= cols + 1; j++ ) { cell[i][j] = newCell[i][j]; } } } function numOfNeighbors( i, j ) { var count = 0; count += cell[i-1][j-1] + cell[i-1][j] + cell[i-1][j+1]; count += cell[i][j-1] + cell[i][j+1]; count += cell[i+1][j-1] + cell[i+1][j] + cell[i+1][j+1]; return count; } |