Part 7
Thinking about Thinking
In which we'll take the player's guess, compare it to
the real solution, and work out how accurate his guess was.
Abstract Concepts
One of the main things that people have problems with when
programming is begin able to take an idea in their head, and
turn that idea into computer code that does exactly what they
want it to do. What I want to show you in this chapter is
how we take one concept and turn it into code.
The key (as always) is being able to break your idea into
smaller and smaller rules. If you break it down far enough,
then you'll have something that can easily be written in OPL.
What you must remember is when writing these rules, you must
mention everything you do. You can't say "compare this
ball to those four," you need to say what you're comparing,
to which ball, and what to do depending on the result.
Checking The Guess
Breaking It Down
Before we can tell the computer what to do, we need to have
a clear understanding on the thought processes that that our
brain goes through. If we were making a cup of tea, it's no
good having a rule that goes:
Boil Kettle
You need something like:
Take kettle to tap
Remove lid
Put kettle under tap
Turn on tap
DO wait a bit
UNTIL kettle is full
Put lid on kettle
Put kettle on table
Plug in power cable to kettle (it's an old fashioned one)
Switch on power at mains
Switch on kettle
DO
wait a bit
UNTIL kettle switch moves to off position
Of course, there's nothing to stop you calling the above
PROC boil_kettle: is there.
Right, so this is the level of detail we'll need to break
down any computer action. Let's now look at MASTER and how
I've broken it down, although you might want to have a go
yourself before having a look at my solution.
Again, remember there is no right or wrong way when doing
routines like this. If your way works, great! Just because
it's slightly different from mine, you understand it and the
user gets the same end result.
Checking Those Balls
The routine in Master checks to see how many balls are the
right colour in the right place, and how many are the right
colour but in the wrong place. These two numbers will be used
to display the 'hint' to the player so he or she can make
another guess to try and logically work out the solution.
Always keep your overall goal of a procedure in mind. It
helps immensely. Now
Code Breakdown
So what we'll do here is break down exactly the thought processes
that you go through when comparing a guess in Master to the
correct four colour solution.
Some Counters
To keep track of things, we'll start with two 'counters' in
our heads.. the number of balls that are the right colour
in the right place, and the right colour but in the wrong
place. So the first thing to do is
(Right Place)=0
(Wrong Place)=0
Check all balls are guessed (if not, return)
The guess button can be pressed at any time so we should check
to see everything is in order before we process the guess.
(Counter)=0
DO
(Counter) is increased by one
IF guess position (counter) does not have a colour (ie it has a value of zero)
Go back into game loop, print up warning message
ENDIF
UNTIL (counter) equals four
Have we won?
This check is obvious. Have we got the solution correct? And
as we're already thinking like a computer, we'll use a DO...
UNTIL loop
(Counter)=0
DO
(Counter) is increased by one
IF guess position (counter) EQUALS colour in solution position (counter)
(Right Place) is increased by one
ENDIF
UNTIL (counter) equals four
IF (Right Place) equals four
Then the guess is 100% correct, do the victory routine
ENDIF
All the above should be pretty obvious, and easy to code
(now we've bbroken it down into the small logical steps computer
programming requires).
How many balls are the right colour in the right place?
Well, we have the steps already don't we? We can use the code
above because the (Right Place variable is going to carry
the number of balls we need.
How many balls are the right colour, but in the wrong
place?
Stop and think how you do this before we break it into steps.
You take the first ball, and see if it matches anything in
the solution (ignoring a ball if it is in the same postion
(ioe the second guess compared to the second ball in the solution
is something you don't do).
(Wrong Place)=0
(Counter One)=0
DO
(Counter One) is increased by one
(Counter Two)=0
DO
(Counter Two) is increased by one
IF (Counter One) and (Counter Two) are different
IF guess position (Counter One) equals solution position (Counter Two)
Add one to (Wrong Place)
ENDIF
ENDIF
UNTIL (Counter Two) equals four
UNTIL (Counter One) equals four
So now (Wrong Place) holds the number of balls that are the
right colour, but in the wrong place.
Or does it?
The 'Gotcha'
PICTURE
1-2-3-4 Guess
PICTURE 1-5-5-1 Solution
Have a look at this example. In your head, you know the correct
solution is "one in the right place." But if you
follow through the steps above, you 'll get "one in the
right place and one in the wrong place." Why?
Because the red ball guessed in first place is not only counted
in the 'right place' code, it is also counted in the 'wrong
place' code by being matched up with forth ball in the solution.
One way to get round this is this simple rule that each guess
ball can only be used once, as can each ball in the solution.
So to facilitate this, we copy the guess and the solution
into temporary arrays. When we match up balls in either the
right place or the wrong place, we change the value in the
array to something that wouldn't normally be there - we change
a guess ball to 0, and a solution ball to 99. This way they
cannot be counted again.
This is one example in how 'pseudo-code' can help you pick
up bugs and logical flaws before you actually sit in front
of the keyboard and start typing.
The Completed Code
So, here we have all the above in OPL.
LOCAL foo%, gnu%,right_place%,wrong_place%
LOCAL foobar%(4),guessbar%(4)
rem *** Create a copy of the solution so we can remove balls
rem *** as there position is noted. Ditto with guess array
foo%=0
DO
foo%=foo%+1
foobar%(foo%)=solution%(foo%)
guessbar%(foo%)=guess%(foo%)
UNTIL foo%=4
rem *** check all balls are guessed
foo%=0
DO
foo%=foo%+1
IF guessbar%(foo%)=0 : giPRINT "Not all spaces filled..." : RETURN : ENDIF
UNTIL foo%=4
breakout%=99 : rem *** Eventull incdrement turn counter
rem *** right pieces in right place
foo%=0
DO
foo%=foo%+1
IF guessbar%(foo%)=foobar%(foo%)
right_place%=right_place%+1
foobar%(foo%)=0 : rem remove from stemp solution
guessbar%(foo%)=99 : rem remove from guess
ENDIF
UNTIL foo%=4
IF right_place%=4 : rem Victory
m_victory:
RETURN
ENDIF
foo%=0
DO
foo%=foo%+1
gnu%=0
DO
gnu%=gnu%+1
IF guessbar%(foo%)=foobar%(gnu%)
wrong_place%=wrong_place%+1
foobar%(gnu%)=0
gnu%=4
ENDIF
UNTIL gnu%=4
UNTIL foo%=4
giPRINT NUM$(right_place%,1)+" in the right place, "+NUM$(wrong_place%,1)+" in the wrong place"
m_showguess:(right_place%,wrong_place%,turn%)
It's not called from the event loop yet (but it shouldn't
be that hard to figure out how), and we haven't yet got around
to displaying the generated result. All that will be covered
in Part 8.
But as with everything, you should be able to get down and
do it yourself, so if you want a little challenge over the
next fortnight... away you go!
Got any questions or comments arising from this tutorial.
Need help with OPL. Head to the forums
for help from the friendly community.
|