[2021-Fall] Lab07 of CS61A of UCB


Accounts


Q2: Retirement

Add a time_to_retire method to the Account class. This method takes in an amount and returns how many years the holder would need to wait in order for the current balance to grow to at least amount, assuming that the bank adds balance times the interest rate to the total balance at the end of every year.

問題描述如下: 每一年你的 balance 都會有利息, 問你哪一年你達到了 amount 可以退休了, 用代碼模擬這個過程即可

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
    year, curAmount = 0, self.balance
    while True:
        year += 1
        curAmount *= (1 + self.interest)
        if curAmount > amount:
            return year

Q3: FreeChecking

Implement the FreeChecking class, which is like the Account class from lecture except that it charges a withdraw fee after 2 withdrawals. If a withdrawal is unsuccessful, it still counts towards the number of free withdrawals remaining, but no fee for the withdrawal will be charged.

和普通的 withdraw 方法相比, 我們要額外檢查一個參數 - free_withdrawals, 它表示我們可以在不支付消費的情況下取款的次數. 這里要注意兩個點:

  1. 取款失敗也會扣免費次數
  2. 在要支付小費的情況下, 得小費+余額>取款金額才能成功取款

注意好這兩個點寫出代碼就沒有什么難度了

def withdraw(self, amount):
    if self.free_withdrawals > 0:
        if amount > self.balance:
            self.free_withdrawals -= 1
            return "Insufficient funds"
        if amount > self.max_withdrawal:
            self.free_withdrawals -= 1
            return "Can't withdraw that amount"
        self.free_withdrawals -= 1
        self.balance = self.balance - amount
    else:
        if amount + self.withdraw_fee > self.balance:
            self.free_withdrawals -= 1
            return "Insufficient funds"
        if amount + self.withdraw_fee > self.max_withdrawal:
            self.free_withdrawals -= 1
            return "Can't withdraw that amount"
        self.balance = self.balance - amount - self.withdraw_fee

Magic: the Lambda-ing


Description

下面要實現的是一個卡牌游戲, 兩個玩家都有一副卡牌, 並且持有手牌. 雙方玩家需要在每個回合中打出一張手牌. 每張手牌都有攻擊力和防御力, 能量高的人獲勝. 能量計算方式如下 $$(持有手牌的攻擊力)-(對方卡牌的防御力)/2$$

第一個勝利 8 回合以上的人獲得游戲的勝利.

同時還有下面幾張特殊卡牌:

  1. AI 卡: 強制讓對手出的卡牌的攻擊力減去它的防御力, 然后讓它的防御力 * 2
  2. Tutor 卡: 強制讓對手棄三張卡牌並重新抽三張牌
  3. TA 卡: 強制交換對手出的卡牌的攻擊力和防御力
  4. Instructor 卡: 根據對手出的卡牌來增加自己卡牌堆里面的卡牌的攻擊力和防御力, 然后刪除對手卡牌堆里所有跟他出的卡身材(攻擊力和防御力)一樣的

Q4: Making Cards

To play a card game, we're going to need to have cards, so let's make some! We're gonna implement the basics of the Card class first.

First, implement the Card class constructor in classes.py. This constructor takes three arguments:

  • a string as the name of the card
  • an integer as the attack value of the card
  • an integer as the defense value of the card

Each Card instance should keep track of these values using instance attributes called name, attack, and defense.

You should also implement the power method in Card, which takes in another card as an input and calculates the current card's power. Refer to the Rules of the Game if you'd like a refresher on how power is calculated.

在本體中我們要完成構造函數的代碼和計算能量的函數, 其實就是把上面的規則翻譯成代碼, 很簡單.

class Card:
    cardtype = 'Staff'

    def __init__(self, name, attack, defense):
        """
        Create a Card object with a name, attack,
        and defense.
        """
        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
        """
        return self.attack - opponent_card.defense / 2

Q5: Making a Player

Now that we have cards, we can make a deck, but we still need players to actually use them. We'll now fill in the implementation of the Player class.

A Player instance has three instance attributes:

  • name is the player's name. When you play the game, you can enter your name, which will be converted into a string to be passed to the constructor.
  • deck is an instance of the Deck class. You can draw from it using its .draw() method.
  • hand is a list of Card instances. Each player should start with 5 cards in their hand, drawn from their deck. Each card in the hand can be selected by its index in the list during the game. When a player draws a new card from the deck, it is added to the end of this list.

Complete the implementation of the constructor for Player so that self.hand is set to a list of 5 cards drawn from the player's deck.

Next, implement the draw and play methods in the Player class. The draw method draws a card from the deck and adds it to the player's hand. The play method removes and returns a card from the player's hand at the given index.

Call deck.draw() when implementing Player.__init__ and Player.draw. Don't worry about how this function works - leave it all to the abstraction!

在這一題中進一步對手牌完善了描述, 我們一開始有 5 張手牌. 我們需要完成下面的功能:

  1. 構造函數, 在這里要從 deck 中取出 5 張手牌, 為了代碼的簡潔我們這里可以在這里使用 List comprehension
  2. draw 函數, 從卡牌堆取一張牌到手牌, 這個直接用 deck.draw() 即可
  3. play 函數, 其實就是出牌函數, 我們需要根據索引出牌, 記得把牌刪掉, 要區分 python 中的 .remove().pop() 方法
def __init__(self, deck, name):
    """Initialize a Player object.
    """
    self.deck = deck
    self.name = name
    self.hand = [deck.draw() for i in range(5)]

def draw(self):
    """Draw a card from the player's deck and add it to their hand.
    """
    assert not self.deck.is_empty(), 'Deck is empty!'
    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.
    """
    card = self.hand[card_index]
    self.hand.pop(card_index)
    return card

Optional Questions

Q6: AIs: Defenders

Implement the effect method for AIs, which reduces the opponent card's attack by the opponent card's defense, and then doubles the opponent card's defense.

Note: The opponent card's resulting attack value cannot be negative.

這個問題要我們實現前面提到過的 AI 卡的功能, 就按照那個功能寫代碼即可, 注意如果攻擊力算出來小於 0, 我們需要把它設置為 0

def effect(self, opponent_card, player, opponent):
    """
    Reduce the opponent's card's attack by its defense,
    then double its defense.
    """
    opponent_card.attack -= opponent_card.defense
    if opponent_card.attack < 0:
        opponent_card.attack = 0
    opponent_card.defense *= 2

Q7: Tutors: Flummox

Implement the effect method for TAs, which swaps the attack and defense of the opponent's card.

也就是實現上面的 Tutor 卡, 注意這里我們要如何實現棄牌, 我們不應該破壞封裝, 也就是我們要假裝不知道內部實現細節, 那么查看 Player 類有什么方法我們可以使用. 顯然, 我們可以用 play 把前三張牌打出去, 然后從牌堆里 draw 三張牌出來

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.
    """
    # discard 3 cards
    for i in range(3):
        opponent.play(i)
    # draw 3 cards
    for i in range(3):
        opponent.draw()
    # You should add your implementation above this.
    print('{} discarded and re-drew 3 cards!'.format(opponent.name))

Q8: TAs: Shift

Implement the effect method for TAs, which swaps the attack and defense of the opponent's card.

TA 卡的功能很簡單, 無非就是交換攻擊力和防御力而已, 在 python 中要實現這個功能是十分簡潔的

def effect(self, opponent_card, player, opponent):
    """
    Swap the attack and defense of an opponent's card.
    """
    opponent_card.attack, opponent_card.defense = opponent_card.defense, opponent_card.attack

Q9: The Instructor Arrives

A new challenger has appeared! Implement the effect method for the Instructors, who add the opponent card's attack and defense to all cards in the player's deck and then removes all cards in the opponent's deck that have the same attack or defense as the opponent's card.

Note: If you mutate a list while iterating through it, you may run into trouble. Try iterating through a copy of the list instead. You can use slicing to make a copy of a list:

 >>> original = [1, 2, 3, 4]
 >>> copy = original[:]
 >>> copy
 [1, 2, 3, 4]
 >>> copy is original
 False

也就是我們要實現上面的 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.
    """
    orig_opponent_deck_length = len(opponent.deck.cards)

    # add the attack and defense of the opponent's card ...
    for card in player.deck.cards:
        card.attack += opponent_card.attack
        card.defense += opponent_card.defense

    # remove all cards in the opponent's deck that share ...
    for card in opponent.deck.cards[:]:
        if card.attack == opponent_card.attack and card.defense == opponent_card.defense:
            opponent.deck.cards.remove(card)


    # 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM