friar tux has asked for the wisdom of the Perl Monks concerning the following question:

hi, I am trying to save the first variable in a random number generator for comparison against later numbers generated my problem is it won't retain the first number it generates can some one tell me why? here is the script index.html

<html> <center> <img src=./pix/submit.jpg> <hr> <form action=/cgi-bin/dice.cgi method=post> <a href= cgi-bin/dice.cgi?roll=1 >roll the dice</a> </center> </html>

then it goes to the dice.cgi script

#! /usr/bin/perl use CGI ':standard'; print "Content-type:html\n\n"; $dice1= int (rand(6)+1); $dice2= int (rand(6)+1); $match = param('match'); $roll = param ('roll'); print "<img src=http://localhost/pix/die$dice1.gif>"; print "<img src=http://localhost/pix/die$dice2.gif>"; if ($roll== 1) { } $rolla = $dice1 ; $rollb = $dice2 ; $total= $dice1+$dice2; print "$rolla"; print "$rollb"; print "$total"; if ($total ==7) { print "lucky seven"; print "<a href= http://localhost/>play again</a>" ; exit() } elsif ($total ==11) { print "eleven wins"; print "<a href= http://localhost/>play again</a>" ; exit() }elsif ($total ==2) { print "snake eyes"; print "<a href= http://localhost/>play again</a>" ; exit() }elsif ($total ==12) { print "double six"; print "<a href= http://localhost/>play again</a>" ; exit() } print "<a href= dice.cgi>roll again</a>"

I know I can write it to an outside text file but that doesn't seem efficient any ideas on how to retain the two $dice numbers for the first roll then compare them after to each roll after?

Replies are listed 'Best First'.
Re: saving a random number while generating a new one
by JavaFan (Canon) on Mar 30, 2011 at 14:15 UTC
    Have the CGI program create the link as well, and it can pass the previous roll as a parameter.

    Note that this isn't really a Perl question, you'd have a similar problem (and solution) if you had programmed this in C, Python, Java or some other language.

Re: saving a random number while generating a new one
by jethro (Monsignor) on Mar 30, 2011 at 14:19 UTC

    HTML is a stateless protocol. Usually you need external storage to remember anything. In your case I think there is a simple solution though. You can store the values in the link. Use something like print "<a href=\"dice.cgi?rolla=$rolla:rollb=$rollb\">roll again</a>". Check out the CGI documentation how you can access the parameter list

      I tried to carry over with the link like you suggested but it doesn't seem to work it still replaces the numbers for some reason.thanx tho it puts me on the right track

Re: saving a random number while generating a new one
by Sinistral (Monsignor) on Mar 30, 2011 at 14:38 UTC

    What you're encountering is a fundamental misunderstanding of how CGI scripts work. When your user is interacting with your HTML page and CGI script, here's what's happening:

    1. User's browser requests index.html, receives the HTML, and renders it on their local computer
    2. User clicks the roll the dice link, which sends another request for dice.cgi
    3. The web server receives the request for dice.cgi, knows that it is a script, and runs Perl to produce the output
    4. The web server collects the output from your script (the print in your Perl code) and sends it out the network connection to the user's browser
    5. The user's browser receives the HTML output by your Perl code and renders that

    Note that your script is running again and again as if it had never run before. It has no state, and the code you've shown has no way of retaining state. As you mention, you can use a file to save previous runs. As an alternative, what you might do is to use CGI::Session to have a session for the user that retains all the runs that they've made. If you don't want something that heavy, then you could use DBI along with DBD::SQLite to have a SQLite database (which is a flat file, ultimately) for your data storage. If you don't want DBD::SQLite, you could use a full blown database engine such as DBD::mysql or DBD::Pg.

    Based on your code, it seems that you are not yet familiar with HTML/CGI idioms or syntax, so I would actually pursue a simple text file (Perl excels at reading and parsing simple text files) as your data collection mechanism

      Good responses, and since it hasn't been mentioned and (though it's a pain) you can also pass state data along using "hidden" parameters (if you've got a form/submit), and/or using cookies. Of course there are security issues with some of these approaches.
Re: saving a random number while generating a new one
by locked_user sundialsvc4 (Abbot) on Mar 30, 2011 at 18:07 UTC

    One good way to handle things like this is to generate a small “pool” of random values which is then stored in the session-state.   Numbers are withdrawn from the pool until it is empty, at which time it is reloaded.   This may also enable you to recall the random numbers that were previously issued.   And, they are, indeed, (pseudo-)random.

Re: saving a random number while generating a new one
by fidesachates (Monk) on Mar 30, 2011 at 14:51 UTC
    You have some good suggestions and explanations already from my fellow monks. I just want to suggest that the easiest solution is probably javafan's regarding the link. To be more detailed with it, use the GET method of posting and retrieving data. The downside is that anyone can change the number by changing their url.

    The better, but slightly harder solution is to use sessions.