SUDOKU (python) nach #C portieren.

OP #7006641
Lesenswert?

Hallo
Ich mache gerade den Versuch ein SUDOKU Programm (python) nach #C zu 
portieren.
Ich bin Hobby Programmierer. Es funktioniert schon ein wenig.
In der einen for Schleife gibt es Probleme. Manchmal wird die Variable 
nicht mit dem Startwert 1 belegt, sondern geht z.B mit 11 weiter.

Vielen Dank für eure Hilfe
Peter
Angehängte Dateien:
Gast #7006652
Lesenswert?

Peter W. schrieb:
> In der einen for Schleife gibt es Probleme

Mag das daran liefgen, dass Du alle Schleifenvariablen global 
deklarierst, aber die Funktion, in der Du sie benutzt, moch innerhalb 
der Schleife rekusiv aufrufst. So benutzt Du die gleiche Instanz der 
Schleifenvariablen gleichzeitig mehrfach Das kann eigentlich nur 
schiefgehen.

hint: for (int i=0; i<9; i++){...}

HTH
(re)
Gast #7007312
Lesenswert?

Peter W. schrieb:
> Leider ist die Ausgabe immer noch genau so falsch

Die Schleifenvariablen sind ja auch immer noch global definiert.

| #include <stdio.h>
|
| #define FALSE 0
| #define TRUE !(FALSE)
|
| char zeile=0, spalte=0, zahl=0, x=0, y=0, xi=0, yi=0, xLO, yLO, xD, yD;

Als erstes sollten die lokal definiert sein, so wie oben vorgeschlagen.
Dann kann man weitersehen.

(re)
Gast #7007441
Lesenswert?

Peter W. schrieb:
> Ich weiß nicht wie ich das mit zahl, x und y in der funktion loesung
> machen soll

... indem man für die Schleife keine globale Variable nimmt, wie in

| #include <stdio.h>
|
| char zeile=0, spalte=0, zahl=0, x=0, y=0, xi=0, yi=0, xLO, yLO, xD, yD;

sondern die schleifenvariable nur innerhalb der Schleife deklariert:

| void loesung()
| :
| for (int x=0;x<9;x++){
|    :
|    for(int y=0;y<9;y++){
|       :
|       for (int zahl=1;zahl<10;zahl++){
|         :
|         loesung();
|       }
|    }
| }
und außerhalb unzugänglich lässt. Ich hoffe, das ist jetzt klarer.


Nebenbei aber noch für unser Verständnis:

(a) Welche Sprache wird das nun eigentlich? Weil:
* Du schreibst von "#C", aber zu "C#" passt die Syntax nicht so recht, 
und
* die Dateiendung deutet aber auf "C++", aber
* der Code selbst ist weder c++/cpp noch C#, sondern eher 
"Kernigham-Ritchie-C (1978)", wozu die Dateiendung aber nicht passt.

Die drei Kandidaten haben bis auf das "C" im Namen nur recht wenig 
gemeinsam.
Könntest Du das aufklären?



(b) Die Funktion "loesung ()" wird rekursiv aufgerufen, jedoch jedesmal 
mit den gleichen Aufrufparametern (nämlich keinen). Das deutet 
normalerweise auf einen Programmierfelher hin. Ist das so gewollt?


(c) Der Rückgabewert von "char loesung()" ist nur für bestimmte Pfade 
fefiniert ("return 0;"), im allgemeinen Fall jedoch von Zufall abhängig. 
Das deuet normalerweise auf einen Programmierfehler hin, aber

(d) Der Rückgabewert von "char loesung()" wird überhaupt nirgends 
ausgewertet, auch nicht beim rekursiven Aufruf. Auch das deutet 
normalerweise auf Programmierfehler hin. Hat diese Konstruktion einen 
besonderen Hintergrund?

HTH;
(re)
Gast #7007726
Lesenswert?

Bitte

nimm int anstatt char, das ist geläufig, char ist sehr ungewöhnlich

die Variable in der for Schleife definieren, weniger fehleranfällig und 
nicht style von vor 30 jahren

Also for(int x = ...

Nicht immer erst die variable definieren und dann x Zeilen darunter 
initalisieren, einfach

int blub = 32;

Und KEINE globalen variablen!

Nach der Korrektur können wir über Logikfehler diskutieren
OP #7008253
Lesenswert?

Erst mal vielen Dank für die Antworten

Ich habe jetzt alle Variablen als lokal geändert. In der Funktion 
loesung "return" berichtigt.
Jetzt erhalte ich als Ausgabe das ungelöste sudoku!
Wie gesagt, ich versuche die datei sudoku.py zu portieren. Ich arbeite 
mit DevC++. Die Kommentare in sudok12.cpp sind die vom pyhton Programm.

mfG
Peter
Angehängte Dateien:
Gast #7008410
Lesenswert?

Prima, schon ein wenig Fortschritt.

Ich würde in Zeile 99, kurz vor der letzten schließenden Klammer von 
'loesung()' mal versuchsweise ein "ausgabe();" plazieren. Nur zum 
Testen, Erklärung weiter unten.



Die Fragen nach dem Hintergrund von (b) und (d) waren übrigens durchaus 
ernst gemeint. Das Beheben des "seltsamen Aussehens" ist zwar auch schon 
ein Fortschritt, behebt aber nicht den eventuellen Denkfehler, der einen 
dazu gebracht hat, dieses Konstrukt so zu formulieren, sondern nur den 
Hinweis auf den Denkfehler.



Aber weiter mit konkreteren Dingen: In Zeile 88 hast Du das Konstrukt

| zahlen[x][y] = zahl;
| loesung();
| zahlen[x][y] = 0;

welches sich mir nicht direkt erschließt.
Wo immer in "zahlen[x][y]" eine Zahl eingetragen wird, wird sie direkt 
nach dem Aufruf wieder auf "0" gesetzt.

Deswegen bekommst Du immer wieder die originale Besetzung heraus.



Deswegen die Frage (b) nach der Sinnhaftigkeit des rekursiven Aufrufs.
Der soll vermutlich dazu dienen, die weiteren fehlenden Zahlen 
einzusetzen.

In Zeile 82 prüft "loesung()" jede Zelle ab, ob sie noch zu besetzen 
ist. Nun hätte ich erwartet, dass der entweder terminiert oder ein 
"fertig" ausgibt, wenn er findet, dass alle Zellen besetzt sind - das 
würde man daran erkennen, dass er bis zur letzten schließenden Klammer 
von loesung() in Zeile 99 kommt.

Da hätte ich jetzt entweder sowas wie ein "return TRUE;" erwartet.
Oder ein aufruf von ausgabe(), bevor die Funktion verlassen wird.
Die würde dann in jedem Fall ein gelöstes Sudoku ausgeben, bevor es 
wieder mit Nullen überschrieben wird.


Besser würde man es natürlich mit einem Rückgabewert machen, so wie es 
vorher schon in Fragmenten angefangen war, aber der Rückgabewert muss 
dann auch 1.) in jedem Zweig zurückgegeben werden und 2.) nach dem 
Aufruf ausgewertet werden.


Funktioniert das bei Dir, mit dem "ausgabe()"?

HTH
(re)
OP #7009345
Lesenswert?

re schrieb:
> Ich würde in Zeile 99, kurz vor der letzten schließenden Klammer von
> 'loesung()' mal versuchsweise ein "ausgabe();" plazieren. Nur zum
> Testen, Erklärung weiter unten.

Das war der richtige Tip - jetzt funktioniert es, aber warum?

DevC++ in der Fehlersuche ist total Fehleranfällig, und nervt total! 
Gibt es ein alternatives einfaches Programm, welches funktioniert?

re schrieb:
> Aber weiter mit konkreteren Dingen: In Zeile 88 hast Du das Konstrukt
>
> | zahlen[x][y] = zahl;
> | loesung();
> | zahlen[x][y] = 0;
>
> welches sich mir nicht direkt erschließt.
> Wo immer in "zahlen[x][y]" eine Zahl eingetragen wird, wird sie direkt
> nach dem Aufruf wieder auf "0" gesetzt.

Die Zahlen werden nur gelöscht, wenn zahl = 10 ist. Dann wird aus: 
for (int zahl= 1; zahl< 10; zahl++) rausgesprungen und durch return 
gelangt man zur zeile: zahlen[x][y] = 0;

Es funktioniert!

Vielen Dank für die Unterstützung

mfG
Peter
Angehängte Dateien:
Gast #7009507
Lesenswert?

Peter W. schrieb:
> aber warum?

Naja, auf die Gefahr hin, mich zu wiederholen: Die Funktion "loesung()" 
in Deinem Programm ruft sich selbst rekursiv auf, wenn noch etwas zu tun 
ist (also ein Feld noch 0 enthält) und sie läuft nur dann (ohne weitere 
Rekursion) bis zum Ende durch, wenn die Lösung fertig ist, also kein 
einziges Feld mehr "0" enthält.

Davon, dass die Lösung fertig ist und die Funktion bis zum Ende gelangt, 
merkt aber niemand etwas, wenn dort nicht sowas wie "ausgabe()" oder 
"return FERTIG" steht, oder sonstwas mit dieser Bedeutung.

HTH ;-)



Peter W. schrieb:
> Die Zahlen werden nur gelöscht, wenn zahl = 10 ist. Dann wird aus:
> for (int zahl= 1; zahl< 10; zahl++) rausgesprungen und durch return
> gelangt man zur zeile: zahlen[x][y] = 0;

Mit Verlaub, da bist Du aber schwer auf dem Holzweg:

(a) Die Zahlen werden immer "gelöscht". Ansonsten müsste da ein if 
oder sowas stehen. Durch "return" gelangt man nicht zu irgendwelchen 
Zeilen, sondern nur aus dem aktuellen Funktionkontext heraus.
(b) Wenn "loesung()" mit "return" verlassen wird, bist du in jedem Fall 
hinter dem Aufruf von "loesung()" (Zeile 89) und danach geht es in jedem 
Fall mit "zahlen[x][y]=0;" weiter.
(c) Im Übrigen wird "zahl" niemals "10" - schließlich ist es ja nur 
innerhalb der Schleife sichtbar und dort wird auf "zahl<10" geprüft, 
bevor der Schleifenkörper durchlaufen wird.

Aber egal, es geht ja nun.



Peter W. schrieb:
> DevC++ in der Fehlersuche ist total Fehleranfällig, und nervt total!
> Gibt es ein alternatives einfaches Programm, welches funktioniert?

Meinst Du Compiler oder IDE? Und warum benutzt Du es denn, wenn es so 
nervt?
Und ja, gibt es. Tausende. Welches für Dich passt, hängt davon ab, was 
Du von ihm erwartest.

Davon abgesehen, ich denke, bevor man Werkzeuge zum Debugging anwirft, 
sollte man für sich selbst erstmal klargestellt haben, wie die 
Funktionsweise des eigenen Programms und seiner Teile sein soll.

Wenn das nicht steht, dann bastelt man meist nur an den Symptomen, aber 
nicht am eigentlichen Problem.



my2ct
(re)
OP #7010347
Lesenswert?

Also der Test im debugger läuft das so:

1.wenn eine zahl (beginnend von 1 bis 9) an der freien Position paßt, 
wird  sie geschrieben - und wieder rekursiv loesung() aufgerufen.
2. dann wird die nächste freie Position gesucht u.s.w
3. paßt keine zahl 1 bis 9 wird for (int zahl= 1; zahl< 10; zahl++) 
durch return verlassen und man gelangt zur letzten berechneten Position: 
nach loesung() zur zeile zahlen[x][y]=0;
4. die zahl der letzte Position wird gelöscht und von der letzten 
gespeicherten zahl weiter geteste, ob sie geht.

Sehe ich das alles falsch?

Kannst Du eine "einfache" IDE für C# empfehlen?

mfG
Peter
Gast #7010387
Lesenswert?

Peter W. schrieb:

> Kannst Du eine "einfache" IDE für C# empfehlen?

Für Windows: VisualStudio (unerreicht im Komfort)
Für Linux: MonoDevelop

Die sind allerdings beide nicht "einfach" im Sinne von "primitiv", 
sondern im Sinne von "erstmal relativ einfach zu benutzen".

Sie sind aber beide doch recht mächtig und deswegen kommt man bei beiden 
früher oder später doch an den Punkt, wo man sich auch mit der IDE 
selber beschäftigen muss.

Dein Projekt kann man aber wohl noch völlig problemlos abfackeln, ohne 
diesen Punkt zu erreichen...
Gast #7010467
Lesenswert?

Du hast C Code in cpp C++ Dateien und sprichst von C#
Das letztere ist eine völlig andere Programmiersprache von Microsoft
da könntest du auch den Code zeigen und nach einer Java IDE fragen, lös 
dich von dem c#/C-Sharp begriff - ist hier völlig falsch
Gast #7010684
Lesenswert?

Peter W. schrieb:
> 3. paßt keine zahl 1 bis 9 wird for (int zahl= 1; zahl< 10; zahl++)
> durch return verlassen  [...]
>
> Sehe ich das alles falsch?

Nun... sie wird aber auch dann mit return verlassen, wenn doch eine 
oder mehrere Zahlen passen. Die eingesetzte Zahl wird in jedem Fall 
früher oder später im Array wieder "gelöscht", bevor loesung() zu einem 
Ende kommt.

Und deswegen ist es wichtig, dass bei irgendeiner Rekursionstiefe einmal 
signalisiert wird, wenn eine Lösung tatsächlich gefunden wurde, bevor 
sie letztendlich doch wieder mit '0' überschrieben wird - wie Du ...

Peter W. schrieb:
> Jetzt erhalte ich als Ausgabe das ungelöste sudoku!

... ja selbst beobachtet hast.


HTH
(re)
Gast #7013435
Lesenswert?

Peter W. schrieb:
> Visual stuio community [...] läuft so einfach bei mir nicht
>
> Windows 7 ist mein Freund.

Naja, da sind unsere Freudeskreise wohl etwas disjunkt.

Etwas herumfragen in 4ma hat da übrigens einen Rechner zutage gefördert, 
auf dem MSVS(v15) auch unter Win7(64,SP1) auf einem Prozessorkern, etwa 
6GB RAM und insgesamt 60 GB Plattenplatz ganz zufriedenstellend läuft. 
Sollte also auch bei Dir ohne besondere Klimmzüge gehen.


Peter W. schrieb:
> Ist mir zu gewaltig

Ja, "schlank" geht anders. Aber wenn es der GDB nun nicht sein soll und 
teuere kommerzielle Produkte auch nicht infrage komen, dann muss man 
diese Kröte möglicherweise schlucken, wenn man Wert auf komfortables 
Debugging legt.

my2ct
(re)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren