I would like to solicit your thoughts and ideas (code can come later) about how you would approach a project idea I just tossed together. I chose this as a testbed for me to play with objects, specifically multiple instances of a few specific objects, and as I thought about it, it raised a lot of questions about how to manage, contain, signal all of those objects that do almost the same thing at the same time.
I want to build an OO bingo simulator. While it is not necessarily the most efficient approach, let's academically assume it needs to be object-oriented.
We have 75 ball objects, which can be picked randomly by a machine, and which therefore need an awareness of being picked(), since no ball can come up twice in a game.
We have a scorecard grid with 25 square objects on it, and appropriate values for each column of the grid (B: 1-15,i:16-30, etc.), which are chosen randomly on each card. If we work with all 75 possible numbers (maybe not the best approach), each number needs to know if it's on the bingo card for this game, whether it's matched a number that's already been picked(), and whether it's a Freebie (middle square on the card - 'FREE' instead of a number)
Initial questions:
Can like objects be grouped by some mechanism such that changing an external parameter has them respond to that change, or do they each need to be iterated/manipulated each time to become "aware" of global changes? For example, a number is picked() - can the squares "know" if one matches the new number, or do I need to trigger each one to check?
Maybe I'm thinking in more of a parallel-thread mode here, one thread per object, which remains "active" during the game. Is that way out there? It's probably over my head at this point anyway.
Reel me in; tell me what you think.
27 2036
We have 75 ball objects, which can be picked randomly by a machine, and which therefore need an awareness of being picked(), since no ball can come up twice in a game.
Actually, I believe that the machine is the object in question and that balls are data that it dispences. The machine (object) has a better chance of encapsulating awareness of which numbers have been dispensed than a ball does.
We have a scorecard grid with 25 square objects on it, and appropriate values for each column of the grid (B: 1-15,i:16-30, etc.), which are chosen randomly on each card. If we work with all 75 possible numbers (maybe not the best approach), each number needs to know if it's on the bingo card for this game, whether it's matched a number that's already been picked(), and whether it's a Freebie (middle square on the card - 'FREE' instead of a number)
Initial questions:
Can like objects be grouped by some mechanism such that changing an external parameter has them respond to that change, or do they each need to be iterated/manipulated each time to become "aware" of global changes? For example, a number is picked() - can the squares "know" if one matches the new number, or do I need to trigger each one to check?
I've got similar thoughts here. Going to look for some examples
Maybe I'm thinking in more of a parallel-thread mode here, one thread per object, which remains "active" during the game. Is that way out there? It's probably over my head at this point anyway.
Reel me in; tell me what you think.
Do you have Robin Dunn's book: wxPython in Action?
Actually, I believe that the machine is the object in question and that balls are data that it dispences. The machine (object) has a better chance of encapsulating awareness of which numbers have been dispensed than a ball does.
I've got similar thoughts here. Going to look for some examples
Do you have Robin Dunn's book: wxPython in Action?
I haven't read it all, just looked up a few things.
I'm not really interested in the GUI in particular, more the logic. If the GUI objects are easier to build/attach to than abstract code items, that's fine.
The reason for the balls, instead of the machine, as objects is that I want to exercise multiple identical objects in action. JFYI.
The reason for the balls, instead of the machine, as objects is that I want to exercise multiple identical objects in action. JFYI.
Ok, I'll buy that. So if each ball instance needs to know which number was just picked() here's how I'd (almost) lay out the structure: - # I do this a bit differently, but Mr. Dunn says something like this:
-
-
class NumberDispenser(object):
-
def __init__(self):
-
self.clients = []
-
-
def RegisterClient(self, client):
-
self.clients.append(client)
-
-
def UpdateClients(self, data):
-
for client in self.clients:
-
client.Update(data) # This part I don't like:
-
# having to know the name of the client function here
-
-
class NumberClient(object):
-
def __init__(self, server, name):
-
self.name = name
-
server.RegisterClient(self)
-
-
def Update(self, data):
-
print self.name, data
-
-
-
if __name__ == "__main__":
-
server = NumberDispenser()
-
client1 = NumberClient(server, "client #1")
-
client2 = NumberClient(server, "client #2")
-
-
# call this in response to some event or whatever
-
server.UpdateClients(6545)
I haven't read it all, just looked up a few things.
I'm not really interested in the GUI in particular, more the logic. If the GUI objects are easier to build/attach to than abstract code items, that's fine.
Actually, I don't use the GUI stuff from the book. I really like (and use similar design) the Model-View-Controler idea. There is also threading discussion toward the end.
Actually, I don't use the GUI stuff from the book. I really like (and use similar design) the Model-View-Controler idea. There is also threading discussion toward the end.
OK, that's not ringing any bells. Can you elaborate on this - what, where, refs?
Ok, I'll buy that. So if each ball instance needs to know which number was just picked() here's how I'd (almost) lay out the structure: -
def UpdateClients(self, data):
-
for client in self.clients:
-
client.Update(data) # This part I don't like:
-
# having to know the name of the client function here
-
-
...
-
if __name__ == "__main__":
-
server = NumberDispenser()
-
client1 = NumberClient(server, "client #1") # <===
-
client2 = NumberClient(server, "client #2") # <===
-
Regarding that, my original thought, which is admittedly BASIC-esque, was to define an array where each element would become an instance. I don't know how to translate that here, but such a construct would alleviate much of the naming overhead. I guess it would also be redundant, since if I did that I wouldn't need the objects at all. :) But like I said, it's an academic exercise...
Can I use some form of eval() to create something like (this is just off the top of my head, trying to get the idea across): -
varhdr = 'client'
-
-
for i in range(75):
-
eval(varhdr+str(i)+' = NumberClient(server, "client #'+str(i)+'")')
-
Don't know if that's close to a proper use of eval; in SB we had a means of constructing dynamic lines of code like that so they could be reused, as in a loop.
This problem is what I was referring to when I mentioned a curiousity about how people would "group"control of these objects.
Actually, the use of a class variable, as discussed in that other thread, may make sense here. Such as, when a number is picked, - NumberClient.LastPicked=32
-
-
for square in grid:
-
# execute instance.CheckPicked code here
-
# each instance of NumberClient class now has
-
# a self.LastPicked value of 32 to process against
-
-
Regarding that, my original thought, which is admittedly BASIC-esque, was to define an array where each element would become an instance. I don't know how to translate that here, but such a construct would alleviate much of the naming overhead. I guess it would also be redundant, since if I did that I wouldn't need the objects at all. :) But like I said, it's an academic exercise...
Can I use some form of eval() to create something like (this is just off the top of my head, trying to get the idea across): -
varhdr = 'client'
-
-
for i in range(75):
-
eval(varhdr+str(i)+' = NumberClient(server, "client #'+str(i)+'")')
-
Don't know if that's close to a proper use of eval; in SB we had a means of constructing dynamic lines of code like that so they could be reused, as in a loop.
This problem is what I was referring to when I mentioned a curiousity about how people would "group"control of these objects.
Actually, the use of a class variable, as discussed in that other thread, may make sense here. Such as, when a number is picked, - NumberClient.LastPicked=32
-
-
for square in grid:
-
# execute instance.CheckPicked code here
-
# each instance of NumberClient class now has
-
# a self.LastPicked value of 32 to process against
-
-
A list comprehension is what you are looking for. A comprehension is a very handy tool when you don't need much stuff going on in a loop, but you do need elements appended to a list. This technique creates the list object and fills it in all at once. Notice, also, the C-line string formatting. I use it all the time. - class NumberDispenser(object):
-
def __init__(self):
-
self.clients = []
-
-
def RegisterClient(self, client):
-
self.clients.append(client)
-
-
def UpdateClients(self, data):
-
for client in self.clients:
-
client.Update(data) # This part I don't like:
-
# having to know the name of the client function here
-
-
class NumberClient(object):
-
def __init__(self, server, name):
-
self.name = name
-
server.RegisterClient(self)
-
-
def Update(self, data):
-
print self.name, data
-
-
-
if __name__ == "__main__":
-
server = NumberDispenser()
-
# list comprehension syntax uses [] on around the expession, generators use ()
-
instanceList = [NumberClient(server, "client%d" %i) for i in range(5)]
-
for inst in instanceList:
-
print inst.name
The list comprehension here - instanceList = [NumberClient(server, "client%d" %i) for i in range(5)]
is equivalent to - instanceList = []
-
for i in range(5):
-
instanceList.append(NumberClient(server, "client%d" %i))
which may be easier to read. I learned comprehensions so long ago that I have forgotten if the benefits actually outweigh the mashed syntax. If I get a break, I'll look it up and get back to you.
The list comprehension here - instanceList = [NumberClient(server, "client%d" %i) for i in range(5)]
is equivalent to - instanceList = []
-
for i in range(5):
-
instanceList.append(NumberClient(server, "client%d" %i))
which may be easier to read. I learned comprehensions so long ago that I have forgotten if the benefits actually outweigh the mashed syntax. If I get a break, I'll look it up and get back to you.
Not sure what you're looking up, but I get the listcomp. That does what I was thinking; it didn't occur to me to use the inline string formatting to achieve the desired result.
bvdet 2,851
Expert Mod 2GB
I have a couple of simple thoughts on your Bingo project:
The balls could be a list. - x = random.sample(range(1, 26, 1),25)
-
>>> x
-
[17, 23, 12, 18, 9, 6, 13, 10, 24, 7, 15, 3, 22, 4, 11, 8, 2, 14, 20, 25, 1, 19, 16, 5, 21]
When it is time to select a ball, pop it from the list.
The 'game' could be a dictionary of lists. The dictionary keys are 'card1', 'card2',...... and each list would be filled randomly with unique numbers. When a number is selected, each player's card is scanned for a match, and if a match is found, the list position is set to False. -
for card in dd.keys():
-
if ball in dd[card]:
-
dd['card1'][dd.['card1'].index(ball)] == False
After a match is found, a card scan method could be called to check for Bingo.
My contribution to this tread is probably be limited by my experience. I try to keep things simple. Most of the applications I have developed involve calculations in 3D space, manipulation of lists, dictionaries, tuples and strings, and reading/writing small data files. Classes incorporate instance variables and functions and sometimes methods when useful. Typically I do not modify instance data externally. I have a Python project coming up - add a steel angle brace between two structural steel beams. At the right time I'll start a thread on it.
Please keep this thead going - I want to know how it turns out.
Best Regards,
BV
ps - tru911m (Mark), Are you from Baltimore, MD? I detailed the structural steel for the Hippodrome PAC on N. Eutah a few years ago. Beautiful structure.
Hi BV,
Yes, I'm a lifelong Baltimoron as we jokingly say. I remember the Hippodrome from its declining days as a moviehouse back in the 70s. It's great that that area is receiving some deserved attention to (at lease some of ) the irreplaceable structures there. It used to be the grand shopping mecca downtown, before malls and the burbs took over.
As for the bingo, I'm pretty straightforward myself. In fact I keep slipping off the path I've laid for myself, in that this project has the arbitrary requirement that these items use objects to accomplish the task, even though it can be directly handled without them.
I'm trying, through use, to exercise my understanding of the interactions and management of simple objects, and I really want to create a couple of classes (balls in machine, squares on the bingo card) that must be instantiated many times (75 numbers, 25 squares) to get the hang of dealing with them all.
In fact, one misconception I keep falling back to is that an 'object' is more like a 'bot' - as if each of these items takes up CPU on its own in a separate thread, and all I have to do is 'talk' to them like IRC bots or something. In fact, I know better, that I have to go 'process' each one based on some sort of event, but that's what I keep seeing in my head, and I'm trying to shake it.
OK, getting a really basic start here. I apologize if any of this repeats -- until it clicks, I'm having some issues retaining a few things.
Based on Barton's tutorial on variables in classes, I just received an unexpected result. Here's a sample: - class BingoCard:
-
def __init__(self):
-
self.card=[]
-
def FillGrid(self):
-
for row in range(5):
-
for col in range(5):
-
self.card.append((row,col)) # replace tuples with objects
-
def ShowGrid(self):
-
print self.card
-
-
card=BingoCard()
-
card.FillGrid()
-
card.ShowGrid()
-
print card.card
I expected to need ShowGrid() to get at my generated bingo card. What I didn't expect is that the last line, print, will also display the grid.
Since self.card is defined in BingoCard.__init__, I thought it would be inaccessible from the outside world, but the output shows differently: - [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]
-
[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]
What am I forgetting?
Not sure what you're looking up, but I get the listcomp. That does what I was thinking; it didn't occur to me to use the inline string formatting to achieve the desired result.
I'm still having my original dilemma on these results.
I see how the listcomp generates the strings, but how do I make each string result become the name of a variable that I use to instantiate my object, all "hands off"?
(I'm working on this part right now...)
I'm still having my original dilemma on these results.
I see how the listcomp generates the strings, but how do I make each string result become the name of a variable that I use to instantiate my object, all "hands off"?
(I'm working on this part right now...)
Skip that -- I found it: - self.name=name # passed in when instantiated
-
Skip that -- I found it: - self.name=name # passed in when instantiated
-
actually I was thinking of this line: -
# it is legal to access the variables directly
-
print inst1.cv1
It is not only legal, but common practice. I, however, try to avoid it.
It is not only legal, but common practice. I, however, try to avoid it.
I know you prefer setters and getters. (You'll be proud of me in my results post, in a minute). I get that it could be dicey if you write to vars from the outside, based on our earlier discussion. I'm not as clear on why it's a bad practice to "read", or return results from, internal vars, however. Is it just a purity thing?
Early results:
Here's BingoCard() that consists of 25 Square() objects. The instances are named individually (thanks Barton!) and also stored in a compound list, and able to be referenced directly (item[x][y]).
I chose to skip the listcomp for now to simplify my own comprehension (ptp). However, I've seen evidence that the listcomp is actually more efficient, and I will make the conversion after all of my logic is worked out.
Here's my starter code: - import random
-
-
class BingoCard:
-
-
def __init__(self):
-
self.card=[]
-
def FillGrid(self):
-
for row in range(5):
-
self.rowlist=[]
-
for col in range(5):
-
self.rowlist.append(Square(self,"%d"%row,"%d"%col))
-
self.card.append(self.rowlist[:])
-
-
def ShowGrid(self):
-
for row in self.card:
-
print
-
for sq in row:
-
sq.ShowName()
-
-
class Square:
-
-
def __init__(self, parent, row,col):
-
self.row=row
-
self.col=col
-
self.name="square-"+str(row)+"-"+str(col)
-
self.parent=parent
-
-
def ShowName(self):
-
print self.name+" ",
-
-
-
card=BingoCard()
-
card.FillGrid()
-
card.ShowGrid()
-
print
-
print
-
card.card[2][1].ShowName()
and here's my output: - square-0-0 square-0-1 square-0-2 square-0-3 square-0-4
-
square-1-0 square-1-1 square-1-2 square-1-3 square-1-4
-
square-2-0 square-2-1 square-2-2 square-2-3 square-2-4
-
square-3-0 square-3-1 square-3-2 square-3-3 square-3-4
-
square-4-0 square-4-1 square-4-2 square-4-3 square-4-4
-
-
square-2-1
Now that the object distribution is working, I can replicate it for the BingoMixer() and BingoBall()s, and start adding smarts to the objects. I'm pretty psyched. :)
Getting there... one little thing that I noticed:
There's no need for the extra lookup required by self. references here. -
def FillGrid(self):
-
for row in range(5):
-
self.rowlist=[]
-
for col in range(5):
-
self.rowlist.append(Square(self,"%d"%row,"%d"%col))
-
self.card.append(self.rowlist[:])
-
Use function scope variables for things like this. ie -
def FillGrid(self):
-
for row in range(5):
-
rowlist=[]
-
for col in range(5):
-
rowlist.append(Square(self,"%d"%row,"%d"%col))
-
self.card.append(rowlist[:]) # since you want [:] probably don't need to slice
-
Getting there... one little thing that I noticed:
There's no need for the extra lookup required by self. references here.
OK, I got the function (method?) local thing.
I was concerned that, because I was using rowlist in a loop, to populate the card, that I didn't want any crosslinks between items on different rows, so I forced a copy [:] in the append. I see that wasn't necessary after trying it, but I err on the side of caution since all those rules for mutables aren't yet second-nature for me.
BINGO!!!
I've got a working model.
Don't know if I should post the code, it's a little over 200 lines. Could probably be more elegant, but the logic's good, and objects abound!
Thanks guys. Give me the go-ahead if I should put it up here; if it's too much, no problem. Is there a separate area for uploads etc.?
BINGO!!!
I've got a working model.
Don't know if I should post the code, it's a little over 200 lines. Could probably be more elegant, but the logic's good, and objects abound!
Thanks guys. Give me the go-ahead if I should put it up here; if it's too much, no problem. Is there a separate area for uploads etc.?
Post away (up to 10000 character limit).
OK, I got the function (method?) local thing.
Yes, to use proper OO parlance, "method" is, of course, correct. Scope rules for functions still apply, though.
I was concerned that, because I was using rowlist in a loop, to populate the card, that I didn't want any crosslinks between items on different rows, so I forced a copy [:] in the append. I see that wasn't necessary after trying it, but I err on the side of caution since all those rules for mutables aren't yet second-nature for me.
What is actually taking place is:
1. create an empty list and assign it to the name "rowlist"
2. fill it in the loop
-now here's the fun part-
3. assign a reference (self.card[i]) to that object (internally, refcount += 1) - creating two refferences to the same object
4. reassign the value of "rowlist" to an empty list (refcount -= 1) - only self.card[i] remains "pointing" to to the list.
and so on.
As a bonus when refcount = 0 the object will be garbage collected. This is the reason we don't ever worry about memory management. Some programmers will
to free up memory immediately and make the reference to "object" invalid, some will
(which keeps "object" assigned, but releases the memory for GC). For large objects the former is probably a good practice. Most often it's OK to just leave the object hanging around.
Post away (up to 10000 character limit).
Okie Dokie.
Let's start with my output. We start with a randomly generated bingo card. Then we're given the number of balls pulled from the machine, and their order, followed by BINGO!!!, and the final winning card with matched numbers blacked out for the visual effect. This allows us to validate the program operation against the initial random values chosen. - B I N G O
-
-
8 26 36 48 75
-
2 22 38 58 64
-
10 24 ## 51 63
-
3 30 44 59 69
-
15 25 41 53 62
-
-
30 balls drawn:
-
-
46 55 53 26 58 16 30 22 64 49 67 32 50 4 21 20 6 2 18 27 62 11 23 15 35 5 51 66 47 38
-
-
BINGO!!!
-
-
B I N G O
-
-
8 ## 36 48 75
-
## ## ## ## ##
-
10 24 ## ## 63
-
3 ## 44 59 69
-
## 25 41 ## ##
Of course, while testing, I had stuff printing all over the place at various intervals, but in the end it condensed nicely to this compact display.
The code has a lot of logic redundancy since the BingoCard and BingoSquare behave very similarly to the BingoMixer and BingoBall, with the exception of the 5x5 requirement for the layout of the card, and the fact that each column only contains a subset of the random numbers drawn, ensuring a somewhat smooth distribution across the card.
My only lazy point, I realize this morning, is that I believe the numbers in a column on a real bingo card are sorted in ascending order. If I'd thought of this, I probably would have populated them in a column-first order, which would allow me to sort the elements of that sublist easily. As it is, I generated the card in a row-first order, and although I can visualize the solution, I don't feel like messing with it right now. :) So here goes: -
import random
-
-
class BingoCard:
-
-
def __init__(self,prnt):
-
self.card=[]
-
self.parent=prnt
-
self.BingoPatterns=[\
-
[[0,0],[0,4],[2,2],[4,0],[4,4]],\
-
[[0,0],[1,1],[2,2],[3,3],[4,4]],\
-
[[4,0],[3,1],[2,2],[1,3],[0,4]],\
-
[[0,0],[0,1],[0,2],[0,3],[0,4]],\
-
[[1,0],[1,1],[1,2],[1,3],[1,4]],\
-
[[2,0],[2,1],[2,2],[2,3],[2,4]],\
-
[[3,0],[3,1],[3,2],[3,3],[3,4]],\
-
[[4,0],[4,1],[4,2],[4,3],[4,4]],\
-
[[0,0],[1,0],[2,0],[3,0],[4,0]],\
-
[[0,1],[1,1],[2,1],[3,1],[4,1]],\
-
[[0,2],[1,2],[2,2],[3,2],[4,2]],\
-
[[0,3],[1,3],[2,3],[3,3],[4,3]],\
-
[[0,4],[1,4],[2,4],[3,4],[4,4]]\
-
]
-
-
def FillCard(self):
-
if len(self.card):
-
for row in self.card:
-
for square in row:
-
square.ResetMatched()
-
square.ResetNumber()
-
else:
-
for row in range(5):
-
rowlist=[]
-
for col in range(5):
-
rowlist.append(BingoSquare(self,"%d"%row,"%d"%col))
-
self.card.append(rowlist)
-
-
def ShowCard(self):
-
print; print'B\tI\tN\tG\tO'
-
for row in self.card:
-
print
-
for square in row:
-
if square.GetMatched():
-
print '##\t',
-
else:
-
print '%d\t' % square.GetNumber(),
-
print
-
-
def NewGame(self):
-
NumbersLeft=[]
-
for i in range(5):
-
NumbersLeft.append(range(1+(i*15),16+(i*15)))
-
self.FillCard()
-
for row in self.card:
-
for i in range(5):
-
rnum=random.randint(0,len(NumbersLeft[i])-1)
-
row[i].SetNumber(NumbersLeft[i][rnum])
-
#print i,NumbersLeft[i][rnum]
-
#print square.GetNumber()
-
NumbersLeft[i]=NumbersLeft[i][:rnum]+NumbersLeft[i][rnum+1:]
-
#print NumbersLeft
-
self.card[2][2].SetNumber(0)
-
self.card[2][2].SetMatched()
-
#self.ShowCard()
-
-
def CheckMatches(self,num):
-
for row in self.card:
-
for square in row:
-
if square.GetNumber()==num:
-
square.SetMatched()
-
-
def CheckBingo(self):
-
for set in self.BingoPatterns:
-
bingo=True
-
for coords in set:
-
if not self.card[coords[0]][coords[1]].GetMatched():
-
bingo=False
-
break
-
if bingo: return True
-
return False
-
-
-
class BingoSquare:
-
-
def __init__(self, prnt, row,col):
-
self.row=row
-
self.col=col
-
self.name="sqr"+str(row)+str(col)
-
self.parent=prnt
-
self.number=0
-
self.matched=False
-
-
def ShowName(self):
-
pass
-
print self.name+" ",
-
-
def SetNumber(self,num):
-
self.number=num
-
-
def ResetNumber(self):
-
self.number=None
-
-
def GetNumber(self):
-
return self.number
-
-
def SetMatched(self):
-
self.matched=True
-
-
def ResetMatched(self):
-
self.matched=False
-
-
def GetMatched(self):
-
return self.matched
-
-
-
-
class BingoMixer:
-
-
def __init__(self,prnt):
-
self.balls=[]
-
self.parent=prnt
-
-
def FillBox(self):
-
if len(self.balls):
-
for ball in self.balls:
-
ball.ResetDrawn()
-
ball.ResetNumber()
-
else:
-
for ball in range(75):
-
self.balls.append(BingoBall(self,"%d"%ball))
-
-
def ShowBox(self):
-
for ball in self.balls:
-
ball.ShowName()
-
-
def ShowBalls(self):
-
for ball in self.balls:
-
print ball.GetNumber(), # ball.GetDrawn()
-
-
def ShowDrawn(self):
-
for i in range(len(self.balls)):
-
if not self.balls[i].GetDrawn():
-
self.drawnBalls=self.balls[:i]
-
print; print '%d balls drawn:' % len(self.drawnBalls)
-
print
-
for ball in self.drawnBalls:
-
print ball.GetNumber(),
-
break
-
print
-
-
def NewGame(self):
-
NumbersLeft=range(1,76)
-
self.FillBox()
-
for ball in self.balls:
-
rnum=random.randint(0,len(NumbersLeft)-1)
-
ball.SetNumber(NumbersLeft[rnum])
-
#print ball.GetNumber()
-
NumbersLeft=NumbersLeft[:rnum]+NumbersLeft[rnum+1:]
-
#print NumbersLeft
-
#self.ShowBalls()
-
-
-
class BingoBall:
-
-
def __init__(self, parent, ballno):
-
self.name="ball"+str(ballno)
-
self.parent=parent
-
self.number=0
-
self.drawn=False
-
-
def ShowName(self):
-
print self.name,
-
-
def SetNumber(self,num):
-
self.number=num
-
-
def ResetNumber(self):
-
self.number=None
-
-
def GetNumber(self):
-
return self.number
-
-
def SetDrawn(self):
-
self.drawn=True
-
-
def ResetDrawn(self):
-
self.drawn=False
-
-
def GetDrawn(self):
-
return self.drawn
-
-
class BingoGame:
-
import random
-
random.seed()
-
-
def __init__(self):
-
self.card=BingoCard(self)
-
self.mixer=BingoMixer(self)
-
-
def Play(self):
-
bingo=False
-
self.card.NewGame()
-
self.mixer.NewGame()
-
self.card.ShowCard()
-
-
for ball in self.mixer.balls:
-
thisNum=ball.GetNumber()
-
ball.SetDrawn()
-
#print;print thisNum
-
self.card.CheckMatches(thisNum)
-
#self.card.ShowCard()
-
if self.card.CheckBingo():
-
break
-
-
self.mixer.ShowDrawn()
-
print; print 'BINGO!!!'
-
self.card.ShowCard()
-
quit()
-
-
-
if __name__ == '__main__':
-
game=BingoGame()
-
game.Play()
-
I left my quit() in an inopportune place, but it doesn't really affect the outcome. What's the proper way to end something? Just have it come back to main and drop off the bottom, or do you have to load and use sys.exit() all the time?
Plenty of room here for tightening, especially since my use of objects was an academic exercise. Learning about object use and efficiency was my primary goal here, so object-related critique would be most helpful to my learning process.
Thanks all!
bvdet 2,851
Expert Mod 2GB
Mark,
That's really cool. It works fine in Pythonwin without the quit(). Thanks for posting.
BV
The code has a lot of logic redundancy since the BingoCard and BingoSquare behave very similarly to the BingoMixer and BingoBall, with the exception of the 5x5 requirement for the layout of the card, and the fact that each column only contains a subset of the random numbers drawn, ensuring a somewhat smooth distribution across the card.
I'm still having a look at this. I may be time to start exploring "inheritance" where a super class has the common elements in it and subclasses inherit and/or override aspects of the parent class.
What's the proper way to end something? Just have it come back to main and drop off the bottom?
That's it!
Plenty of room here for tightening, especially since my use of objects was an academic exercise. Learning about object use and efficiency was my primary goal here, so object-related critique would be most helpful to my learning process.
As I say, I'm still having a look. I'll get back to you.
PS It's good to see you messing around in the other forums. It can be fun.
What is actually taking place is:
1. create an empty list and assign it to the name "rowlist"
2. fill it in the loop
-now here's the fun part-
3. assign a reference (self.card[i]) to that object (internally, refcount += 1) - creating two refferences to the same object
4. reassign the value of "rowlist" to an empty list (refcount -= 1) - only self.card[i] remains "pointing" to to the list.
and so on.
The same type of thing happens when a function uses a local (functions scope) variable to (say) build a list and then returns that list to the caller. The local reference parishes but the object is kept alive because the caller now has a reference to it.
Sign in to post your reply or Sign up for a free account.
Similar topics
by: Slash |
last post by:
Hello everyone
I'm looking for seminar topics (and project ideas too) for my final
year in Computer Engineering. I'm considering doing something...
|
by: Tom |
last post by:
I am looking for some ideas for how to design the layout of the form for
data entry and to display the data for the following situation:
There are...
|
by: micangello |
last post by:
i need ideas on what my final year project can be about
i have studied 2 years of pure math (advanced calculus and algebra, topology,...
|
by: Kinokunya |
last post by:
Hi guys,
My group and I will be working on our final year project, the scope to
do a program/web-based application similar areas of...
|
by: teenabhardwaj |
last post by:
How would one discover a valid source for learning news, comfort, and help for engineering designs? Covering through piles of books takes a lot of...
|
by: Kemmylinns12 |
last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and...
|
by: CD Tom |
last post by:
This only shows up in access runtime. When a user select a report from my report menu when they close the report they get a menu I've called Add-ins...
|
by: Naresh1 |
last post by:
What is WebLogic Admin Training?
WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge...
|
by: jalbright99669 |
last post by:
Am having a bit of a time with URL Rewrite. I need to incorporate http to https redirect with a reverse proxy. I have the URL Rewrite rules made...
|
by: antdb |
last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine
In the overall architecture, a new "hyper-convergence" concept was...
|
by: Matthew3360 |
last post by:
Hi there. I have been struggling to find out how to use a variable as my location in my header redirect function.
Here is my code.
...
|
by: AndyPSV |
last post by:
HOW CAN I CREATE AN AI with an .executable file that would suck all files in the folder and on my computerHOW CAN I CREATE AN AI with an .executable...
|
by: WisdomUfot |
last post by:
It's an interesting question you've got about how Gmail hides the HTTP referrer when a link in an email is clicked. While I don't have the specific...
| |