第8講 ハート型・左右上下対称形・点対称形・上下対称性形・上下対称形第2案と問題から解答へ
第5話 左右対称第2案
テキストファイル自動実験版

テキストファイル手動実験版

void sayutaisyou(char a) {
  char k = hnt / 9;//中央列の個数の平均
  char s[3] = { k - 1,k,k + 1 };//平均がk
  char p;
  if (hnt % 2 == 1) {//中央列以外は左右対称であるためにセルの個数は必ず偶数になるから
    //セルの総数を奇数にするためには中央列の個数を奇数にしなければならない
    while (1) {
      p = s[rand() % 3]; //{ k - 1, k, k + 1}から1つを選ぶ
      if (p % 2 == 1)break;//ヒント数が奇数の場合中央列はのセルの個数は奇数にするしかない
    }
  }
  if (hnt % 2 == 0) {
    while (1) {
      p = s[rand() % 3];
      if (p % 2 == 0)break;
    }
  }
  char e[9];//大は小を兼ねる Y[a][]の過去を記録
  char i = 0;
  while (i <= p) {//すでに入っているセルとの重複を避ける
    X[a][i] = 4;
    if (i == 0) {
      Y[a][i] = rand() % 9;
      e[i] = Y[a][i];
    }
    if (i > 0) {
      while (1) {
        Y[a][i] = rand() % 9;
        char h = 1;
        for (char j = 0; j < i; j++) {
          if (Y[a][i] == e[j]) {
            h = 0;//1つでも一致したらwhile文は継続させる
            break;
          }
        }
        if (h == 1) {//hが 1 ということは過去のいずれとも一致しないので
          //while文を終了させる
          e[i] = Y[a][i];
          break;
        }
      }
    }
    i++;
  }
  if (p == 0)cout << "中央列には1個も入りません。";
  for (char j = 0; j < p; j++) {
    sudoku[a][Y[a][j]][X[a][j]] = 1;
  }
  char st = rand() % 36;
  char tbk[8] = { 5,7,11,13,17,19,23,29 };//すべて素数であり36とは互いに素
  char tb = tbk[rand() % 8];
  for (i = 0; i < (hnt - p) / 2; i++) {
    X[a][i] = ((st + tb * i) % 36) / 9;
    //例えば、st = 20、tb = 13とすると
    //20,33,10,23,0,13,26,3,16,29,6,19,32,
    //9,22,35,12,25,2,15,28,5,18,31,8,21,34,11,24,1,14,27,4,17,30,7
    //以下同じ循環を繰り返すが、重複なしに1巡目で0,1,2,・・・,35もれなく並べられること
    //この手法を私たちは何度も使ってきた
    Y[a][i] = ((st + tb * i) % 36) % 9;
    X[a][i + 1] = 8 - X[a][i];//左右対称な位置
    Y[a][i + 1] = Y[a][i];
    //sudoku[a][Y[a][i]][X[a][i]] = 1;
    //sudoku[a][Y[a][i + 1]][X[a][i + 1]] = 1;
  }
}


第4話へ
 第6話へ

トップへ