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

Snowy

Frischling

  • »Snowy« ist der Autor dieses Themas

Beiträge: 54

Wohnort: Stuttgart

  • Private Nachricht senden

1

31.12.2013, 16:01

C++ Problem - Programm Hängt sich in einer Endlosschleife auf

Hallo liebe Community,

ich habe ein Problem mit einem Übungsprogramm, welches ich derzeit schreibe. Ich versuche darin alle Grundlagen von C++ zu verwenden, um diese zu festigen und ein wenig mit diesen zu experimentieren. Leider stecke ich jetzt schon eine Weile lang an einem Problem, wo ich nicht mehr weiter weis und den Fehler auch nicht mehr nachvollziehen kann (entzieht sich vielleicht meinem derzeitigen Kenntnisstand). Was ich bisher geschrieben habe, ist ein kleines Hauptmenü, wo folgendes Problem besteht:

Sobald man das "Spiel" starten möchte bekomme ich eine Endlosschleife, was z.B. bei dem Menüpunkt Credits nicht passiert.
Eigentlich sollte ja erst einmal der User seinen Namen eingeben, allerdings wird das einfach ignoriert und der "cout" - Befehl ständig wiederholt. Habe auch schon probiert eine normale "cin" Eingabe zu machen, mit einer int Variable, um zu schauen ob es vllt an der derzeitigen Abfrage hapert, hat aber das gleiche Resultat gebracht.

Hier erstmal der Quellcode (PS: Irgendwie geht die Formatierung flöten, wenn ich es mit code oder cpp Poste. Daher habe ich die Zweite Datei mal so gepostet.):

Ich danke schon mal im Voraus und bei der Gelegenheit wünsche ich schon mal einen guten Rutsch ins neue Jahr.

Gruß,
Snowy

:

main.cpp:

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
// Übungsprojekt
// 30.12.2013
//
#include <iostream>
#include <Windows.h>
#include "structs.hpp"

using namespace std;

// Funktions Prototypen
void Credits();
void GameStart();
void CharacterCOUT();
void PlayerInventoryCOUT();

// Instanz für den Spieler bilden
S_Player Player;

// Instanz für den Gegner bilden
S_Oger Oger;

int main()
{

    int loop = 1;
    char MenuChoice;

    // Hauptmenü Schleife - Kann nur durch Beenden beendet werden.
    do
    {

 // Konsole wird gesäubert
 system("cls");

 // Ausgabe des Hauptmenüs
//
 cout << "\n\n" << endl;
 cout << "================-" << endl;
 cout << " 1. (S)tarten -" << endl;
 cout << " 2. (C)redits -" << endl;
 cout << " 3. (B)eenden -" << endl;
 cout << "================-" << endl;
 cout << endl;
 cout << " Eingabe: ";

 cin >> MenuChoice;

 // Festgelegt was unter welchem Menüpunkt passiert
 switch ( MenuChoice )
 {
 // Das Spiel wird gestartet
 case('S'):
 case('s'):
 {

 GameStart();

 } break;
 // Es werden die Credits augerufen
 case('C'):
 case('c'):
 {

 Credits();

 } break;
 // Programm wird beendet
 case('B'):
 case('b'):
 {
 cout << "\n Programm wird beendet..." << endl;
 loop = 0;

 } break;
 // Flasche Eingabe durch den Spieler wirft eine Fehlermeldung aus
 default:
 {
 cout << "\n Du hast eine falsche Eingabe gemacht!" << endl;
 }
 }

    } while ( loop != 0);

    return 0;
}

// GameStart - Startet das eigentliche Spiel
void GameStart()
{


    // Spieler initsialisieren
    Player.Name[30] = '\0';
    Player.Life = 100;
    Player.Mana = 100;
    Player.Energy = 100;

    Player.Level = 1;
    Player.XP = 0;

    Player.Money = 250;
    Player.Healpot = 0;
    Player.Manapot = 0;

    // Gegner initsialisieren
    Oger.Name[30] = '\0';
    Oger.Life = 300;
    Oger.Mana = 200;

    Oger.Money = 50;
    Oger.XP = 80;

    Oger.Magic_Attack   = 12;

 // Abfrage des Spielernamens
 cout << "\n Bitte gib deinen Spielernamen ein: ";
 cin.get (Player.Name, 29);
 cin.ignore();

 // Ausgabe der Charakter Eigenschaften und des Inventars des Spielers
 CharacterCOUT();
 PlayerInventoryCOUT();

}

// Credits - Gibt die Credits aus
//
void Credits()
{
    int CreditsLoop = 1; 
    char CreditsChoice;

 // CreditsSchleife
 do
 {

 // Konsole wird gesäubert
 system("cls");

 cout << endl;
 cout << " -========================================================================- " << endl;
 cout << " - Diese Programm wurde von mir geschrieben, um Grundlagen der C++ Pro- - " << endl;
 cout << " - grammierung zu festigen und erste Erfahrungen zu sammeln. - " << endl;
 cout << " -========================================================================- " << endl;
 cout << endl;
 cout << " 1. (Z)urueck" << endl;
 cout << endl;
 cout << " Eingabe: ";

 cin >> CreditsChoice;

 // Spieler muss mit der Taste "Z" in das Hauptmenü zurückkehren
 switch ( CreditsChoice )
 {
 case('Z'):
 case('z'):
 {

 cout << "\n Hauptmenue wird aufgerufen..." << endl;

 CreditsLoop = 0;

 } break;
 default:
 {

 cout << "\n Du hast eine falsche Eingabe gemacht!" << endl;
 }
 }
 } while ( CreditsLoop != 0);

}

// CharacterCOUT - Gibt die kompletten Charaktereigenschaften aus
//
void CharacterCOUT()
{
    cout << endl;
    cout << " -== Charakter Eigenschaften==- " << endl;
    cout << endl;
    cout << " --------------------------------" << endl;
    cout << " Name: " << Player.Name << endl;
    cout << " ================================" << endl;
    cout << " Leben: " << Player.Life << endl;
    cout << " Ausdauer: " << Player.Energy << endl;
    cout << " Mana: " << Player.Mana << endl;
    cout << " ================================" << endl;
    cout << " Level: " << Player.Level << endl;
    cout << " Erfahrung: " << Player.XP << endl;
    cout << " ================================" << endl;
}

// PlayerInventoryCOUT - Gibt das Inventar des Spielers aus
void PlayerInventoryCOUT()
{
    cout << endl;
    cout << " -== Inventar ==- " << endl;
    cout << endl;
    cout << " ================================" << endl;
    cout << " Gold: " << Player.Money << " Gold " << endl;
    cout << " Heiltraenke: " << Player.Healpot << " x" << endl;
    cout << " Manatraenke: " << Player.Manapot << " x" << endl;
    cout << " ================================" << endl;
}



structs.hpp

// Spieler-und Gegnerstruktur
// 31.12.2013
//

// Spieler
//
struct S_Player
{
char Name[30];

int Life;
int Mana;
int Energy;

int Level;
int XP;

int Money;
int Healpot;
int Manapot;

int Player_Shield;
};

// Feind - Oger
//
struct S_Oger
{
char Name[30];

int Life;
int Mana;

int XP;

int Money;

int Magic_Attack;
};
return 0;

2

31.12.2013, 18:24

Hallo ich habe zwar nicht den code im detail analysiert aber ich würde das anderst schreiben.
Ich würde es so in etwa schreiben.

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
enum
{
    STATE_MAINMENU = 0,
    STATE_GAME,
    STATE_QUIT

};
int main()
{
    //init the stuff
    int state = STATE_MAINMENU;
    bool isrunning = true;

    while(isrunning)
    {
        if(state == STATE_MAINMENU)
        {
            //zeige main menü und vararbeite die eingabe
        }
        if(state == STATE_QUIT)
        {
            //some input has come to close the app
            isrunning = false; // set the bool to false to interupt the while loop
            
        }

    }
}



Ich würde diese schleife in eine Runtime klasse packen, und je eine klasse für das Menü/Inputverarbeitung , und natürlich für den spieler machen.

Du müsstest halt evt. andere STATES definieren.
Hoffentlich hillft dir das ein wenig.
Grüsse Spitzohr

3

31.12.2013, 18:33

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
 case('B'):
 case('b'):
 {
 cout << "\n Programm wird beendet..." << endl;
 loop = 0;

 } break;
 // Flasche Eingabe durch den Spieler wirft eine Fehlermeldung aus

 }
    } while ( loop != 0);


Du setzt loop auf null - fragst aber nach: "ist nicht null". ^^

MfG Chris

PS: Debugger benutzen

Edit: Denkfehler
LostLife ein 3D RPG - development

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »ChrisIsOn« (02.01.2014, 00:01)


4

31.12.2013, 22:05

Oder einfach glich std::getline benutzen.
Codebeispiel:

C-/C++-Quelltext

1
2
std::string input;
std::getline(std::cin, input);

So muss man sich auch keinen großen Kopf um *hust* bestimmte *hust* Dinge machen. :)

MfG
Check

Snowy

Frischling

  • »Snowy« ist der Autor dieses Themas

Beiträge: 54

Wohnort: Stuttgart

  • Private Nachricht senden

5

01.01.2014, 17:51

@Spitzohr: Mit dem enum habe ich bisher noch nicht gearbeitet. Ich weis nur, das er sowas ähnliches wie const ist. Kann es aber soweit nachvollziehen was du damit bewirken willst. Ich glaube mir fehlt aber noch etwas das Verständnis, für den Einsatz damit.

@ChrisIsOn: Ja das war so schon gedacht, da das Programm mit dem drücken der B Taste geschlossen werden sollte und somit die Schleife natürlich aufhören musste. Sprich die Schleife soll solange laufe, wie die Variable "loop" nicht 0 ist.

@LetsGo: Dein Ratschlag hat geholfen, mit "cin >>" konnte ich das Endlosschleifenproblem lösen. Allerdings habe ich nun das folgende Problem, dass nun nur 1 Wort erfasst werden kann. Sprich ich kann bei dem Namen nicht Vor- und Nachname eingeben, da nur das letzte Wort gespeichert wird.

@Checkmateing: Schleicht sich da die Grippe an? :) Ne im ernst, ich bin gerade etwas planlos was du mit "*hust*" genau meinst. ^^
return 0;

KeksX

Community-Fossil

Beiträge: 2 107

Beruf: Game Designer

  • Private Nachricht senden

6

01.01.2014, 18:59

Komische Sache eigentlich. Du hast hier ein "perfektes" Problem geschaffen, aus dem du super lernen kannst.

Kleiner Tipp: Lies nochmal genau durch, wie chars eigentlich so aussehen in C++ und wie >> bzw. get() einlesen. Ich möchte nicht zu viel verraten, aber das Stichwort "newline" sollte dir helfen :)
WIP Website: kevinheese.de

FSA

Community-Fossil

  • Private Nachricht senden

7

01.01.2014, 19:32

Bezüglich enum: Es ist nur entfernt so etwas wie const. Es wird benutzt, wenn man logisch zusammenhängende Konstanten definieren möchte.

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

8

01.01.2014, 19:43

Enum kann man schon als Sammel-"constexpr" auffassen. Jedenfalls die alten C++03 Enums, die man aber ohnehin besser nicht mehr verwenden sollte.
Die neuen strongly typed Enumerations sind wohl kaum noch als gesammelte "constexpr" Werte aufzufassen.

Snowy

Frischling

  • »Snowy« ist der Autor dieses Themas

Beiträge: 54

Wohnort: Stuttgart

  • Private Nachricht senden

9

08.01.2014, 09:22

Sodelle,

hat bisschen länger gedauert da ich mich noch um ein paar andere Probleme gekümmert habe. Habe mich der Sache noch einmal angenommen und das Problem nun lösen können. Was mich allerdings irritiert ist, dass mein "logischerer" (korrigiert mich, wenn ich falsch liege) Versuch irgendwie nicht funktioniert hat. Daher würde ich gerne noch einmal euren Rat einfordern.

Derzeit habe ich es so gelöst:

C-/C++-Quelltext

1
2
cin.ignore();
cin.get (Player.Name, 29);


Sprich den Eingabebuffer komplett leeren und dann durch den Benutzer wieder füllen lassen. Da stellt sich mir gerade halt einwenig die Frage, ob das eine "gute" Lösung ist oder mehr an eine Notkonstruktion erinnert, die das Problem nur umschifft.

Ich hatte eigenlich gedacht, das es sich mit:

C-/C++-Quelltext

1
cin.getline (Player.Name, 29);


hätte lösen lassen müssen. Allerdings wurde bei dieser Variante die Eingabe des Namens übersprungen und das Array Player.Name[30] blieb einfach leer. Ich steig leider nicht dahinter, warum diese Lösung nicht funktioniert. Aber vielleicht habe ich mich auch komplett im Hirn daran aufgehangen und sehe den Wald vor lauter Bäumen nicht mehr.

Zusatz:
Ich habe bei meiner Suche im Internet ein schickes Merkblatt, zwecks Ein- und Ausgabe gefunden. Vielleicht hilft es dem ein oder anderen, der ähnliche Probleme damit hat weiter:

https://people.fh-landshut.de/~hpk/Cpp/Merkblatteinaus.pdf

Zwecks enum muss ich mich komplett noch mal schlau machen, da ich sogut wie nichts davon verstanden habe.

Besten Dank für die Antworten.

Gruß,
Snowy
return 0;

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

10

08.01.2014, 13:38

Bezüglich enum: Es ist nur entfernt so etwas wie const. Es wird benutzt, wenn man logisch zusammenhängende Konstanten definieren möchte.
Ich würde es eher so beschreiben, dass man einen Datentyp erschafft, der nur spezielle Werte annehmen kann und diese Werte auch separate Namen haben. Konstanten sind enums ja nicht.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige