代码Python入门(十、面向对象编程实战)

编写模块
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# 简单游戏模块

class Player(object):
    """A player for a game."""

    def __init__(self, name, score = 0):
        self.name = name
        self.score = score

    def __str__(self):    # 为该对象创建其字符串表示方式:当对象被打印时会显示这个字符串
        rep = self.name + ":\t" + str(self.score)
        return rep

    def ask_yes_no(question):   
        """Ask a yes or no question."""
        response = None
        while response not in ("y", "n"):
            response = input(question).lower()
        return response

    def ask_number(question, low, high):
        """Ask for a number within a range."""
        response = None
        while response not in range(low, high):
            response = int(input(question))
        return response

    if __name__ == "__main__":   # 如果改程序是直接运行的,if语句条件为真。如果该文件是作为模块使用的,则为假。
        print("You ran this module directly (and did not 'import' it).")   # 告诉用户该文件应该被引用而不是直接运行
        input("\n\nPress the Enter key to exit.")


#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# 卡牌游戏需要用到的基础类


class Card(object):  # 该类基于object类  ,卡牌类

    """A playing card."""
    RANKS = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
    SUITS = ["c", "d", "h", "s"]     # 花色

    def __init__(self, rank, suit, face_up = True):
        self.rank = rank
        self.suit = suit
        self.is_face_up = face_up   # bool变量 卡牌是否面朝上

    def __str__(self):    # 为该对象创建其字符串表示方式:当对象被打印时会显示这个字符串
        if self.is_face_up:
            rep = self.rank + self.suit
        else:
            rep = "XX"
        return rep

    def flip(self):   # 翻牌
        self.is_face_up = not self.is_face_up


class Hand(object):     # 手牌类
    """A hand of playing cards."""
    def __init__(self):
        self.cards = []

    def __str__(self):     # 为该对象创建其字符串表示方式:当对象被打印时会显示这个字符串
        if self.cards:
            rep = ""
            for card in self.cards:
                rep += str(card) + "\t"
        else:
            rep = ""
        return rep

    def clear(self):    # 清牌
        self.cards = []

    def add(self, card):   # 添牌
        self.cards.append(card)

    def give(self, card, other_hand):  # 交换牌
        self.cards.remove(card)
        other_hand.add(card)


class Deck(Hand):    # 副牌类, 继承Hand类
    """A deck of palying cards"""
    def populate(self):   # 创建一副牌
        for suit in Card.SUITS:
            for rank in Card.RANKS:
                self.add(Card(rank, suit))

    def shuffle(self):   # 洗牌
        import random
        random.shuffle(self.cards)

    def deal(self, hands, per_hand = 1):   # 发牌  per_hand(玩家应得牌数),hands(玩家列表)
        for rounds in range(per_hand):
            for hand in hands:
                if self.cards:
                    top_card = self.cards[0]
                    self.give(top_card, hand)
                else:
                    print("Can't continue deal. Out of cards!")

    if __name__ == "__main__":
        print("This is a module with classes for playing cards!")
        input("\n\nPress the enter key to exit.")

引入模块

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
卡牌游戏: 二十一点(blackjack)
玩法:
玩家根据点数来玩牌
每个玩家都希望总点数尽量接近21点而不爆掉
带数字的牌以其面值计算点数
A牌算作1点或11点(由玩家决定),J、Q、K则算作10点
计算机是庄家,同时跟1-7名玩家对垒。每轮牌局开始时,计算机给每位参与者(包括自己)发两张牌。玩家可以查看自己的全部牌,
程序会把玩家的总点数显示出来。但此时庄家的一张牌暂时是看不到的。
接下来,每位玩家都会得到一个继续拿牌的机会。每位玩家每次都只能要一张牌,想要多少次都可以。但是如果玩家的总点数超过了
21(即“爆掉”),玩家就输了。如果所有玩家都爆掉了,计算机就翻开它自己的第一张牌。本局结束。否则,赌局继续。只要计算机
的总点数小于17,那他就必须继续拿牌。如果计算机爆掉了,则所有没有爆掉的玩家就赢了;否则,每位没爆掉的玩家的总点数就会
拿来跟计算机的比。如果玩家的总点数大,则玩家赢。如果玩家的总点数小,则玩家输。如果两者的总点数相等,则玩家跟计算机握
手言和(平手)。
"""
import Games, Cards_Module    # 引入模块


class BJ_Card(Cards_Module.Card):    # 卡牌类, 继承Card类
    """A Blackjack Card."""
    ACE_VALUE = 1          # "A"的值,默认为1

    @property
    def value(self):     # 获取牌所对应的值
        if self.is_face_up:
            v = BJ_Card.RANKS.index(self.rank) + 1
            if v > 10:
                v = 10
        else:
            v = None
        return v


class BJ_Deck(Cards_Module.Deck):   # 副牌类, 继承Deck类
    """A Blackjack Deck."""
    def populate(self):     # 重写populate方法,允许BJ_Deck对象填入BJ_Card对象
        for suit in BJ_Card.SUITS:
            for rank in BJ_Card.RANKS:
                self.cards.append(BJ_Card(rank, suit))


class BJ_Hand(Cards_Module.Hand):  # 手牌类  , 继承Hand类
    """ A Blackjack Hand."""
    def __init__(self, name):   # 重写构造器,添加一个表示拥有者的name特性
        super(BJ_Hand, self).__init__()   # super(BJ_Hand,self)用于找到BJ_Hand的父类,也可以直接调用父类名
        self.name = name

    def __str__(self):   # 重写该方法,使其可以显示这手牌的总点数
        rep = self.name + ":\t" + super(BJ_Hand,self).__str__()
        if self.total:
            rep += "(" + str(self.total) + ")"
        return rep

    @property
    def total(self):
        # 如果当前这手牌中有一张牌的value为None,则total为None
        for card in self.cards:
            if not card.value:
                return None

        # 把牌的点数加起来,A的点数记为1
            t = 0
            for card in self.cards:
                t += card.value

        # 判断当前这手牌中有没有A
        contains_ace = False
        for card in self.cards:
            if card.value == BJ_Card.ACE_VALUE:
                contains_ace = True

        # 如果有A且total够小,则将A记为11
        if contains_ace and t <= 11:
            # 因为已经为这张A加了1,所有这里只加10
            t += 10

        return t

    def is_busted(self):  # 判断是否爆掉
        return self.total > 21


class BJ_Player(BJ_Hand):   # 玩家类  继承BJ_Hand类
    """A Blackjack Player."""
    def is_hitting(self):   # 是否再次叫牌
        response = Games.Player.ask_yes_no("\n" + self.name +", do you want a hit?(Y/N):")
        return response == "y"

    def bust(self):   # 声明该玩家爆掉
        print(self.name, "busts.")
        self.lose()

    def lose(self):   # 声明玩家输了
        print(self.name, "loses.")

    def win(self):    # 声明玩家赢了
        print(self.name, "wins.")

    def push(self):   # 声明玩家平手
        print(self.name, "pushes.")


class BJ_Dealer(BJ_Hand):   # 庄家类   继承BJ_Hand类
    """A Blackjack Dealer."""
    def is_hitting(self):   # 总点数不足17必须叫牌
        return self.total < 17

    def bust(self):    # 声明庄家爆掉
        print(self.name, "busts.")

    def flip_first_card(self):   # 翻开庄家的第一张牌
        first_card = self.cards[0]
        first_card.flip()


class BJ_Game(object):   # 21点游戏 类,用于创建一局游戏
    """A Blackjack Game."""
    def __init__(self, names):
        self.players = []
        for name in names:   # 玩家加入游戏
            player = BJ_Player(name)
            self.players.append(player)

        self.dealer = BJ_Dealer("Dealer")   # 创建庄家

        self.deck = BJ_Deck()   # 定义一副牌
        self.deck.populate()    # 构造一副牌
        self.deck.shuffle()     # 洗牌

    @property
    def still_playing(self):   # 存活玩家列表
        sp = []
        for player in self.players:
            if not player.is_busted():
                sp.append(player)
        return sp

    def __additional_cards(self, player):   # 向玩家或庄家加发一张牌
        while not player.is_busted() and player.is_hitting():
            self.deck.deal([player])
            print(player)
            if player.is_busted():
                player.bust()

    def play(self):
        # 给每个人发两张牌
        self.deck.deal(self.players + [self.dealer], per_hand=2)
        self.dealer.flip_first_card()  # 隐藏庄家的第一张牌
        for player in self.players:
            print(player)
        print(self.dealer)

        # 给所有玩家加牌
        for player in self.players:
            self.__additional_cards(player)

        self.dealer.flip_first_card()  # 翻开庄家的第一张牌
        if not self.still_playing:
            # 由于所有玩家都爆掉了,因此直接亮出庄家手中的牌即可
            print(self.dealer)
        else:
            # 给庄家加牌
            print(self.dealer)
            self.__additional_cards(self.dealer)

            if self.dealer.is_busted():
                # 所有还在玩的玩家都获胜
                for player in self.still_playing:
                    player.win()
            else:
                # 每位还在玩的玩家分别跟庄家比点数
                for player in self.still_playing:
                    if player.total > self.dealer.total:
                        player.win()
                    elif player.total < self.dealer.total:
                        player.lose()
                    else:
                        player.push()

        # 清空所有人手中的牌
        for player in self.players:
            player.clear()
        self.players.clear()


def main():
    print("\t\tWelcome to Blackjack!\n")
    names = []     # 玩家列表
    number = Games.Player.ask_number("How many players? (1-7):", low = 1, high = 8)
    for i in range(number):     # 添加玩家
        name = input("Enter player name:")
        names.append(name)
    print()

    game = BJ_Game(names)    # 创建游戏

    again = None
    while again != "n":
        game.play()      # 开始游戏
        again = Games.Player.ask_yes_no("\nDO you want to play again?:(Y/N)")   # 再来一局?

# 程序主体
main()
input("\n\nPress the enter key to exit.")


你可能感兴趣的:(Python)