LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   perl newbie. hangman.cgi script displaying strangely (additional code) on the web. (http://www.linuxquestions.org/questions/programming-9/perl-newbie-hangman-cgi-script-displaying-strangely-additional-code-on-the-web-114854/)

WorldBuilder 11-11-2003 12:21 PM

perl newbie. hangman.cgi script displaying strangely (additional code) on the web.
 
Hi all,

I'm a newbie trying to learn perl and cgi. I have written a script which you can find here. There are several problems.[list=1][*]When you first arrive at that url, you'll notice that there is additional html-like code visible on the page, as well as an extra "New Game" button. Why are those visible?[*]You'll also notice that when you first arrive at that url, the game doesn't actually work. You can input letters, but nothing happens when you guess.[*]If you click one of the "New Game" buttons, though, it will THEN start a "working" game! Why doesn't it just do that from the get-go?[*]Even when a new game is started, you only get 9 tries for letters, not 10. Why?[*]When you complete a game (win or lose), it should flash text saying "Sorry (or Congratulations), you're word was 'whatever'. It does, but it also adds more of that html-like code there. Why?[*]The "letter-guessing" line is solid. How can I make it dashed, so that each dash represents a letter in the word?[*]If at that point you start a new game, the last letter you guessed on the previous game starts off as a newly-chosen letter for the new game. Why?[/list=1]
I think that's it for problems. Any ideas would be most appreciated! Thank you so much! Here's the code the the perl/cgi script:
Code:

#!/usr/bin/perl

use CGI ':standard';
use CGI::Carp 'fatalsToBrowser';
use Fcntl;
use SDBM_File;

$max_tries = 10;

%current = ( 'word'      => "evermeet",
            'tries_left' => "10",
            'letters'    => "",
            'revealed'  => "________",);

tie(%hash, 'SDBM_File', '/tmp/game_file.sdbm', O_CREAT|O_RDWR, 0666) || die $!;

&PrintHeader();

my $tries_left = $current{'tries_left'};
my @guessed_letters = split( //, $current{'letters'} );
my $secret_word = $current{'word'};
my $revealed_word = $current{'revealed'};
my $this_guess = "";
my $guessed_string = "";
my $found_letter = 0;

$this_guess = param('guess');
$found_letter = &GuessLetter($this_guess);

        if( $tries_left > 0 ) {
                if( ($current{'word'} eq $current{'revealed'}) && ($tries_left < $max_tries) )
                {
&PrintContent();
&win();
                }
        else {

        if( $found_letter == 0 ) {
            $tries_left--;
        }

        push(@guessed_letters, $this_guess );
        $guessed_string = join( "", @guessed_letters );

$current{'tries_left'} = $tries_left;
$current{'letters'} = $guessed_string;

&PrintContent();

$hash{$id} = $current{'word'}."~".$current{'tries_left'}."~".  $current{'letters'}."~".$current{'revealed'};

        }
        }
        else {
&PrintContent();
&lose();
        }

untie(%hash);

sub generate_gameid() {
    for ($j = 0; $j <= 9; $j++) {
        $id .= int(rand 9);
    }

    return $id;
}

sub win {
    my $the_cookie = cookie (  -name=>'gameid',
                              -value=>$id,
                              -expires=>'+1h');

    print header(-cookie=>$the_cookie),
    start_html("Hangman - Congratulations!"),
    "Congratulations, your word was:",
    h2($current{'word'}),
    start_form,
    submit (-name=>"new_game", -label=>"New Game"),
    end_form,
    end_html;
}

sub lose
{
    my $the_cookie = cookie (  -name=>'gameid',
                              -value=>$id,
                              -expires=>'+1h');

    print header(-cookie=>$the_cookie),
    start_html("Hangman - Sorry!"),
    "Sorry, your word was:",
    h2($current{'word'}),
    start_form, submit (-name=>"new_game", -label=>"New Game"),
    end_form,
    end_html;
}

sub PrintHeader() {
    my $the_cookie;
    my $saved_game;

    if(param('new_game')) {
        $id = &generate_gameid();
        $the_cookie = cookie (  -name=>'gameid',
                              -value=>$id,
                              -expires=>'+1h');
        &InitGame();
    }
    else {
        $id = cookie('gameid');
        $saved_game = $hash{$id};
        &LoadGame($saved_game);
    }

    print header(-cookie=>$the_cookie);
}

sub PrintContent() {
    print start_html(  -title=>"Hangman!",  -onLoad=>"document.forms[0].guess.select()"),
    h1("Hangman!"),
    h1($current{'revealed'}),
    "Tries Remaining: ",
    b($current{'tries_left'}),
    br,
    "Letters guessed so far: ",
    b(em(join " ", split //, $current{'letters'})),
    br,
    start_form,
    "Next Guess: ",
    textfield (  -name=>"guess",  -size=>5,  -maxlength=>1,  -default=>''),
    br, br,
    submit (-name=>"submit", -label=>"Guess"),
    submit (-name=>"new_game", -label=>"New Game"),
    end_form,
    end_html;
}

sub InitGame() {
    my $word = &FetchWord();

    $current{'word'} = $word;
    $current{'tries_left'} = $max_tries;
    $current{'letters'} = "";
    $current{'revealed'} = &MakeLines($word);
}

sub LoadGame() {
    my $foo = $_[0];
    my @saved_game = split(/~/,$foo);

    $current{'word'} = $saved_game[0];
    $current{'tries_left'} = $saved_game[1];
    $current{'letters'} = $saved_game[2];
    $current{'revealed'} = $saved_game[3];
}

sub FetchWord() {
    my $word = "superman";
    my @lines;
    my @words;

    my $line_count = 0;
    my $word_count = 0;

    my $rand_line = 0;
    my $rand_word = 0;

    open( DICTIONARY, "words.txt" ) or die "Cannot open file: $!\n";

    @lines = <DICTIONARY>;
    $line_count = @lines;

    $rand_line = int(rand $line_count);

    @words = split(/,/, $lines[$rand_line] );
    $word_count = @words;

    $rand_word = int(rand $word_count);

    $word = $words[$rand_word];
    chomp($word);

    close( DICTIONARY );

    return $word;
}

sub MakeLines() {
    my @word = split(//, $_[0]);
    my $letter = "";
    my $blanks = "";

    foreach $letter(@word) {
        $blanks .= "_";
    }

    return $blanks;
}

sub GuessLetter() {
    my $guess = $_[0];
    my @word = split(//,$current{'word'});
    my $letter = "";
    my @old_revealed = split(//,$current{'revealed'});
    my @new_revealed = @old_revealed;
    my $new_revealed_string = "";
    my $got_one = 0;
    my $count = 0;

    foreach $letter(@word) {
        if($guess eq $letter) {
            print LOG "Matched letter [$guess] at position [$count]\n";

            $new_revealed[$count] = $guess;
            $got_one = 1;
        }
        else {
            $new_revealed[$count] = $old_revealed[$count];
        }

        $count++;
    }

    $new_revealed_string = join("",@new_revealed);
    $current{'revealed'} = $new_revealed_string;

    return $got_one;
}

Again, I'm a newbie, so please be gentle! :eek: Thanks, guys!

Chris

WorldBuilder 11-11-2003 01:11 PM

Quote:

6. The "letter-guessing" line is solid. How can I make it dashed, so that each dash represents a letter in the word?
Nevermind... I figured out that one. Still pulling my hair out about the rest. Help! Thanks!

WorldBuilder 11-12-2003 06:13 PM

Hi again, guys...

Ok, I have fixed everything regarding this script, except for one final thing... When first visiting the site, it says:
"Sorry, your word was:"
New Game button

If I then press the "New Game" button, that game starts and works fine.

I don't understand why it doesn't go directly to a new, working game. Can anyone help me with that? I've been pulling my hair out for a while on this one. URL is http://www.bartlett-family.net/cgi-bin/hangman2.cgi
New code:
Code:

#!/usr/bin/perl

use CGI ':standard';
use CGI::Carp 'fatalsToBrowser';
use Fcntl;
use SDBM_File;

$max_tries = 10;

%current = ('tries_left' => 10, 'letters' => '', 'revealed' => '________');

tie(%hash, 'SDBM_File', '/tmp/game_file.sdbm', O_CREAT|O_RDWR, 0666) || die $!;

&PrintHeader();

my $tries_left = $current{'tries_left'};
my @guessed_letters = split( //, $current{'letters'} );
my $secret_word = $current{'word'};
my $revealed_word = $current{'revealed'};
my $this_guess = 0;
my $guessed_string = "";
my $found_letter = 0;

$this_guess = param('guess');
$found_letter = &GuessLetter($this_guess);

if( $tries_left-1 > 0) {

  if( ($current{'word'} eq $current{'revealed'}) && ($tries_left <= $max_tries) ) {
      #&PrintContent();
      &win();
  }
  else {
      if( $found_letter == 0 && $this_guess) {
        $tries_left--;
      }

      push(@guessed_letters, $this_guess);
      $guessed_string = join( "", @guessed_letters);

      $current{'tries_left'} = $tries_left;
      $current{'letters'} = $guessed_string;

      &PrintContent();

      $hash{$id} = $current{'word'}."~".$current{'tries_left'}."~". $current{'letters'}."~".$current{'revealed'};
  }
}
else {
  #&PrintContent();
  &lose();
}

untie(%hash);
exit(0);

sub generate_gameid() {
  for ($j = 0; $j <= 9; $j++) {
      $id .= int(rand 9);
  }
  return $id;
}

sub win {
  #my $the_cookie = cookie ( -name=>'gameid',
  #                          -value=>$id,
  #                          -expires=>'+1h');

  #print header(-cookie=>$the_cookie),
  print start_html("Hangman - Congratulations!"),
  "Congratulations, your word was:",
  h2($current{'word'}),
  start_form,
  submit (-name=>"new_game", -label=>"New Game"),
  end_form,
  end_html;
}

sub lose {
  #my $the_cookie = cookie ( -name=>'gameid',
  #                          -value=>$id,
  #                          -expires=>'+1h');

  #print header(-cookie=>$the_cookie),
  print start_html("Hangman - Sorry!"),
  "Sorry, your word was:",
  h2($current{'word'}),
  start_form, submit (-name=>"new_game", -label=>"New Game"),
  end_form,
  end_html;
}

sub PrintHeader {
  my $the_cookie;
  my $saved_game;

  if(param('new_game')) {
      $id = &generate_gameid();
      $the_cookie = cookie ( -name=>'gameid',
                            -value=>$id,
                            -expires=>'+1h');
  &InitGame();
  }
  else {
      $id = cookie('gameid');
      $saved_game = $hash{$id};
      &LoadGame($saved_game);
  }
  print header(-cookie=>$the_cookie);
}

sub PrintContent {
  print start_html( -title=>"Hangman!", -onLoad=>"document.forms[0].guess.select()"),
  h1("Hangman!"),
  h1({-style=>'letter-spacing:5px'},$current{'revealed'}),
  "Tries Remaining: ",
  b($current{'tries_left'}),
  br,
  "Letters guessed so far: ",
  b(em(join " ", split //, $current{'letters'})),
  br,
  start_form,
  "Next Guess: ",
  textfield ( -name=>'guess', -size=>5, -maxlength=>1, -default=>'', override=>1),
  submit (-name=>'submit', -label=>'Guess'),br,br,
  submit (-name=>'new_game', -label=>'New Game'),
  end_form,
  end_html;
}

sub InitGame {
  my $word = &FetchWord();
  $current{'word'} = $word;
  $current{'tries_left'} = $max_tries;
  $current{'letters'} = "";
  $current{'revealed'} = &MakeLines($word);
}

sub LoadGame {
  my $foo = $_[0];
  my @saved_game = split(/~/,$foo);
  $current{'word'} = $saved_game[0];
  $current{'tries_left'} = $saved_game[1];
  $current{'letters'} = $saved_game[2];
  $current{'revealed'} = $saved_game[3];
}

sub FetchWord {
  #my $word = "superman";
  my @lines;
  my @words;
  my $line_count = 0;
  my $word_count = 0;
  my $rand_line = 0;
  my $rand_word = 0;
  open( DICTIONARY, "words.txt" ) or die "Cannot open file: $!\n";
  @lines = <DICTIONARY>;
  close( DICTIONARY );
  $line_count = @lines;
  $rand_line = int(rand $line_count);
  @words = split(/,/, $lines[$rand_line] );
  $word_count = @words;
  $rand_word = int(rand $word_count);
  $word = $words[$rand_word];
  chomp($word);
  return $word;
}

sub MakeLines {
  my $blanks;
  $blanks .= "_" for (1..length($_[0]));
  return $blanks;
}

sub GuessLetter {
  my $guess = $_[0];
  my @word = split(//,$current{'word'});
  my $letter = "";
  my @old_revealed = split(//,$current{'revealed'});
  my @new_revealed = @old_revealed;
  my $new_revealed_string = "";
  my $got_one = 0;
  my $count = 0;

  foreach $letter(@word) {
      if(lc($guess) eq lc($letter)) {
        #print LOG "Matched letter [$guess] at position [$count]\n";
        $new_revealed[$count] = $guess;
        $got_one = 1;
      }
#      else {
#        $new_revealed[$count] = $old_revealed[$count];
#      }
      $count++;
  }

  $new_revealed_string = join("",@new_revealed);
  $current{'revealed'} = $new_revealed_string;

  return $got_one;
}

Thanks in advance!

Chris

8nasmith 11-21-2003 05:12 AM

my god whats that all about i have trouble just loading linux never mind programming it

WorldBuilder 11-21-2003 07:09 AM

lol, yeah. It can take a while to get used to. I got the script working... Even added a scoring feature.

Chris


All times are GMT -5. The time now is 11:42 AM.