Objects, classes and their terminology — Object-oriented programming
Create and working with objects — Object-oriented programming
Tiled images — Tiled images
Programming Tips —
Week 6,
Prime Numbers (while loops)
- All data entities in Python are objects. Compound objects consist of multiple pieces of data.
- New types of compound objects can be defined using the keyword
class
. For example, a class for card decks could be created using the definition statementclass Deck:
- The data for objects in the class are contained in user-defined fields. For example, the Deck class could include a
cards
field that corresponds to a list of cards. - Functions defined inside the class definition are methods. These method create and manipulate the object and the data in corresponding fields. For example, the Deck class might include a
shuffle
method that shuffles a Deck object. - Lecture examples - Character, Ball
- More examples - Class Structure, Class Errors
- Python does not support Overload
- The class initializer
__init__
generates instances of class objects. In Python, this initializer can be called via the expressionclass_name(...)
. For example, an instance of theDeck
class can be created via the statementmy_deck = Deck(...)
. - The first parameter to class methods is, by convention, always named
self
. This name refers to the object being acted on by the method. - Class fields for an object are defined/modified in class methods via
self.class_field = ...
For example,self.cards = []
would assign an empty list to thecards
field in a class method for a Deck object. - Class methods can be applied to a class object via
class_object.class_method(...)
. For example, ashuffle
method could be applied to a deck via the statementmy_deck.shuffle()
. - Objects for user-defined classes are mutable. In particular, modification of a field in an object via a class method mutates the object.
- Lecture examples - Character, Diffusing Particles Blackjack Template
- More examples - Class Structure, Class Errors, Bubbles, Flowers
-
Each Python class has a hidden constructor method that
- constructs (makes) the object,
- calls
__init__
to initialize the object, - then returns this object.
- so return statement is no needed in __init__
# This is the special method that initializes the object
# that is being created.
def __init__(self):
pass
# This method runs whenever an object is printed.
def __str__(self):
pass
- A tiled image is a single image that consists of a set of smaller images laid out in a regular grid.
- Tield images are useful since loading a single large image is faster than loading many small images.
- Small images in the tiled image can be drawn by specifying the appropriate source rectangle for
draw_image
using the size of the small image and its position in the grid. - Lecture examples - Tiled Images
- More examples - Bunny Emotions
- Tips: replace www by dl while using dropbox.
dl
specifies that the file is for download
# while loop introduction
# while test:
# body
def get_primes(text):
if int(text) <= 1:
print "Please input number bigger than 1"
return []
nums = range(2, int(text) + 1)
ans = []
# The loop continues until all composite numbers
# have been removed from nums and all prime
# numbers have been transferred to ans.
while len(nums) > 0:
x = nums[0]
ans.append(nums[0])
for n in list(nums):
if n % x == 0:
nums.remove(n)
print "Prime numbers in range:", ans
return ans
Mini-project # 6 - Blackjack
http://www.codeskulptor.org/#user39_y2HWRg78AU_0.py
# Mini-project #6 - Blackjack
import simplegui
import random
# load card sprite - 936x384 - source: jfitz.com
CARD_SIZE = (72, 96)
CARD_CENTER = (36, 48)
card_images = simplegui.load_image("http://storage.googleapis.com/codeskulptor-assets/cards_jfitz.png")
CARD_BACK_SIZE = (72, 96)
CARD_BACK_CENTER = (36, 48)
card_back = simplegui.load_image("http://storage.googleapis.com/codeskulptor-assets/card_jfitz_back.png")
OFFSET = 40
FONT = "serif"
# initialize some useful global variables
in_play = False
outcome = ""
score = 0
# define globals for cards
SUITS = ('C', 'S', 'H', 'D')
RANKS = ('A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K')
VALUES = {'A':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, 'T':10, 'J':10, 'Q':10, 'K':10}
# define card class
class Card:
def __init__(self, suit, rank):
if (suit in SUITS) and (rank in RANKS):
self.suit = suit
self.rank = rank
else:
self.suit = None
self.rank = None
print "Invalid card: ", suit, rank
def __str__(self):
return self.suit + self.rank
def get_suit(self):
return self.suit
def get_rank(self):
return self.rank
def draw(self, canvas, pos):
card_loc = (CARD_CENTER[0] + CARD_SIZE[0] * RANKS.index(self.rank),
CARD_CENTER[1] + CARD_SIZE[1] * SUITS.index(self.suit))
canvas.draw_image(card_images, card_loc, CARD_SIZE, [pos[0] + CARD_CENTER[0], pos[1] + CARD_CENTER[1]], CARD_SIZE)
# define hand class
class Hand:
def __init__(self):
# create Hand object
self._cards = []
def __str__(self):
# return a string representation of a hand
_str_cards = ""
for idx in range(len(self._cards)):
_str_cards += (self._cards[idx].get_suit() + self._cards[idx].get_rank() + " ")
return "Hand contains " + _str_cards
def add_card(self, card):
# add a card object to a hand
self._cards.append(card)
def get_value(self):
# count aces as 1, if the hand has an ace, then add 10 to hand value if it doesn't bust
# compute the value of the hand, see Blackjack video
self._value = 0
_ace_count = 0
for idx in range(len(self._cards)):
self._value += VALUES[self._cards[idx].get_rank()]
if self._cards[idx].get_rank() == "A":
_ace_count += 1
if self._value + 10 <= 21 and _ace_count:
return self._value + 10
else:
return self._value
def draw(self, canvas, pos):
# draw a hand on the canvas, use the draw method for cards
for idx in range(len(self._cards)):
self._cards[idx].draw(canvas, [pos[0] + idx * (CARD_SIZE[0] + OFFSET), pos[1]])
# define deck class
class Deck:
def __init__(self):
# create a Deck object
self._cards = [Card(suit, rank) for suit in SUITS for rank in RANKS]
def shuffle(self):
# shuffle the deck
# use random.shuffle()
random.shuffle(self._cards)
def deal_card(self):
# deal a card object from the deck
return self._cards.pop()
def __str__(self):
# return a string representing the deck
_str_cards = ""
for idx in range(len(self._cards)):
_str_cards += (self._cards[idx].get_suit() + self._cards[idx].get_rank() + " ")
return "Deck contains " +_str_cards
#define event handlers for buttons
def deal():
global outcome, in_play, status, score
# Player lose if Deal button is clicked during the middle of a round
if in_play:
score -= 1
status = "You Give up."
outcome = "New deal?"
in_play = False
return
# Create a blackjack deck and Shuffle
global bj_deck
bj_deck = Deck()
bj_deck.shuffle()
# Create player and dealer hands and add two cards to each hand
global player_hand, dealer_hand
player_hand = Hand()
dealer_hand = Hand()
for dummy_idx in range(2):
player_hand.add_card(bj_deck.deal_card())
dealer_hand.add_card(bj_deck.deal_card())
status = ""
outcome = "Hit or stand?"
in_play = True
def hit():
global score, player_hand, bj_deck, in_play, outcome, status
# if the hand is in play, hit the player
if player_hand.get_value() <= 21 and in_play:
player_hand.add_card(bj_deck.deal_card())
# if busted, assign a message to outcome, update in_play and score
if player_hand.get_value() > 21:
in_play = False
score -= 1
status = "You have busted and lose"
outcome = "New deal?"
else:
outcome = "Hit or stand?"
def stand():
global score, player_hand, dealer_hand, bj_deck, in_play, outcome, status
# if hand is in play, repeatedly hit dealer until his hand has value 17 or more
if player_hand.get_value() <= 21 and in_play:
while dealer_hand.get_value() < 17:
dealer_hand.add_card(bj_deck.deal_card())
# assign a message to outcome, update in_play and score
if dealer_hand.get_value() > 21:
score += 1
status = "Dealer has busted. You win"
outcome = "New deal?"
elif dealer_hand.get_value() >= player_hand.get_value():
score -= 1
status = "You Lose."
outcome = "New deal?"
elif dealer_hand.get_value() < player_hand.get_value():
score += 1
status = "You Win!"
outcome = "New deal?"
in_play = False
# draw handler
def draw(canvas):
# test to make sure that card.draw works, replace with your code below
global score, player_hand, dealer_hand, outcome, in_play
# Draw text
canvas.draw_text("Blackjack", [120, 100], 50, "Blue", FONT)
canvas.draw_text("Score " + str(score), [400, 100], 35, "White", FONT)
canvas.draw_text("Dealer", [40, 170], 30, "Black", FONT)
canvas.draw_text(status, [200, 170], 30, "Navy", FONT)
canvas.draw_text("Player", [40, 370], 30, "Black", FONT)
canvas.draw_text(outcome, [200, 370], 30, "Navy", FONT)
# Draw player and dealer hand
player_hand.draw(canvas, [40, 400])
dealer_hand.draw(canvas, [40, 200])
if in_play:
canvas.draw_image(card_back, CARD_BACK_CENTER, CARD_SIZE,
[CARD_BACK_CENTER[0] + 40, CARD_BACK_CENTER[1] + 200], CARD_SIZE)
# initialization frame
frame = simplegui.create_frame("Blackjack", 600, 600)
frame.set_canvas_background("Green")
#create buttons and canvas callback
frame.add_button("Deal", deal, 200)
frame.add_button("Hit", hit, 200)
frame.add_button("Stand", stand, 200)
frame.set_draw_handler(draw)
# get things rolling
deal()
frame.start()
# remember to review the gradic rubric