oopy-dots-demo
# oopyDotsDemo.py
# starts with betterDotsDemo and adds:
# * a dotCounter that counts all the instances of Dot or its subclasses
# * a MovingDot subclass of Dot that scrolls horizontally
# * a FlashingMovingDot subclass of MovingDot that flashes and moves
import random
from tkinter import *
class Dot(object):
dotCount = 0
def __init__(self, x, y):
Dot.dotCount += 1
self.x = x
self.y = y
self.r = random.randint(20,50)
self.fill = random.choice(["pink","orange","yellow","green",
"cyan","purple"])
self.clickCount = 0
def containsPoint(self, x, y):
d = ((self.x - x)**2 + (self.y - y)**2)**0.5
return (d <= self.r)
def draw(self, canvas):
canvas.create_oval(self.x-self.r, self.y-self.r,
self.x+self.r, self.y+self.r,
fill=self.fill)
canvas.create_text(self.x, self.y, text=str(self.clickCount))
def onTimerFired(self, data):
pass
class MovingDot(Dot):
def __init__(self, x, y):
super().__init__(x, y)
self.speed = 5 # default initial speed
def onTimerFired(self, data):
self.x += self.speed
if (self.x > data.width):
self.x = 0
class FlashingMovingDot(MovingDot):
def __init__(self, x, y):
super().__init__(x, y)
self.flashCounter = 0
self.showFlash = True
def onTimerFired(self, data):
super().onTimerFired(data)
self.flashCounter += 1
if (self.flashCounter == 5):
self.flashCounter = 0
self.showFlash = not self.showFlash
def draw(self, canvas):
if (self.showFlash):
canvas.create_rectangle(self.x-self.r, self.y-self.r,
self.x+self.r, self.y+self.r,
fill="lightGray")
super().draw(canvas)
def init(data):
data.dots = [ ]
def mousePressed(event, data):
for dot in reversed(data.dots):
if (dot.containsPoint(event.x, event.y)):
dot.clickCount += 1
return
dotType = (len(data.dots) % 3)
if (dotType == 0):
data.dots.append(Dot(event.x, event.y))
elif (dotType == 1):
data.dots.append(MovingDot(event.x, event.y))
else:
data.dots.append(FlashingMovingDot(event.x, event.y))
def redrawAll(canvas, data):
for dot in data.dots:
dot.draw(canvas)
canvas.create_text(data.width/2, 10, text="%d Dots" % Dot.dotCount)
def keyPressed(event, data):
pass
def timerFired(data):
for dot in data.dots:
dot.onTimerFired(data)
####################################
# use the run function as-is
####################################
def run(width=300, height=300):
def redrawAllWrapper(canvas, data):
canvas.delete(ALL)
canvas.create_rectangle(0, 0, data.width, data.height,
fill='white', width=0)
redrawAll(canvas, data)
canvas.update()
def mousePressedWrapper(event, canvas, data):
mousePressed(event, data)
redrawAllWrapper(canvas, data)
def keyPressedWrapper(event, canvas, data):
keyPressed(event, data)
redrawAllWrapper(canvas, data)
def timerFiredWrapper(canvas, data):
timerFired(data)
redrawAllWrapper(canvas, data)
# pause, then call timerFired again
canvas.after(data.timerDelay, timerFiredWrapper, canvas, data)
# Set up data and call init
class Struct(object): pass
data = Struct()
data.width = width
data.height = height
data.timerDelay = 100 # milliseconds
init(data)
# create the root and the canvas
root = Tk()
canvas = Canvas(root, width=data.width, height=data.height)
canvas.pack()
# set up events
root.bind("<Button-1>", lambda event:
mousePressedWrapper(event, canvas, data))
root.bind("<Key>", lambda event:
keyPressedWrapper(event, canvas, data))
timerFiredWrapper(canvas, data)
# and launch the app
root.mainloop() # blocks until window is closed
print("bye!")
run(400, 200)
oopy-playing-cards-demo
# oopy-playing-cards-demo.py
# Demos class attributes, static methods, repr, eq, hash
import random
class PlayingCard(object):
numberNames = [None, "Ace", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "Jack", "Queen", "King"]
suitNames = ["Clubs", "Diamonds", "Hearts", "Spades"]
CLUBS = 0
DIAMONDS = 1
HEARTS = 2
SPADES = 3
@staticmethod
def getDeck(shuffled=True):
deck = [ ]
for number in range(1, 14):
for suit in range(4):
deck.append(PlayingCard(number, suit))
if (shuffled):
random.shuffle(deck)
return deck
def __init__(self, number, suit):
# number is 1 for Ace, 2...10,
# 11 for Jack, 12 for Queen, 13 for King
# suit is 0 for Clubs, 1 for Diamonds,
# 2 for Hearts, 3 for Spades
self.number = number
self.suit = suit
def __repr__(self):
return ("<%s of %s>" %
(PlayingCard.numberNames[self.number],
PlayingCard.suitNames[self.suit]))
def getHashables(self):
return (self.number, self.suit) # return a tuple of hashables
def __hash__(self):
return hash(self.getHashables())
def __eq__(self, other):
return (isinstance(other, PlayingCard) and
(self.number == other.number) and
(self.suit == other.suit))
# Show this code in action
print("Demo of PlayingCard will keep creating new decks, and")
print("drawing the first card, until we see the same card twice.")
print()
cardsSeen = set()
diamondsCount = 0
# Now keep drawing cards until we get a duplicate
while True:
deck = PlayingCard.getDeck()
drawnCard = deck[0]
if (drawnCard.suit == PlayingCard.DIAMONDS):
diamondsCount += 1
print(" drawnCard:", drawnCard)
if (drawnCard in cardsSeen): break
cardsSeen.add(drawnCard)
# And then report how many cards we drew
print("Total cards drawn:", 1+len(cardsSeen))
print("Total diamonds drawn:", diamondsCount)