0

So I build a tiny bingo program for my wife to use at her candle parties. The boards are already generated. This is just a program to call out the numbers.

import random
a = []
a = list(range(1,76))
random.shuffle(a)

def pop(x):
    while 1:
        b = a.pop(0)
        if b <= 15:
            print 'b', b,
        elif b > 15 and b <=30:
            print 'i', b,
        elif b > 30 and b <=45:
            print 'n', b,
        elif b > 45 and b <=60:
            print 'g', b,
        else:
            print 'o', b,
        raw_input('')

pop(1)

Now her parties are getting larger and she is worried about someone cheating so I would like to add in a feature where I could type in the numbers that supposedly won and have the program let me know if those numbers where indeed called. I have tried running it to a file with

def pop(x):
    while 1:
        b = a.pop(0)
        with open('bingo.txt', 'w') as file1:
            file1.write(b,'\n')
        if b ...

but it just opens and then closes back down. No errors or any text to the file. It doesn't need to go to a file. I just thought that if it did, I could then add in a searchfile feature at the end and know whether the number was called or not. What would be the best way to find out if the numbers on the "winning" line were actually called?

1 Answers1

4

I would accumulate the numbers called in a set which would get returned from pop. then I'd add a function to read in the "winning" numbers (into a set) and check if that new set is a subset of the numbers which were called:

import random
import ast

def pop(a,accumulated=None):
    print "type q to move on to verification"
    if accumulated is None:
        accumulated = set()
    v = 'I can put any string here, as long as it is not "q" :-)'
    while v.lower() != 'q':
        b = a.pop(0)
        if b <= 15:
            print 'b', b,
        elif b > 15 and b <=30:
            print 'i', b,
        elif b > 30 and b <=45:
            print 'n', b,
        elif b > 45 and b <=60:
            print 'g', b,
        else:
            print 'o', b,
        accumulated.add(b)
        v = raw_input('')
    return accumulated

def verify(numbers):
    new_nums = raw_input("enter numbers separated by ',': ")
    nums = ast.literal_eval(new_nums)
    assert( len(nums) == 5 ) #Need 5 numbers to win
    result = set(nums).issubset(numbers)
    print "Verified? ",result
    return result
    #alternatively, and probably slightly more efficient
    # print numbers.issuperset(nums)
    #I prefer the other though as `subset` is easier for me to remember


def robust_verify(numbers):
   """
   keep trying to verify the numbers until we succeed
   """
   try:
       verify(numbers)
   except (AssertionError,SyntaxError,TypeError):  #other error conditions might go here too, but these are the ones I can think of right now ...
       robust_verify(numbers)


def play_bingo(game_vals=None,accumulated=None):
    if game_vals is None:
        game_vals = list(range(1,76))  #list strictly not necessary here, but why not?
        random.shuffle(game_vals)

    nums = pop(game_vals,accumulated=accumulated)
    if not robust_verify(nums):
        play_bingo(game_vals=game_vals,accumulated=nums)


play_bingo()

This is made a little more robust by making sure that verify succeeds (e.g. that your user doesn't accidentally enter a number as 15a,17,22,...)

As a side note, your attempt at using a file failed because you were opening a file, writing a number to it and closing it each time you "draw" a new number. Since you're opening the file as 'w' any file that is already there gets clobbered -- and so you can only ever store the last number drawn by that method. You'd want to move your while loop into the with statement in order to get that method to work properly (or open the file for appending ('a'), but repeatedly opening a file for appending is typically not a good solution).

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • 1
    `b > 15 and b <=30` could be `15 < b <= 30` – Matt Nov 14 '12 at 17:48
  • @Matt -- Don't you just love operator chaining magic? I would probably use that in my code too, but I just copied OP's code for simplicity. – mgilson Nov 14 '12 at 17:51
  • Very Nice. Easy enough to make into sets and compare them. The only problem is that, in my understanding, once the numbers are played and turned into a set to compare, they are out of play for later comparison. Meaning that if someone calls 'bingo' prematurely and the tested numbers are false, every number that was played prior to testing is now unavailable for further comparison. Am I incorrect in how that would work? Thank you for your help. As you can see, I am quite the novice user. –  Nov 14 '12 at 21:47
  • @kriskringle -- Notice how in the function `play_bingo`, there is the last `if` clause? Basically that says, if the verification failed (a player was trying to cheat) then we call `play_bingo` again -- Only this time, we pass the `game_vals` as an argument which then becomes (or continues to be) the pool for `pop`. So, to answer your question, I think it should be robust against false bingos :) -- Unless there's a bug I didn't think of -- which happens sometimes. – mgilson Nov 14 '12 at 22:21
  • I think that the only way I can explain what I mean is through an example. Theoretically, When I run the program I get 1, 2 ,3 ,4 and 7. I hit q to check if I have a winner and check with numbers 1,2,3,4and 5. It returns false because 5 has not been called. It continues on with the remaining pool of numbers and eventually calls 5. However, if I now hit q to check again with the winning numbers 1,2,3,4 and 5, it will still say false. Even though we know 1 - 4 have been called, the verification function will not recognize any of the numbers called prior to the initial verification. –  Nov 14 '12 at 23:09
  • @kriskringle -- Ahh, I see it now. See my update. I haven't tested it, but I think that should fix it. – mgilson Nov 15 '12 at 01:53
  • @kriskringle -- Sorry, most robustly, it should be `nums = pop(game_vals,accumulated=accumulated)`. That's what I get for not creating a well defined API :) – mgilson Nov 15 '12 at 02:52