Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

04.07.2011, 19:48

fehlerhafter Tic Tac To code

Um meine kleinen Fähigkeiten ein bischen zu testen, habe ich versucht ein kleines Tic Tac To Spiel zu programmieren.
Dabei bin ich natürlich schon auf ein paar Fehler gestoßen :thumbdown: :D
Deswegen würde ich doch gerne darum bitten dass sich das mal ein erfahrener Programmierer anschaut :D

PS: Ein paar Sachen sind noch nicht fertig, wie zum Beispiel das Zurücksetzen der GameOver Variable.
Andererseits wär ich schon froh wenn das Spiel ansich funktionieren würde :lol: .
Achja, ich hoffe es stört keinen, dass ich den Spoiler Button nicht gefunden habe :thumbsup: .

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <iostream>

namespace Spiel {
    char Spielfeld[] = {'0','1','2','3','4','5','6','7','8'}; 
    int Turn;
}

void GameTurn(); 
void resetSpielfeld(char cCHar[]);
void resetTurn(int iInt);

void main() {
    using namespace std;
    using namespace Spiel;

    char s1 = '|';
    char s2 = '-';
    char p  = '+';

    cout << Spielfeld[0] << s1 << Spielfeld[1] << s1 << Spielfeld[2] << endl;
    cout << s2 << p << s2 << p << s2 << endl;
    cout << Spielfeld[3] << s1 << Spielfeld[4] << s1 << Spielfeld[5] << endl;
    cout << s2 << p << s2 << p << s2 << endl;
    cout << Spielfeld[6] << s1 << Spielfeld[7] << s1 << Spielfeld[8] << endl;
    // Aufbau des Spielfeldes
    GameTurn();
}

void GameTurn() {
    using namespace std;
    using namespace Spiel;

    char Index; 
    bool GameOver;
    char PlayerMark;
    bool PlayerWin;
    char PlayAgain;

    for ( Turn = 1; Turn < 10; ++Turn) { // allgemener Spielzug,zählt den aktuellen Zug
        
        if ( Turn % 2 == 0 ) { 
            PlayerMark = 'O';
        } else { PlayerMark = 'X';//bestimmt welcher Spieler an der Reihe ist
        
        } do { cin >> Index;// nimmt die Eingabe des Spielers an; Spieler X beginnt, dann folgt Spieler O
        cout << Index << PlayerMark << endl; // nur ein kleiner Test ob sich die Variablen PlayerMArk und Index verändern; funtioniert

        if (Spielfeld[Index] != 'O') {
            if (Spielfeld[Index] != 'X') {
                Spielfeld[Index] = PlayerMark; /* bestimmt ob das Feld noch frei ist, wenn ja, 
                                               wird dem Feld der Wert der Variable PlayerMark zugewiesen;
                                               Dies geschieht aktuell nicht */
            }
        }
        if (Spielfeld[0] == Spielfeld[1] == Spielfeld[2]
        ||  Spielfeld[0] == Spielfeld[3] == Spielfeld[6]
        ||  Spielfeld[8] == Spielfeld[7] == Spielfeld[6]
        ||  Spielfeld[8] == Spielfeld[5] == Spielfeld[2]
        ||  Spielfeld[4] == Spielfeld[0] == Spielfeld[8]
        ||  Spielfeld[4] == Spielfeld[2] == Spielfeld[6]
        ||  Spielfeld[4] == Spielfeld[3] == Spielfeld[5]
        ||  Spielfeld[4] == Spielfeld[1] == Spielfeld[7]) { /* wenn drei in einer Reihe liegende Felder den gleichen Wert besitzen
                                                            wechseln sowohl GameOver als auch PlayerWin ihren Wert zu true;
                                                            der do-loop wird beendet*/
            GameOver = true;
            PlayerWin = true;
        }
}   while (GameOver = false);

}   if (GameOver == true) {
    if (PlayerWin == true) {
    cout << "Player " << PlayerMark << "wins" << endl; /* der Spieler der am Zug ist während GameWin zu true wechselt
                                                       wird als Gewinner angezeigt */
    }
    cout << "Play again?" << endl;
    cout << "yes(y) or no(n)" << endl;
    cin  >> PlayAgain;// fragt nach einem erneutem game

    if (PlayAgain == 'y') {
        resetSpielfeld(Spielfeld[]); 
        resetTurn(Turn); /* setzt sowohl das Spielfeld als auch die Variable Turn zurück;
                         Allerdings fordert Spielfeld einen Index Wert;
                         dann jedoch ist der array mit dem in dem argument array in resetSpielfeld inkompitabel.
                         Hierfür weiß ich keine Lösung*/
    }
}
}

MCP

Alter Hase

Beiträge: 513

Wohnort: Paderborn

Beruf: Software-Entwickler

  • Private Nachricht senden

2

04.07.2011, 19:56

Die Einrückung ist grausig. ^^
Hab es nur überflogen, was mir spontan aufgefallen ist:
Wo wird Turn definiert (Zeile 39) und was macht das while in Zeile 68 und warum wird da kein Vergleich sondern eine Zuweisung durchgeführt und der Anweisungsblock weggelassen? So macht das while ja nix.

Was für Fehler hast Du denn sonst noch? Fehlercodes wären schön und ein ordentlich eingerückter Code.

Harry222

Alter Hase

Beiträge: 864

Beruf: Student

  • Private Nachricht senden

3

04.07.2011, 20:42

Wo wird Turn definiert (Zeile 39)
Zeile 5 ;)

Es macht (so weit ich das sehe) übrigens überhaupt keinen Sinn, diese Variable global zu definieren!
Statt

C-/C++-Quelltext

1
2
3
//...
for ( Turn = 1; Turn < 10; ++Turn) {
//...
könnte man dann auch einfach

C-/C++-Quelltext

1
2
3
//...
for (int Turn = 1; Turn < 10; ++Turn) {
//...
benutzen und

C-/C++-Quelltext

1
2
3
4
//...
    int Turn;
}
//...
weglassen! ;)
Oder sehe ich das falsch? :rolleyes:

Und außerdem:
Welchen sinn hat in Zeile 81 die resetTurn-Funktion? :huh:
Du hast da u.a. geschrieben:
setzt [..] auch die Variable Turn zurück
Die Variable Turn wird aber doch schon in der for-Schleife zurückgesetzt: ;)

C-/C++-Quelltext

1
2
3
//...
for ( Turn = 1 /* ZURÜCKSETZEN */; Turn < 10; ++Turn) {
//...


Und natürlich die Einrückung, wie MCP schon gesagt hat!

Das war erstmal, was mir so an Schönheitsfehlern aufgefallen ist! ^^
Und zu den Fehlern...
Du initalisierst GameOver und die anderen Variablen garnicht!
Sollte eher so aussehen (mit Standardwerten initalisieren)

C-/C++-Quelltext

1
2
3
4
5
6
7
//...
    char Index = ... //je nach dem mit welchem Wert du initalisieren möchtest...; 
    bool GameOver = false;
    char PlayerMark = ...;
    bool PlayerWin = ...;
    char PlayAgain = ...;
//...

Solltest du nämlich z.B. GameOver nicht initalisieren und falls dann die in der ersten Runde auch kein Spieler gewinnt und somit GameOver in Zeile 65 auch nicht auf true gesetzt wird, hat GameOver in Zeile 68 auch noch keinen Wert, mit dem Verglichen werden kann!

Und zu dem Anwendungsblock der while (GameOver = false)...
Dadurch soll so wie ich das verstehen das Spiel wiederholt werden, falls keiner gewonnen hat, oder!?
Versuch also so:

C-/C++-Quelltext

1
2
3
4
5
6
7
//...
while (GameOver == false){
    for (int Turn = 1; Turn < 10; ++Turn) { // allgemener Spielzug,zählt den aktuellen Zug
    //...
    }
}
//...


Das war eigentlich erstmal alles, was mir im Moment auffällt! :lol:

Mfg Harry222

PS: Puh, diese schreiberei macht mich eich fertig! Hoffentlich hat es sich auch gelohnt! ^^ ;)

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Harry222« (04.07.2011, 21:13)


NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

4

04.07.2011, 20:46

Er meint das Turn ausserhalb des Namespaces Spiel ;)
Ahh, doch nicht.

@Rexona for men: Versuch auf using namespace zu verzichten. Es spart vllt ein paar Sekunden beim Tippen aber kostet unter Umständen Stunden beim Debugen.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

5

04.07.2011, 20:48

Die Einrückung ist grausig. ^^
Visual C++ Express nimmt das einrücken automatisch vor, wie sehe denn ein gut eingerückter Code aus? :D

Zitat

Wo wird Turn definiert (Zeile 39)
In Zeile 5 im namespace Feld, da ich Turn in mehreren Funktionen benötige :P .


Zitat

was macht das while in Zeile 68 und warum wird da kein Vergleich sondern eine Zuweisung durchgeführt
Das while gehört eigentlich zu einem do in Zeile 45, ja und eigentlich sollte das auch ein Vergleich sein :rolleyes: :D .

Zitat

Fehlercodes wären schön

Stimmt, hatte ich vergessen :whistling: , hier zu array in Zeile 80:

Quellcode

1
error C2059: Syntaxfehler: ']' 

kommt wenn ich keinen Wert die die eckige Klammer gebe, tu ich aber genau das gibts de folgenden Error:

Quellcode

1
2
error C2664: 'resetSpielfeld': Konvertierung des Parameters 1 von 'char' in 'char []' nicht möglich
1>      Die Konvertierung eines ganzzahligen Typs in einen Zeigertyp erfordert ein reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat

6

04.07.2011, 20:50

Zitat

@Rexona for men: Versuch auf using namespace zu verzichten. Es spart vllt ein paar Sekunden beim Tippen aber kostet unter Umständen Stunden beim Debugen.
Okay, auch wenns angenehm ist und ich es einfach mal testen wollte :D

Oberon

Treue Seele

Beiträge: 181

Wohnort: Österreich

Beruf: Student

  • Private Nachricht senden

7

04.07.2011, 20:51

Beim kurzen Überfliegen sind mir zwei Dinge aufgefallen:
1. Es heißt int main. Alles andere ist nicht standardkonform.
2. Entscheide dich für Englisch ODER Deutsch (am besten auch in den Kommentaren)

Zum Fehler kann man nichts sagen, wenn du nichts du dazu sagst (Compilerfehler? Laufzeitfehler? Falsches Programmverhalten?).
EDIT: Na also, geht doch! ;) Nimm die eckigen Klammern weg, dann sollte es gehenkompilieren.

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

8

04.07.2011, 20:54

C-/C++-Quelltext

1
resetSpielfeld(...);

müsstest du eigentlich so aufrufen:

C-/C++-Quelltext

1
resetSpielfeld(Spielfeld); 

Dann wird aber eine unaufgelöstes externes Symbol Fehlermeldung kommen weil die Funktion nicht definiert ist. (wenn das der komplette Code ist)

VS rück nicht immer richtig ein. Da musst du etwas nachhelfen.
Das mit dem Einrücken ist eigentlich ganz einfach. Nach jeder " { " rückst du ein stück weiter ein und nach jeder " } " ein stück weniger.

beispiel:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void IOwx::onClose()
{
    if(m_TextPanel)
    {
        for(unsigned int page = 0; page < m_Parent->GetPageCount(); ++page)
        {
            if(m_Parent->GetPage(page) == m_TextPanel)
            {
                m_Parent->DeletePage(page);
            }
        }
        m_TextPanel = NULL;
    }
}

Was der Code macht brauch dich aber nicht zu interessieren^^
Du kannst mehrere Zeilen gleichzeitig einrücken indem du sie markierst und tab drückst. Ausrücken geht mit shift+tab.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

9

04.07.2011, 21:31

Zitat

1. Es heißt int main. Alles andere ist nicht standardkonform.
Ist geändert :)

Zitat

2. Entscheide dich für Englisch ODER Deutsch (am besten auch in den Kommentaren)
Ja, ist mir jetzt auch erst aufgefallen, allerdings ne schlechte Angewohnheit von mir :whistling:

Zitat

Falsches Programmverhalten?
Bisher bin ich immer erst zu dem Punkt gekommen, wo ein Spielfeld eigentlich den Wert von PlayerMark annehmen sollte, sprich
sich nach Eingabe des Spielers verändern sollte zu X oder O.
Hat bisher nicht funktioniert.

Zitat

müsstest du eigentlich so aufrufen:


C-/C++-Quelltext
1
resetSpielfeld(Spielfeld);


Dann wird aber eine unaufgelöstes externes Symbol Fehlermeldung kommen weil die Funktion nicht definiert ist. (wenn das der komplette Code ist)
Ich hab jetzt die [] aus dem default argument aus der Funktion resetSpielfeld rausgenommen und bekomme in der Richtung jetzt keinen Fehler mehr, allerdings weiß ich nicht ob das so richtig ist :rolleyes: :D .

Zitat

(wenn das der komplette Code ist)

Tatsächlich fehlt da noch einbischen was, aber ich bin froh wenn dieser Teil schon mal läuft :P

So hier ein aktualisierter Code( hoffentlich bessere Einrückung, kleinere Kommentare und Berichtigungen)
Außerdem hab ich noch die reset Funktionen erstmal rausgenommen, bis der Rest funktioniert.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <iostream>


int GameTurn(); 

int main() {
    using namespace std;

    char Spielfeld[] = {'0','1','2','3','4','5','6','7','8'}; 
    char s1 = '|';
    char s2 = '-';
    char p  = '+';
                    // Aufbau des Spielfeldes
    cout << Spielfeld[0] << s1 << Spielfeld[1] << s1 << Spielfeld[2] << endl;
    cout << s2 << p << s2 << p << s2 << endl;
    cout << Spielfeld[3] << s1 << Spielfeld[4] << s1 << Spielfeld[5] << endl;
    cout << s2 << p << s2 << p << s2 << endl;
    cout << Spielfeld[6] << s1 << Spielfeld[7] << s1 << Spielfeld[8] << endl;
    
    GameTurn();
}

int GameTurn() 
{
    using namespace std;

    char Spielfeld[] = {'0','1','2','3','4','5','6','7','8'}; 
    int Turn;
    char Index; 
    bool GameOver;
    char PlayerMark;
    bool PlayerWin;

    for ( Turn = 1; Turn < 10; ++Turn)// allgemener Spielzug,zählt den aktuellen Zug
    {
         
        if ( Turn % 2 == 0 ) 
        { 
            PlayerMark = 'O';
    } else { PlayerMark = 'X';//bestimmt welcher Spieler an der Reihe ist
        
} do 
    { cin >> Index;// nimmt die Eingabe des Spielers an; Spieler X beginnt, dann folgt Spieler O
    
        cout << Index << PlayerMark << endl; // nur ein kleiner Test ob sich die Variablen PlayerMArk und Index verändern; funtioniert

        if (Spielfeld[Index] != 'O')
        {
            if (Spielfeld[Index] != 'X') 
            {
                Spielfeld[Index] = PlayerMark; //prüft ob das Feld noch frei ist wenn ja wird es besetzt
            }
        }
        if (Spielfeld[0] == Spielfeld[1] == Spielfeld[2]
        ||  Spielfeld[0] == Spielfeld[3] == Spielfeld[6]
        ||  Spielfeld[8] == Spielfeld[7] == Spielfeld[6]
        ||  Spielfeld[8] == Spielfeld[5] == Spielfeld[2]
        ||  Spielfeld[4] == Spielfeld[0] == Spielfeld[8]
        ||  Spielfeld[4] == Spielfeld[2] == Spielfeld[6]
        ||  Spielfeld[4] == Spielfeld[3] == Spielfeld[5]
        ||  Spielfeld[4] == Spielfeld[1] == Spielfeld[7])//prüft ob eine Gewinnbedingung erfüllt wurde
        { 
            GameOver = true;
            PlayerWin = true;
        }
    }   while (GameOver == false);

}   if (GameOver == true)
    {
    if (PlayerWin == true)
        {
    cout << "Player " << PlayerMark << "wins" << endl; // zeigt den Spieler am Zug als Gewinner an
        }
    }
    return 0;
}


Das Problem ist Zeile 47-52, aus irgendeinem Grund wird kein X oder O in das Spielfeld eingetragen ?( .

Achja, und danke schonmal für die nette Hilfe :) .

MCP

Alter Hase

Beiträge: 513

Wohnort: Paderborn

Beruf: Software-Entwickler

  • Private Nachricht senden

10

04.07.2011, 21:47

Oha, das mit Turn hat mich tatsächlich etwas aus der Bahn geworfen. Das hätte ich in dem Namespace niemals vermutet und nicht so weit oben geschaut. ^^
Beim einrücken sollte man sich auch für ein System entscheiden. Manchen ist die Java-Einrückung lieber, wobei ich den C++ Style lieber mag:

C-/C++-Quelltext

1
2
3
4
5
6
7
int main(string args[])
{
   for(int i=0; i<10;++i)
   {
    //...
   }
}


Java-Style:

C-/C++-Quelltext

1
2
3
4
5
int main(string args[]) {
    for(int i=0; i<10;++i) {
        //...
    }
 }


Die schließende Klammer sollte auf jedenfall immer auf der selben Höhe sein, wie der Anfang des öffnenden Blocks (wenn das verständlich formuliert ist). Alles in einem Block sollte eingerückt sein.
Das macht es viel leichter zu erkennen wo ein Bereich anfängt und aufhört.
Ich nehme mal die Stelle:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for ( Turn = 1; Turn < 10; ++Turn)// allgemener Spielzug,zählt den aktuellen Zug 
    { 
        
        if ( Turn % 2 == 0 )  
        {  
            PlayerMark = 'O'; 
    } else { PlayerMark = 'X';//bestimmt welcher Spieler an der Reihe ist 
        
} do  
    { cin
    //...
    } while (GameOver == false);
    //...
}


Besser wäre es so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for ( Turn = 1; Turn < 10; ++Turn)// allgemener Spielzug,zählt den aktuellen Zug 
{ 
    if ( Turn % 2 == 0 )  
    {  
        PlayerMark = 'O'; 
    }
    else
    {
        PlayerMark = 'X';//bestimmt welcher Spieler an der Reihe ist 
    }
    
    do  
    {
        //...
    } while (GameOver == false);
    //...
}

Werbeanzeige