Damebrettspiel - Speicherzugriffsfehler
-
Huhu und zwar habe ich ein kleines Problem mit meinem Dameprogramm.
Nach ca. 5 Zügen wird mir immer Speicherzugriffsfehler ausgegeben und nichts geht mehr woran liegt das ?main.cpp:
#include <iostream> #include "Dame.hpp" //#include <Dame.cpp> nur für windows using namespace std; int main() { CheckersWithPlayers checkers; checkers.initBoard(); CheckersWithPlayers Savefile; Savefile.initBoard(); checkers.printBoard(); while(true) { char zurueck; Savefile = checkers; checkers.setboardplayer1(); checkers.tokencounter(); checkers.printBoard(); cout << "zuruecksetzen mit '-' Enter? Ansonsten druecken Sie 'n' und bestaetigen(Enter) um fortzufahren!" << endl; cin >> zurueck; if(zurueck == '-') { // zurücksetzen WHITE checkers = Savefile; checkers.printBoard(); Savefile = checkers; checkers.setboardplayer1(); checkers.tokencounter(); checkers.printBoard(); } Savefile = checkers; checkers.setboardplayer2(); checkers.tokencounter(); checkers.printBoard(); cout << "zuruecksetzen mit '-' Enter? Ansonsten druecken Sie 'n' und bestaetigen(Enter) um fortzufahren!" << endl; cin >> zurueck; if(zurueck == '-') { // zurücksetzen BLACK checkers = Savefile; checkers.printBoard(); Savefile = checkers; checkers.setboardplayer2(); checkers.tokencounter(); checkers.printBoard(); } } }
Dame.hpp
#include <vector> #pragma once /* class CheckersWithPlayers ruft der Reihe nach alle Funktionen ab und beinhaltet die Vektoren des Brettes void initBoard setzt die Spielsteine Seite Spieler 1: setzt auf den oberen 3 Reihen [i-Zahlenseite] über die Länge der Buchstabenreihe [j-Buchstabenreihe] die B-Spielsteine immer mit einem Feld (waagerecht) Abstsand sowie in der 2ten Reihe[i] um 1 Feld versetzt Seite Spieler 2: setzt auf den unteren 3 Reihen [i-Zahlenseite] über die Länge der Buchstabenreihe [j-Buchstabenreihe] die W-Spielsteine immer mit einem Feld (waagerecht) Abstsand sowie in der 2ten Reihe[i] um 1 Feld versetzt void print Board erzeugt das Spielbrett erzeugt ein 10x10 Spielbrett und gibt die Seitenbeschriftung aus, die obere Zahlenreihe wird durch Buchstaben ersetzt und die linke Zahlenreihe wird invers ausgegeben void setboardplayer1 Spielzüge Spieler 1 (WHITE) beinhaltet die Eingabe des Spielzuges sowie alle möglichen Spielzüge die getätigt werden können und deren Gültigkeit für Spieler 1 void setboardplayer2 Spielzüge Spieler 2 (BLACK) beinhaltet die Eingabe des Spielzuges sowie alle möglichen Spielzüge die getätigt werden können und deren Gültigkeit für Spieler 2 void tokencounter aktueller Spielstand nimmt die Gesamtanzahl der aktuellen Spielsteine(WHITE & BLACK) und zieht bei "vernichten" eines Spielsteines bei der "Farbe" einen ab main vereint das Programm mit allen Dateien und führt es der Reihe nach aus CheckersWithPlayers wird in checkers "gepackt" - die Spielsteine werden gesetzt in checkers - CheckersWithPlayers wird in Savefile "gepackt" - die Spielsteine werden gesetzt in Savefile - das Spielbrett wird erzeugt --> nun 2x der selbe Ablauf einmal Spieler1 und einmal Spieler2 - checkers wird in Savefile gespeichert - Spieler macht seinen Zug - Spielstand wird abgerufen- Brett wird erzeugt - falls 'n'+ (Enter): nächster Spieler - falls '-': Brett vor dem Zug wird geladen- Spieler kann erneut seinen Zug machen - Spielstand wird abgerufen - Brett wird erzeugt */ class CheckersWithPlayers { public: void initBoard(); void printBoard(); void setboardplayer1(); void setboardplayer2(); void tokencounter(); private: char Board [10][10] = {}; };
Dame.cpp
#include <iostream> #include <vector> #include <iomanip> #include "Dame.hpp" using namespace std; void CheckersWithPlayers::initBoard() { // Seite Spieler 1 (WHITE) for(int i = 0; i < 3; i++) { for(int j = 0; j <10; j++) { if((j % 2) == 0) { if((i % 2) == 0) { Board[i][j] = 'W'; } else { Board[i][(j + 1)] = 'W'; } } } } // Seite Spieler 2 (BLACK) for(int i = 0; i < 3; i++) { for(int j = 0; j < 10; j++) { if((j % 2) == 0) { if((i % 2) != 0) { Board[(i + 7)][j] = 'B'; } else { Board[(i + 7)][(j + 1)] = 'B'; } } } } } void CheckersWithPlayers::printBoard() { // Buchstabe Position [j] cout << " "; for(int k = 0; k <10; k++) { cout << " " << static_cast<char> (k + 65); } cout << endl << endl; // Zahl Position [i] for(int i = 9; i >=0; i--) { cout <<setw(3)<< i+1 << " "; for(int j = 0; j <10; j++) { if(Board[i][j] != 0){ cout << "[ " << Board[i][j] << " ]"; } else { cout << "[ ]"; } } cout << endl; } } void CheckersWithPlayers::setboardplayer1() { cout << endl; cout << "Spieler 1 (WHITE) ist an der Reihe !" << endl; cout << "Bitte geben Sie Start- und Zielposition Ihres Steines an (Bsp.: A3 B4):" << endl; int SN; // Startnumber int EN; // Endnumber char SC; // Startchar char EC; // Endchar cin >> SC >> SN >> EC >> EN; SN = SN-1; EN = EN-1; SC = SC-'A'; EC = EC-'A'; if(Board[EN][EC] == 0 && SN+1 == EN && (SC+1 == EC || EC+1 == SC)) { Board[EN][EC] = Board[SN][SC]; Board[SN][SC] = 0; cout << "Ihr Zug ist gueltig !" << endl; cout << endl; } else if(SN+2 == EN && (SC+2 == EC || EC+2 == SC) && Board[SN+1][SC+(EC-SC)/2] == 'B') { Board[EN][EC] = Board[SN][SC]; Board[SN][SC] = 0; Board[SN+1][SC+(EC-SC)/2] = 0; cout << "Ihr Zug ist gueltig !" << endl; cout << endl; } else { cout << "Ihr Zug ist ungueltig !" << endl; cout << "Bitte erneut eingeben !" << endl; setboardplayer1(); } } void CheckersWithPlayers::setboardplayer2() { cout << endl; cout << "Spieler 2 (BLACK) ist an der Reihe !" << endl; cout << "Bitte geben Sie Start- und Zielposition Ihres Steines an (Bsp.: B8 C7):" << endl; int SN; int EN; char SC; char EC; cin >> SC >> SN >> EC >> EN; SN = SN-1; EN = EN-1; SC = SC-'A'; EC = EC-'A'; if(Board[EN][EC] == 0 && SN-1 == EN && (SC-1 == EC || EC-1 == SC)) { Board[EN][EC] = Board[SN][SC]; Board[SN][SC] = 0; cout << "Ihr Zug ist gueltig !" << endl; cout << endl; } else if(SN-2 == EN && (SC-2 == EC || EC-2 == SC) && Board[SN-1][SC+(EC-SC)/2] == 'W') { Board[EN][EC] = Board[SN][SC]; Board[SN][SC] = 0; Board[SN-1][SC+(EC-SC)/2] = 0; cout << "Ihr Zug ist gueltig !" << endl; cout << endl; } else { cout << "Ihr Zug ist ungueltig ! " << endl; cout << "Bitte erneut eingeben !" << endl; setboardplayer2(); } } void CheckersWithPlayers::tokencounter() { int white = 0; int black = 0; for(int i = 0; i <= 9; i++) { for(int k = 0; k <= 9; k++) { if(Board[i][k] == 'W') { white++; black++; } } } cout << "Weiss: " << white << endl << "Schwarz: " << black << endl; }
Danke
-
Was sagt denn der Debugger?
-
Was heißt ca?
Wenn ich das grade richtig sehe überprüfst du nicht, ob deine Eingabe auf dem Spielfeld ist.
-
Du könntest auch mal überlegen, ob du wirklich 2x Code zum Einlesen eines Zuges und Prüfen der Gültigkeit brauchst. Das sollte doch für beide Farben praktisch identischer Code sein!
-
@Th69 Debugger spuckt mir nur die Warnung aus das [10][10] kein Char ist immer wenn es aufgerufen wird !
@Schlangenmensch sry für die wahrscheinlich doofe Frage aber wie meinst du das? Bzw. setzt man das um ?ca. heißt das es auf meinem Rechner 16gb ram für 5 Züge reicht und auf einem anderen Rechner mit 4gb ram gingen gerade mal 3 Züge ich weiß allerdings nicht ob es was damit zu tuen hat.
-
felix92 schrieb:
@Th69 Debugger spuckt mir nur die Warnung aus das [10][10] kein Char ist immer wenn es aufgerufen wird !
... und das zu Recht.
Board
geht von0
bis9
,Board[10][10]
ist schon Speicher, der dir nicht gehört.felix92 schrieb:
@Schlangenmensch sry für die wahrscheinlich doofe Frage aber wie meinst du das?
Board[EN][EC] = Board[SN][SC]; Board[SN][SC] = 0; cout << "Ihr Zug ist gueltig !" << endl;
Du greifst hier lustig auf alle möglihen Speicherbereiche zu, nur weils der Benutzer eingibt. Prüfe zuerst, ob das Eingegebene überhaupt im Bereich von
Brett
liegt.
-
felix92 schrieb:
@Th69 Debugger spuckt mir nur die Warnung aus das [10][10] kein Char ist immer wenn es aufgerufen wird
Glaub ich, [10][10] gibt es auch nicht.
-
Also quasi [10][10] auf [0][9] ändern ?
aber dann gibt er mir doch ein falsches "Brett" aus
Sry aber verstehe das nicht so ganz ist der Speicher nicht frei für alle anstehenden Aufgaben ?
-
Irgendwo wirst du wohl über die Arraygrenzen [9][9] hinausgehen. Aber da hilft dir der Debugger weiter, Step für Step durchgehen.
-
Der gibt mir halt nur aus das [10][10] kein Char ist als Warnung funktionieren tut es ja für maximal 5 Züge
-
Dein lieber Debugger sagt Dir doch sicher aus, wo Du auf
Brett[10][10]
zugreifst ...
-
felix92 schrieb:
Der gibt mir halt nur aus das [10][10] kein Char ist als Warnung funktionieren tut es ja für maximal 5 Züge
Das ist der Compiler. Wenn du deinen Code im Debugger ausführst, sagt der dir, wo er raus fliegt.
Da wir in einem C++ Forum sind, könntest du auch über die Verwendung von std::array nachdenken und mit at() zugreifen, das schmeißt eine Exception, wenn du außerhalb deiner Grenzen bist.Ich habe keine Lust, deine Logik nachzuvollziehen, aber, wenn du nur erlaubte Züge machst, würde ich mir mal die Randbedingungen anschauen. Vor allem, wenn du einen anderen Stein schlägst, da rechnest du einen Index hoch. Das sieht verdächtig aus.
-
Wichtig für dich vielleicht auch noch: wenn du einmal was falsches eingegeben hast, ist der ifstream "cin" im Failed-Status und nachfolgende Einleseoperationen finden dann nicht mehr statt.
Schau dir vielleicht mal die Clear-Funktion an:
http://en.cppreference.com/w/cpp/io/basic_ios/clear
http://www.cplusplus.com/reference/ios/basic_ios/clear/
-
felix92 schrieb:
Also quasi [10][10] auf [0][9] ändern ?
Hä was? NEIN! Du verstehst es wirklich nicht oder? Du legst das Array Board mit 10 Zeilen und 10 Spalten an. Du willst aber später auf die 11. Zeile und die 11. Spalte zugreifen. Wie soll das gehen?! Es wird bei 0 angefangen zu zählen, das heißt dein maximaler Zugriffsbereich ist Board[9][9]...
-
Ich habe folgende Vermutung:
die COMPILER-Warnmeldung zu dem Feld[10][10] wird hier als DEBUGGER-Fehlermeldung dargestellt. Daher vermutet hier jeder, dass es wirklich um einen Debugger ging, der tatsächlich gar nicht im Spiel war. Ich habs jetzt mal diverse Züge lang gespielt und wenn man keine Fehleingaben macht, kommt man schon weit - es ist bislang nicht abgestürzt. Daher denke ich, dass der Fehler von dem fehlenden Clear nach Fehleingaben und der darauf folgenden Endlosrekursion kommt.Mir ist noch was aufgefallen:
a) Doppelsprünge sind nicht möglich, man kann also nicht 2 Figuren schlagen.
b) Sprünge sind nicht pflicht. Ich kenne Dame so, dass man schlagen muss, wenn man kann.
-
Ja gut konntest du nicht wissen aber das ist gewollt so laut der Aufgabe
mein Problem liegt wirklich nur noch darin das der Speicherzugriffsfehler nicht mehr auftritt !? Um ehrlich zu sein verstehe ich auch garnicht warum das passiert bzw. wo der Fehler liegt