Forum: PC-Programmierung Suche Hilfe bei dem Spiel Hangman in C++


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Mirko (mirkomikro)


Lesenswert?

Hallo,


if (user != troll) {

ich versuche mein erstes Spiel in C++ zu programmieren - Hangman. Hier 
der Link für Nicht-Kenner: https://en.wikipedia.org/wiki/Hangman_(game)

Im Groben ist mein Spiel spielbar...
Natürlich ist es noch nicht alles, nach meinen Wünschen entsprechend 
umgesetzt, aber das werde ich noch peu à peu integrieren, soweit es 
meine Fähigkeiten zulassen.


Nun zu meinem Problem, wobei ich nicht weiterkomme:

Beim Spiel Hangman wird ein Buchstabe in einem Wort gesucht und wenn es 
was findet, in irgend einer Form dargestellt, dass man weiß auf welcher 
Position es ist, wie bei Glücksrad (für die ältere Generation unter 
euch).

Mein Wunsch wäre z.B. so: Eingabe "e" -> e_e_ (lol die Formatierung 
spielt nicht mit)

Da ich mir nicht anders zu helfen wusste, habe ich das sehr rudimentär 
umgesetzt, da ich nicht weiß, wie ich den Wert von string.find so 
ausgeben kann, dass die Buchstaben so dargestellt werden und beim 
nächsten Erraten noch die neuen Buchstaben hinzugefügt werden.

Hat jemand für mich ein Tip oder ein Beispiel, das mir das aufschlüsseln 
kann?

Wäre sehr dankbar, Ihr würdet mir viele schlaflose Nächte ersparen... :D

1
/*
2
 * Hangman - The Game
3
 */ 
4
5
6
#include <iostream>
7
#include <string>
8
9
10
bool loop        = true;
11
int attempt        = 5;
12
std::string secretWord  = "concealed";
13
std::string guess;
14
15
16
// Won game
17
int won () {
18
  if (secretWord == guess) {
19
    loop = false;
20
    std::cout << "\nCongratulations, you have won!\n";
21
  }
22
  return 0;
23
}
24
25
26
// Lost Game
27
int lost () {
28
  if (attempt == 0) {
29
    loop = false;
30
    std::cout << "\nGame over!\n";
31
  }
32
  return 0;
33
}
34
35
36
// Exit Game
37
int exit () {
38
  if (guess == "exit") {
39
    loop = false;
40
    std::cout << "\nByebye!\n";
41
  }
42
  return 0;
43
}
44
45
46
// Notification
47
int notification () {
48
  std::cout << "Note your result on a paper!\n\n";
49
  return 0;
50
}
51
52
53
int main () {
54
55
  // Welcome Screen
56
  std::cout << "Hangman - The Game\n\n";
57
58
  while (loop) {
59
60
    // Input guess
61
    std::cout << "Attempt: " << attempt << "\n";
62
    std::cout << "Hint   : Secret\n";
63
    std::cout << "Rules  : Only write lower case letters or the secret word.\n";
64
    std::cout << "Guess  : ";
65
    std::cin >> guess;
66
67
    size_t found = secretWord.find (guess);
68
    if (found != std::string::npos) {
69
      // Do stuff if guess is valid
70
      if (guess == "c") {
71
        std::cout << "\nc**c*****\n";
72
        notification();
73
      }
74
      if (guess == "o") {
75
        std::cout << "\n*o*******\n";
76
        notification();
77
      }
78
      if (guess == "n") {
79
        std::cout << "\n**n******\n";
80
        notification();
81
      }
82
      if (guess == "e") {
83
        std::cout << "\n****e**e*\n";
84
        notification();
85
      }
86
      if (guess == "a") {
87
        std::cout << "\n*****a***\n";
88
        notification();
89
      }
90
      if (guess == "l") {
91
        std::cout << "\n******l**\n";
92
        notification();
93
      }
94
      if (guess == "d") {
95
        std::cout << "\n********d\n";
96
        notification();
97
      }
98
    }
99
    else {
100
      // Do stuff when guess is invalid
101
      std::cout << "\n";
102
      attempt--;
103
    }
104
105
    won();
106
    lost ();
107
    exit ();
108
    }
109
}

}


else {
 exit ()
}

: Bearbeitet durch User
von Micha (nichtgast)


Lesenswert?

Hi,

zuerst mal was anderes. Wenn du aus einer Funktion nichts zurückgeben 
willst, dann mach statt dem in ein void als Rückgabetyp. Alles andere 
ist verwirrend.

Code mag ich gar nicht liefern, du willst ja lernen.

du könntest einen weiteren String anlegen, der so viele '*' enthält, wie 
dein Suchwort.

string::find liefert dir die position des gesuchten chars zurück. Du 
kannst dann also hergehen und an der Position in deinem zusätzlichen 
String das '*' durch den passenden Buchstaben ersetzten.

Danach gibts du einfach immer nur deinen zweiten String aus. Der enthält 
dann automatisch mehr und mehr Buchstaben des Lösungswortes.


Grüße

: Bearbeitet durch User
von Roger S. (edge)


Angehängte Dateien:

Lesenswert?

Mirko schrieb:
> Hat jemand für mich ein Tip oder ein Beispiel, das mir das aufschlüsseln
> kann?

Hier ein quick&dirty refactoring das Deiner Anforderung entspricht.

Cheers.

von Mirko (mirkomikro)


Lesenswert?

Hallo,


und danke für die zwei unterschiedlichen Ansätze an Antworten.
Den Code habe ich mal überflogen, aber ohne Erklärung.... Mein Programm 
wurde auch geändert... was ich so eigentlich erstmal nicht wollte.

Deswegen tendiere ich zu ersterem...

Micha schrieb:
> Hi,
>
> zuerst mal was anderes. Wenn du aus einer Funktion nichts zurückgeben
> willst, dann mach statt dem in ein void als Rückgabetyp. Alles andere
> ist verwirrend.

Dadurch, dass ich etwas ändern musste, habe ich die Funktionen einfach 
rausgenommen, somit sollten die Verwirrungen entworren sein, 
hoffentlich.


Micha schrieb:
> du könntest einen weiteren String anlegen, der so viele '*' enthält, wie
> dein Suchwort.
>
> string::find liefert dir die position des gesuchten chars zurück. Du
> kannst dann also hergehen und an der Position in deinem zusätzlichen
> String das '*' durch den passenden Buchstaben ersetzten.
>
> Danach gibts du einfach immer nur deinen zweiten String aus. Der enthält
> dann automatisch mehr und mehr Buchstaben des Lösungswortes.

Ich habe den String hiddenWord angelegt und musste dann erstmal 
recherchieren wie der Befehl aussehen muss. Hab dann gemerkt, dass ich 
nur mit einem Char arbeiten konnte und musste somit meinen "Exit" 
rausschmeißen und hier und da etwas anpassen.
Nach einem kurzen Test bin ich auch zufrieden, aber jetzt habe ich das 
Problem, dass z.B. zwei gleiche Werte nicht erkannt werden, sondern nur 
der erste. Wie kann ich den ganzen String Buchstabe für Buchstabe 
überprüfen?

1
/*
2
 * Hangman - The Game
3
 */ 
4
5
6
#include <iostream>
7
#include <string>
8
9
10
char guess;
11
bool loop        = true;
12
int attempt        = 5;
13
std::string secretWord  = "concealed";
14
std::string hiddenWord  = "*********";
15
16
17
int main () {
18
19
  // Welcome Screen
20
  std::cout << "Hangman - The Game\n\n";
21
22
  while (loop) {
23
24
    // Input guess
25
    std::cout << "Attempts: " << attempt << "\n";
26
    std::cout << "Hint    : Secret\n";
27
    std::cout << "Rules   : Only write lower case letters.\n";
28
    std::cout << "Guess   : ";
29
    std::cin >> guess;
30
31
    size_t found = secretWord.find (guess);
32
    if (found != std::string::npos) {
33
      //Do stuff if guess is valid
34
      hiddenWord[found] = guess;
35
      std::cout << "\n" << hiddenWord << "\n\n";
36
    }
37
    else {
38
      //Do stuff when guess is invalid
39
      std::cout << "\n";
40
      attempt--;
41
    }
42
43
    if (secretWord == hiddenWord) {
44
      std::cout << "\nCongratulations, you have won!\n";
45
46
    }
47
48
    if (attempt == 0) {
49
      loop = false;
50
      std::cout << "\nGame over!\n";
51
    }
52
    }
53
}

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Mirko schrieb:
> Nach einem kurzen Test bin ich auch zufrieden, aber jetzt habe ich das
> Problem, dass z.B. zwei gleiche Werte nicht erkannt werden, sondern nur
> der erste.

Das ist ja auch nicht verwunderlich. Dein Aufruf von 
std::string:::find() gibt dir das erste Vorkommen des gesuchten 
Buchstaben. Die Funktion weiß ja nicht, dass der schon mal gefunden 
wurde und du diesmal das zweite Vorkommen suchst.

> Wie kann ich den ganzen String Buchstabe für Buchstabe überprüfen?

Eine Möglichkeit wäre, mit dem secretWord das umgekehrte zu machen wie 
mit dem hiddenWord, also alle gefundenen Buchstaben durch Sternchen 
ersetzen. Besteht das hiddenWord nur noch aus Sternchen, hat man 
gewonnen.

von Roger S. (edge)


Lesenswert?

Mirko schrieb:
> Nach einem kurzen Test bin ich auch zufrieden, aber jetzt habe ich das
> Problem, dass z.B. zwei gleiche Werte nicht erkannt werden, sondern nur
> der erste. Wie kann ich den ganzen String Buchstabe für Buchstabe
> überprüfen?

Mit einem simplen for-loop anstatt dem std::string::find()
1
for (size_t i = 0; i < secretWord.size(); i++) {
2
  if (secretWord[i] == guess) {
3
    // your sophisticated handling goes here (instead of printing)
4
    std::cout << "found at position: " << i << "\n";
5
  }
6
}

von Mirko (mirkomikro)


Lesenswert?

Roger S. schrieb:
> Mirko schrieb:
>> Nach einem kurzen Test bin ich auch zufrieden, aber jetzt habe ich das
>> Problem, dass z.B. zwei gleiche Werte nicht erkannt werden, sondern nur
>> der erste. Wie kann ich den ganzen String Buchstabe für Buchstabe
>> überprüfen?
>
> Mit einem simplen for-loop anstatt dem std::string::find()

Ha, genau das hab ich gesucht! Ich hab schon mit einer for Schleife 
experimentiert, aber es hat nicht so geklappt. Jetzt muss ich nur noch 
das Konstrukt darum ändern, aber ich denke das bekomme ich schon hin. 
Danke vielmals.

von Daniel A. (daniel-a)


Lesenswert?

Als nächstes, versuch es mal z.B. mit dem Wort "Bär".

von Tim S. (Firma: tsx89) (freak_ts) Benutzerseite


Lesenswert?

Mirko schrieb:
> if (user != troll) {
> }
> else {
> exit ()
> }
1
Undefined variable 'user', Undefined variable 'troll',
2
Syntaxerror at exit (), no-whitespace, need semicolon.
3
EOF.
Schade - Ich kann's nicht richtig ausführen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.