トップ > プログラミング > Sudoku ナンバープレイスを課題にしたプログラム作りです。
2010/08/10 17:39
4. マス目の状態の確認
手順2の記述に入る前に、81個のマス目の状態を確認するためのコードを書き加えてみます。
手順1の記述では、9×9 のマス目に入る数字の候補を'123456789'という文字列として、81個の要素を持つ配列に設定しました。81個の要素は、0 から 80 までの添字の値で識別されるのですが、9 行 9 列のマス目との対応をどうするのかについては、触れていませんでした。次図のように、対応させることにします。各マス目の中の数字は、添字になります。
任意の時点で何度でもこの確認作業を行えるように、関数としてコードを記述してみます。
function PrintGridState()
{
// 全てのマス目の状態を表示する。
global $grid;
$col = 0;
$row = 0;
$blk = 0;
for($n = 0; $n < count($grid); $n++)
{
if($col == 0)
{ // 行番号を表示
$row++; // $row = $row + 1 のことです。
echo "$row "; // $row . ' ' と書くこともできます。
}
if(strlen($grid[$n]) == 1)
echo $grid[$n]; // 確定した一つの数字を表示
else
echo "($grid[$n])"; // 候補が複数の場合、括弧内に表示
if(++$col == 9) // if()の評価の前に$col = $col + 1 を実行
{ // 9列で改行
echo "\n"; // 改行します。
$col = 0;
$blk = 0;
}
elseif(++$blk == 3)
{ // 3列ごとに隙間を空ける
echo ' ';
$blk = 0;
}
}
}
関数は'function 関数名(){…}'と記述されます。{}の中には処理が記述されます。関数の特徴は、関数を呼び出さない限り、制御が{}内に移らないことです。ここでは、関数名をPrintGridStateとしました。
'global $grid;'という記述は、関数の外で定義されている変数 $grid を関数内でも使うことを宣言しています。手順1により、$gridには候補値が設定されています。この宣言なしで$gridを使った場合、$grid に値を設定しない限り、初期状態では何も設定されていません。
$col、$row は、行と列を表す変数です。$blk は3列ごとに空白を挿入し見やすくするために使っている変数です。候補が複数の場合は、括弧内に複数の候補を並べて表示するようにしました。表示には echo 文を使います。ダブルクォーテーション内には文字列だけでなく、変数や改行を表す特殊文字を書けます。変数は評価されて、変数の持つ値に置き換えられます。Perl も同様の記述ができます。PHP と Perl はともに、変数の先頭に'$'を付けるので、こういった記述が可能になるわけです。便利な機能です。文字列を連結させる演算子'.'を使った記述に比較して、読みやすいと思います。'\n'は改行文字です。
'$row++' は、'$row = $row + 1' 同じです。$row の値に 1 を加算し、$row に格納します。'if(++$col == 9)~'は、$col の値が9 かどうかを判定していますが、判定する前に $col に 1 を加算しています。'$col++; if($col == 9)~'と同義です。
手順1の記述と合わせたコードと、その実行結果を以下に記します。コードはsudoku.php というファイルに格納しましたので、コマンドプロンプトから php を呼び出すときに、引数として sudoku.php を指定して実行させています。
数独パズルを解く。
<?php
// 数独パズルを解く。
// 9x9のマス目に候補値を設定する。
$grid = array();
for($n = 0; $n < 81; $n++)
{
$grid[$n] = '123456789';
}
// 全てのマス目の状態を表示する。
PrintGridState();
exit;
function PrintGridState()
{
// 全てのマス目の状態を表示する。
global $grid;
$col = 0;
$row = 0;
$blk = 0;
for($n = 0; $n < count($grid); $n++)
{
if($col == 0)
{
$row++;
echo "$row ";
}
if(strlen($grid[$n]) == 1)
echo $grid[$n];
else
echo "($grid[$n])";
if(++$col == 9)
{
echo "\n";
$col = 0;
$blk = 0;
}
elseif(++$blk == 3)
{
echo ' ';
$blk = 0;
}
}
}
?>
'PrintGridState();'と関数を呼び出した後に、'exit;'でプログラムの実行を終了させています。'exit;'を書かなくても問題はありませんが、関数の下に実行可能なコードが書かれているかどうかを気にする必要がないように、明示的に終了させたまでです。