<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Backtracking Algorithmus]]></title><description><![CDATA[<p>Hallo Leute,<br />
ich weiß, dass es bei google unzählige Treffer zu diesem Thema gibt, allerdings möchte ich eine Lösung nicht einfach copy-pasten.</p>
<p>Das Programm schreibe ich zur Übung. Ich habe bisher nicht viel erfahrung mit C++.</p>
<p>Mein Ansatz ist Folgender:</p>
<p>(Eine Funktion, die überprüft, ob das Sudoku gültig ist, habe ich schon geschrieben)</p>
<pre><code class="language-cpp">int arr[9][9]; //sudokufeld, global (also außerhalb einer Funktion erstellt)
               //0 bedeutet, das Feld ist leer

//backtracking funktion
for(int y=0;y!=9;++y)
{
   for(int x=0;x!=9;++x)
   {
   }
}
</code></pre>
<p>Mit diesen beiden Schleifen gehe ich das Feld zeilenweise ab.<br />
Als erstes Suche ich ein unbesetztes Feld:</p>
<pre><code class="language-cpp">for(int y=0;y!=9;++y)
{
   for(int x=0;x!=9;++x)
   {
      if(arr[x][y]==0)
      {
      }
   }
}
</code></pre>
<p>In dieses Feld setze ich jetzt systematisch die Zahlen von 1 bis 9 ein</p>
<pre><code class="language-cpp">for(int y=0;y!=9;++y)
{
   for(int x=0;x!=9;++x)
   {
      if(arr[x][y]==0)
      {
         for(int a=1;a!=10;++a)
         {
            arr[x][y]=a;
         }
      }
   }
}
</code></pre>
<p>Dann wird geprüft, ob das Sudoku durch das Einsetzten der neuen zahl noch gültig ist</p>
<p>bool erfolg=FALSE; //Kontroll variable</p>
<p>for(int y=0;y!=9;++y)<br />
{<br />
for(int x=0;x!=9;++x)<br />
{<br />
if(arr[x][y]==0)<br />
{<br />
for(int a=1;a!=10;++a)<br />
{<br />
arr[x][y]=a;</p>
<p>if(pruefen()) //wenn das sudoku so gültig ist<br />
{<br />
controle=TRUE<br />
break; //schleife verlassen und nächstes feld verlassen<br />
}<br />
}<br />
if(control==FALSE)<br />
{<br />
//FEHLER<br />
}<br />
else<br />
control=FALSE; //control zurücksetzen<br />
}<br />
}<br />
}<br />
[/cpp]<br />
Mein Problem ist jetzt, dass ich nicht &quot;backtracken&quot; kann. D.h. wenn alle Zahlen von 1 bis 9 für das aktuelle Feld kein gültiges Sudoku liefern, müsste ich ja im zuletzt bearbeiteten Feld den Wert um 1 erhöhen.<br />
Ich habe bei meinem Programm jetzt folgendes Versucht</p>
<pre><code class="language-cpp">if(control==FALSE)
{
   //FEHLER
   arr[x][y]=0;                           //aktuelles Feld auf 0 zurück setzten
   x=x-1;                                 //ein Feld zurück gehen
   if(x&lt;0){x=8;--y;}
   for(zahl=arr[x][y]+1;zahl!=10;++zahl)  //wert im vorletzten Feld erhöhen, bis
      if(pruefen())                       //sich ein gültiges Sudoku ergibt
         break;
</code></pre>
<p>Das Problem dabei ist natürlich, dass ich mit dieser Methode nur EIN Feld zurück gehen kann.<br />
Hat jemand eine Idee, wie ich diese Backtracking Methode implementieren könnte?<br />
Und nehmt Rücksicht darauf, dass ich nicht wirklich viel C++ kann <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<p>Bin für alle Ideen offen!</p>
<p>Mfg Sudokumaster</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/232415/backtracking-algorithmus</link><generator>RSS for Node</generator><lastBuildDate>Fri, 25 Sep 2026 08:04:42 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/232415.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 22 Jan 2009 15:39:58 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Backtracking Algorithmus on Thu, 22 Jan 2009 15:39:58 GMT]]></title><description><![CDATA[<p>Hallo Leute,<br />
ich weiß, dass es bei google unzählige Treffer zu diesem Thema gibt, allerdings möchte ich eine Lösung nicht einfach copy-pasten.</p>
<p>Das Programm schreibe ich zur Übung. Ich habe bisher nicht viel erfahrung mit C++.</p>
<p>Mein Ansatz ist Folgender:</p>
<p>(Eine Funktion, die überprüft, ob das Sudoku gültig ist, habe ich schon geschrieben)</p>
<pre><code class="language-cpp">int arr[9][9]; //sudokufeld, global (also außerhalb einer Funktion erstellt)
               //0 bedeutet, das Feld ist leer

//backtracking funktion
for(int y=0;y!=9;++y)
{
   for(int x=0;x!=9;++x)
   {
   }
}
</code></pre>
<p>Mit diesen beiden Schleifen gehe ich das Feld zeilenweise ab.<br />
Als erstes Suche ich ein unbesetztes Feld:</p>
<pre><code class="language-cpp">for(int y=0;y!=9;++y)
{
   for(int x=0;x!=9;++x)
   {
      if(arr[x][y]==0)
      {
      }
   }
}
</code></pre>
<p>In dieses Feld setze ich jetzt systematisch die Zahlen von 1 bis 9 ein</p>
<pre><code class="language-cpp">for(int y=0;y!=9;++y)
{
   for(int x=0;x!=9;++x)
   {
      if(arr[x][y]==0)
      {
         for(int a=1;a!=10;++a)
         {
            arr[x][y]=a;
         }
      }
   }
}
</code></pre>
<p>Dann wird geprüft, ob das Sudoku durch das Einsetzten der neuen zahl noch gültig ist</p>
<p>bool erfolg=FALSE; //Kontroll variable</p>
<p>for(int y=0;y!=9;++y)<br />
{<br />
for(int x=0;x!=9;++x)<br />
{<br />
if(arr[x][y]==0)<br />
{<br />
for(int a=1;a!=10;++a)<br />
{<br />
arr[x][y]=a;</p>
<p>if(pruefen()) //wenn das sudoku so gültig ist<br />
{<br />
controle=TRUE<br />
break; //schleife verlassen und nächstes feld verlassen<br />
}<br />
}<br />
if(control==FALSE)<br />
{<br />
//FEHLER<br />
}<br />
else<br />
control=FALSE; //control zurücksetzen<br />
}<br />
}<br />
}<br />
[/cpp]<br />
Mein Problem ist jetzt, dass ich nicht &quot;backtracken&quot; kann. D.h. wenn alle Zahlen von 1 bis 9 für das aktuelle Feld kein gültiges Sudoku liefern, müsste ich ja im zuletzt bearbeiteten Feld den Wert um 1 erhöhen.<br />
Ich habe bei meinem Programm jetzt folgendes Versucht</p>
<pre><code class="language-cpp">if(control==FALSE)
{
   //FEHLER
   arr[x][y]=0;                           //aktuelles Feld auf 0 zurück setzten
   x=x-1;                                 //ein Feld zurück gehen
   if(x&lt;0){x=8;--y;}
   for(zahl=arr[x][y]+1;zahl!=10;++zahl)  //wert im vorletzten Feld erhöhen, bis
      if(pruefen())                       //sich ein gültiges Sudoku ergibt
         break;
</code></pre>
<p>Das Problem dabei ist natürlich, dass ich mit dieser Methode nur EIN Feld zurück gehen kann.<br />
Hat jemand eine Idee, wie ich diese Backtracking Methode implementieren könnte?<br />
Und nehmt Rücksicht darauf, dass ich nicht wirklich viel C++ kann <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<p>Bin für alle Ideen offen!</p>
<p>Mfg Sudokumaster</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1650323</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1650323</guid><dc:creator><![CDATA[Sudokumaster]]></dc:creator><pubDate>Thu, 22 Jan 2009 15:39:58 GMT</pubDate></item><item><title><![CDATA[Reply to Backtracking Algorithmus on Thu, 22 Jan 2009 15:43:19 GMT]]></title><description><![CDATA[<p>*edit:</p>
<p>der unformatierte Codeschnipsel oben sollte wie Folgt aussehen</p>
<pre><code class="language-cpp">bool erfolg=FALSE; //Kontroll variable 

for(int y=0;y!=9;++y) 
{ 
    for(int x=0;x!=9;++x) 
    { 
        if(arr[x][y]==0) 
        { 
            for(int a=1;a!=10;++a) 
            { 
                arr[x][y]=a; 

                if(pruefen()) //wenn das sudoku so gültig ist 
                { 
                    controle=TRUE 
                    break; //schleife verlassen und nächstes feld verlassen 
                } 
            } 
            if(control==FALSE) //wenn keine gültige Zahl gefunden wurde
            { 
                //FEHLER 
            } 
            else 
                control=FALSE; //control zurücksetzen 
        } 
    } 
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1650330</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1650330</guid><dc:creator><![CDATA[Sudokumaster]]></dc:creator><pubDate>Thu, 22 Jan 2009 15:43:19 GMT</pubDate></item><item><title><![CDATA[Reply to Backtracking Algorithmus on Thu, 22 Jan 2009 16:17:23 GMT]]></title><description><![CDATA[<p>Hmm... Um jz alles zu lesen bin ich ein wenig zu faul...<br />
Aber hier mal ein paar Tips:</p>
<p>Sudokumaster schrieb:</p>
<blockquote>
<pre><code class="language-cpp">bool erfolg=FALSE; //FALSE ist nen makro aus irgend nem windows-header auf false - also kannste das auch gleich nehmen

for(int y=0;y!=9;++y)
{
    for(int x=0;x!=9;++x)
    {
        if(arr[x][y]==0) //prüf doch auf != 0 und mach dann nen continue - da hat man ne einrückungsebene weniger...
        {
            for(int a=1;a!=10;++a)
            {
                arr[x][y]=a;

                if(pruefen()) //wenn das sudoku so gültig ist 
                { 
                    controle=TRUE //e zu viel + semikolon vergessen + marko genutzt...
                    break; //schleife verlassen und nächstes feld verlassen 
                } 
            } 
            if(control==FALSE) //wenn keine gültige Zahl gefunden wurde
            { //wieder das hässliche makro...
                //FEHLER 
            } 
            else 
                control=FALSE; //control zurücksetzen
//control ist hier also auf jeden fall auf false gesetzt... könnte man also auch schon am anfang der schleife machen...
        } 
    } 
}
</code></pre>
</blockquote>
<p>würde man also besser so schreiben:</p>
<pre><code class="language-cpp">bool erfolg=false;

for(int y=0; y != 9; ++y)
{
    for(int x=0; x!=9; ++x)
    {
        if(arr[x][y]!=0)
             continue;

        control=false; //control zurücksetzen

        for(int a=1;a!=10;++a)
        {
           arr[x][y]=a;

           if(pruefen())
           { 
                control = true;
                break; //schleife verlassen und nächstes feld verlassen
                  //der kommentar klingt ein wenig komisch - überhaupt solltest du die schleife doch nicht gleich ganz verlassen, nur weil der eine wert nicht gestimmt hat...
           }
        } 
        if(! control) //wenn keine gültige Zahl gefunden wurde
        {
            //FEHLER 
        } 
    }
}
</code></pre>
<p>machen wir mal ein wenig weiter:</p>
<pre><code class="language-cpp">int arr[9][9]; //sudokufeld, global (also außerhalb einer Funktion erstellt)
               //0 bedeutet, das Feld ist leer
</code></pre>
<p>übergib es doch besser immer an die Funktionen - globale Variable sind hässlich und erzeugen oft Fehler und sind immer daran schuld, dass man net mehr durchsieht -.-</p>
<p>außerdem würde ich es so machen:</p>
<pre><code class="language-cpp">bool arr[9]/*x*/[9]/*y*/[9]/*moeglichkeiten*/;
</code></pre>
<p>für alle unbekannten felder initialisiert du einfach die 3. dimension komplett mit true - also es könnten alle 9 zahlen drin stehen<br />
-&gt; so lange in der 3. dimension mehr als einmal true steht sind noch mehrere möglichkeiten offen - wenn nur einmal true vorkommt, steht die zahl fest und bei nur false ist es nicht möglich das soduko zu lösen...</p>
<p>du gehst also dann das ganze feld durch und schließt immer die zahlen aus, die nicht mehr hinkommen dürfen, überprüfst also:<br />
- zeilen<br />
- spalten<br />
- quadrate</p>
<p>das ganze wirst du wahrscheinlich mehrfach machen müssen - wie oft sollte vom soduko abhängig sein - maximalstens [i]hmm...[i] - kommt drauf an ^^</p>
<p>dein ansatz würde ewig dauern da du so weit ich das sehe alle möglichkeiten durchgehen möchtest - da wird selbst der tollste rechner paar jahre brauchen xD</p>
<p>selbst wenn bei einem 9x9 feld 50% der felder gegeben sind müsstest du noch 40 felder durch bruteforce rausbekommen...<br />
würdest also schon 40^9 möglichkeiten haben - also über 262 billionen - müsstest also auch so oft das feld testen...</p>
<p>bb</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1650358</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1650358</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Thu, 22 Jan 2009 16:17:23 GMT</pubDate></item><item><title><![CDATA[Reply to Backtracking Algorithmus on Thu, 22 Jan 2009 18:20:33 GMT]]></title><description><![CDATA[<p>Danke für deine Antwort!</p>
<p>ich hoffe ich habe deinen Vorschlag richtig verstanden:</p>
<p>zuerst habe ich ein array erstellt:<br />
bool field[9][9][9];<br />
Dann habe ich ALLE felder auf true gesetzt.<br />
Dann habe ich alle Felder, die nicht unbelegt sind (also != 0) in der 3. Dimension mit false belegt, bis auf die Stelle, der dem Wert an der Stelle entspricht.<br />
Beispiel:</p>
<pre><code class="language-cpp">for(int y=0;y!=9;++y)
{
    for(int x=0;x!=0;++x)
    {
        if(arr[x][y]) //wenn feld belegt
        {
            for(int z=0;z!=9;++z)
                field[x][y][z]=false; //die 3. Dimension an der Stelle gleich false setzen

            if(arr[x][y]==1)            //
                field[x][y][0]=true;    //  die stelle, die dem wert des Feldes entspricht
            if(arr[x][y]==2)            //  wieder auf true setzen
                field[x][y][1]=true;    //
                 //usw
        }
</code></pre>
<p>Damit ist das array schonmal initialisiert.<br />
Dann gehts ans prüfen. Wenn ich alles richtig verstanden habe, müsste folgende Funktion stimmen, oder?</p>
<pre><code class="language-cpp">//zeilen prüfen

int control=0;
int zc; //copy von z
for(int y=0;y!=9;++y)
{
    for(int x=0;x!=9;++x)
    {
        control=0;
        for(int z=0;z!=9;++z)
        {
            if(field[x][y][z]==true)  //durchzaehlen, wie viele offene Möglichkeiten es an der stelle gibt
            {
                ++control;
                zc=z;
            }
        }

        if(control==0)
            return 1; //unloesbar

        if(control==1) //das feld [x][y] ist eindeutig
        {
            for(int g=0;g!=9;++g)
            {
                if(g!=x)                   //alle felder der Reihe außer dem mit nur
                    field[g][y][zc]=false; //einer möglichkeit an der stelle zc 'false' setzten
            }
        }

    }
}
</code></pre>
<p>ist das von der idee her richtig?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1650435</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1650435</guid><dc:creator><![CDATA[Sudokumaster]]></dc:creator><pubDate>Thu, 22 Jan 2009 18:20:33 GMT</pubDate></item><item><title><![CDATA[Reply to Backtracking Algorithmus on Fri, 23 Jan 2009 10:07:24 GMT]]></title><description><![CDATA[<p>Hi ^^</p>
<pre><code class="language-cpp">for (int y (0); y != 9; ++y)
{
    for (int x (0); x != 9 ; ++x) //
    {
        if (arr[x][y])
        { //ein bestimmter Wert ist gesetzt
            for (int z (0); z != 9; ++z)
                field[x][y][z] = false; //alle Stellen auf false setzen

            field[x][y][arr[x][y&rsqb;&rsqb; = true; //und nur das eine auf true setzen
            continue; //dann gehen wir zum nächsten Feld
        }

        //wenn wir hier hin kommen, ist das feld nicht gesetzt

        for (int z (0); z != 9; ++z)
            field[x][y][z] = true;

        //wir setzen also alles einfach auf true
    }
}
</code></pre>
<p><code>field[x][y][arr[x][y&rsqb;&rsqb; = true;</code> ist zwar ein bisschen hässlich, aber man kann ja nicht alles haben ;o)<br />
würde auch mit 2 for schleifen gehen, also in etwa so was:</p>
<pre><code class="language-cpp">int z = 0;
for (int end (arr[x][y]); z != end; ++z)
    field[x][y][z] = false;

field[x][y][++z] = true;

for (++z; z != 9; ++z)
    field[x][y][z] = false;
</code></pre>
<p>ich weiß aber nicht genau ob das eleganter ist - musst du selbst entscheiden, was du hübscher findest, was du besser verstehst oder was auch immer ^^</p>
<p>Sudokumaster schrieb:</p>
<blockquote>
<p>Damit ist das array schonmal initialisiert.<br />
Dann gehts ans prüfen.</p>
</blockquote>
<p>Sudokumaster schrieb:</p>
<blockquote>
<p>Wenn ich alles richtig verstanden habe, müsste folgende Funktion stimmen, oder?</p>
</blockquote>
<p>Hmm.. Ich meinte das eigtl ein wenig anders... ^^</p>
<pre><code class="language-cpp">for (int y (0); y != 9; ++y)
{
    for (int x (0); x != 9; ++x)
    {
        /*die zeile durchgehen und jedes mal, wenn ein feld nur ein true hat,
          alle felder in dem gleichen quadrat, in der gleichen zeile und in der gleichen spalte,
          an der stelle, wo das true bei dem einen feld steht, auf false setzen*/
    }
}
</code></pre>
<p>bb</p>
<p>edit:<br />
aber wenn du möchtest, dann kannst du es auch so machen, wie du es gemacht hast - ich denke, es geht so, wie du es gemacht hast ^^<br />
nur ist es eben wieder nicht sooo übersichtlich ;-P</p>
<p>aber ich würd das schleifeninnere anders machen ^^:</p>
<pre><code class="language-cpp">int control = 0;
        int copy_z;
        for (int z (0); z != 9; ++z)
        {
            if (field[x][y][z])
            { 
                ++control; 
                copy_z = z; 
            } 
        } 

        if (!control)
            return 1; //unloesbar

        if (control == 1) //das feld [x][y] ist eindeutig 
        {
            int x2 (0);
            for(; x2 != x; ++x2)
            {
                field[x2][y][copy_z] = false;
            }

            for(++x2; x2 != 9; ++x2) 
            {
                field[x2][y][copy_z] = false;
            } 
        }
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1650711</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1650711</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Fri, 23 Jan 2009 10:07:24 GMT</pubDate></item></channel></rss>