?
Solved

pascal programming question computer game

Posted on 1999-11-17
9
Medium Priority
?
245 Views
Last Modified: 2010-04-16
my mum saids that i need to learn programming, so i started an evening course but the teacher is not very good. i cant understand him.i am trying to work out a problem in my exercise book THIS IS NOT HOMEWORK. it involves random numbers please help me with this.
I want to write a computer game called paper, sissors. stone.
the computer picks a random  one of paper, sissors, or stone without telling the user which it has chosen. asks the user one of these by entering a suitable number. The winner is decided as follows

paper beats stone (because paper wraps stone)
Scissors beats paper (because scissors cuts paper)
Stone beats scissors (because stone blunts scissors)
  The user has to enter a number that the program puts on the screen for example 1=paper,2 =scissors 3=stone

If both chose the same, it's a draw. After each round the computer declares who has won and why, and offers the user another round. if the user does not want to play again the computer displays the final score of the games played, won, lost and drawn together with a 'goodbye' message.
I WOULD VERY MUCH APPRECIATE YOUR HELP IN SOLVING THIS PROBLEM

SAMZMAN
0
Comment
Question by:samzman
  • 9
9 Comments
 
LVL 1

Expert Comment

by:nrico
ID: 2216946
This oughtn't be hard :-). Pascal, eh?
I'm gonna try to use a "TOP-DOWN" programming method. The problem is, I never use a "method". I just sit down and code. Anyway, that's how you SHOULDN'T do it :-)

Let's see:

First, we need to make a loop the program runs in, only stopping at a certain command from the user. That'd obviously be a
  Repeat
    <Game>
  Until <User wants to quit>
or a
  While <User not quitting> Do
  Begin
    <Game>
  End;
Since, I guess, the first one is easier, we'll do a Repeat...Until loop.

For reading ease, we'll put the game in a separate function (you have had "Procedures and Functions", haven't you?), which returns "True" if the user wants to quit and "False" if he doesn't.
Since we don't want to make things too complicated, we'll introduce a variable to hold the users response.
The main procedure now looks a bit like this (PlayGame is the function that plays the game):

Var
  UserQuit:Boolean;

Begin
  Repeat
    UserQuit:=PlayGame;
  Until UserQuit;
  <Display ending message>
End.

| Note that you could also write
| Repeat Until PlayGame;,
| it's the same thing. (It just doesn't
| sound very logical :-).

Now that we've got that settled, I'm gonna submit this block of text and create a new one.
0
 
LVL 1

Expert Comment

by:nrico
ID: 2217005
Back for more? ;-)

We're gonna describe the PlayGame function, but first, we need some extra variables to hold things like:

Var
  GamesWon,GamesLost,GamesDrawn,
  UserChose,ComputerChose:Integer;
 
I hope the names of these variables are obvious...

Okay, the computer needs to choose a random number (Scissors, paper or stone). The function Random(X) returns a random number between 0 and X-1, so obviously, if we want a number from 1 to X, we add 1 to it. The code would be something like:
  ComputerChose:=Random(3)+1;
Which would net "ComputerChose" a random value from 1 to 3.
Except that it ISN'T RANDOM AT ALL! Every time you run the program, you'll notice the numbers are always the same. That's because a computer CAN'T PRODUCE TRULY RANDOM NUMBERS! It just repeats a series of seemingly random numbers from 0..1 every time you call the procedure, and multiplies that by X.

To counter this problem, we set the "pointer" that points to the first number the computer will return to another value. If we determine this pointer by using the system clock, we'll have other numbers each time we run the program (You can't possibly run two programs at the exact same time... Well, not DOS programs anyway).

We do this using the procedure "Randomize", which only needs to be called once. We put this in our main program, and we get something that looks like this:

Var
  UserQuit:Boolean;
  GamesWon,GamesLost,GamesDrawn,
  UserChose,ComputerChose:Integer;

Begin
  Randomize;
  Repeat
    UserQuit:=PlayGame;
  Until UserQuit;
  WriteLn('*********************************');
  WriteLn(' You have won '+GamesWon+' times');
  WriteLn(' You have lost '+GamesLost+' times');
  WriteLn(' The game ended in a draw '+GamesDrawn+' times');
  WriteLn('*********************************');
  WriteLn;
  WriteLn('Thank you for playing and see you next time!');
End.

| You'll see that we have added some status messages
| at the end and a "good-bye" phrase.
| The status message is (of course) composed of
| some text and the values of GamesWon, GamesLost and
| GamesDrawn, which will be filled in our game
| function.

Still not a problem? Let's move along!
0
 
LVL 1

Expert Comment

by:nrico
ID: 2217061
Okay, finally we're getting to the "PlayGame" function.

Right now, we have this:

Function PlayGame:Boolean;
Begin
  ComputerChose:=Random(3)+1;
End;

Now the user gets to take his pick. We write a line indicating that he may choose something:

WriteLn('Take your pick:');
WriteLn('1=Scissors  2=Paper  3=Stone');

That's easy. Now, to read the users input. We *could* simply read it in through a ReadLn, but it's often better (and nicer) to simply react to the first character he enters. Reading one character at a time is done by the function "ReadKey", which returns a character. The character type in Pascal is called a "Char", so we need another variable:

Var
  Character:Char;
But I most often use
  Ch:Char;
'cuz it's less typework ;-)!
Now, we don't want to let the user enter things that are not valid, so we need another loop that only proceeds once the user gives valid input.

  Repeat
    Ch:=ReadKey;
  Until <Ch is in '1','2' or '3'>.

We _could_ combine a lot of "If" conditions there, which would look a terrible lot like this:

 (((Ch='1') Or (Ch='2')) Or Ch='3')

It's cleaner to use a set. With a set, we can check if Byte or Char values are within a certain collection. Using a set, we can simply do this:
 
  Repeat
    Ch:=ReadKey;
  Until Ch In ['1','2','3'];

Looks a lot better, doesn't it?
Well now, we can compare....

Oops! The computer select is a number, the user select is a char. We can't really compare those! Luckily, we now the ASCII code of the character '1' (It's 49). If '1' is 49, and '2' is 50, and '3' is 51... See it? We get the asci code, and simply subtract 48 from it: Presto, we got the value!

  UserChose:=Asc(Ch)-48;

(If you don't know what ASCII is, ask your teacher. I can't really explain it :-(. Okay, it's a system where every character also has a number)

What's our code 'till now (yep, you guessed it, another block of code!):

Var
  UserQuit:Boolean;
  GamesWon,GamesLost,GamesDrawn,
  UserChose,ComputerChose:Integer;
  Ch:Char

Function PlayGame:Boolean;
Begin
  ComputerChose:=Random(3)+1;
  WriteLn('Take your pick:');
  WriteLn('1=Scissors  2=Paper  3=Stone');
  Repeat
    Ch:=ReadKey;
  Until Ch In ['1','2','3'];
  UserChose:=Asc(Ch)-48;
End;

Begin
  Randomize;
  Repeat
    UserQuit:=PlayGame;
  Until UserQuit;
  WriteLn('*********************************');
  WriteLn(' You have won '+GamesWon+' times');
  WriteLn(' You have lost '+GamesLost+' times');
  WriteLn(' The game ended in a draw '+GamesDrawn+' times');
  WriteLn('*********************************');
  WriteLn;
  WriteLn('Thank you for playing and see you next time!');
End.
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
LVL 1

Expert Comment

by:nrico
ID: 2217140
Now comes the hardest part, comparing the two values. For reading (and typing) ease, we'll introduce another function for that:

Function WhichWins(Val1,Val2):Integer;
Begin
End;

This function will return 1 if "Val1" wins, 2 if "Val2" wins and 0 if neither wins. The first part is easy: If both are the same, the game obviously ends in a draw:

If Val1=Val2 Then WhichWins:=0;

We don't need to check for that anymore.
From this point, it just gets plain old ugly in many, many combined "if" statements. (If I make an error in this, please be forgiving. Normally, I have a compiler handy to correct my mistakes)
So here we go:

If Val1=Val2 Then WhichWins:=0
Else
If Val1=1 Then
Begin { Scissors(1) }
  If Val2=2 Then
    WhichWins:=1 { Scissors(1) beats Paper(2) }
  Else
    WhichWins:=2; { Stone(3) beats Scissors(1) }
End Else
If Val1=2 Then
Begin { Paper(2) }
  If Val2=1 Then
    WhichWins:=2 { Scissors(1) beats Paper(2) }
  Else
    WhichWins:=1 { Paper(2) beats Stone(3) }
End Else
Begin { Stone(3) }
  If Val2=1 Then
    WhichWins:=1 { Stone(3) beats Scissors(1) }
  Else
    WhichWins:=2 { Paper(2) beats Stone(3) }
End;

I hope I got everything right... :-)

| Note that, after the first check inside the
| Begin...End parts, we don't check anymore,
| because if Val2 isn't Val1, and it isn't the one
| we've already checked for, it must be the remaining
| one!

Now that we've got that running, let's get back to our PlayGame function:

For local storing of the result of a round, we introduce
Var
  RoundResult:Integer;
0 means draw, 1 means computer wins, 2 means player wins;

And we add this:

  RoundResult:=WhichWins(ComputerChose,UserChose);

To let the computer tell what he had, we want a constant array with strings (You could use "if" statements again, but this is more elegant).

Const
  Names:Array[1..3] Of String=('Scissors','Paper','Stone');

Now we can report the result:

WriteLn('I had '+Names[ComputerChose]);
If RoundResult=0 Then
Begin
  WriteLn('It''s a draw!');
  Inc(GamesDrawn)
End Else
If RoundResult=1 Then
Begin
  WriteLn('I won!');
  Inc(GamesLost)
End Else
Begin
  WriteLn('You won!');
  Inc(GamesWon);
End;

| We use the number the computer chose as an
| index in the array with strings. That's easy!
| And "inc" simply INCreases a number. Duh!

Then, simply ask for play again (we can use Ch again...)

WriteLn('Play again? (Y/N');
Repeat
  Ch:=UpCase(ReadKey);
Until Ch In ['Y','N'];
If Ch='Y' Then PlayGame:=False Else PlayGame:=True;

| Remember that PlayGame needed to return a
| "play again?" - answer?

Now, I think we have it all covered. So here comes the final code:
0
 
LVL 1

Accepted Solution

by:
nrico earned 100 total points
ID: 2217150
Var
  UserQuit:Boolean;
  GamesWon,GamesLost,GamesDrawn,
  UserChose,ComputerChose:Integer;
  Ch:Char

Function WhichWins(Val1,Val2:Integer):Integer;
Begin
If Val1=Val2 Then WhichWins:=0
Else
If Val1=1 Then
Begin { Scissors(1) }
  If Val2=2 Then
    WhichWins:=1 { Scissors(1) beats Paper(2) }
  Else
    WhichWins:=2; { Stone(3) beats Scissors(1) }
End Else
If Val1=2 Then
Begin { Paper(2) }
  If Val2=1 Then
    WhichWins:=2 { Scissors(1) beats Paper(2) }
  Else
    WhichWins:=1 { Paper(2) beats Stone(3) }
End Else
Begin { Stone(3) }
  If Val2=1 Then
    WhichWins:=1 { Stone(3) beats Scissors(1) }
  Else
    WhichWins:=2 { Paper(2) beats Stone(3) }
End;
End;

Function PlayGame:Boolean;
Begin
  ComputerChose:=Random(3)+1;
  WriteLn('Take your pick:');
  WriteLn('1=Scissors  2=Paper  3=Stone');
  Repeat
    Ch:=ReadKey;
  Until Ch In ['1','2','3'];
  UserChose:=Asc(Ch)-48;
  WriteLn;
  WriteLn('I had '+Names[ComputerChose]);
  If RoundResult=0 Then
  Begin
    WriteLn('It''s a draw!');
    Inc(GamesDrawn)
  End Else
  If RoundResult=1 Then
  Begin
    WriteLn('I won!');
    Inc(GamesLost)
  End Else
  Begin
    WriteLn('You won!');
    Inc(GamesWon);
  End;
  WriteLn;
  WriteLn('Play again? (Y/N');
  Repeat
    Ch:=UpCase(ReadKey);
  Until Ch In ['Y','N'];
  If Ch='Y' Then PlayGame:=False Else PlayGame:=True;
End;

Begin
  Randomize;
  Repeat
    UserQuit:=PlayGame;
  Until UserQuit;
  WriteLn('*********************************');
  WriteLn(' You have won '+GamesWon+' times');
  WriteLn(' You have lost '+GamesLost+' times');
  WriteLn(' The game ended in a draw '+GamesDrawn+' times');
  WriteLn('*********************************');
  WriteLn;
  WriteLn('Thank you for playing and see you next time!');
End.

| Good luck with it! If you have any questions, please post them!
0
 
LVL 1

Expert Comment

by:nrico
ID: 2217155
Oops!!!
I forgot the line
  RoundResult:=WhichWins(ComputerChose,UserChose);

in the PlayGame function.
Sorry :-)
0
 
LVL 1

Expert Comment

by:nrico
ID: 2229237
?? Are you actually going to evaluate this :-) ??
0
 
LVL 1

Expert Comment

by:nrico
ID: 2268446
Helllooooooooooooooooooooo???
0
 
LVL 1

Expert Comment

by:nrico
ID: 2271474
I don't think you remember your asked this question, do you?
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article will show how Aten was able to supply easy management and control for Artear's video walls and wide range display configurations of their newsroom.
Today, unlike web development, the mobile landscape is complex enough for a software engineer and Android is posing more challenging environment thanks to its fragmentation issues on hardware and software fronts.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
Loops Section Overview

599 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question