#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; }