第7講 左右対称形・上下対称形・点対称形・左右にも上下に対称・ハート型
第4話 左右対称形・上下対称形のコード例
テキストファイルは一番下にあります。

を実現するプログラム例
    if (s == n * n - 1) { //一番奥の部屋に到達
      int k = rand() % 3;
      if (k == 0)hitaisyou(a);
      if (k == 1)sayutaisyou(a);
      if (k == 2)jyogetaisyou(a);
      cn[a]++;
      if (cn[a] == 1)return; //数独が1個できた時点でとめる
    }
  tobi:;
  }
}
void hitaisyou(char a) {
  char hb; //部屋番号
  char tbs[13] = { 11,13,17,19,23,29,31,37,41,43,47,53,59 }; //飛びの選択肢
  //素数であれば81と互いに素は保証されている
  char st = rand() % 81; //始めの位置
  char tb = tbs[rand() % 13]; //飛び
  char h = 0; //可否の否
  char* gohr = (char*)calloc(hnt, sizeof(char));
  for (char t = 0; t < hnt; t++) {
     gohr[t] = (st + t * tb) % 81;
  }
  for (char j = 0; j < n; j++) {
    for (char k = 0; k < n; k++) {
      if (keizoku == 0)return;
      hb = n * j + k; //部屋番号の再初期化 = 空欄の数字候補の個数の小さい順に入れる
      char h = 0; //可否の否
      for (char t = 0; t < hnt; t++) {
        if (gohr[t] == hb) {
          h = 1;//可否の可
          break;
        }
      }
      if (h == 1) {
        mondai[a][j][k] = sudoku[a][j][k]; //問題用の配列に代入
        gensudoku[a][j][k] = sudoku[a][j][k];
      }
    }
  }
  free(gohr); //メモリ解放
}
void sayutaisyou(char a) {
  jyogetaisyou(a);
  char sudokud[n][n];
  char mondaid[n][n];
  char gensudokud[n][n];
  for (char i = 0; i < n; i++) {
    for (char j = 0; j < n; j++) {
      sudokud[j][i] = sudoku[a][i][j];
      gensudokud[j][i] = gensudoku[a][i][j];
      mondaid[j][i] = mondai[a][i][j];
    }
  }
  for (char i = 0; i < n; i++) {
    for (char j = 0; j < n; j++) {
      sudoku[a][i][j] = sudokud[i][j];
      gensudoku[a][i][j] = gensudokud[i][j];
      mondai[a][i][j] = mondaid[i][j];
    }
  }
}
void jyogetaisyou(char a) {
  char c[3];
  if (hnt % 2 == 0) {
    for (char i = 0; i < 3; i++)c[i] = 2 * i;
  }
  if (hnt % 2 == 1) {
    for (char i = 0; i < 3; i++)c[i] = 2 * i + 1;
  }
  char q = c[rand() % 3];

  char e[n];
  e[0] = rand() % 9;
  char i = 1;
  while (i < q) {
    e[i] = rand() % 9;
    while (1) {
      char h = 1;
      e[i] = rand() % 9;
      for (char j = 0; j < i; j++) {
        if (e[i] == e[j]) {
            h = 0;
            break;
        }
      }
      if (h == 1)break;
    }
    i++;
  }
  for (char i = 0; i < q; i++) {
    mondai[a][4][e[i]] = sudoku[a][4][e[i]];
    gensudoku[a][4][e[i]] = sudoku[a][4][e[i]];
  }
  char hb; //部屋番号
  char tbs[6] = { 5,11,13,17,19,23 }; //飛びの選択肢
  //素数であれば36と互いに素は保証されている
  char st = rand() % 36; //始めの位置
  char tb = tbs[rand() % 6]; //飛び
  char h = 0; //可否の否
  char* gohr = (char*)calloc(hnt, sizeof(char));
  for (char t = 0; t < hnt - q; t++) {
    gohr[t] = (st + t * tb) % 36;
  }
  for (char j = 0; j < 4; j++) {
    for (char k = 0; k < n; k++) {
      if (keizoku == 0)return;
      hb = n * j + k; //部屋番号の再初期化 = 空欄の数字候補の個数の小さい順に入れる
      char h = 0; //可否の否
      for (char t = 0; t < (hnt - q) / 2; t++) {
        if (gohr[t] == hb) {
          h = 1;//可否の可
          break;
        }
      }
      if (h == 1) {
        mondai[a][j][k] = sudoku[a][j][k];
        mondai[a][8 - j][k] = sudoku[a][8 - j][k];
        gensudoku[a][j][k] = sudoku[a][j][k];
        gensudoku[a][8 - j][k] = sudoku[a][8 - j][k];
      }
    }
  }
  free(gohr); //メモリ解放
}
テキストファイル

次の課題は点対称形です。

ノーヒントで皆さんに挑戦していただきます。



第3話へ
 第5話へ

トップへ