Need help improving number guessing game

James Stroud jstroud at mbi.ucla.edu
Mon Dec 15 05:40:08 EST 2008


feba wrote:

> I don't see the aim of your changes to setup(). I can kinda understand
> checking to make sure that you didn't make the minimum higher than the
> maximum, but I think where you put minr/maxr would make it use the
> same minr/maxr as the end of the previous game, wouldn't it?

No. Each function call creates its own name space. The function as Bruno 
has written it will have default values (mini & maxi). A call to this 
function can set different values optionally:


setup(2)          #==> range from 2 to 99
setup(maxi=101)   #==> range from 1 to 101
setup(5, 10)      #==> range from 5 to 10
setup(10, 5)      #==> throws an error

>> Minor point for a short program, but still good practice : use
>> constants. IE :
> 
> I had done this initially, but it seemed wasteful and needlessly
> confusing in this situation.

No. Tracking down and changing hard-coded values within a module is 
wasteful and needlessly confusing. Creating well named and well 
documented module level constants is good style and will make your life 
easier in the long run.

>> I assume 'p1sc' means "player_1_score" ?
>> If so, you may want to use a dict for scores:
> 
> I don't really understand dicts yet; actually, the tutorial I'm
> following (http://www.briggs.net.nz/log/writing/snake-wrangling-for-
> kids/ , designed for tweens, but other than the pointless anecdote and
> joke here and there, I've found it a very good guide) doesn't even
> seem to mention them, from a search of the pdf. Actually, apparently I
> stopped and started working on this just before the chapter on
> functions and modules.

scores = {'player 1' : 0, 'player 2' : 0 }
scores['player 2'] = 10        #==> now player 2's score is 10
scores['player 1'] += 1        #==> now player 1's score is 1
print scores['player 0']       #==> prints "0"
print scores['player 2'] * 2   #==> prints "20"

If you get that, you'll have about all you need to know about dicts to 
use them for keeping track of scores (and other values) in your game.

> I'll look into that later on, but for now I'm pretty happy with how it
> works.

Try it sooner rather than later. I didn't get this kind of advice when I 
was first learning. It would have shaved months from my learning curve.


>> You should either put this in it's own function (could be named 'main'),
>> or at least "protect" it with an "if __name__ == '__main__':" test.
> 
> Could you go into a bit more detail on this? I don't understand what
> should be its own function, nor do I understand what that line would
> do or how to use it.

The idea is that everything you write is reusable and can be imported as 
a module. Upon importing a module, it's code is executed. So, as 
written, if someone imports it as a library module, they will start 
playing the game. Wrapping in the "if __name__ == '__main__':" test 
prevents the main loop of the game from executing on import. Only when 
the module is "__main__" will that test evaluate to true and its 
commands execute.

For small programs like you have here, I'd do it like this (again 
combining ideas):

def num_players(game, prompt='1 or 2 Players?\n> '):
   while True:
     num = input(prompt)
     try:
       num = int(num)
     except ValueError:
       print "Bad Value"
     else:
       break
   game['pnum'] = num

def main(game=None):
   if game is None:
     game = {}
   print("WELCOME TO THE SUPER NUMBER GUESSING GAME!")
   num_players(game)
   game['play'] = 1
   # P1 goes first
   game['player'] = "P1"
   #Scores, keep track of times player guessed first.
   game['p1sc'], game['p2sc'] = 0, 0
   setup(game)

   while game['play'] == 1:
     guessing(game)

if __name__ == "__main__":
   main()


I just threw a little advanced stuff at you. But you would be doing 
yourself a huge favor if you struggled to understand it. The idea is 
that since game is a dict, you can modify game inside of the functions, 
and all you do is pass the game around to functions that need the values 
of its contents.

For example:

def setup(game):
     game['a'], game['b'] = 1, 99
     game['target'] = random.randint(a, b)

def playagain(game):
     playover = input("PLAY AGAIN? Y/N: ")
     if playover.strip().lower() == "y":
         game['play'] = 1
         setup(game)
     else:
         print("GOOD BYE. PLAY AGAIN SOON!")
         quit()


Notice that I just made return values obsolete.

You will also notice that management of all of your values now becomes 
more tractable using the mutability of dict ("game"). Long, ugly lines 
now become simple function calls. See if you can understand what I'm 
doing here and try to propagate the idea through your game using the 
game dict.

If you can do it, you'll be at least 80% of the way to understanding 
object oriented programming, by the way.

James


-- 
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com



More information about the Python-list mailing list