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

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

void sayujyogetaisyou(char a) {
  char q = 0;
  if (hnt % 2 == 1) {//ヒント数が奇数の場合には真ん中の座標(4, 4)に入れないないとだめ
    //左右にも上下にも対称は線対称にして点対称であることと同値であり、
    //点対称の要請から真ん中入力は必要
    Y[a][0] = 4;
    X[a][0] = 4;
    q++;
  }
  if ((hnt - q) % 4 == 2) {//中央列と中央行にの両方に入れてしまうと4で割った時に余りが2であるから、
    //どちらか一方を選ばないと矛盾してしまう
    char b = rand() % 2;
    if (b == 0) {
      Y[a][q] = 4;
      X[a][q] = rand() % 4;
      q++;
      Y[a][q] = 4;
      X[a][q] = 8 - X[a][q - 1];
      q++;
    }
    if (b == 1) {
      Y[a][q] = rand() % 4;
      X[a][q] = 4;
      q++;
      Y[a][q] = 8 - Y[a][q - 1];
      X[a][q] = 4;
      q++;
    }
  }
  if ((hnt - q) % 4 == 0) {//(hnt - q) % 4 == 2の場合とは異なり、両方に入れないと4の倍数にならない
    Y[a][q] = 4;
    X[a][q] = rand() % 4;
    q++;
    Y[a][q] = 4;
    X[a][q] = 8 - X[a][q - 1];
    q++;
    Y[a][q] = rand() % 4;
    X[a][q] = 4;
    q++;
    Y[a][q] = 8 - Y[a][q - 1];
    X[a][q] = 4;
    q++;
  }
  char st = rand() % 16;//中央行と中央列を除いた左上1/4部分に対応
  char tbs[5] = { 3,5,7,11,13 };//すべて素数であるから16との互いに素は保証されている
  char tb = tbs[rand() % 5];
  for (char i = 0; ; i++) {
    Y[a][q] = ((st + tb * i) % 16) / 4;//中央行と中央列を除いた左上1/4部分に対応
    X[a][q] = ((st + tb * i) % 16) % 4;
    //例えば、st = 10,tb = 7とすると
    //10,1,8,15,6,13,4,11,2,9,0,7,14,5,12,19
    //一巡しただけで0~15までに数字がもれなく重複なしにそろう
    //二巡以降も全く同じ動きする
    Y[a][q + 1] = Y[a][q];
    X[a][q + 1] = 8 - X[a][q];//左右対称性
    Y[a][q + 2] = 8 - Y[a][q];//上下対称性
    X[a][q + 2] = X[a][q];
    Y[a][q + 3] = 8 - Y[a][q];//点対称性
    X[a][q + 3] = 8 - X[a][q];
    q += 4;
    if (hnt == q)break;
  }
  //for (char i = 0; i < q; i++)sudoku[a][Y[a][i]][X[a][i]] = 1;
}




第1話へ
 第3話へ

トップへ