1. 程式人生 > >程式碼Python入門(十、面向物件程式設計實戰)

程式碼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 = "<empty>"
        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入門面向物件程式設計實戰

編寫模組#!/usr/bin/env python # -*- coding: UTF-8 -*- # 簡單遊戲模組 class Player(object): """A player for a game.""" def __init__(self, n

程式碼Python入門檔案

常見檔案運算:output = open('/tmp/spam','w') 建立輸出檔案('w'是指寫入) input = open('data','r') 建立輸入檔案('r'是指讀寫) in

Python入門基礎(9)__面向物件程式設計_3

繼承 子類自動繼承父類的所有方法和屬性 繼承的語法:  class 類名(父類名)   pass 1.子類繼承父類,可以直接使用父類中已經封裝好的方法,不需要再次開發 2.子類可以根據需求,封裝自己特有的屬性和方法 3.當父類中的方法滿足不了子類的需求時,可以對方法進行重寫 例如:

python入門面向對象屬性方法繼承

mage eat div 實例變量 統一 object 地址 面向對象 實例方法 任何東西1)屬性(特征:通常可以用數據來描述)(類變量和實例變量)2)可以做一些動作(方法)類來管理對象的數據。屬性:類變量和實例變量(私有變量)方法: 1)實例方法 2)類方法

Python入門異常處理

Python 異常處理 python提供了兩個非常重要的功能來處理python程式在執行中出現的異常和錯誤。你可以使用該功能來除錯python程式。 異常處理: 本站Python教程會具體介紹。 斷言(Assertions):本站Python教程會具體介紹。

Python入門File檔案方法

Python File(檔案) 方法 file 物件使用 open 函式來建立,下表列出了 file 物件常用的函式: 序號 方法 描述 1 file.close() 關

Python入門檔案I/O

Python 檔案I/O 本章只講述所有基本的的I/O函式,更多函式請參考Python標準文件。 列印到螢幕 最簡單的輸出方法是用print語句,你可以給它傳遞零個或多個用逗號隔開的表示式。此函式把你傳遞的表示式轉換成一個字串表示式,並將結果寫到標準輸出如下: #!/usr/

scala開發快速入門 | 第六篇 面向物件程式設計

類的定義、變數的宣告初始化、private修飾變數、伴生類伴生物件 1)Class 關鍵字宣告一個類Person    2)類成員變數的宣告的時候必須初始化    3)編譯完後 通過位元組碼檔案發現 定義的變數都是private型別。    *    val 宣告的成

scala開發快速入門 | 第六篇 面向物件程式設計

trait簡介在scala中並沒有提供java語言的interface關鍵字來定義介面,而是可以使用trait實現多重繼承,繼承的時候使用extends和with關鍵字。/*定義三個trait*/ trait TraitDemo01 { // 抽象方法定義 def say(

面向物件2— 隱藏屬性私有屬性私有方法__del__ 等四種如何使用測量物件的引用個數

一、隱藏屬性 在一個方法裡面去規範傳遞的屬性值。(更安全),為每一個屬性新增set   get 方法 二、私有屬性 1、在外部使用私有成員的名字時,會提示找不到。 2、例如self.__

Node.js的學習入門module.exports與exports

user clas ret class script say req 引用 ole /*User.js*/ exports.userName = ‘Tom‘; exports.sayHello = function () { return ‘wwwwww‘ } /

為什麼結構化程式設計面向物件程式設計軟體工程架構設計最後沒有成為軟體領域的銀彈

為什麼結構化程式設計、面向物件程式設計、軟體工程、架構設計最後沒有成為軟體領域的銀彈? 從計算機語言開始講,一步一步的概述和講解,最終會有一個結論,大家往後看,即可明白。 1.機器語言(1940年之前) 機器語言,直接使用二進位制碼0和1來表示機器可以識別的指令和資料。 比如0100011111000

201771010134楊其菊《面向物件程式設計(java》第六週學習總結

第十六週學習總結 第一部分:理論知識   1. 程式是一段靜態的程式碼,它是應用程式執行的藍本。程序是程式的一次動態執行,它對應了從程式碼載入、執行至執行完畢的一個完整過程。作業系統為每個程序分配一段獨立的記憶體空間和系統資源,包括:程式碼資料以及堆疊等資源。每一個程序的內部資料和狀態都是完全獨立的。多工

帶你走入angular--angular入門angularJS專案開發流程

用 angularJS 開發的前提是安裝 nodejs。 前端用 AngularJS 開發專案的流程如下:    新建專案資料夾(如webapp)     --> npm安裝全域性bower

從零開始學USBUSB的描述符

USB裝置使用描述符報告其屬性。描述符是具有定義格式的資料結構。每個描述符都以位元組寬度欄位開頭,該欄位包含描述符中的總位元組數,後跟一個標識描述符型別的位元組寬度欄位。 使用描述符允許簡單地儲存各個配置的屬性,因為每個配置可以重用具有相同特徵的其他配置的描述符或描述符的部分。以這種方式,描

四則運算計算器面向物件程式設計思維

寫計算器感知  1,定義介面   public interface ICalculate     {         double Operation(double operatorX, double opertorY);     }  2,定義類  public clas

Python讀書筆記008:面向物件程式設計

編寫類:class Person: ''' Class to represent a person ''' def __init__(self): self.name = '' self.age = 0>&

Go語言學習(二)面向物件程式設計-結構體

1.結構體的初始化方式 例如自定義一個結構體 package main import( "fmt" ) type Rect struct{ //type和struct為關鍵字 x,y float64 //結構體成員 widh

python面向物件程式設計

面向物件程式設計 面向物件--Object Oriented Programming,簡稱oop,是一種程式設計思想。在說面向物件之前,先說一下什麼是程式設計正規化,程式設計正規化你按照什麼方式來去程式設計,去實現一個功能。舉個例子,你要做飯,可以用電磁爐,也可以用煤氣灶。不同的程式設計正規化本質上代表對各

Cris 的Python筆記面向物件其他細節語法

文章目錄 1、類屬性,例項屬性,例項方法,類方法,靜態方法 2、垃圾回收和特殊/魔術方法 1、類屬性,例項屬性,例項方法,類方法,靜態方法 class A(object): '''