#include "puzutl.h"
#define ROWS 3 // ブロックサイズ
#define COLS 3
#define M (ROWS*COLS) // 問題図の大きさ
int mat[M][M]; // 0:空きマス,1〜9:確定数字
int IsThisOK( int row, int col, int k) // mat[row][col] に k を置けるか?
{
int rowBlock, colBlock;
int xrow, xcol;
for( xrow=0; xrow< M; xrow++) { // 同じ行にkが使われていないか?
if( mat[xrow][col] == k) return 0;
}
for( xcol=0; xcol< M; xcol++) { // 同じ列にkが使われていないか?
if( mat[row][xcol] == k) return 0;
}
// 同じブロックにkが使われていないか?
rowBlock = row/ROWS*ROWS;
colBlock = col/COLS*COLS;
for( xrow=0; xrow<ROWS; xrow++) {
for( xcol=0; xcol< COLS; xcol++) {
if( mat[rowBlock+xrow][colBlock+xcol] == k) return 0;
}
}
return 1;
}
void printdata()
{
for( int row=0; row< M; row++) {
for( int col=0; col< M; col++) {
printf( "%c", ".123456789"[mat[row][col]]);
}
printf( "\n");
}
}
void find( int p) // 調査位置p
{
if( p >= M*M) {
ps( "見つけた\n");
printdata(); // 解答図を出力する
return;
}
int row, col, k;
row = p/M; // 調査位置pを[行][列]に変換する
col = p%M;
if( mat[row][col]) {
find( p+1);
}
else {
for( k=1; k<= M; k++) {
if( IsThisOK( row, col, k)) {
mat[row][col] = k;
find( p+1);
mat[row][col] = 0;
}
}
}
}
YesNo setdata( int row, const char* s) // 指定行に問題を入力する
{
int col = 0;
while(*s && col < M) {
if( *s == '.') {
mat[row][col++] = 0;
}
else if( *s >= '1' && *s <= '9'){
mat[row][col++] = *s - '0';
}
else {
pe( "データ文字(%c,HEX:%x)を認識出来ません@行(%d)\n", *s, *s, row);
return NO;
}
s++;
}
if( *s && col != M) {
pe( "列数(%d)が合いません,期待値(%d)\n", col, M);
return NO;
}
return YES;
}
YesNo readdata( cstring fn)
{
if( !is_exist_file(fn)) {
pe( "ファイル(%s)が存在しません。\n", fn);
return NO;
}
TextFile tf(fn);
cstring s;
int row = 0;
while( s=tf.gets()) {
if( setdata(row,s) == NO) return NO;
row++;
}
if( row != M) {
pe( "行数(%d)が合いません。期待値(%d)\n", row, ROWS);
return NO;
}
return YES;
}
int main( int argc, const char* argv[])
{
Option opt( argc, argv);
cstring fn = opt.argv(0);
if( !*fn) {
pe( "データファイルを指定して下さい\n");
exit(0);
}
if( readdata( fn)) { // 問題図を読み込む
printdata(); // 問題図を出力する
find( 0); // 左上([0][0])から虱潰しで検索する
}
return 0;
}