Computergegner TicTacToe

    Computergegner TicTacToe

    Hallo zusammen,
    ich hänge bei meinem Computergegner bei TicTacToe fest.
    Ich möchte, dass der PC einen zufälligen Zug auswählt, sobald ich meinen Zug getätigt habe. Das klappt auch, nur zieht der PC manchmal 2-4 Züge aufeinmal und ich finde den Fehler einfach nicht.
    Wenn ich auf ein Feld klicke (also meinen Zug beendet habe und der PC nun an der Reihe ist), wird die Prozedur Zufallszahl aufgerufen, die eine Zahl zwischen 1-9 wählt und anschließend die Prozedur des Computerzugs aufruft. Diese prüft dann, ob das entsprechende Feld schon gefüllt ist. Wenn ja, wird eine weitere Zahl gewählt und falls das Feld leer sein sollte, wird es mit dem Zug des Computers gefüllt.
    Hier ein Ausschnitt des betreffenden Quelltextes:


    Delphi-Code

    1. procedure TComputergegner.CPZufallszahl;
    2. // Zieht Zufallszahl zur Auswahl des Spielzuges des Computers
    3. begin
    4. randomize;
    5. Zufallszahl := random(9) + 1;
    6. CPSpielerZug;
    7. end;
    8. procedure TComputergegner.CPSpielerZug;
    9. // Computer zieht mithilfe einer Zufallszahl, wenn diese ein bereits belegtes Feld auswählt wird erneut gezogen
    10. begin
    11. if CPSpieler = 2 then
    12. begin
    13. if Zufallszahl = 1 then
    14. begin
    15. if CPFeld1.caption = '' then
    16. begin
    17. CPFeld1.caption := 'O';
    18. CPFeld1.enabled := false;
    19. CPCodespielfeld[1, 1] := 'O';
    20. CPCountererhoehung;
    21. CPGewinnpruefung;
    22. CPSpieler := 1;
    23. end
    24. else
    25. begin
    26. CPZufallszahl;
    27. end;
    28. end;
    29. end;
    30. end;


    Der Quelltext geht genauso für die Zahlen 2-9 weiter.
    Warum zieht der Computer manchmal so viele Züge hintereinander? Ich bin mit meinem Latein am Ende ?(

    Ich danke schonmal für Tipps!!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DeddyH“ ()

    Ich habe Deinen Code mal durch den Formatter meines Delphi gejagt, damit die Einrückungen besser zur Geltung kommen. Fällt Dir jetzt etwas auf, insbesondere darauf, wann (unter welchen Umständen) der aktive Spieler gewechselt wird? Übrigens sollte man Randomize nur einmalig im Programm aufrufen.
    10 Minuten Nachdenken ersparen oftmals 10 Stunden Fehlersuche.
    Danke für die Antwort!
    Der Spieler wird ja nur gewechselt, wenn ein Zug vollendet wird. Im Fall vom Computerspieler wird solange eine Zahl ausgewählt, bis ein freies Feld gefunden wird.
    Das mit Randomize wusste ich nicht, warum ist das denn so?

    Ich habe vorhin selbst eine Lösung gefunden, ich habe das Wiederaufrufen von CPZufallszahl an eine andere Stelle gesetzt und plötzlich funktioniert es ^^
    Ich kann mir grob denken warum, aber verständlich kann ich es glaube ich nicht erklären :D
    Ich hatte eine Showmessage bei jeder möglichen Zahl hinter Zeile 27 gelegt, um zu schauen wie oft eine neue Zahl gewählt werden muss.. es hörte mit den Showmessages gar nicht mehr auf.. :D
    ich prüfe jetzt erst alle Zahlen von 1 - 9 durch, ehe ich eine neue Zahl ziehe und nicht mehr nach jeder Zahlenmöglichkeit.. kommt mir im nachhinein auch logischer vor als meine erste Lösung :D

    Eine Frage hätte ich noch.. ich weiß nicht ob ich die hier runter stellen kann oder lieber einen neuen Post aufmache...
    -> Gibt es eine Möglichkeit, Dateipfade im Quelltext automatisch ändern zu lassen? Also dass man nicht bei gefühlt 100en Zeilen den Dateipfad manuell ändern muss?
    Meine Idee wäre jetzt, das gesamte Programm auf einen Stick zu ziehen und alle Dateipfade im Quelltext auf den Ordner im Stick anzupassen.
    Da die USB-Laufwerke ja bei jedem PC anders sind, müsste nur der Buchstabe vom Laufwerk manuell geändert werden.. Jetzt könnte man doch theoretisch den Buchstaben vom Laufwerk als User in ein Edit-Feld eingeben und im Quelltext dann praktisch als Variable speichern und in den Dateipfad eintragen..
    Beispiel:

    Delphi-Code

    1. Dateipad := EditLaufwerk.text + '\USB\Ordner\Datei.txt';

    Geht sowas? ?(
    Moin... 8o
    1. neue Frage, neuer Threat...Macht es beim Suchen einfacher. Weil es nicht viel ist, lassen wir es mal durchgehen. ;)
    2. Prinzipiell ist das möglich aber nicht zu empfehlen. ;) Der Benutzer ist die Schwachstelle mit z.b. Tippfehlern.
    - entweder eine Auswahlbox mit den automatisch generierten Laufwerksbuchstaben ( :/ eher nicht gut)
    oder
    - den Ordner vom Programm selbst ermitteln lassen :thumbsup: (geil)

    Schau dir mal die Befehle an (es gibt ein Lazarus Pondon):
    ParamStr (siehe Anmerkung): docwiki.embarcadero.com/Libraries/Seattle/de/System.ParamStr
    IncludeTrailingPathDelimiter: docwiki.embarcadero.com/Librar…ludeTrailingPathDelimiter
    ExtractFilePath
    : docwiki.embarcadero.com/Librar….SysUtils.ExtractFilePath

    Beispiel:

    Delphi-Code

    1. DatenPfad := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + 'Daten';

    Die Daten liegen dann relativ zur EXE. Die Dateien liegen dann in DatenPfad + Dateiname . Das Programm arbeitet nur mit dem DatenPfad...ohne Benutzereingaben...fertsch. 8o

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „haentschman“ ()

    Vielleicht wird es ja noch gelesen:


    DatenPfad := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + 'Daten';


    ist aber keine gute Idee, denn das ist der Pfad zum Programm (also der EXE) welche in ...\Programme oder ...\ProgrammeX86 liegt und da hat der Benutzer, wenn er kein Admin ist, keine Schreibrechte!
    Dafür wurden extra die ...\User\... Verzeichnisse "erfunden" ;)

    Ciao
    Stefan