第8講 ハート型・左右上下対称形・点対称形・上下対称性形・上下対称形第2案と問題から解答へ
第9話 関数fと関数sudokukaihoの変更部分
void sudokukaiho(char a, char g) {//数独を解くエンジン
  nextcell(a, g);//座標(Y[a][g], X[a][g])の取得
  char y = Y[a][g];
  char x = X[a][g];
  if (keizoku == 0)return;//数独を発見したスレッドからの連絡および閉じよの指令
  for (char i = 0; i < mx[a][y][x]; i++) {

      char gy[n] = { 0,0,0,0,0,0,0,0,0 };
   char r[n] = { 0,0,0,0,0,0,0,0,0 };
   char b[n] = { 0,0,0,0,0,0,0,0,0 };
   mondai[a][y][x] = lst[a][y][x][i];
   //候補の数字を代入 例えば、mondai[0][1]なら{2, 4}の2,4の順に代入する
   if (keizoku == 0)return;
   //x[y][x]と同じ行にあるセルへの影響を調べる。
   //具体的には座標(y, j)においてmondai[a][y][x]が候補数字に入っている場合には
   //候補から外し、候補数字の個数も一つ減らす。
   for (char j = 0; j < n; j++) {
     if (j != x) {//自己を対象から外す。
       if (mondai[a][y][j] == 0) {//空欄のみを解析対象にする。
         for (char k = 0; k < mx[a][y][j]; k++) {
           if (keizoku == 0)return;
           if (mondai[a][y][x] == lst[a][y][j][k]) {
             lst[a][y][j][k] = lst[a][y][j][mx[a][y][j] - 1];
             lst[a][y][j][mx[a][y][j] - 1] = mondai[a][y][x];
             mx[a][y][j]--;
             gy[j] = 1;//座標(y, j)においてmondai[a][y][x]が候補数字から外され、
             //候補数字数も減らされたことを記録している。
           }
         }
       }
     }
   }
   if (keizoku == 0)return;
   for (char j = 0; j < n; j++) {
     if (j != y) {//自己を対象から外す。
       if (mondai[a][j][x] == 0) {//空欄のみを解析対象にする。
         for (char k = 0; k < mx[a][j][x]; k++) {
           if (keizoku == 0)return;
           if (mondai[a][y][x] == lst[a][j][x][k]) {
             lst[a][j][x][k] = lst[a][j][x][mx[a][j][x] - 1];
             lst[a][j][x][mx[a][j][x] - 1] = mondai[a][y][x];
             mx[a][j][x]--;
             r[j] = 1;//座標(j, x)においてmondai[a][y][x]が候補数字から外され、
             //候補数字数も減らされたことを記録している。
           }
         }
       }
     }
   }
   if (keizoku == 0)return;
   char s = 3 * (y / 3);
   char t = 3 * (x / 3);
   for (char j = 0; j < n; j++) {
     char yy = s + (j / 3);
     char xx = t + (j % 3);
     if (yy != y && xx != x) {//自己を対象から外す。
       if (mondai[a][yy][xx] == 0) {//空欄のみを解析対象にする。
         for (char k = 0; k < mx[a][yy][xx]; k++) {
           if (keizoku == 0)return;
           if (mondai[a][y][x] == lst[a][yy][xx][k]) {
             lst[a][yy][xx][k] = lst[a][yy][xx][mx[a][yy][xx] - 1];
             lst[a][yy][xx][mx[a][yy][xx] - 1] = mondai[a][y][x];
             mx[a][yy][xx]--;
             b[j] = 1;//座標(j, x)においてmondai[a][y][x]が候補数字から外され、
             //候補数字数も減らされたことを記録している。
           }
         }
       }
     }
   }

   if (g + 1 < tm)sudokukaiho(a, g + 1);//内側部屋へ
   if (cn1[a] == 2) {
     return;//複数解
   }
   if (keizoku == 0)return;
   if (g + 1 == tm) {
     for (char j = 0; j < n; j++) {
       for (char k = 0; k < n; k++) {
         gensudoku[a][j][k] = mondai[a][j][k];//解答の保存
       }
     }
   cn1[a]++;
   }
   
for (char j = 0; j < n; j++) {//以下復元作業
      if (gy[j] == 1) {
        mx[a][y][j]++;
      }
      if (r[j] == 1) {
        mx[a][j][x]++;
      }
      if (b[j] == 1) {
        char yy = 3 * (y / 3) + (j / 3);
        char xx = 3 * (x / 3) + (j % 3);
        mx[a][yy][xx]++;
      }
    }

  }
}
void f(char a, char s) {//ヒント数0の数独を解く関数
  if (keizoku == 0)return;
  char y = Y[a][s];
  char x = X[a][s];
  //kyokusyokaiseki(a, y, x);
  char ii;
  if (mx[a][y][x] > 0)ii = rand() % mx[a][y][x]; else ii = 0;
  for (char i = 0; i < mx[a][y][x]; i++) {
    char iii = (ii + i) % mx[a][y][x];
    
char g[n] = { 0,0,0,0,0,0,0,0,0 };
    char r[n] = { 0,0,0,0,0,0,0,0,0 };
    char b[n] = { 0,0,0,0,0,0,0,0,0 };
    sudoku[a][y][x] = lst[a][y][x][iii]; //2次元配列に候補数字を代入
    //座標(y, x)に値sudoku[a][y][x]が入ったことによってy行にある他のセル
    //への影響を調べています。具体的にはy行にある他のセルの候補数字sudoku[a][y][x]
    //が入っている場合にsudoku[a][y][x]を候補数字から外します。
    //自己から他セルへの影響を調べています。
    for (char j = 0; j < n; j++) {
      if (j != x) {//自分自身を含めない
        if (sudoku[a][y][j] == 0) {//空欄のみを対象とする
          for (char k = 0; k < mx[a][y][j]; k++) {
            if (keizoku == 0)return;
            if (sudoku[a][y][x] == lst[a][y][j][k]) {
              lst[a][y][j][k] = lst[a][y][j][mx[a][y][j] - 1];
              lst[a][y][j][mx[a][y][j] - 1] = sudoku[a][y][x];
              mx[a][y][j]--;
              g[j] = 1;//座標(y,j)上で行われた。この情報は復元するときに必要
              break;
            }
          }
        }
      }
    }
    if (keizoku == 0)return;
    //座標(y, x)に値sudoku[a][y][x]が入ったことによってy行にある他のセル
    //への影響を調べています。具体的にはy行にある他のセルの候補数字にsudoku[a][y][x]
    //が入っている場合にsudoku[a][y][x]を候補数字から外します。
    //自己から他セルへの影響を調べています。
    for (char j = 0; j < n; j++) {
      if (j != y) {//自分自身を含めない
        if (sudoku[a][j][x] == 0) {//空欄のみを対象とする
          for (char k = 0; k < mx[a][j][x]; k++) {
            if (keizoku == 0)return;
            if (sudoku[a][y][x] == lst[a][j][x][k]) {
              lst[a][j][x][k] = lst[a][j][x][mx[a][j][x] - 1];
              lst[a][j][x][mx[a][j][x] - 1] = sudoku[a][y][x];
              mx[a][j][x]--;
              r[j] = 1;//座標(y,j)上で行われた。この情報は復元するときに必要
              break;
            }
          }
        }
      }
    }
    if (keizoku == 0)return;
    //座標(y, x)に値sudoku[a][y][x]が入ったことによって同じブロックにある他のセル
    //への影響を調べています。具体的にはブロックにある他のセルの候補数字にsudoku[a][y][x]
    //が入っている場合にsudoku[a][y][x]を候補数字から外します。
    //ただし、x列とy行についてはすでに調べているので、それらの空欄は対象から外してあります。
    //自己から他セルへの影響を調べています。
    for (char j = 0; j < n; j++) {
      char yy = 3 * (y / 3) + (j / 3);
      char xx = 3 * (x / 3) + (j % 3);
      if (yy != y && xx != x) {//自分自身を含めないおよび行と列との重複を防ぐ
        if (sudoku[a][yy][xx] == 0) {//空欄のみを対象とする
          for (char k = 0; k < mx[a][yy][xx]; k++) {
            if (keizoku == 0)return;
            if (sudoku[a][y][x] == lst[a][yy][xx][k]) {
              lst[a][yy][xx][k] = lst[a][yy][xx][mx[a][yy][xx] - 1];
              lst[a][yy][xx][mx[a][yy][xx] - 1] = sudoku[a][y][x];
              mx[a][yy][xx]--;
              b[j] = 1;//座標(y,j)上で行われた。この情報は復元するときに必要
              break;
            }
          }
        }
      }
    }

    if (keizoku == 0)return;
    if (s + 1 < hnt)f(a, s + 1); //1つ奥の部屋に入室
    if (keizoku == 0)return;
    if (cn[a] == 1)return; //数独が1個できた時点で止める
    if (s == hnt - 1) { //一番奥に部屋に到達
      for (char c = 0; c < 9; c++) {
        for (char d = 0; d < 9; d++) {
          if (sudoku[a][c][d] == 0) {
            if (keizoku == 0)return;
            mxcp[a][c][d] = mx[a][c][d];
            for (char k = 0; k < mx[a][c][d]; k++) {
              lstcp[a][c][d][k] = lst[a][c][d][k];
            }
          }
        }
      }
      cn[a]++;
      if (cn[a] == 1)return; //数独が1個できた時点でとめる
    }
    
for (char j = 0; j < n; j++) {//以下復元作業
      if (g[j] == 1) {
        mx[a][y][j]++;
      }
      if (r[j] == 1) {
        mx[a][j][x]++;
      }
      if (b[j] == 1) {
        char yy = 3 * (y / 3) + (j / 3);
        char xx = 3 * (x / 3) + (j % 3);
        mx[a][yy][xx]++;
      }
    }

tobi:;
  }
}



第8話へ
 第10話へ

トップへ