Sudoku Probleme generieren

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Sudoku Probleme generieren

    Hallo ich mache gerade ein Projekt in C. Es geht darum Sudoku's zu erstellen. Ich weiß, dass ich dass irgendwie über Backtracking machen muss. Habe aber keine Ahnung wie ich das machen soll.

    Kann mir da jemand helfen?

    Mein Lösungsansatz sah wie folgt aus, hängt sich aber natürlich dann irgendwann auf.

    Ein Auszug:

    Quellcode

    1. printf("Alles auf Null Setzen ...\n");
    2. for(j=0;j<9;j++) for(i=0;i<9;i++) s_matrix [j][i] = 0;
    3. printf("Starte Erstellung ...\n");
    4. srand( (unsigned)time( NULL ) );
    5. for(Laufzahl=1;Laufzahl!=10;Laufzahl++)
    6. {
    7. for(Verteilt=0;Verteilt!=9;)
    8. {
    9. j = (((double) rand() / (double) RAND_MAX) * 9 + 0);
    10. i = (((double) rand() / (double) RAND_MAX) * 9 + 0);
    11. printf("l%d\tv%d\tz%d\ts%d\n",Laufzahl,Verteilt,j,i);
    12. check = (s_matrix [j][i]); //Ist das Feld schon belegt (alle Felder sind von vorne mit "0" belegt)
    13. if ( check == 0 ) check = test_ispalte(&s_matrix[0][i],Laufzahl); //Test Spalte (Funktion) wenn "0" dann OK
    14. if ( check == 0 ) check = test_jzeile(&s_matrix[j][0],Laufzahl); //Test Zeile (Funktion) wenn "0" dann OK
    15. if ( check == 0 ) check = test_box(&s_matrix[0][0],j,i,Laufzahl); //Test 3*3Feld (Funktion) wenn "0" dann OK
    16. if ( check == 0) // Wenn alles OK dann setzen
    17. {
    18. s_matrix [j][i] = Laufzahl;
    19. Verteilt++;
    20. }
    21. }
    22. }
    Alles anzeigen
  • Ich weis nicht obs dir hilft, aber ich hab mal ein Programm zum automatischen Lösen geschrieben.
    Kannst wenn du willst jedenfalls die Überprüfung übernehmen, ob eine Zahl für das Feld zulässig ist

    Quellcode

    1. // Copyright Christoph Egger
    2. //Berechnet eine Mögliche Lösung für das Sudoku
    3. //Als eingabe wird eine Textdatei mit 9 Zeilen zu je 9 Zahlen mit ' ' als
    4. //Abstand angenommen, 0 steht für ein Leeres Feld
    5. #include <stdio.h>
    6. bool step(int feld[9][9], int filled, int searchdepth, char* filename);
    7. inline void get_next_empty(int* posx, int* posy, int feld[9][9]);
    8. void print_solution(int feld[9][9]);
    9. inline bool test_feld(int feld[9][9]);
    10. void save_solution(int feld[9][9], char* filename);
    11. int main()
    12. {
    13. char buffer[255];
    14. int feld[9][9];
    15. int filled = 0;
    16. int searchdepth = 0;
    17. printf("Dateiname des zu lösenden Sudokus eingeben!\n");
    18. scanf("%s", buffer);
    19. printf("\n\n");
    20. searchdepth = 10000;
    21. FILE* theFile = fopen(buffer,"r");
    22. if(theFile == NULL)
    23. {
    24. return -1;
    25. }
    26. for (int z = 0; z < 9; z++)
    27. {
    28. for(int s = 0; s < 9; s++)
    29. {
    30. fscanf(theFile, "%d", &feld[z][s]);
    31. if (feld[z][s] != 0) filled++;
    32. }
    33. }
    34. fclose(theFile);
    35. return step(feld, filled, searchdepth, buffer);
    36. }
    37. bool step(int feld[9][9], int filled, int searchdepth, char* filename)
    38. {
    39. static int iteration = 0;
    40. static bool printed = false;
    41. if(++iteration > searchdepth)
    42. {
    43. print_solution(feld);
    44. printf("Zu viele Durchläufe nötig!\n");
    45. return false;
    46. }
    47. int posx;
    48. int posy;
    49. get_next_empty(&posx, &posy, feld);
    50. if (posx == -1 || posy == -1)
    51. {
    52. printf("SuDoKu nach %d durchläufen gelöst:\n\n", iteration);
    53. print_solution(feld);
    54. save_solution(feld, filename);
    55. return true;
    56. }
    57. filled++;
    58. for (int i = 1; i < 10; i++)
    59. {
    60. feld[posx][posy] = i;
    61. if (test_feld(feld))
    62. {
    63. if (step(feld, filled, searchdepth, filename))
    64. return true;
    65. else
    66. {
    67. }
    68. }
    69. }
    70. feld[posx][posy] = 0;
    71. if (!printed)
    72. {
    73. print_solution(feld);
    74. printed = true;
    75. }
    76. return false;
    77. }
    78. inline void get_next_empty(int* posx, int* posy, int feld[9][9])
    79. {
    80. *posx = -1;
    81. *posy = -1;
    82. for (int x = 0; x < 9; x++)
    83. {
    84. for (int y = 0; y < 9; y++)
    85. {
    86. if (feld[x][y] == 0)
    87. {
    88. *posx = x;
    89. *posy = y;
    90. break;
    91. }
    92. }
    93. if(*posx != -1) break;
    94. }
    95. }
    96. inline bool test_feld(int feld[9][9])
    97. {
    98. bool first = true;
    99. int zff;
    100. int x;
    101. int y;
    102. //Zeilen
    103. for (zff = 1; zff < 10; zff++)
    104. {
    105. for (y = 0; y < 9; y++)
    106. {
    107. for (x = 0; x < 9; x++)
    108. {
    109. if (feld[x][y]==zff)
    110. {
    111. if (first)
    112. {
    113. first = false;
    114. }
    115. else
    116. {
    117. return false;
    118. }
    119. }
    120. }
    121. first = true;
    122. }
    123. }
    124. first = true;
    125. //Spalten
    126. for (zff = 1; zff < 10; zff++)
    127. {
    128. for (x = 0; x < 9; x++)
    129. {
    130. for (y = 0; y < 9; y++)
    131. {
    132. if (feld[x][y]==zff)
    133. {
    134. if (first)
    135. {
    136. first = false;
    137. }
    138. else
    139. {
    140. return false;
    141. }
    142. }
    143. }
    144. first = true;
    145. }
    146. }
    147. //Quadrate
    148. int x2, y2;
    149. for (zff = 1; zff < 10; zff++)
    150. {
    151. for (x2 = 0; x2 < 3; x2++)
    152. {
    153. for (y2 = 0; y2 < 3; y2++)
    154. {
    155. first = true;
    156. for (x = 0; x < 3; x++)
    157. {
    158. for (y = 0; y < 3; y++)
    159. {
    160. if (feld[x + (x2 * 3)][y + (y2 * 3)]==zff)
    161. {
    162. if (first)
    163. {
    164. first = false;
    165. }
    166. else
    167. {
    168. return false;
    169. }
    170. }
    171. }
    172. }
    173. }
    174. }
    175. }
    176. return true;
    177. }
    178. void print_solution(int feld[9][9])
    179. {
    180. for (int i = 0; i < 9; i++)
    181. {
    182. printf("%d %d %d %d %d %d %d %d %d\n", feld[i][0], feld[i][1], feld[i][2], feld[i][3], feld[i][4], feld[i][5], feld[i][6], feld[i][7], feld[i][8]);
    183. }
    184. printf("\n\n");
    185. }
    186. void save_solution(int feld[9][9], char* filename)
    187. {
    188. char newFilename[255];
    189. sprintf(newFilename, "%s.solution", filename);
    190. FILE* theFile = fopen(newFilename,"w");
    191. if(theFile == NULL)
    192. {
    193. printf("Fehler beim Speichern!");
    194. }
    195. for (int i = 0; i < 9; i++)
    196. {
    197. fprintf(theFile, "%d %d %d %d %d %d %d %d %d\n", feld[i][0], feld[i][1], feld[i][2], feld[i][3], feld[i][4], feld[i][5], feld[i][6], feld[i][7], feld[i][8]);
    198. }
    199. fprintf(theFile, "\n\n");
    200. }
    Alles anzeigen
  • Danke für deine Antwort, das hilft mir schon etwas weiter.

    :!: Ich wußte gar nicht das es in C bool gibt, gibt es doch auch nicht oder. C verwendet für

    Quellcode

    1. false = 1;
    2. true = 0;


    :?: Kannst du mir noch erklären wo und wie du jetzt Backtracking benutzt und was die Funktion inline bool test_feld(int feld[9][9]) eigentlich macht, steig ich irgendwie net so ganz dahinter?! Und was bedeutet inline?
  • also genau das was ich hier tue:

    Quellcode

    1. check = (s_matrix [j][i]); //Ist das Feld schon belegt (alle Felder sind von vorne mit "0" belegt)
    2. if ( check == 0 ) check = test_ispalte(&s_matrix[0][i],Laufzahl); //Test Spalte (Funktion) wenn "0" dann OK
    3. if ( check == 0 ) check = test_jzeile(&s_matrix[j][0],Laufzahl); //Test Zeile (Funktion) wenn "0" dann OK
    4. if ( check == 0 ) check = test_box(&s_matrix[0][0],j,i,Laufzahl); //Test 3*3Feld (Funktion) wenn "0" dann OK
  • Hm ein Sudoku ist doch ne Frage der Intelligenz, das heisst, man kann es maschinell nur durch ausprobieren lösen ? Wie ineffektiv 8)

    Nee - ma ne andere Frage:
    Also so ein olles Rätsel erstellen ist ja nicht das Problem nur, man trägt in
    jede Zeile oder Spalte die Ziffern von 1 bis 9 ein und muss diese dann nicht-identisch permutieren lol eine S9-Gruppe ? ;)

    Die Frage ist: wieviele Möglichkeiten gibt es denn ? sind das etwa (9 ! ) *(8 !) * (7 !) ... * (2 !) ? Weil aus der Eindeutigkeit könnte man dann errechnen, wieviele Ziffern man HÖCHSTENS weglassen kann, damit das Rätsel noch eindeutig bleibt ? Oder halt wiviele Ziffern noch dastehen dürfen, damit es eindeutig lösbar ist - muss es ja, sonst isses ja langweilig ;)
  • Zumindest kommt man durch ausprobieren 100%ig auf eine Lösung.

    Hier mal zu deiner Frage zur Anzahl der Möglichkeiten:

    http://de.wikipedia.org/wiki/Sudoku
    Die Zahl der möglichen 9 × 9-Sudokus beträgt nach Berechnung von Bertram Felgenhauer (im Jahr 2005) 6.670.903.752.021.072.936.960. Diese Zahl ist gleich 9! · 722 · 27 · 27.704.267.971, der letzte Faktor ist eine Primzahl.

    Durch triviale Umformung kann diese Konstante in die Finis-Normalform überführt werden, die in diesem Fall sogar einer Primfaktorzerlegung gleich kommt: 7 · 5 · 38 · 220 · 27.704.267.971. Die Zahl wurde unabhängig davon durch Ed Russell bestätigt. Nach Ed Russell und Frazer Jarvis gibt es 5.472.730.538 Möglichkeiten bei Berücksichtigung von Symmetrien. Die Zahl gültiger 16 × 16-Sudokus ist unbekannt.
  • Aber einen Tipp wie ich das ganze jetzt machen kann hat keiner? Oder soll ich einfach die frage nochmal eindeutig formulieren.

    Ich möchte gerne erklärt haben wie ich Sudokurätsel erstellen kann. Dabei ist mir nicht wichtig wie viele Felder ich maximal freilassen darf oder in welcher Anordnung diese zu einander stehen. Mir geht es darum zufällige ausgefüllte Felder zu erstellen, die dann weiter verarbeitet werden können.

    Wie kann ich das machen?