paiza Aランクレベルアップセット「 STEP: 20 陣取りの結末 PHP編」

丸一日苦心して、それでも通らなかったので、他の方の解いたコードをチラ見しました。無念!

しかし拝見しなかったら、一週間やそこらじゃ解けなかったでしょう。感謝です。

ポイントは3つ

  • 新規に「*」になった座標を配列に入れる
  • その配列の中身がある限りwhile文でループ
  • 処理が終わったら、その配列の中身の使った分をひとつ消去
 <?php
    // 自分の得意な言語で
    // Let's チャレンジ!!


    $s = explode(" ",trim(fgets(STDIN)));
    $h = $s[0];
    $w = $s[1];
    
    //map取得
    for ($i = 0; $i < $h; $i++) {
        $hoge = trim(fgets(STDIN));
        for ($j = 0; $j < $w; $j++) {
            $map[$i][$j] = mb_substr($hoge, $j, 1); 
            if($map[$i][$j]=="*"){
                $y = $i;
                $x = $j;
            }
        }
    }
    //print_r($map);

    
    //初期処理
    //新たに*にした場所を$newstarに格納する
    
    if($y>=1 && $map[$y-1][$x]=="."){
        $map[$y-1][$x] = "*"; 
        $newstar[]=array($y-1,$x);
    }
    if($y<$h-1 && $map[$y+1][$x]=="."){
        $map[$y+1][$x] = "*"; 
        $newstar[]=array($y+1,$x);
    }
    if($x>=1 && $map[$y][$x-1]=="."){
        $map[$y][$x-1] = "*"; 
        $newstar[]=array($y,$x-1);
    }
    if($x<$w-1 && $map[$y][$x+1]=="."){
        $map[$y][$x+1] = "*";
        $newstar[]=array($y,$x+1);
    }
    
    
    while(count($newstar)>=1){//移動可能な座標がある限り続ける
        
        $y = $newstar[0][0];
        $x = $newstar[0][1];
        
        //共通操作
        if($y>=1 && $map[$y-1][$x]=="."){
            $map[$y-1][$x] = "*"; 
            $newstar[]=array($y-1,$x);
        }
        if($y<$h-1 && $map[$y+1][$x]=="."){
            $map[$y+1][$x] = "*"; 
            $newstar[]=array($y+1,$x);
        }
        if($x>=1 && $map[$y][$x-1]=="."){
            $map[$y][$x-1] = "*"; 
            $newstar[]=array($y,$x-1);
        }
        if($x<$w-1 && $map[$y][$x+1]=="."){
            $map[$y][$x+1] = "*"; 
            $newstar[]=array($y,$x+1);
        }
        
        array_shift($newstar);//いまつかった配列を消す
        
    }
    
    //print_r($newstar);

    
    //出力
    for ($i = 0; $i < $h; $i++) {
        for ($j = 0; $j < $w; $j++) {
            echo($map[$i][$j]);
        }
        echo("\n");
    }


?>

配列$newstarに、初期座標の上下左右が*にできるなら、そのy,xを格納していきます。

今度はその移動可能な座標を基点に、同様に処理をします。処理後は使用済みの座標を消します。

while文はあまりなじみがなかったので、「配列の中身がある限りループ」という条件式の発想がまったくなく、見たとき衝撃を受けました。

kue

paizaAランクレベルアップメニュー(各言語あり)

https://paiza.jp/works/mondai/a_rank_level_up_problems

参考にさせて頂いたコード:「陣取りゲーム (paizaランク A 相当)をPHPで解いてみた」

https://rnsr0371.boy.jp/2020/09/11/jintori_game/
1+