PHPとJavaScriptで『人材獲得作戦・4 試験問題』を解いてみた(つづく。)
今さらですが、試験問題はここにあります。
http://okajima.air-nifty.com/b/2010/01/post-abc6.html
幅優先検索ロジックでPHPで解いてみまして、そして、同じロジックでJavaScriptで探索経過を再現してみましたが。
まだ、解けていない部分があります。
それは、最短経路ではない。orz
まあ、自分なりの不完全な答えを恥ずかしながらお見せします。w
後日に、最短経路込みの回答を追記します。
- ここに実際の画面を見れます。
http://benny.sakura.ne.jp/tmp/run.php
ソース
<?php class map { public $map; public $sx; public $sy; public $queue = array(); public $history_map; function __construct(){ $map = file("./map.txt"); foreach($map as $row => $line) { $line =str_split($line); foreach($line as $col => $word) { $this->map[$row][$col] = $word; //Sの原点を設定 if($word == "S") { #キューを初期化 $this->queue[] = array($row,$col); } } } } function run() { while ($this->_getNext()){} } #次へ行けるポイントを見つける private function _getNext() { #キューが空になったら探索を終了させる if(!$this->queue) return false; #キューの先頭から今回の探索起点ポイントをゲット list($sx,$sy) = array_shift($this->queue); if(!$this->history_map) { $this->history_map[$sx][$sy] = $this->map; } #方向を見る,順番は↓ → ← ↑ $nextPoint['down'] = array($sx, $sy + 1); $nextPoint['right'] = array($sx + 1, $sy); $nextPoint['left'] = array($sx - 1, $sy); $nextPoint['up'] = array($sx, $sy - 1); #四つの方向から次へ行けるポイントをすべて探し出す foreach ($nextPoint as $v) { list($x, $y) = $v; switch($this->map[$x][$y]) { #「*」だったら、殺す case "*": continue; break; #「G」だったら、描画して終了! case "G": $this->_print_map($this->history_map[$sx][$sy]); return false; break; #空白だったら且つ未探索ポイントだったら、キューに入れる default: if(!$this->history_map[$x][$y]){ array_unshift($this->queue, $v); $this->history_map[$x][$y] = $this->history_map[$sx][$sy]; $this->history_map[$x][$y][$x][$y] = "#"; } continue; break; } } return true; } #経路を描画する private function _print_map($map) { echo "<pre>"; foreach ($map as $row => $line) { foreach ($line as $word) { echo $word; } } echo "</pre><br />"; } } $map = new map(); $map->run(); ?>
<script type="text/javascript" src="jquery.js"></script> <script> $(document).ready(function(){ //マップ制御実行 $("#map").map_run(); }); (function($){ $.fn['map_run'] = function(){ var map = new Array(); var history_map = new Array(); var map_dom = $(this); var sx; var sy; var queue = new Array(); var n = 0; var timerID; var _fn = { init : function (){ var rows = map_dom.text().split('\n'); for (var x = 0; x < rows.length; x++){ var line = rows[x].split(''); map[x] = []; for (var y = 0; y < line.length; y++){ map[x][y] = line[y]; if(line[y] == "S"){ queue[0] = [x,y]; history_map[x+"_"+y] = this.get_new_map_str(map_dom.text()); } } } }, run : function (){ timerID = window.setInterval(function (){ _fn.get_next(); }, 100); }, get_next : function (){ //キューが空になったら探索を終了させる if(queue.length == 0) return false; //キューの先頭から今回の探索起点ポイントをゲット var sxy = queue.shift(); sx = sxy[0]; sy = sxy[1]; this.print_map(history_map[sx+"_"+sy]); //方向を見る var nextPoint = []; nextPoint['down'] = [sx, sy + 1]; nextPoint['right'] = [sx + 1, sy]; nextPoint['left'] = [sx - 1, sy]; nextPoint['up'] = [sx, sy - 1]; //四つの方向から次へ行けるポイントをすべて探し出す for (next in nextPoint) { var x = nextPoint[next][0]; var y = nextPoint[next][1]; switch (map[x][y]) { //「*」だったら、殺す case '*': continue; break; //「G」だったら、描画して終了! case 'G': this.print_map(history_map[sx+"_"+sy]); clearInterval(timerID); return false; break; default: if(!history_map[x+"_"+y]){ queue.unshift([x,y]); history_map[x+"_"+y] = this.get_new_map_str(history_map[sx+"_"+sy], x, y); } continue; break; } } return true; }, print_map : function (map){ map_dom.text(map); }, get_new_map_str : function (map_str, step_x, step_y) { var rows = map_str.split('\n'); var map_array = []; for (var x = 0; x < rows.length; x++){ var line = rows[x].split(''); map_array[x] = []; for (var y = 0; y < line.length; y++){ map_array[x][y] = line[y]; } } if(step_x && step_y){ map_array[step_x][step_y] = "#"; } for (var x = 0; x < map_array.length; x++) { line[x] = map_array[x].join(""); } return line.join("\n"); } } _fn.init(); _fn.run(); }; })(jQuery); </script> <pre id ="map" > ************************** *S* * * * * * * ************* * * * * ************ * * * * ************** *********** * * ** *********************** * * G * * * *********** * * * * ******* * * * * * ************************** </pre>