2021年7月11日 星期日

文字介面地圖的繪製

學習目標:
  • 了解 Python 如何處理文字介面下的地圖列印方式!

處理過程實作
  1. 請先思考一個平面上,二維圖形的排列方式:           
         
       
       
    PS:
    • 使用全形字來表示一個佔有空間,連空白也是!
    • 第一行為地產名稱,名稱最右方,放置地產所有者的代號
    • 第二行放置地產的價值
    • 第三行放置剛好路過的玩家代號
    • 計算的結果,就是48個格式X27行的全形字地圖大小
  2. 試著寫個程式,印出第一行 playMap.py:
    import Stores
    
    class playMap:
    
        def printMap(self):
            mapEmpty = " "
            mapWall = "|"
            myStores = Stores.Stores()
            # 印出第一行
            for i in range(0,7):
                print(mapEmpty + self.getStoreName(myStores.getStoreData(str(i))[1]),end = '')
                if (i < 6):
                    print(mapWall,end='')
                else:
                    print()
    
        # 控制每一行的格式大小
        def getStoreName(self,data):
            storeName = ""
            if (len(data) <= 4):
                storeName = data + (4-len(data))*" "
            return storeName
    if __name__ == "__main__":
        myMap = playMap()
        myMap.printMap()
    
  3. 持續修改,將第二行的部份,數字轉成全形,列印出來:
    import Stores
    
    class playMap:
    
        def printMap(self):
            mapEmpty = " "
            mapWall = "|"
            myStores = Stores.Stores()
            # 印出第一行
            for i in range(0,7):
                if (myStores.getStoreData(str(i))[2] == "-1"):
                    owner = " "
                else:
                    owner = self.transferNo(myStores.getStoreData(str(i))[2])
    
                print(mapEmpty + self.getStoreName(myStores.getStoreData(str(i))[1]) + owner,end = '')
                if (i < 6):
                    print(mapWall,end='')
                else:
                    print()
            # 印出第二行
            for i in range(0,7):
                print(mapEmpty + self.getStoreName(self.transferNo(myStores.getStoreData(str(i))[3])) + mapEmpty,end = '')
                if (i < 6):
                    print(mapWall,end='')
                else:
                    print()        
    
        # 控制每一行的格式大小
        def getStoreName(self,data):
            storeName = ""
            if (len(data) <= 4):
                storeName = data + (4-len(data))*" "
            return storeName
    
        # 半形全形轉換功能
        def transferNo(self,data):
            nums = (0,"0",1,"1",2,"2",3,"3",4,"4",5,"5",6,"6",7,"7",8,"8",9,"9")
            tmp = []
            dataleng = len(data)
            for j in range(0,dataleng):
                tmp.append(0)
    
            newdata = ""
            for i in range(1,dataleng+1):
                tmp[(dataleng-i)] = int(data)%10
                data = int(int(data) / 10)
    
            for i in range(0,len(tmp)):
                newdata += nums[nums.index(tmp[i])+1]
    
            return newdata
    
    if __name__ == "__main__":
        myMap = playMap()
        myMap.printMap()
    
  4. 印出第三行,請考慮清楚每位玩家的位置:
    import Stores
    
    class playMap:
    
        def printMap(self,userPo):
            mapEmpty = " "
            mapWall = "|"
            myStores = Stores.Stores()
            # 印出第一行
            for i in range(0,7):
                if (myStores.getStoreData(str(i))[2] == "-1"):
                    owner = " "
                else:
                    owner = self.transferNo(myStores.getStoreData(str(i))[2])
    
                print(mapEmpty + self.getStoreName(myStores.getStoreData(str(i))[1]) + owner,end = '')
                if (i < 6):
                    print(mapWall,end='')
                else:
                    print()
            # 印出第二行
            for i in range(0,7):
                print(mapEmpty + self.getStoreName(self.transferNo(myStores.getStoreData(str(i))[3])) + mapEmpty,end = '')
                if (i < 6):
                    print(mapWall,end='')
                else:
                    print()
    
            # 印出第三行
            po_tmp = ""
            for i in range(0,7):
                po_tmp = mapEmpty
                for j in range(len(userPo)):
                    if (userPo[j] == str(i)):
                        po_tmp = po_tmp + self.transferNo(str(j+1))
                    else:
                        po_tmp = po_tmp + mapEmpty
                po_tmp = po_tmp + mapEmpty
                if (i < 6):
                   print(po_tmp + mapWall,end = '')
                else:
                   print(po_tmp,end = '')
            print()
    
        # 控制每一行的格式大小
        def getStoreName(self,data):
            storeName = ""
            if (len(data) <= 4):
                storeName = data + (4-len(data))*" "
            return storeName
    
        # 半形全形轉換功能
        def transferNo(self,data):
            nums = (0,"0",1,"1",2,"2",3,"3",4,"4",5,"5",6,"6",7,"7",8,"8",9,"9")
            tmp = []
            dataleng = len(data)
            for j in range(0,dataleng):
                tmp.append(0)
    
            newdata = ""
            for i in range(1,dataleng+1):
                tmp[(dataleng-i)] = int(data)%10
                data = int(int(data) / 10)
    
            for i in range(0,len(tmp)):
                newdata += nums[nums.index(tmp[i])+1]
    
            return newdata
    
    if __name__ == "__main__":
        myMap = playMap()
        userPo = ['6','3','4','1']
        myMap.printMap(userPo)
    
  5. 再印出4~7行:
    import Stores
    
    class playMap:
    
        def printMap(self,userPo):
            mapEmpty = " "
            mapWall = "|"
            mapLine = "-"
            myStores = Stores.Stores()
            # 印出第一行
            for i in range(0,7):
                if (myStores.getStoreData(str(i))[2] == "-1"):
                    owner = " "
                else:
                    owner = self.transferNo(myStores.getStoreData(str(i))[2])
    
                print(mapEmpty + self.getStoreName(myStores.getStoreData(str(i))[1]) + owner,end = '')
                if (i < 6):
                    print(mapWall,end='')
                else:
                    print()
            # 印出第二行
            for i in range(0,7):
                print(mapEmpty + self.getStoreName(self.transferNo(myStores.getStoreData(str(i))[3])) + mapEmpty,end = '')
                if (i < 6):
                    print(mapWall,end='')
                else:
                    print()
    
            # 印出第三行
            po_tmp = ""
            for i in range(0,7):
                po_tmp = mapEmpty
                for j in range(len(userPo)):
                    if (userPo[j] == str(i)):
                        po_tmp = po_tmp + self.transferNo(str(j+1))
                    else:
                        po_tmp = po_tmp + mapEmpty
                po_tmp = po_tmp + mapEmpty
                if (i < 6):
                   print(po_tmp + mapWall,end = '')
                else:
                   print(po_tmp,end = '')
            print()
    
            # 印出第四行
            print(48*mapLine)
    
            # 印出第五行,修改自第一行
            for i in (23,7):
                if (myStores.getStoreData(str(i))[2] == "-1"):
                    owner = " "
                else:
                    owner = self.transferNo(myStores.getStoreData(str(i))[2])
            lines = ""
            lines = lines + mapEmpty + self.getStoreName(myStores.getStoreData(str(23))[1]) + owner + mapWall
            lines = lines + 34*mapEmpty
            lines = lines + mapWall + mapEmpty + self.getStoreName(myStores.getStoreData(str(7))[1]) + owner
            print(lines)
            
            # 印出第六行,修改自第五行
            lines = ""
            lines = lines + mapEmpty + self.getStoreName(self.transferNo(myStores.getStoreData(str(23))[3])) + owner + mapWall
            lines = lines + 34*mapEmpty
            lines = lines + mapWall + mapEmpty + self.getStoreName(self.transferNo(myStores.getStoreData(str(7))[3])) + owner
            print(lines)
    
            # 印出第七行,修改自第三行
            po_tmp = ""
            lines = mapEmpty
            for j in range(len(userPo)):
                if (userPo[j] == str(str(23))):
                    po_tmp = po_tmp + self.transferNo(str(j+1))
                else:
                    po_tmp = po_tmp + mapEmpty
            po_tmp = po_tmp + mapEmpty
            lines = lines + po_tmp + mapWall
            po_tmp = ""
            lines = lines + 34*mapEmpty
            for j in range(len(userPo)):
                if (userPo[j] == str(str(7))):
                    po_tmp = po_tmp + self.transferNo(str(j+1))
                else:
                    po_tmp = po_tmp + mapEmpty
            po_tmp = po_tmp + mapEmpty
            lines =  lines + mapWall + po_tmp
            print(lines)
    
        # 控制每一行的格式大小
        def getStoreName(self,data):
            storeName = ""
            if (len(data) <= 4):
                storeName = data + (4-len(data))*" "
            return storeName
    
        # 半形全形轉換功能
        def transferNo(self,data):
            nums = (0,"0",1,"1",2,"2",3,"3",4,"4",5,"5",6,"6",7,"7",8,"8",9,"9")
            tmp = []
            dataleng = len(data)
            for j in range(0,dataleng):
                tmp.append(0)
    
            newdata = ""
            for i in range(1,dataleng+1):
                tmp[(dataleng-i)] = int(data)%10
                data = int(int(data) / 10)
    
            for i in range(0,len(tmp)):
                newdata += nums[nums.index(tmp[i])+1]
    
            return newdata
    
    if __name__ == "__main__":
        myMap = playMap()
        userPo = ['6','23','7','1']
        myMap.printMap(userPo)
    
處理主要流程程式,導入地圖程式:
  1. 將上述程完成後,加入主要程式流程 main.py:
    # 引用 random 類別中的 randrange() 函數
    from random import randrange
    
    # 引用 Player 物件
    import Player
    
    # 引用 Chance 物件
    import Chance
    
    # 引用 Stores 物件
    import Stores
    
    # 引用 playMap 物件
    import playMap
    
    # 常用函式、參數設定區域
    ## 遊戲方格總數
    areas = 24
    
    ## 處理玩家是否有經過「開始」
    def playerPo(steps):
        if (steps >= areas):
            return (steps % areas)
        else:
            return steps
    
    # 程式流程開始
    # 使用 if __name__
    if __name__ == "__main__":
    
        # 要求玩家要輸入遊戲人數
        players_num = eval(input("請輸入玩家人數:"))
    
        # 建立玩家物件
        players = []
    
        # 按照遊戲人數,使用 Player 類別
        # 逐次產生玩家名稱、玩家代號、玩家初始遊戲幣、玩家初始位置等物件內容
        for i in range(players_num):
            players.append(Player.Player())
            # 要求玩家輸入玩家名稱
            players[i].setName(input("請輸入玩家名稱:"))
            
        # 輸出資料
        for i in range(players_num):
            print(players[i].getName())
            print(players[i].getPo())
            print(players[i].getMoney())
            
        # 設定玩家順序值
        i = 0
        myMap = playMap.playMap()
        players_po = ['0','0','0','0']
        
        # 開始進行遊戲
        while True:    
        ##### a.) 印出地圖
            myMap.printMap(players_po)
        ##### b.) 擲骰子
            input("按下 Enter 進行遊戲.....")
            newstep = randrange(1,6)
            print(players[i].getName() + "擲骰子:" + str(newstep) + " 點")
            print(players[i].getName() + "前進中...")
            # 設定玩家新的位置
            players[i].setPo(newstep)
            
        ##### c.) 移動到骰子點數的框格
            newpo = players[i].getPo() 
            # I. 可能經過起點
            if newpo >= areas:
                newpo = playerPo(newpo)
                if newpo == 0:
                    print("玩家回到「開始」位置:", newpo)
                elif newpo < (areas/4):
                    print("玩家越過「開始」位置:", newpo)
            players_po[i] = str(newpo)
            myMap.printMap(players_po)
            print("玩家在新位置:",newpo)
            #  II. 可能落在邊角框格
            if (newpo  == 6):
                print("玩家休息一天")
            elif (newpo  == 18):
                print("玩家再玩一次")
    
            #  III. 可能是在機會與命運框格
            ## 機會的地圖編號是 3,15 兩個號碼
            elif ((newpo == 3) or (newpo == 15)):
                myChance = Chance.Chance()
                chances = myChance.choice()    
                print("玩家中機會:",chances[0])
    
            #  IV. 可能是在地產框格
            else:
                playerStore = Stores.Stores()
                store = playerStore.getStoreData(str(newpo))
                ## 判斷是否有人己取得該地產所有權了
                if store[2] == '-1':
                    print("該地產無人所有!")
                else:
                    print("該地產為:" + str(players[int(store[2])].getName()) + "所有")
               
        ##### e.)
            # 輪至下一位玩家
            i = i + 1
            if (i >= players_num):
                i = i - players_num
            
        ##### f.) 結束遊戲條件
            ends = input("是否結束遊戲?Y:是 N:繼續")
            if ((ends == "Y") or (ends == "y")):
                break