sudoku in c++

Hallo ich habe das Sudoku von Guillermo mal in c++ umgesetzt. Kam bei dir in c auch ein Stack overflow ?

Wenn Ich in c++ die Random Funktion aufrufe und einen Wert über 12 nehmen läuft alles perfekt, aber ist der random wert (rand()%9+1) schmiert mein Programm fast instant ab und die Fehlermeldung ist Stackoverflow..

Kann mir da einer vielleicht weiterhelfen ?
 
Hi.
Hallo ich habe das Sudoku von Guillermo mal in c++ umgesetzt. Kam bei dir in c auch ein Stack overflow ?

Wenn Ich in c++ die Random Funktion aufrufe und einen Wert über 12 nehmen läuft alles perfekt, aber ist der random wert (rand()%9+1) schmiert mein Programm fast instant ab und die Fehlermeldung ist Stackoverflow..
Also erstmal sollte man niemals etwas wie rand() % x verwenden. Gute Zufallszahlen erzeugt man so:
C:
rand() / (RAND_MAX + 1.0) * x
Schreib dir eine Funktion dafür die Werte in einem bestimmten Interval zurückgibt.

Ein Stack-Overflow deutet darauf hin, das deine Rekursionstiefe zu hoch ist. Versuche das Problem iterativ zu lösen. Oder du hast einfach einen Fehler gemacht und eine Endlos-Rekursion programmiert... dann zeig deinen Code.

Gruß
 
Hier die Version Ohne deinen Vorschlag, so wie ich sie im moment noch "verwende" (wenns klappen würden :p )

Code:
#include <iostream> 
#include <time.h>
#include <stdlib.h>

using namespace std;

int sfeld[9][9]; // "Spielfeld"

// Zum ermitteln in welchem Block die Koordinaten x, y liegen
int welcher_block(int x, int y)
{
	int block = 0;
	
	if((x >= 0 && x <= 2) && (y >= 0 && y <= 2)) block = 0;
	if((x >= 0 && x <= 2) && (y >= 3 && y <= 5)) block = 3;
	if((x >= 0 && x <= 2) && (y >= 6 && y <= 8)) block = 6;
	
	if((x >= 3 && x <= 5) && (y >= 0 && y <= 2)) block = 1;
	if((x >= 3 && x <= 5) && (y >= 3 && y <= 5)) block = 4;
	if((x >= 3 && x <= 5) && (y >= 6 && y <= 8)) block = 7;
	
	if((x >= 6 && x <= 8) && (y >= 0 && y <= 2)) block = 2;
	if((x >= 6 && x <= 8) && (y >= 3 && y <= 5)) block = 5;
	if((x >= 6 && x <= 8) && (y >= 6 && y <= 8)) block = 8;

	return block;
}

//Ermitteln der Startpositionen des übergeben Blocks
int pruefe_block(int block, int zahl)
{
	int begin_x = 0;
	int begin_y = 0;
	int exist = 0;
	
	switch(block)
	{
		case 0: begin_x = 0; begin_y = 0; break;
		case 1: begin_x = 3; begin_y = 0; break;
		case 2: begin_x = 6; begin_y = 0; break;
		
		case 3: begin_x = 0; begin_y = 3; break;
		case 4: begin_x = 3; begin_y = 3; break;
		case 5: begin_x = 6; begin_y = 3; break;
		
		case 6: begin_x = 0; begin_y = 6; break;
		case 7: begin_x = 3; begin_y = 6; break;
		case 8: begin_x = 6; begin_y = 6; break;
	}
	
	for(int y = begin_y; y <= (begin_y+2); y++)
	{
		for(int x = begin_x; x <= (begin_x+2); x++)
		{
			if(sfeld[x][y] == zahl)
				exist = 1;
		}
	}
	return exist;
}

// Prüfen ob die Zahl schon in der Reihe X vorhanden ist
int pruefe_reihe_x(int x, int zahl)
{
	int vorhanden = 0;
	for(int i = 0; i <9; i++)
	{
		if(sfeld[x][i] == zahl)
		vorhanden = 1;
	}
	return vorhanden;
}

// Prüfen ob die Zahl schon in der Reihe Y vorhanden ist
int pruefe_reihe_y(int y, int zahl)
{
	int vorhanden = 0;
	for(int i = 0; i <9; i++)
	{
		if(sfeld[i][y] == zahl)
		vorhanden = 1;
	}
	return vorhanden;
}

//Erzeugen der ZZahl an der Position X,Y
int erzeuge_zahl(int x, int y)
{
	int zahl = rand()%9+1;
	int block = welcher_block(x,y);
	
	if( ( pruefe_block(block,zahl) == 0 )&& 
			( pruefe_reihe_x(x, zahl) == 0) && 
				( pruefe_reihe_y(y,zahl) == 0) )
	{
			return zahl;
	}else return erzeuge_zahl(x,y);
}

//Anzeigen des befüllten "Spielfeldes"
void anzeigen(int array_feld[][9], int zeilen, int spalten)
{
	for(int y = 0; y < spalten; y++)
	{
		for(int x = 0; x < zeilen; x++)
		{
			cout << "\t " << array_feld[x][y] << " ";
		}
		if(y == 2 || y == 5 ||y == 8)
		{
			cout << endl;
		}
		cout << endl;
	}
}

int  main ()
{
	srand ( (unsigned) time (NULL));
	
	for(int y = 0; y < 9; y++)
	{
		for(int x = 0; x <9 ; x++)
		{
			erzeuge_zahl(x,y);
		}
	}
	
	anzeigen(sfeld);
	return 0;
}

Was ich noch festgestellt habe, ist dass wenn ich die rand() funktion mit Modulo verwende und den wert über auf 12 setzte --> rand()%12+1 --> Funktioniert es in den meisten fällen ohne dass er mir nen Stackoverflow erzeugt.. geh also alles über 12 funktioniert.. aber darunter hängt es sich direkt auf


// Hatte ich wohl nen kleinen Tippfehler drinne.. --> klappt aber trotzdem nicht :(
 
Zuletzt bearbeitet:
Ich erhalte folgende Fehlermeldungen:
Code:
sudoku.cpp: In function 'int erzeuge_zahl(int, int)':
sudoku.cpp:93:32: error: 'prufe_reihe_x' was not declared in this scope
sudoku.cpp:94:31: error: 'prufe_reihe_y' was not declared in this scope
sudoku.cpp: In function 'int main()':
sudoku.cpp:129:19: error: too few arguments to function 'void anzeigen(int (*)[9], int, int)'
sudoku.cpp:101:6: note: declared here
\edit: Ansonsten liegt das Problem in der erzeuge_zahl Funktion, die ständig selbst aufgerufen wird. In Kombination mit der Verwendung des Modulo-Operators um eine Zufallszahl im Bereich 1 bis 9 zu generieren geht das dann schief.

Die Lösung ist die Zufallszahlen anders zu generieren und Iteration statt Rekursion zu verwenden.

Gruß
 
Zuletzt bearbeitet:
Ich hab das Sudoku mal umgebastelt und zum laufen gebracht.
Ist zwar jetzt etwas anders als vorher, aber es läuft und hat sogar noch ein zwei zusatz funktionen bekommen. :)

Code:
#include <iostream>
#include <time.h>

using namespace std;

int anz_felder = 9;
int block_groesse = 3;
int zu_loesen = 0;
int versuche = 0;

int sfeld[9][9];
char rfeld[9][9];


// Durchsucht die Reihe X nach Zahl. 
// Wenn false zurück gegeben wird ist die Zahl nicht in der Reihe X
// Richtung 1 --> horizontal | Richtung 2 --> vertikal 
bool pruefe_reihe(int z, int zahl, int richtung)
{
	for(int i = 0; i < anz_felder; i++)
	{
		if(richtung == 1)
		{
			if(sfeld[z][i] == zahl)
			return true;
		}if(richtung == 2) 
		{
			if(sfeld[i][z] == zahl)
			return true;
		}
	}
	return false; 
}

// Durchsucht den 3x3 / 4x4 Block nach der angegeben Zahl
bool pruefe_block(int x, int y, int zahl)
{
	int x_start = (x/block_groesse)*block_groesse;
	int y_start = (y/block_groesse)*block_groesse;

	for(int yy = y_start; yy < y_start+block_groesse; yy++)
	{
		for (int xx = x_start; xx < x_start+block_groesse; xx++)
		{	
			if(sfeld[xx][yy] == zahl)
				return true;
		}
	}
	return false;
}

// Verbindet pruefe_block mit pruefe_reihe
// True --> Zahl vorhanden || False --> Zahl nicht vorhanden

bool check(int x, int y, int zahl)
{
	if(pruefe_reihe(x,zahl,1)== true)
		return true;
	if(pruefe_reihe(y,zahl,2) == true)
		return true;
	if(pruefe_block(x,y,zahl) == true)
		return true;
	return false;
}

// Eine zufallszahl wird erstellt zwischen 1 und 9 
int erzeuge_zahl(int x, int y)
{
	int zahl = rand()%9+1;
	if(check(x,y,zahl)== false)
	{
		return zahl;
	}
	return erzeuge_zahl(x,y);
}
// Ein Block wird zufällig mit 9 Zahlen gefuellt
void fuelle_block(int x, int y)
{
	if(x<9)
	{
		for(int yy = y; yy < y+block_groesse; yy++)
		{
			for (int xx = x; xx < x+block_groesse; xx++)
			{ 
				sfeld[xx][yy] = erzeuge_zahl(xx,yy);
			}
		}
		fuelle_block(x+3,y+3);
	} 
}
// Kopiere das INT Array in CHAR --> um Buchstaben abzuspeichern
void kopiere_feld(int spiel_feld[][9], char kopie_feld[][9])
{
	for(int y= 0; y < anz_felder; y++)
	{
		for(int x = 0; x < anz_felder; x++)	
		{
			kopie_feld[x][y] = spiel_feld[x][y]+48;
		}
	}
}
// 
void ersetze_feld( int x, int y, char buchstabe)
{
		rfeld[x][y] = buchstabe;
}

void ersetze_auf_feld(int anzahl_felder)
{
	char buchstabe = 'a'; 
	for(int i = 0; i < anzahl_felder; i++)
	{
		int x = rand() % anz_felder + 1;
		int y = rand() % anz_felder + 1;
		if(rfeld[x][y] >= 49 && rfeld[x][y] <= 57)
			ersetze_feld(x, y, buchstabe+i); 
		else i--;
	}
}
// Auswahl des Schwierigkeitsgrad
void schwierigkeit(int stufe)
{
	int anzahl_felder = 1;
	switch(stufe)
	{
	case 1: anzahl_felder = 10; 
			zu_loesen = anzahl_felder; 
			ersetze_auf_feld(anzahl_felder);
			break;
	case 2: anzahl_felder = 18; 
			zu_loesen = anzahl_felder; 
			ersetze_auf_feld(anzahl_felder);
			break;
	case 3: anzahl_felder = 25; 
			zu_loesen = anzahl_felder; 
			ersetze_auf_feld(anzahl_felder);
			break;	
	default: anzahl_felder = 10;
			zu_loesen=anz_felder;
			ersetze_auf_feld(anzahl_felder);
			break;
	}
	
}
// zum ueberpruefen ob der eingegeben Wert für den eingegebenen Buchstaben
// richtig ist.
int pruefe_eingabe(char buchstabe, int zahl)
{
	int richtig = 0;
	for(int y = 0; y < anz_felder; y++)
	{
		for(int x = 0; x < anz_felder; x++)
		{
			if(rfeld[x][y] == buchstabe)
			{
				if(sfeld[x][y] == zahl)
				{
					rfeld[x][y] = zahl+48;
					return richtig = 1;
				}
			}
		}
	}
	return richtig;
}

int geloest (char array_feld[][9])
{
	int geloest = 1;
	for(int x = 0; x < anz_felder; x++)
	{
		for(int y = 0; y < anz_felder; y++)
		{
			if(array_feld[x][y] >= 97)
				geloest = 0; // Noch nicht alle werte richtig
		}
	}
	return geloest;
}
//anzeigen von den verschiedenen Feldern (arrays) { 1 --> sfeld (spielfeld) 2 --> rfeld (Ratefeld)}
void anzeigen(int i)
{
	
	cout <<"|===|===|===||===|===|===||===|===|===|"<<endl;
	
	for(int y = 0; y <anz_felder; y++)
	{
		for(int x = 0; x < anz_felder; x++)
		{
			if(i==1)
			{
				if(x == 2 || x == 5 || x == 8) 
				{
					cout <<"| "<< sfeld[x][y] <<" |";
				} else cout <<"| " << sfeld[x][y] << " ";
			}else if(i==3)
			{
				if(x == 2 || x == 5 || x == 8) 
				{
					cout <<"|"<<x<<"/"<<y<<"|";
				}else cout <<"|" <<x<<"/"<<y<< "";
			}else {
				if(x == 2 || x == 5 || x == 8)
				{
					cout <<"| "<< rfeld[x][y] <<" |";
				} else cout <<"| " << rfeld[x][y] << " ";
			}
		}
		if(y == 2 || y == 5 || y == 8)
			cout << endl <<"|===|===|===||===|===|===||===|===|===|"<< endl;
		else cout << endl <<"|---|---|---||---|---|---||---|---|---|"<< endl;
	}	
}
//fuelle das Feld an pos(x,y) mit dem int Wert
void fuelle_feld(int x, int y, int wert)
{
	sfeld[x][y] = wert;
}

// Loesen des Sudokus.
bool loese(int x, int y)
{
	if(y == anz_felder)
	{
		x++;
		if(x == anz_felder)
			return true;	// Man ist am letzten Feld des Spielfeldes angelangt
		y = 0;
	}
	if(sfeld[x][y] > 0)
		return loese(x, y+1);
	
	for(int z = 1; z <= anz_felder; z++)
	{
		if(check(x, y, z) == false) // Wenn check --> False --> Zahl nicht vorhanden
		{	
			sfeld[x][y] = z;		// setze an Position x, y --> Zahl
			if(loese(x,y+1) == true)// Wenn loese --> true --> abbruch
				return true;
		}
	}
	sfeld[x][y] = 0;	// Falls kein Abbruch durch return true --> spielfeld auf 0 setzten
	return false;		
}
// Zum eingeben eines eigenen Sudokus (begint oben Links bei Feld 0,0)
// bei einem Leeren Feld muss eine 0 eingetragen werden.
void erstelle_eigenes(int groesse, int bgroesse, int edit)
{
	int x = 0, y = 0, eingabe;
	int ende = 0;
	if(edit == 1)
		anzeigen(1);
	else { cout << "Beispiel:"<<endl;
	anzeigen(3);
	}
	cout << "Geben Sie (0) - fuer leeres Feld \n (10) - zum beenden \n (12) - Feld zurueck\n";
	do{
		cout << "Bitte Ihren Wert fuer "<<x<< "/" <<y<<" eingeben:";
		cin >> eingabe;
		if(eingabe == 12)
		{
			x--;
		}
		if(eingabe != 10 && eingabe != 12)
		{
			fuelle_feld(x,y,eingabe);
			x++;
			if(x == anz_felder)
			{ 
				y++; x = 0; 
				if(x == anz_felder && y == anz_felder)
				{ 
					ende = 1;
				}
			}
		}else ende = 1;
				
	}while(ende != 1);
	
	kopiere_feld(sfeld, rfeld);
	cout << "Ihre eingaben: \n";
		anzeigen(1);
		cout <<"Sind die Daten korrekt? \n (1) - ja \n (2) nein. bearbeiten" <<endl;
		cin >> eingabe;
		if(eingabe == 1)
		{	
			cout <<"Hier Ihr geloestet Sudoku."<<endl;
			loese(0,0);
			anzeigen(1);
		}else erstelle_eigenes(groesse, bgroesse, 1);
	
}


void erstelle_sudoku(int groesse, int bgroesse)
{
	int eingabe = 0;
	char auswahl = ' ';
	anz_felder = groesse;
	block_groesse= bgroesse;
	
	fuelle_block(0,0);
	loese(0,0);
	kopiere_feld(sfeld,rfeld);
	cout << "Willkommen zum Sudoku."<<endl;
	cout << "Waehlen Sie Ihren Schwierigkeitsgrad: \n(1) - leicht \n(2) - mittel \n(3) - schwer "<<endl;
	cin >> eingabe;
	schwierigkeit(eingabe);
	
	do{
		anzeigen(2);
		cout << "Es sind noch "<<zu_loesen<<" Felder zu loesen."<<endl;	
		cout << "Welches Feld moechten Sie loesen? (Eingabe: Buchstabe Zahl): "<< endl;
		cin >> auswahl >> eingabe;
		
		if(pruefe_eingabe(auswahl, eingabe) == 1)
			{
				cout << "Richtig! " <<endl;
				zu_loesen--;
			}
			else { 
				cout << "Leider Falsch ! "<<endl;
				versuche++;
			}
	} while(geloest(rfeld) == 0);
	cout << "Herzlichen Glueckwunsch Sie haben das Sudoku geschafft.\nSie haben "<< versuche<<" x Falsch gelegen." <<endl;
}
// Menue zur auswahl zwischen Spielen / Eingeben eines Sudokus / Beenden
void menue()
{
	int eingabe = 0;
	cout << "Willkommen zu SUdoku"<<endl;
	cout << "Bitte waehlen Sie aus: \n (1) - ein Sudoku spielen \n (2) - ein Sudoku eingeben \n (0) - beenden"<<endl;
	cin >>eingabe;
	switch (eingabe)
	{
	case 1: erstelle_sudoku(9,3); break;
	case 2: erstelle_eigenes(9,3,0); break;
	
	case 0: break;
	default: erstelle_sudoku(9,3);
	}
}

int main()
{
	srand((unsigned) time(0));
	menue();
	return 0;
}

Falls Fragen dazu da sind, werde ich die gerne beantworten.

Mfg

BBros
 
Zurück