You are not logged in.

  • Login

1

Monday, January 8th 2007, 2:23pm

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:

C Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
printf("Alles auf Null Setzen ...\n");
	for(j=0;j<9;j++) for(i=0;i<9;i++) s_matrix [j][i] = 0;
 
	printf("Starte Erstellung ...\n");
 
        srand( (unsigned)time( NULL ) );
	for(Laufzahl=1;Laufzahl!=10;Laufzahl++)
	{		
		for(Verteilt=0;Verteilt!=9;)
		{
			j = (((double) rand() / (double) RAND_MAX) * 9 + 0);
			i = (((double) rand() / (double) RAND_MAX) * 9 + 0);
			printf("l%d\tv%d\tz%d\ts%d\n",Laufzahl,Verteilt,j,i); 
 
			check = (s_matrix [j][i]); //Ist das Feld schon belegt (alle Felder sind von vorne mit "0" belegt)
				if ( check == 0 ) check = test_ispalte(&s_matrix[0][i],Laufzahl); //Test Spalte (Funktion) wenn "0" dann OK
				if ( check == 0 ) check = test_jzeile(&s_matrix[j][0],Laufzahl); //Test Zeile (Funktion) wenn "0" dann OK
				if ( check == 0 ) check = test_box(&s_matrix[0][0],j,i,Laufzahl); //Test 3*3Feld (Funktion) wenn "0" dann OK
 
			if  ( check == 0) // Wenn alles OK dann setzen
			{
				s_matrix [j][i] = Laufzahl;
				Verteilt++;
			}
		}
	}

2

Monday, January 8th 2007, 6:23pm

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

C Quellcode

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

3

Wednesday, January 10th 2007, 10:08am

OK DANKE!

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

C Quellcode

1
2
false = 1;
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?

4

Wednesday, January 10th 2007, 3:14pm

inline kannst du einfach weglassen.

ob es bool gibt oder nicht kann ich dir nicht sagen, ich verwende einen C++-Compiler, der kanns jedenfalls.

bool test_feld[9][9] überprüft ob alle bedingungen für ein sudoku eingehalten werden.

backtracking musst du dir selber überlegen, ich hab das einfach intuitiv programmiert ;)

5

Wednesday, January 10th 2007, 4:09pm

also genau das was ich hier tue:

C Quellcode

1
2
3
4
check = (s_matrix [j][i]); //Ist das Feld schon belegt (alle Felder sind von vorne mit "0" belegt)
   if ( check == 0 ) check = test_ispalte(&s_matrix[0][i],Laufzahl); //Test Spalte (Funktion) wenn "0" dann OK
   if ( check == 0 ) check = test_jzeile(&s_matrix[j][0],Laufzahl); //Test Zeile (Funktion) wenn "0" dann OK
   if ( check == 0 ) check = test_box(&s_matrix[0][0],j,i,Laufzahl); //Test 3*3Feld (Funktion) wenn "0" dann OK

6

Wednesday, January 10th 2007, 5:18pm

Jo nur das ganz6e in einer funktion.

7

Sunday, January 14th 2007, 4:17am

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 ;-)

8

Sunday, January 14th 2007, 10:49am

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.

9

Sunday, January 14th 2007, 10:29pm

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?

10

Monday, January 15th 2007, 12:33pm

Try and Error. Besetze die Felder irgendwie zufällig (aber zulässig) und probier am Schluss ob der PC es selber Lösen kann. Was genialeres würde mir da auch nicht einfallen.

11

Monday, January 15th 2007, 2:02pm

Genau dass ist mein Plan. Ich bin auch schon sehr weit, unter Umständen brauch er allerdings sehr lange für eine Lösung. Ich arbeite gerade am schneller werden.

Aber Danke!

Similar threads

Social bookmarks