本课程为莱斯大学在cousera上Python网课的课后作业
链接:Python交互式程序设计入门
二十一点是一种扑克牌游戏,起源于法国,参加者尽量使手中牌的总点数达到21点,或是接近21点,但不能超过,再和庄家比较总点数的大小以定输赢。游戏截图如下:
该交互式程序使用了SimpleGUI库进行界面设计,具体代码如下:
import SimpleGUICS2Pygame.simpleguics2pygame as simplegui
import random
# Mini-project #6 - Blackjack
# 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")
# 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):
self.cards = [] # create Hand object
def __str__(self):
return [str(card) for card in self.cards]
def add_card(self, card):
self.cards.append(card) # add a card object to a hand
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
value = 0
A_exist = False
for card in self.cards: # compute the value of the hand, see Blackjack video
if isinstance(card, Card):
value += VALUES[card.get_rank()]
if card.get_rank() == 'A':
A_exist = True
if A_exist and value + 10 <= 21:
value += 10
return value
def draw(self, canvas, pos):
for card_index in range(len(self.cards)): # draw a hand on the canvas, use the draw method for cards
if card_index <= 4:
self.cards[card_index].draw(canvas, pos[card_index])
# define deck class
class Deck:
def __init__(self):
self.cards = [Card(suit, rank) for suit in SUITS for rank in RANKS]# create a Deck object
def shuffle(self):
# shuffle the deck
random.shuffle(self.cards) # use random.shuffle()
def deal_card(self):
return self.cards.pop() # deal a card object from the deck
def __str__(self):
return [str(card) for card in self.cards]
#define event handlers for buttons
def timer_handler():
global outcome, timer
outcome = ''
timer.stop()
def deal():
global outcome, in_play, player, dealer, dec, score, timer
if not in_play:
outcome = ''
else:
score -= 1
outcome = 'dealer wins'
timer = simplegui.create_timer(1000, timer_handler)
timer.start()
dealer, player = Hand(), Hand()
dec = Deck()
dec.shuffle()
dealer.add_card(dec.deal_card())
dealer.add_card(dec.deal_card())
player.add_card(dec.deal_card())
player.add_card(dec.deal_card())
in_play = True
def hit():
global outcome, in_play, player, dealer, dec, score
# if the hand is in play, hit the player
if in_play:
player.add_card(dec.deal_card())
# if busted, assign a message to outcome, update in_play and score
if player.get_value() > 21:
in_play = False
score -= 1
outcome = 'player went bust, dealer wins'
def stand():
global outcome, in_play, player, dealer, dec, score
# if hand is in play, repeatedly hit dealer until his hand has value 17 or more
if in_play:
while dealer.get_value() < 17:
dealer.add_card(dec.deal_card())
# assign a message to outcome, update in_play and score
if dealer.get_value() > 21:
in_play = False
score += 1
outcome = 'dealer went bust, player wins'
else:
if dealer.get_value() >= player.get_value():
in_play = False
score -= 1
outcome = 'dealer wins'
else:
in_play = False
score += 1
outcome = 'player wins'
# draw handler
def draw(canvas):
# test to make sure that card.draw works, replace with your code below
pos_player = [[84, 420], [174, 420], [264, 420], [354, 420], [444, 420]]
pos_dealer = [[84, 172], [174, 172], [264, 172], [354, 172], [444, 172]]
canvas.draw_text('Score = %d'%score, [495, 20], 20, 'White')
canvas.draw_text(outcome, [250, 150], 30, 'Red')
canvas.draw_text('Dealer', [80, 150], 30, 'White')
canvas.draw_text('Player', [80, 400], 30, 'White')
canvas.draw_text('Blackjack', [80, 80], 50, 'Black')
if in_play:
canvas.draw_image(card_back, CARD_CENTER, CARD_SIZE, [120, 220], CARD_BACK_SIZE)
dealer.cards[1].draw(canvas, pos_dealer[1])
canvas.draw_text('Hit or stand?', [250, 400], 30, 'White')
else:
dealer.draw(canvas, pos_dealer)
canvas.draw_text('New deal?', [250, 400], 30, 'White')
player.draw(canvas, pos_player)
#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()
详细作业要求参考课程。