こんばんは、夜分遅くに失礼します。
現在9*9のパズルの問題(ナンプレ)を入力させたくC+でコードを稚拙にも書いていたのですが、うまく動かず(コンパイルエラー)こちらで質問させて頂きました。
意図としてはmainでsetdata,readdataを使い、問題を文字行か単文字を入力、読み込ませたいところです.
check関数、bactr関数は問題を解く関数ですので、ここは手を加えなくても大丈夫かと思います。
setdata、readdata、mainの直すべきところ、アドバイスを教えていただきたいです。
入力例ファイル
100700600
020000050
003009000
700400008
000050020
000006100
402100700
000007080
600020009
#include<iostream> #include <fstream> #include <string> using namespace std; #define ROWS 3 // ブロックサイズ #define COLS 3 #define M (ROWS*COLS) // 問題図の大きさ int mat[M][M]; // 0:空きマス,1~9:確定数字 int check( 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++) { cout<<mat[row][col]<<" "<<endl; } cout<<endl; } } void backtr( int p) // 調査位置p { if( p >= M*M) {//調査完了 cout<< "見つけた"<<endl; printdata(); // 解答図を出力する return; } int row, col, k; row = p/M; // 調査位置pを[行][列]に変換 col = p%M; if( mat[row][col]) { backtr( p+1); } else { for( k=1; k<= M; k++) { if( check( row, col, k)) { mat[row][col] = k; backtr( p+1); mat[row][col] = 0; } } } } int setdata( int row, char s) // 指定行に問題を入力 { int col = 0; while(s && col < M) { if( s == '0') {//マス未確定の時 mat[row][col++] = 0; } else if( s >= '1' && s <= '9'){//確定マス入力 mat[row][col++] = s - '0'; } else { cout<<"データ文字を認識出来ません"<<endl; return 1; } s++; } if( s && col != M) { cout<<"列数(%d)が合いません"<<endl; return 1; } return 0; } int readdata( string fin) { ifstream fin("input.dat"); if(fin.fail()){ cout << "入力ファイルをオープンできません" << endl; return 1; } string s; int row = 0; while( s=tf.gets()) { if( setdata(row,s) == 1) return 1; row++; } if( row != M) { cout<<( "行数(%d)が合いません。期待値(%d)")<<endl; return 1; } return 0; } int main(int argc, const char* argv[]) { Option opt( argc, argv); cstring fn = opt.argv(0); if( !*fn) { cout<<( "データファイルを指定して下さい")<<endl; exit(0); } if( readdata(fn)) { // 問題図読み込み printdata(); // 問題図出力 backtr(0); //[0][0]から虱潰しで検索する(バックトラック呼び出し) } return 0; }
以下修正後です
#include<iostream> #include <fstream> #include <string> using namespace std; #define ROWS 3 // ブロックサイズ #define COLS 3 #define M (ROWS*COLS) // 問題図の大きさ int mat[M][M]; // 0:空きマス,1~9:確定数字 int check( 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++) { cout<<mat[row][col]<<" "; } cout<<endl; } } void backtr( int p) // 調査位置p { if( p >= M*M) {//調査完了 cout<< "find"<<endl; printdata(); // 解答図を出力する return; } int row, col, k; row = p/M; // 調査位置pを[行][列]に変換 col = p%M; if( mat[row][col]) { backtr( p+1); } else { for( k=1; k<= M; k++) { if( check( row, col, k)) { mat[row][col] = k; backtr( p+1); mat[row][col] = 0; } } } } int setdata(int row, string s){// 指定行に問題を入力 if(s.size() != M){ cout<<"Number of columns(" << s.size() << ")not fit"<<endl; return 1; } for(int col = 0; col < M; col++) { if (s[col] >= '0' && s[col] <= '9') { mat[row][col] = s[col] - '0'; } else { cout<<"Unable to recognize data characters"<<endl; return 1; } } return 0; } int readdata(string name) { ifstream fin("input.dat"); if(fin.fail()){ cout << "Unable to open input file" << endl; return 1; } string s; int row = 0; while (getline(fin, s)) { if( setdata(row,s) == 1) return 1; row++; } if( row != M) { cout<<"The number of lines does not match. Expected value "<<endl; return 1; } return 0; } int main(int argc, const char* argv[]) { if(argc != 2) { cout<<"Please specify the data "<<endl; exit(0); } if (!readdata(argv[1])) { // 問題図読み込み printdata(); // 問題図出力 backtr(0); //[0][0]から虱潰しで検索する(バックトラック呼び出し) } return 0; }
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/11/08 19:37
2020/11/09 02:27 編集
2020/11/09 02:31
2020/11/09 04:38
2020/11/09 05:06
2020/11/09 16:47 編集
2020/11/09 17:42 編集
2020/11/09 19:24