2021 fall cs61a lab7
网址 https://inst.eecs.berkeley.edu/~cs61a/fa21/lab/lab07/#topics
problem1:
case1:
case2:
case3:
Account:
class Account:
"""An account has a balance and a holder.
>>> a = Account('John')
>>> a.deposit(10)
10
>>> a.balance
10
>>> a.interest
0.02
>>> a.time_to_retire(10.25) # 10 -> 10.2 -> 10.404
2
>>> a.balance # balance should not change
10
>>> a.time_to_retire(11) # 10 -> 10.2 -> ... -> 11.040808032
5
>>> a.time_to_retire(100)
117
"""
max_withdrawal = 10
interest = 0.02
def __init__(self, account_holder):
self.balance = 0
self.holder = account_holder
def deposit(self, amount):
self.balance = self.balance + amount
return self.balance
def withdraw(self, amount):
if amount > self.balance:
return "Insufficient funds"
if amount > self.max_withdrawal:
return "Can't withdraw that amount"
self.balance = self.balance - amount
return self.balance
def time_to_retire(self, amount):
"""Return the number of years until balance would grow to amount."""
assert self.balance > 0 and amount > 0 and self.interest > 0
"*** YOUR CODE HERE ***"
ans = 0
tmp = self.balance
while True:
if tmp >= amount:
return ans
ans += 1
tmp = tmp * (1 + self.interest)
class FreeChecking(Account):
"""A bank account that charges for withdrawals, but the first two are free!
>>> ch = FreeChecking('Jack')
>>> ch.balance = 20
>>> ch.withdraw(100) # First one's free
'Insufficient funds'
>>> ch.withdraw(3) # And the second
17
>>> ch.balance
17
>>> ch.withdraw(3) # Ok, two free withdrawals is enough
13
>>> ch.withdraw(3)
9
>>> ch2 = FreeChecking('John')
>>> ch2.balance = 10
>>> ch2.withdraw(3) # No fee
7
>>> ch.withdraw(3) # ch still charges a fee
5
>>> ch.withdraw(5) # Not enough to cover fee + withdraw
'Insufficient funds'
"""
withdraw_fee = 1
free_withdrawals = 2
"*** YOUR CODE HERE ***"
def withdraw(self, amount):
if self.free_withdrawals > 0:
self.free_withdrawals -= 1
return Account.withdraw(self, amount)
else:
return Account.withdraw(self, amount + self.withdraw_fee)
cardgame:
# Magic the Lambda-ing!
import random
class Card:
cardtype = 'Staff'
def __init__(self, name, attack, defense):
"""
Create a Card object with a name, attack,
and defense.
>>> staff_member = Card('staff', 400, 300)
>>> staff_member.name
'staff'
>>> staff_member.attack
400
>>> staff_member.defense
300
>>> other_staff = Card('other', 300, 500)
>>> other_staff.attack
300
>>> other_staff.defense
500
"""
"*** YOUR CODE HERE ***"
self.name = name
self.attack = attack
self.defense = defense
def power(self, opponent_card):
"""
Calculate power as:
(player card's attack) - (opponent card's defense)/2
>>> staff_member = Card('staff', 400, 300)
>>> other_staff = Card('other', 300, 500)
>>> staff_member.power(other_staff)
150.0
>>> other_staff.power(staff_member)
150.0
>>> third_card = Card('third', 200, 400)
>>> staff_member.power(third_card)
200.0
>>> third_card.power(staff_member)
50.0
"""
"*** YOUR CODE HERE ***"
return self.attack - opponent_card.defense / 2
def effect(self, opponent_card, player, opponent):
"""
Cards have no default effect.
"""
return
def __repr__(self):
"""
Returns a string which is a readable version of
a card, in the form:
: , [, ]
"""
return '{}: {}, [{}, {}]'.format(self.name, self.cardtype, self.attack, self.defense)
def copy(self):
"""
Returns a copy of this card.
"""
return Card(self.name, self.attack, self.defense)
class Player:
def __init__(self, deck, name):
"""Initialize a Player object.
A Player starts the game by drawing 5 cards from their deck. Each turn,
a Player draws another card from the deck and chooses one to play.
>>> test_card = Card('test', 100, 100)
>>> test_deck = Deck([test_card.copy() for _ in range(6)])
>>> test_player = Player(test_deck, 'tester')
>>> len(test_deck.cards)
1
>>> len(test_player.hand)
5
"""
self.deck = deck
self.name = name
"*** YOUR CODE HERE ***"
self.hand = [deck.draw() for _ in range(5)]
def draw(self):
"""Draw a card from the player's deck and add it to their hand.
>>> test_card = Card('test', 100, 100)
>>> test_deck = Deck([test_card.copy() for _ in range(6)])
>>> test_player = Player(test_deck, 'tester')
>>> test_player.draw()
>>> len(test_deck.cards)
0
>>> len(test_player.hand)
6
"""
assert not self.deck.is_empty(), 'Deck is empty!'
"*** YOUR CODE HERE ***"
self.hand.append(self.deck.draw())
def play(self, card_index):
"""Remove and return a card from the player's hand at the given index.
>>> from cards import *
>>> test_player = Player(standard_deck, 'tester')
>>> ta1, ta2 = TACard("ta_1", 300, 400), TACard("ta_2", 500, 600)
>>> tutor1, tutor2 = TutorCard("t1", 200, 500), TutorCard("t2", 600, 400)
>>> test_player.hand = [ta1, ta2, tutor1, tutor2]
>>> test_player.play(0) is ta1
True
>>> test_player.play(2) is tutor2
True
>>> len(test_player.hand)
2
"""
"*** YOUR CODE HERE ***"
return self.hand.pop(card_index)
def display_hand(self):
"""
Display the player's current hand to the user.
"""
print('Your hand:')
for card_index, displayed_card in zip(range(len(self.hand)), [str(card) for card in self.hand]):
indent = ' ' * (5 - len(str(card_index)))
print(card_index, indent + displayed_card)
def play_random(self):
"""
Play a random card from hand.
"""
return self.play(random.randrange(len(self.hand)))
######################
# Optional Questions #
######################
class AICard(Card):
cardtype = 'AI'
def effect(self, opponent_card, player, opponent):
"""
Reduce the opponent's card's attack by its defense,
then double its defense.
>>> from cards import *
>>> player1, player2 = Player(player_deck, 'p1'), Player(opponent_deck, 'p2')
>>> opponent_card = Card('other', 300, 600)
>>> ai_test = AICard('AI', 500, 500)
>>> ai_test.effect(opponent_card, player1, player2)
>>> opponent_card.attack
0
>>> opponent_card.defense
1200
>>> opponent_card = Card('other', 600, 400)
>>> ai_test = AICard('AI', 500, 500)
>>> ai_test.effect(opponent_card, player1, player2)
>>> opponent_card.attack
200
>>> opponent_card.defense
800
"""
"*** YOUR CODE HERE ***"
opponent_card.attack = max(0, opponent_card.attack - opponent_card.defense)
opponent_card.defense *= 2
def copy(self):
"""
Create a copy of this card.
"""
return AICard(self.name, self.attack, self.defense)
class TutorCard(Card):
cardtype = 'Tutor'
def effect(self, opponent_card, player, opponent):
"""
Discard the first 3 cards in the opponent's hand and have
them draw the same number of cards from their deck.
>>> from cards import *
>>> player1, player2 = Player(player_deck, 'p1'), Player(opponent_deck, 'p2')
>>> opponent_card = Card('other', 500, 500)
>>> tutor_test = TutorCard('Tutor', 500, 500)
>>> initial_deck_length = len(player2.deck.cards)
>>> tutor_test.effect(opponent_card, player1, player2)
p2 discarded and re-drew 3 cards!
>>> len(player2.hand)
5
>>> len(player2.deck.cards) == initial_deck_length - 3
True
"""
"*** YOUR CODE HERE ***"
# You should add your implementation above this.
print('{} discarded and re-drew 3 cards!'.format(opponent.name))
for i in range(3):
del opponent.hand[0]
for i in range(3):
opponent.draw()
def copy(self):
"""
Create a copy of this card.
"""
return TutorCard(self.name, self.attack, self.defense)
class TACard(Card):
cardtype = 'TA'
def effect(self, opponent_card, player, opponent):
"""
Swap the attack and defense of an opponent's card.
>>> from cards import *
>>> player1, player2 = Player(player_deck, 'p1'), Player(opponent_deck, 'p2')
>>> opponent_card = Card('other', 300, 600)
>>> ta_test = TACard('TA', 500, 500)
>>> ta_test.effect(opponent_card, player1, player2)
>>> opponent_card.attack
600
>>> opponent_card.defense
300
"""
"*** YOUR CODE HERE ***"
opponent_card.attack, opponent_card.defense = opponent_card.defense, opponent_card.attack
def copy(self):
"""
Create a copy of this card.
"""
return TACard(self.name, self.attack, self.defense)
class InstructorCard(Card):
cardtype = 'Instructor'
def effect(self, opponent_card, player, opponent):
"""
Adds the attack and defense of the opponent's card to
all cards in the player's deck, then removes all cards
in the opponent's deck that share an attack or defense
stat with the opponent's card.
>>> test_card = Card('card', 300, 300)
>>> instructor_test = InstructorCard('Instructor', 500, 500)
>>> opponent_card = test_card.copy()
>>> test_deck = Deck([test_card.copy() for _ in range(8)])
>>> player1, player2 = Player(test_deck.copy(), 'p1'), Player(test_deck.copy(), 'p2')
>>> instructor_test.effect(opponent_card, player1, player2)
3 cards were discarded from p2's deck!
>>> [(card.attack, card.defense) for card in player1.deck.cards]
[(600, 600), (600, 600), (600, 600)]
>>> len(player2.deck.cards)
0
"""
orig_opponent_deck_length = len(opponent.deck.cards)
"*** YOUR CODE HERE ***"
for i in player.deck.cards:
i.attack += opponent_card.attack
i.defense += opponent_card.defense
tmp_deck = opponent.deck.cards
for i in tmp_deck:
if i.attack == opponent_card.attack or i.defense == opponent_card.defense:
opponent.deck.cards.remove(i)
# You should add your implementation above this.
discarded = orig_opponent_deck_length - len(opponent.deck.cards)
if discarded:
print('{} cards were discarded from {}\'s deck!'.format(discarded, opponent.name))
return
def copy(self):
return InstructorCard(self.name, self.attack, self.defense)
########################################
# Do not edit anything below this line #
########################################
class Deck:
def __init__(self, cards):
"""
With a list of cards as input, create a deck.
This deck should keep track of the cards it contains, and
we should be able to draw from the deck, taking a random
card out of it.
"""
self.cards = cards
def draw(self):
"""
Draw a random card and remove it from the deck.
"""
assert self.cards, 'The deck is empty!'
rand_index = random.randrange(len(self.cards))
return self.cards.pop(rand_index)
def is_empty(self):
return len(self.cards) == 0
def copy(self):
"""
Create a copy of this deck.
"""
return Deck([card.copy() for card in self.cards])
class Game:
win_score = 8
def __init__(self, player1, player2):
"""
Initialize a game of .
"""
self.player1, self.player2 = player1, player2
self.p1_score = 0
self.p2_score = 0
def play_round(self, p1_card, p2_card):
"""
After each player picks a card, play them against
each other.
"""
p1_card.effect(p2_card, self.player1, self.player2)
p2_card.effect(p1_card, self.player2, self.player1)
p1_power = p1_card.power(p2_card)
p2_power = p2_card.power(p1_card)
if p1_power > p2_power:
# Player 1 wins the round.
self.p1_score += 1
result = 'won'
elif p2_power > p1_power:
# Player 2 wins the round.
self.p2_score += 1
result = 'lost'
else:
# This round is a draw.
result = 'tied'
# Display results to user.
print('You {} this round!'.format(result))
print('{}\'s card: {}; Power: {}'.format(self.player1.name, p1_card, p1_power))
print('Opponent\'s card: {}; Power: {}'.format(p2_card, p2_power))
def game_won(self):
"""
Check if the game is won and, if so,
which player won.
"""
if self.p1_score < self.win_score and self.p2_score < self.win_score:
return 0
return 1 if self.p1_score > self.p2_score else 2
def display_scores(self):
"""
Display players' scores to the user.
"""
print('{}\'s score: {}'.format(self.player1.name, self.p1_score))
print('Opponent\'s score: {}'.format(self.p2_score))