Sudoku, Zeitproblem oder logischer Fehler?

Dragonate

Erfahrenes Mitglied
So Leute ich hoffe jemand nimmt sich die Zeit hier mal drüber zuschaun.

Ich habe einen lösenden Sudoku Algorithmus geschrieben, wobei es sich nicht um eine professionelle Backtracking-Methode handelt, sondern um eine eher schlichte Brut-Force Methode, worauf ich aber als Hobby-Programmierer auch schon stolz bin!

Ich habe aber noch ein Problem, dass mein Sudoku-Prog nicht zum Ende kommt.

Woran es meiner Meinung nach dran liegen kann :

Entweder :
Prog hängt in einer Endlosschleife

Oder :
Durch die Brut-Force(Ausprobieren-Methode) findet mein Code die Lösung einfach nicht, was ich mir aber trotz der schlichten Methode bei meiner CPU-Power nicht ganz vorstellen kann.


Jetzt der Code!:

Code:
int main(void)
{ 
  int sudoku[9][9], sperre[9][9], pool[9][9];
  int zahl, spalte, zeile, anzahl, zz, zz1, zz2; 
  int i, j, k, o, p, ok=0;
  long int count=0;
  int check=0, fertig=0, incr1=0, incr2=0, incr3=0, incr4=0, grenze1=3, grenze2=3;

  //----------------------------------------------------------------------------
  //                   Initialisierung der Arrays;
  //----------------------------------------------------------------------------


  for(i=0;i<9;i++){
  
      for(j=0;j<9;j++){
      
          sudoku[i][j]=0;
          sperre[i][j]=0;
          pool[i][j]=0;
          
      }
      
    
  }
  
  printf("Wieviele Zahlen sind vorgegeben?\n\n");
  scanf("%d", &anzahl);
  fflush(stdin);
  
  
  //----------------------------------------------------------------------------
  //                   Eingabe der vorgegebenen Zahlen;
  //----------------------------------------------------------------------------
  
  
  for(i=0;i<anzahl;i++){
                        
      printf("%dte Zahl\n\n", (i+1));
      scanf("%d,%d,%d", &zahl, &spalte, &zeile);
      fflush(stdin); 
      sudoku[spalte-1][zeile-1]=zahl;
      sperre[spalte-1][zeile-1]=zahl;
      pool[spalte-1][zeile-1]=zahl;
      
  }
  
  
  //----------------------------------------------------------------------------
  //                   Befüllung der Arrays durch Zufallszahlen;
  //                   Vorgegebende Zahlen werden dabei nicht berührt;
  //----------------------------------------------------------------------------
  
  srand(time(0));
  
  while(fertig!=1){

      for(k=0;k<9;k++){                               
    
          for(i=incr1;i<grenze1;i++){
          
              for(j=incr2;j<grenze2;j++){
                  
                  if(sperre[j][i]==0){                                  
                                          
                      while(ok==0){
                  
                          zz=rand()%9+1;
                          
                          if((zz==sudoku[incr3][incr4]) || (zz==sudoku[incr3][incr4+1]) || (zz==sudoku[incr3][incr4+2]) || (zz==sudoku[incr3+1][incr4]) || (zz==sudoku[incr3+1][incr4+1]) || (zz==sudoku[incr3+1][incr4+2]) || (zz==sudoku[incr3+2][incr4]) || (zz==sudoku[incr3+2][incr4+1]) || (zz==sudoku[incr3+2][incr4+2])){        
                              ok=0;    
                          }    
                          else{   
                              sudoku[j][i]=zz;
                              ok=1;
                          }                          
              
                      }
                      ok=0;
          
                  }
                  
              }
                     
          }
    
          if(k==0||k==1||k==3||k==4||k==6||k==7){
              incr2+=3;
              grenze2+=3;
              incr3+=3;
          }
          else if(k==2||k==5){
              incr2=0;
              grenze2=3;
              incr3=0;
    
              incr1+=3;
              grenze1+=3;
              incr4+=3;
          }
          
      }
      
  //----------------------------------------------------------------------------
  //                      Kontrolle ob Sudoku gelöst ist;            
  //----------------------------------------------------------------------------
  

      for(o=0;o<9;o++){
                       
          for(p=0;p<9;p++){
                           
              check+=sudoku[o][p];
              
          }
          
          if(check!=45){
              check=0;
              fertig=0;
              break;
          }
          else{
               fertig=1;
               check=0;
          }
          
      }
      
      count++;

  } 
  
  //----------------------------------------------------------------------------
  //                      Ausgabe des hoffentlich gelösten Sudokus;            
  //----------------------------------------------------------------------------
  
  
  printf("\n");
  
  for(i=0;i<9;i++){
  
      for(j=0;j<9;j++){
  
          printf("|  %d  ", sudoku[j][i]);

      }

      printf("\n\n");

  }
 
  printf("\n");
  printf("\n%d", count);

  system("PAUSE");	
  return 0;
}

Noch Nennenswerte Fakten um meinen Code besser zu verstehen :

-Eingabe der vorgegebenen Zahlen sowie Nichtberührung der vorgegebenen funktioniert !

-falls jemand nicht genau weis was mit dieser langen Bedingung los ist:
Code:
if((zz==sudoku[incr3][incr4]) || (zz==sudoku[incr3][incr4+1]) || (zz==sudoku[incr3][incr4+2]) || (zz==sudoku[incr3+1][incr4]) || (zz==sudoku[incr3+1][incr4+1]) || (zz==sudoku[incr3+1][incr4+2]) || (zz==sudoku[incr3+2][incr4]) || (zz==sudoku[incr3+2][incr4+1]) || (zz==sudoku[incr3+2][incr4+2])){
Diese sorgt dafür, das jeweils immer ein 9ner Blöckchen mit Zahlen befüllt wird, ohne das die vorgegebenen Zahlen berührt werden, funktioniert auch Einwandfrei, alles getestet!

-Alles wichtige spielt sich in der GROSSEN WHILE - SCHLEIFE ab (Auch der Sudoku-Kontroll-Part ist befindet sich noch in dieser).
Und nur bedingt durch diese While-Schleife könnte eine Endlosschleife entstehen.
Abbruchkriterium ist die Variable "fertig" !

Ok ich hoffe einer weis woran es liegt (wiegesagt das Programm rechnet, kommt nicht zum ende).
 
Ich habe den Code nicht genau analysiert, das Vorgehen scheint korrekt zu sein. Allerdings füllst du die Felder mit Zufallszahlen, was bedeutet, das extrem selten auch wirklich nur die Zahlen von 1-9 ein einem Block stehen. Dein Programm braucht deswegen so lange, weil es schon allein dafür übermäßig viel Durchläufe braucht, um ein Sudoku zu erstellen, das nur die korrekte Zahlenmenge enthält (1 9mal, 2 9mal, 3 mal, ...). Als nächsten Schritt empfehle ich dir, einen Pool der Zahlen von 1-9 zu verwenden, aus dem du zufällig eine Zahl auswählst und diese dann aus dem Pool entfernst. Beispiel:
Code:
for ( i = 0; i < 9; i++ ) pool[i]=i+1;
limit = 9;
i = rand()%limit;
zz = pool[i];
pool[i] = pool[limit-1];
limit--;
Die in dem jeweiligen Block vorgegebenen Zahl solltest du aber vorher aus dem Pool entfernen.

Für mehr Infos über Sudoku empfehle ich dir http://www.sudopedia.org/.
 
Hi.

@Dragonate: Zum einen verwendest du schlechte Zufallszahlen, aber das hab ich dir schon zweimal gesagt. Bitte denk übrigens dran, deine Themen als erledigt zu markieren!

Andererseits ist wie von Vereth angedeutet deine Methode eine neue Konfiguration des Spielfelds zu finden relativ ineffizient. Es würde ja reichen pro 3er Feld die fehlenden Zahlen in einem Array vorzubereiten und diese dann zu mischen.

Weiterhin ist es nicht wirklich günstig immer das ganze Spielfeld durcheinander zu bringen. Damit die richtige Kombination zu finden bei z.B. 7 fehlenden Zahlen ist wie ein 6er im Lotto mit Zufallszahl -- das kommt nicht so häufig vor.

Es wäre evtl. besser sich erstmal auf die 3er Felder zu beschränken und alle 3er Felder richtig zu belegen. Wenn das dann insgesamt nicht passt könnte man ein 3er Feld auswählen und dieses nochmal ändern.

Und bist du dir denn auch sicher, das das Sudoku lösbar ist?

Gruß
 
Ne meine Zufallszahlen sind astrein.

@ Vereth, so schlau war ich denn doch.

Der Zufallsgenerator generiert die Zahlen von 1-9 und durch diese komplexe Bedingung:
Code:
if((zz==sudoku[incr3][incr4]) || (zz==sudoku[incr3][incr4+1]) || (zz==sudoku[incr3][incr4+2]) || (zz==sudoku[incr3+1][incr4]) || (zz==sudoku[incr3+1][incr4+1]) || (zz==sudoku[incr3+1][incr4+2]) || (zz==sudoku[incr3+2][incr4]) || (zz==sudoku[incr3+2][incr4+1]) || (zz==sudoku[incr3+2][incr4+2])){        
                              ok=0;    
                          }    
                          else{   
                              sudoku[j][i]=zz;
                              ok=1;
                          }

werden bereits vorhandene 'Zahlen nicht mehr generiert. Das funktioniert auch einwandfrei, und zwar wird mein Sudoku folgendermaßen befüllt:
Sudoku besteht ja aus 9 mal 3x3 Quadraten, und mein Code befüllt nacheinander jedes 3x3 Quadrat mit den zufälligen Zahlen 1-9, und keine Zahl kommt doppelt vor!

Dadurch entstehen also nicht zusätzliche extra durchläufe!

@deepthroat, mit der uneffiziens hast du natürlich recht "das ganze Spielfeld durcheinander zu bringen", aber wenn das ersma funktioniert, kann ich darauf das Backtracking aufbauen.
Bedenkt bitte auch, das Zufallszahlen anstelle eines pools garnicht so schlecht sind, nämlich ein Pool[Array] immer durcheinander zu bringen ist eher aufwendiger vom Code und nicht so leicht herzustellen, das auch alle Kombinationsmöglichkeiten entstünden.

Also demnach, müsste die Lösung hier eigentlich auch zum Ziel führen.... verdammt
 
Ne meine Zufallszahlen sind astrein.
Nein, sind sie nicht. Aber du weißt es ja besser...
@ Vereth, so schlau war ich denn doch.

Der Zufallsgenerator generiert die Zahlen von 1-9 und durch diese komplexe Bedingung:
Ja, es ist aber ineffizient (und ziemlich unlesbar) das so zu tun.
Dadurch entstehen also nicht zusätzliche extra durchläufe!
Doch, du mußt ja erst eine Zahl würfeln die noch nicht vergekommen ist. Dafür brauchst du dann einige zusätzliche Durchläufe - vor allem da deine Zufallszahlen schlecht generiert werden.
@deepthroat, mit der uneffiziens hast du natürlich recht "das ganze Spielfeld durcheinander zu bringen", aber wenn das ersma funktioniert, kann ich darauf das Backtracking aufbauen.
Backtracking hat nunmal aber nichts mit dem zufälligen Generieren von Lösungen zu tun.
Bedenkt bitte auch, das Zufallszahlen anstelle eines pools garnicht so schlecht sind, nämlich ein Pool[Array] immer durcheinander zu bringen ist eher aufwendiger vom Code
Aha. Da spricht der Kenner. ;-]
und nicht so leicht herzustellen, das auch alle Kombinationsmöglichkeiten entstünden.
Aha. Wie stellst du denn mit deiner Methode sicher, das alle Kombinationen entstehen? ;-]
Also demnach, müsste die Lösung hier eigentlich auch zum Ziel führen.... verdammt
Müsste ist nicht wird, oder?!

Gruß
 
Na da ist ja jemand wieder ganz schlau....

Da du dich nicht wircklich mit dem Thema beschäftig hast, scheinst du einige Sachen einfach nicht besser zu wissen.

Zu deinen Kommentaren:

Das einzige was du vielleicht zurecht bemängelst, sind meine Zufallszahlen, aber nur in dem Sinne, das der Zufallszahlengenerator von C (rand()) nicht der beste ist, und dadurch Wiederholungen vorkommen können.

Ansonsten :

Das Generieren ist nicht ineffizient, es ist sichergestellt, das alle Nötigen Zahlen generiert werden, ein paar zusätzliche Durchläufe fürs "Neuwürfeln" gibt es, ja und? (Viele sind es nicht, da es nur 9 Möglichkeiten gibt)

Dich stört nur das ich die Sache allgemein mit Zufallszahlen löse, und dazu komme ich jetzt:
Wenn du die Zahlen aus einem Pool nehmen willst, ist das erstmal einfach. Aber wenn der Pool durcheinander gewürfelt werden muss, musst du mit mehreren temporären Variablen arbeiten, um die Werte zu vertauschen, und das dann noch so aufzubauen das alle Kombinationsmöglichkeiten entstehen, ist ein wirckliches Problem.
Und in dem Sinne entstehen durch die Zahlreichen durchläufe mit den Zufallswerten eher alle Kombinationen, mit steigender Warscheinlichkeit.

Und sehr wol kann man Backtracking mit dem Zufallswert-Konstrukt kombinieren mein Freund, das werde ich dir jetzt aber nicht noch extra erklären, falls du es möchtest tu ich das für dich aber auch noch.

"Müsste ist nicht wird"
Das hat du allerdings noch richtig erkannt ;)

Gruß John
 
Das einzige was du vielleicht zurecht bemängelst, sind meine Zufallszahlen, aber nur in dem Sinne, das der Zufallszahlengenerator von C (rand()) nicht der beste ist, und dadurch Wiederholungen vorkommen können.
Du hast es immer noch nicht verstanden und hast keine Ahnung. Ignoranz und Ahnungslosigkeit sind eine ganz schlechte Kombi. Lies dir z.B. diesen Link durch (den ich dir schonmal gegeben habe, john200): http://cplus.kompf.de/artikel/random.html
http://cplus.kompf.de/artikel/random.html
Ansonsten :

Das Generieren ist nicht ineffizient
Doch, ist es.
es ist sichergestellt, das alle Nötigen Zahlen generiert werden, ein paar zusätzliche Durchläufe fürs "Neuwürfeln" gibt es, ja und? (Viele sind es nicht, da es nur 9 Möglichkeiten gibt)
Deine Ignoranz ist wirklich unglaublig. Warum stellst du hier überhaupt eine Frage, wenn du es eh besser weißt?

Im schlechtesten Fall wird die benötigte Zahl gar nicht gezogen.
Dich stört nur das ich die Sache allgemein mit Zufallszahlen löse, und dazu komme ich jetzt:
Wenn du die Zahlen aus einem Pool nehmen willst, ist das erstmal einfach. Aber wenn der Pool durcheinander gewürfelt werden muss, musst du mit mehreren temporären Variablen arbeiten, um die Werte zu vertauschen, und das dann noch so aufzubauen das alle Kombinationsmöglichkeiten entstehen, ist ein wirckliches Problem.

Und in dem Sinne entstehen durch die Zahlreichen durchläufe mit den Zufallswerten eher alle Kombinationen, mit steigender Warscheinlichkeit.
Wenn ein Affe unendlich lange auf einer Schreibmaschine tippt, wird irgendwann Shakespeare entstehen. Das Problem ist nur, das man meist nicht soviel Zeit hat.
Und sehr wol kann man Backtracking mit dem Zufallswert-Konstrukt kombinieren mein Freund, das werde ich dir jetzt aber nicht noch extra erklären, falls du es möchtest tu ich das für dich aber auch noch.
Ich bezweifle das da was sinnvolles rauskommt...
 
Tss du bist echt unglaublich...

Deine Ignoranz ist wirklich unglaublig. Warum stellst du hier überhaupt eine Frage, wenn du es eh besser weißt?

Warum antwortest du auf Fragen, wenn du garnicht Helfen willst ? Sondern nur Vorwurfsvoll deine schlecht durchdachten Änderungen mitteilen möchtest.

Code:
Im schlechtesten Fall wird die benötigte Zahl gar nicht gezogen.
Du verstehst noch nichteinmal diesen einfachen Code ? Es wird in jedem Fall die benötigte Zahl gezogen.
Warum wagst du solche Äußerungen? Entweder verstehst du den Code wircklich nicht, oder du hast dir nicht die Zeit genommen Ihn zu verstehen. Wenn letzteres zutrifft, sollte man sich einfach aus der Angelegenheit raushalten, und nicht versuchen sich mit mangelndem Wissen wichtig zu machen.
Falls du allerdings weiterhin in dieses Thema mit einsteigen willst, ohne den Code wircklich verstanden zu haben, bitte ich darum deine Aussprüche anders zu formulieren, z.B. indem du deine Argumente mit "Ich glaube" oder "Hier könnte vielleicht" oder "Ich bin mir nicht sicher, aber" beginnst. Indem Fall kannst du auch Argumentieren ohne das nötige Hintergrundwissen zu haben, auch wenn es mit großer Warscheinlichkeit dann nicht hilfreich sein wird.

Ach und zu dem "Affen - Shakespeare" Spruch, der Computer ist das schnellste Äffchen der Welt und hat zudem auch noch sehr viel Zeit ;)

Mfg John
 
Haha... gibt es hier auch Moderatoren die so einen Unsinn schließen?
Dragonate hat gesagt.:
Es wird in jedem Fall die benötigte Zahl gezogen.
Weil du 'ne Maschine im Zimmer stehen hast, die ohne Probleme auch mal ein paar Extrarunden drehen kann. Da fällt dann überhaupt nicht auf, wie oft der Rechner "daneben gegriffen" und nicht die gewünschte Zahl gezogen hat.

Keine Ahnung warum hier noch weiter diskutiert wird, du lässt dich ja gar nicht auf die Hilfe von deepthroat ein! Jeder andere wird dir genau das Gleiche erzählen und du wirst es immer noch nicht kapieren!

Gruß
 
Das sage ich doch, der Computer kann jawol ein paar extra runden drehen ohne des zeitlich schwer ins Gewicht fällt, das mache ich mir ja zur Nutze.

Und um noch ein letztes mal auf die "schlechten Zufallszahlen" zurückzukommen. Was fakt ist, ist das immer in jedem Block die Zahl 1-9 vorkommt, was ich genauso wollte.

Was ferner dessen immer noch schlecht an den Zufallszahlen ist, hat ansonsten niemand erklärt. Ich habe dazu gesagt, das ich glaubte das der Zufallsgenerator von C schlecht sei. Wenn das aber nicht der Fall ist und die Zufallszahlen "trotzdem schlecht sind", dann sagt mir doch bitte was, und behauptet nicht alle nur : "Du nutzt schlechte Zufallszahlen"
Ihr sagt ich verstehe nicht warum die schlecht sind, es hat hier aber niemand erklärt ^^

Danke
 
Zurück