Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Simple hangman game

Status
Not open for further replies.

sulfericacid

Programmer
Aug 15, 2001
244
0
0
US
I was wondering if you could help me figure out what's wrong with the script below. I can't get it to the point where they guess a 2nd time and get another valid character right, it adds it to $known. It's only doing one s/// which is the latest one instead of all of them.

Ie:
Secret word is "apple"
User searches A for first letter and it prints "a****"
User searches again for P and it prints "*pp**" instead of "app**.




#!/usr/bin/perl -w

use strict;

my $info = "an apple aaron";

my $guess = 0;
until ($guess eq $info) {


print "Guess character: ";
$guess = <STDIN>;
$guess =~ s/$guess/$guess /;



my $known = $info;
$known =~ s/[^$guess]/\*/g;
my $knownadd = $known; # save $known to prevent variable overwriting
# so we can add more correct guesses later
$knownadd =~ s/[^$guess]/\*/g;


print &quot;$info\n&quot;;

print &quot;$known\n&quot;;
print &quot;$knownadd\n&quot;;
}

&quot;Age is nothing more than an inaccurate number bestowed upon each of us at birth as just another means for others to judge and classify us- sulfericacid
 
this works...

$string = 'an apple aaron';

$length = length($string)-1;

$guessed = $string;

while ($guessed =~ /[^ |*]/) {

print &quot;guess a letter: &quot;;

$letter = <STDIN>;

chomp $letter;

$guessed =~ s/$letter/*/g;

for ($x=0; $x<=$length; $x++) {
if (substr($guessed, $x, 1) eq &quot;*&quot;) {
print substr($string, $x, 1);
}
else {
print &quot;*&quot; unless (substr($string, $x, 1) eq &quot; &quot;);
print &quot; &quot; if (substr($string, $x, 1) eq &quot; &quot;);
}
}

print &quot;\n&quot;;

}

print &quot;GUESSED CORRECTLY!\n&quot;;


regards
Duncan
 
Thanks so much for your help and for the script! I tested it and it works great! I can't really use it though, there are way too many things in it I don't understand and I didn't want a complete rewrite (wanted to be able to say &quot;hey look what I made!&quot;) :). I will surely use this as a reference for ideas though.

Thanks again!

&quot;Age is nothing more than an inaccurate number bestowed upon each of us at birth as just another means for others to judge and classify us- sulfericacid
 
thanks for your comments - i'll type some comments tomorrow next to script

Dunc
 
Here is another way that you could do it. Maybe it is less confusing.

Dunc, what do you think of this?:

$word = &quot;hangman&quot;;
$length = length($word);
$mask = &quot;*&quot; x $length; #use string repetition operator to construct a mask

while ($correct < $length) {
print &quot;$mask\n&quot;;
&choose;
if ($word =~ /$guessed/) {
while ($word =~ m/$guessed/g) {
substr($mask,(pos $word)-1,1,$guessed);
$correct += 1;
}
pos = 0;
}
}
print &quot;$word\n&quot;;

sub choose {
print &quot;\nPlease guess a letter: &quot;;
chomp($guessed = <stdin>);
}



All of the real work is done here:

while ($word =~ m/$guessed/g) {
substr($mask,(pos $word)-1,1,$guessed);
$correct += 1;
}
pos = 0;

After a letter is guessed, a while loop is entered that matches each instance of the guessed letter. Once an instance is found, the while loop repeats itself. However, this construct makes use of the pos() function to return the position+1 of each found instance so that it will know where to start looking in the string again (avoids repetitively finding the same instance). The use of pos allows you to work through the entire work gathering the position of each element.

As each element is found, I used &quot;substr&quot; to substitute the the appropriate &quot;*&quot; with the guessed letter (using pos() to tell the &quot;substr&quot; function where to stick the guessed letter into $mask).
 
hi raklet

It's better than my code!

But... it doesn't work with spaces - there should not be stars where there are spaces

e.g. $word = &quot;an apple aaron&quot;; would give **************

I wrote my code to take care of this - which caused me the biggest headache!

Fair comment?

Regards
Duncan
 
Absolutely fair!

Forgot all about multi words. Here is the mod to fix that. Thanks for the tip.

$word = &quot;an apple aaron&quot;;
while ($word =~ /[\w]/g) { $length++; }
$mask = $word;
$mask =~ s/[\w]/\*/ig;

$correct = 0;

while ($correct < $length) {
print &quot;$mask\n&quot;;
&choose;
if ($word =~ /$guessed/) {
while ($word =~ m/$guessed/g) {
substr($mask,(pos $word)-1,1,$guessed);
$correct += 1;
}
pos = undef;
}
}
print &quot;$word\n&quot;;

sub choose {
print &quot;\nPlease guess a letter: &quot;;
chomp($guessed = <stdin>);
}

Cheers
 
works much better - but quite by accident I guessed 'a' three times - and it acted as if I had guessed all the letters correctly?

I can't see how?

Try 3 guesses of 'a'...

Duncan
 
Sorry, I didn't put any of the error checking in.

The fun exercise for me has been figuring out how to find the position of a character in one string and replace it into the same position in another string.

I didn't know how to do this when the first post came in. Duncan provided an excellent example of how to solve the problem, but I was intrigued and wondered if there was another way. So, I did some looking and found the pos() function.

Anyway, here is the amended code with error checking. You shouldn't be able to guess three &quot;a&quot;s anymore and then have the script give you the answer.

$word = &quot;an apple aaron&quot;;
while ($word =~ /[\w]/g) { $length++; }
$mask = $word;
$mask =~ s/[\w]/\*/ig;
$correct = 0;

while ($correct < $length) {
print &quot;$mask\n&quot;;
&choose;
if ($learned{&quot;$guessed&quot;}) {
print &quot;You already chose that letter.\n\n&quot;;
next;
} else {
$learned{&quot;$guessed&quot;} += 1;
if ($word =~ /$guessed/) {
while ($word =~ m/$guessed/g) {
substr($mask,(pos $word)-1,1,$guessed);
$correct += 1;
}
pos = undef;
} else {
print &quot;Incorrect\n\n&quot;;
next;
}
}
}
print &quot;$word\n&quot;;

sub choose {
print &quot;\nPlease guess a letter: &quot;;
chomp($guessed = <stdin>);
}
 
raklet I can't believe I provide any excellent scripting examples but I am very appreciative of your comments!

thank you

Duncan
 
But you do. I have learned many things from your posts and others have stimulated me to go out and take on bigger challenges.

You are much too modest. Its probably why you are so well liked in this forum. Nice guy - good programmer.
 
raklet

I really am very grateful for your comments. I honestly look at all of the posts to this forum and feel that my answers are just mediocre in contrast to others like yourself. It really is quite a buzz when you can tell that you have genuinely helped someone, and I enjoy that very much. I definitely steer away from some of the more awkward questions as I realise that I have not got a clue how to help! But i'll keep trying.

In all honesty I think I lack confidence - I really hope to be able to get a job using Perl in the future as I enjoy it very much. It's just when I am looking around for jobs they seem to want people who know Perl inside out - and that's not me!

This forum is great as it throws so many diverse problems at you which keeps you on your toes and that is just what I need to gain the confidence I lack!

Thanks again
Duncan
 
Sulfericacid,

Sorry we kind of took over your little project. Didn't mean to spoil the fun by providing all the code. It is hard to know how much or how little information people are actually looking for when they post.

If you still want to attempt this (in a different way that we have provided), you might want to have a look at the index() function. It is used to tell you how many characters are skipped before the specified character or string is found in a variable. Combine the use of index() with substr() and anything else you can dream up and you can do it.

I got carried away with this thread and went on to create a complete hangman (very simple) that randomly chooses a word from a text file and then lets you guess it. It even has a little ascii gallows that show you how much of your criminal is hung. It shows what letters you have guessed and displays status messages about your guesses. If anyone is interested in playing with it, just copy and paste the code. You will have to create your own text file with words in it. I found one on the net that has one word per line. I just open a filehandle to that file to look for words.


Anyway, here is the code. Questions, criticism, comments welcome.

format HANGMAN =

___
| |
@ | Guessed letters: @<<<<<<<<<<<<<<<<<<<<<<<<<<
$hang[0], $chosen
@@@ | Word: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$hang[1], $hang[2], $hang[3], $mask
@ @ | Status: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$hang[4], $hang[5], $message
|
-----------
.

@body = qw (O \\ | / / \\);

open (DICT, &quot;c:/temp/hangmanwords.txt&quot;);
chomp(@array = <DICT>);
close (DICT);

srand();
$rval = rand(@array);

$word = $array[$rval];
while ($word =~ /[\w]/g) { $length++; }
$mask = $word;
$mask =~ s/[\w]/\*/ig;
$correct = 0;

while ($correct < $length) {
system(&quot;cls&quot;);
$~ = HANGMAN;
write;
if ($i == 6) { print &quot;Sorry you are hung! The word was $word.&quot;; exit; }
&choose;
if ($learned{&quot;$guessed&quot;}) {
$message = &quot;You already chose that letter&quot;;
next;
} else {
$learned{&quot;$guessed&quot;} += 1;
$chosen .= $guessed;
if ($word =~ /$guessed/) {
$message = &quot;Good guess&quot;;
while ($word =~ m/$guessed/g) {
substr($mask,(pos $word)-1,1,$guessed);
$correct += 1;
}
pos = undef;
} else {
push (@hang, shift(@body));
$i++;
$message = &quot;That is incorrect&quot;;
next;
}
}
}
system(&quot;cls&quot;);
$mask = $word;
$message = &quot;Congratulations. You guessed it!&quot;;
write;

sub choose {
print &quot;\nPlease guess a letter: &quot;;
chomp($guessed = <stdin>);
return $guessed;
}

 
It happens every once in a while where you describe a project and a person or two takes it upon themselves to do the entire thing. I admit it does take the fun out of doing it, I personally don't want to have a script I can't call my own-- own in which I built from the grounds up. With that aside, I reviewed your codes (haven't tested any of them) but I don't understand them enough to continue with this project right now.

As you can see from my code I started when I made this board, all my programs are written using very basic codes. It might not be the quickest or shortest way to do things but it makes it easier for me to understand (and since all my scripts are open source for free at it makes it easier for other people to understand too).

I thank all of you for your efforts with this but I have to find a different project to work on.

sulfericacid

&quot;Age is nothing more than an inaccurate number bestowed upon each of us at birth as just another means for others to judge and classify us- sulfericacid
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top