Python之十点半小游戏

源码(详细注释):

  1 # -*- coding: utf-8 -*-
  2 
  3 #游戏类
  4 class Game:
  5     #一般游戏进程,从读取存档开始
  6     def Process(self):
  7         #初始回合数为0
  8         self.rounds = 0
  9         #初始Continue标记为True
 10         self.Continue = True
 11         #读取游戏
 12         self.Read(self)
 13         #当Continue标记为True时循环进行游戏
 14         while self.Continue:
 15             #创建一个玩家集合
 16             self.player_set = set()
 17             #初始化扑克牌
 18             self.Card.InitCard(self)
 19             #每轮的开始都将重置每名玩家的部分信息
 20             for i in range(self.player_amount):
 21                 self.player_set.add(i)
 22                 self.player_list[i].banker = False
 23                 self.player_list[i].want = True
 24                 self.player_list[i].inboom = True
 25                 self.player_list[i].bet = 0
 26                 #下面两句是加牌操作,每名玩家1张
 27                 self.player_list[i].hand = [self.cards[0]]
 28                 del self.cards[0]
 29             #进入叫庄环节
 30             self.Banker(self,self.player_amount,self.player_set)
 31     #游戏进程,从零开始
 32     def Start(self):
 33         #初始化扑克牌
 34         self.Card.InitCard(self)
 35         #初始化玩家
 36         self.PlayerInit(self)
 37     #牌点计算器,用于在创建扑克牌对象时提供每张牌的点数
 38     #输入参数:{牌号}
 39     def Calculate(rank):
 40         #字典,数据来源
 41         dictionary = {"A":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9,"10":10,"J":0.5,"Q":0.5,"K":0.5}
 42         #约定点数并返回
 43         value = dictionary[rank]
 44         return value
 45     #玩家初始化
 46     def PlayerInit(self):
 47         while True:
 48             try:
 49                 #输入玩家数量
 50                 self.player_amount = int(input(">>>欢迎来到全新的十点半Lite!\n>>>请您设定玩家数量,最低2人,最高4人:"))
 51                 #当玩家数量正确时执行子程序
 52                 if self.player_amount in (2,3,4):
 53                     self.__PlayerInit(self,self.player_amount)
 54                     break
 55                 #否则提示错误
 56                 else:
 57                     print("\n>>>不支持该数量的玩家哟,换个数试试吧!<<<")
 58             #输入非数字时报错
 59             except:
 60                 print("\n>>>系统监测到了错误,但是系统不知道怎么解决")
 61     #玩家初始化子程序
 62     #输入参数:{玩家数量}
 63     def __PlayerInit(self,player_amount):
 64         #创建空列表,用于放置玩家名
 65         player_name = []
 66         print("\n>>>本局游戏共有{}名玩家~!<<<".format(self.player_amount))
 67         #输入玩家名并添加到列表
 68         for i in range(self.player_amount):
 69             player_name.append(input("您好,{}号玩家!\n-请输入您的大名:".format(i + 1)))
 70         #初始化游戏
 71         self.InitGame(self,player_name,self.player_amount,2)
 72     #初始化游戏,有三种初始化方法
 73     #输入参数:{玩家名称列表,玩家数量,初始化方式}
 74     def InitGame(self,player_name,player_amount,Action):
 75         #Action参数小于3时执行游戏初始化
 76         if Action < 3:
 77             #创建玩家列表,玩家集合
 78             self.player_list = []
 79             self.player_set = set()
 80             #给每位玩家添加初始数据
 81             for i in range(self.player_amount):
 82                 self.player_list.append(self.Players(i,player_name[i],[self.cards[0]],False,True,True,0,100,0))
 83                 self.player_set.add(i)
 84                 #因为中间涉及到了发牌,所以要从牌堆删除发给玩家的牌
 85                 del self.cards[0]
 86             #若Action等于2追加执行,进入叫庄环节
 87             if Action == 2:
 88                 self.Banker(self,self.player_amount,self.player_set)
 89         #Action参数等于3时不进行初始化,直接进入叫庄环节(成功读取到游戏数据)
 90         if Action == 3:
 91             self.Banker(self,self.player_amount,self.player_set)
 92     #叫庄环节
 93     #输入参数:{玩家数量,玩家集合}
 94     def Banker(self,player_amount,player_set):
 95         #进入叫庄意味着游戏正式开始,回合数将加1
 96         self.rounds += 1
 97         while True:
 98             try:
 99                 #输入庄家的玩家序号
100                 banker_number = int(input("第{}局游戏开始,请您选出一名庄家,庄家不需要下注哟!\n>>>请指定庄家的序号,1-{}号都可以:".format(self.rounds,self.player_amount))) - 1
101                 #若玩家序号没有错误将执行子程序
102                 if banker_number in range(self.player_amount):
103                     self.__Banker(self,self.player_amount,banker_number,self.player_set)
104                     break
105                 #玩家序号输入错误则报错
106                 else:
107                     print(">>>请输入正确的玩家序号哟,再试一次吧!<<<")
108             #若输入非数字将报出此错
109             except:
110                 print("\n>>>系统监测到了错误,但是系统不知道怎么解决")
111     #叫庄子程序
112     #输入参数:{玩家数量,庄家编号,玩家集合}
113     def __Banker(self,player_amount,banker_number,player_set):
114         #修改该名玩家的庄家标识符
115         self.player_list[banker_number].banker = True
116         #从玩家集合中除去这名庄家,将其变为闲家集合
117         self.player_set -= {banker_number}
118         print("\n>>>{}号玩家:[{}]通过选举成为了庄家!".format(banker_number + 1,self.player_list[banker_number].name))
119         #进入下注环节
120         self.Bet(self,self.player_amount,banker_number,self.player_set)
121     #下注环节
122     #输入参数:{玩家数量,庄家编号,闲家集合}
123     def Bet(self,player_amount,banker_number,player_set):
124         #对于每名闲家
125         for i in self.player_set:
126             while True:
127                 try:
128                     #输入下注值
129                     bet = int(input("-闲家{}:[{}],轮到你下注了!\n>>>最低下1$,最高可以下20$:".format(i + 1,self.player_list[i].name)))
130                     #限制下注值在1-20范围之间
131                     if bet in range(1,21):
132                         #进入下注子程序
133                         if self.__Bet(self,i,bet):
134                             break
135                     #若下注不符合范围规定则报错
136                     else:
137                         print(">>>下注区间是1-20$,请注意下呢!<<<")
138                 #若输入非整数将报此错
139                 except:
140                     print("\n>>>系统监测到了错误,但是系统不知道怎么解决")
141         #进入补牌环节
142         self.AugmentCard(self,self.player_amount,banker_number,self.player_set)
143     #补牌环节
144     #输入参数:{玩家数量,庄家编号,闲家集合}
145     def AugmentCard(self,player_amount,banker_number,player_set):
146         #初始化补牌轮数为0
147         count = 0
148         #完成补牌的玩家数为0
149         success = 0
150         #设定补牌未完成标识为True
151         insuccess = True
152         print("\n>>>补牌阶段开始,闲家优先!<<<\n")
153         #若补牌未完成标识为True
154         while insuccess:
155             #补牌轮数加1
156             count += 1
157             print("-第{}轮补牌开始!".format(count))
158             #对于每名闲家
159             for i in self.player_set:
160                 #若该名闲家的要牌标记为True且不爆牌标记为True
161                 if self.player_list[i].want and self.player_list[i].inboom:
162                     #玩家可决定是否补牌,若输入为Y、y将进入补牌子程序
163                     if input(">>>闲家{}:[{}]轮到你选择了!\n-目前牌点为{},若要补牌请输入y:".format(i + 1,self.player_list[i].name,self.__calculate(self,i))) in ("Y","y"):
164                         self.__AugmentCard(self,i)
165                     #玩家选择不补牌则将玩家的要牌标记设为False
166                     else:
167                         print("\n>闲家{}不敢补了。".format(i + 1))
168                         self.player_list[i].want = False
169                 #补牌完成了,完成补牌的玩家数量加1
170                 else:
171                     success += 1
172                     #若所有闲家均完成补牌,则将未完成标识符设为False,循环将停止
173                     if success == self.player_amount - 1:
174                         insuccess = False
175         #接下来轮到庄家补牌了
176         i = banker_number
177         while True:
178             #循环条件为庄家要牌标记为True且不爆牌标记为True
179             if self.player_list[i].want and self.player_list[i].inboom:
180                 #玩家可决定是否补牌,若输入为Y、y将进入补牌子程序
181                 if input("\n>>>庄家{}:[{}]请注意!现在轮到你选择了!\n-目前牌点为{},若要补牌请输入y:".format(i + 1,self.player_list[i].name,self.__calculate(self,i))) in ("Y","y"):
182                     self.__AugmentCard(self,i)
183                 #玩家选择不补牌则将玩家的要牌标记设为False
184                 else:
185                     print("\n>庄家{}不敢补了。".format(i + 1))
186                     self.player_list[i].want = False
187             #所有玩家完成补牌,结束循环
188             else:
189                 break
190         #进入决胜环节
191         self.Fight(self,self.player_amount,banker_number)
192     #决胜环节
193     #输入参数:{玩家数量,庄家编号}
194     def Fight(self,player_amount,banker_number):
195         #为了方便决出胜负,创建点数列表用于存放所有玩家的牌点
196         point_list = []
197         #创建奖金,初始值为0
198         bouns = 0
199         #对所有玩家进行操作
200         for i in range(self.player_amount):
201             #奖金为玩家下注总和
202             bouns += self.player_list[i].bet
203             #若玩家未爆牌(手牌点数和小于10.5)
204             if self.player_list[i].point <= 10.5:
205                 #则在点数列表中添加相应玩家的手牌点数
206                 point_list.append(self.player_list[i].point)
207             else:
208                 #否则为这名玩家添加大小为"-1"的点数
209                 point_list.append(-1)
210         #判断玩家是否全爆,判断依据为:"-1"数量是否小于玩家的总数
211         if point_list.count(-1) < self.player_amount:
212             #玩家未全爆,则找出点数最大值
213             biggest = max(point_list)
214             #若点数最大值出现重复现象
215             if point_list.count(biggest) > 1:
216                 #创建获胜玩家列表,重复且最高的玩家都将获胜
217                 winner = [i for i,repeat in enumerate(point_list) if repeat == biggest]
218                 print("\n>>>本轮游戏共有{}名玩家获胜:".format(len(winner)))
219                 #对于每名获胜玩家,进入发奖子程序
220                 for i in winner:
221                     self.__Bouns(self,i,bouns/len(winner),banker_number)
222             #若点数最大值未出现重复现象
223             else:
224                 #获胜者为该最大点数的所有者
225                 i = point_list.index(biggest)
226                 print("\n>>>恭喜玩家{}:[{}]获得本轮的胜利!<<<".format(i + 1,self.player_list[i].name))
227                 #进入发奖子程序
228                 self.__Bouns(self,i,bouns,banker_number)
229         #若所有玩家都爆牌将不进行任何发奖
230         else:
231             print(">>>\n你们都爆了,这里的{}$谁也拿不走!".format(bouns),banker_number)
232         #程序将在此停顿,接到回车键命令后继续进行
233         input("\n>>>戳回车键展示所有玩家的数据<<<\n")
234         #保存游戏数据
235         self.Save(self,self.player_amount)
236         #进入Show程序,程序在展示玩家数据的同时将判断是否有玩家输光,若未出现输光情况则可以继续进行下一轮游戏
237         if self.Show(self,self.player_amount):
238             if input("\n>>>还来一把?\n-输入n可以结束游戏,不输n继续游戏:") in ("n","N"):
239                 #若玩家选择不继续,将结束游戏
240                 self.GameExit(self)
241         #若Show程序发现有玩家已经输光
242         else:
243             print(">>>啊哦,好像有人输光了!<<<")
244             #结束游戏
245             self.GameExit(self)
246     #结束游戏的程序
247     def GameExit(self):
248         self.Continue = False
249         input("\n>>>十点半游戏到此结束!!๑乛◡乛๑\n\n-请按回车键结束程序")
250     #保存游戏的程序
251     #输入参数:{玩家数量}
252     def Save(self,player_amount):
253         #首先进入保存游戏的子程序,子程序将判断系统是否能够保存游戏数据
254         if self.__Save(self):
255             #引入时间库,记录存档时间
256             import datetime as date
257             #重新格式化时间文本
258             time = date.datetime.now().strftime("%Y.%m.%d-%H:%M:%S")
259             #保存数据
260             with open("save.txt","w+") as data:
261                 #游戏数据:保存时间、游戏回合、玩家数量
262                 data.writelines("{}[Savetime]\n{}[Rounds]{}[Players]\n".format(time,self.rounds,self.player_amount))
263                 #玩家数据:玩家序号、玩家名称、玩家金钱
264                 for i in range(self.player_amount):    
265                     data.writelines("{}[Num]{}[Name]{}[Money]\n".format(self.player_list[i].number,self.player_list[i].name,int(self.player_list[i].money)))
266     #保存游戏的子程序,用于判断能否保存游戏数据
267     def __Save(self):
268         try:
269             with open("save.txt","w+"):
270                 #若执行成功程序将返回True
271                 return True
272         #执行失败将报错
273         except:
274             print("\n>>>不知为何,系统无法保存游戏数据<<<")
275     #读取游戏的程序
276     def Read(self):
277         #首先进入读取游戏的子程序,子程序将判断系统是否能够读取游戏数据
278         if self.__Read(self):
279             #读取游戏存档
280             with open("save.txt","r") as data:
281                 save = data.readlines()
282             #让玩家选择是开始新游戏还是继续上一局
283             if input(">>>系统检测到您已存在游戏数据:\n{}\n{}\n>>>是否要接着玩呢?输y继续玩,输其它开始新游戏:".format((save[0])[0:save[0].find("[Savetime]")],save[1])) in ("y","Y"):
284                 player_name = []
285                 #读取玩家数量信息
286                 self.player_amount = int((save[1])[save[1].find("[Rounds]")+8:save[1].find("[Players]")])
287                 #读取游戏回合信息
288                 self.rounds = int((save[1])[0:save[1].find("[Rounds]")])
289                 #读取玩家名称信息
290                 for i in range(self.player_amount):
291                     player_name.append((save[i+2])[save[i+2].find("[Num]")+5:save[i+2].find("[Name]")])
292                 #初始化扑克牌
293                 self.Card.InitCard(self)
294                 #初始化游戏,初始化方法为1
295                 self.InitGame(self,player_name,self.player_amount,1)
296                 #读取玩家金钱信息
297                 for i in range(self.player_amount):
298                     self.player_list[i].money = int((save[i+2])[save[i+2].find("[Name]")+6:save[i+2].find("[Money]")])
299                 #清除读取的save,释放内存
300                 del save
301                 input(">>>已恢复上局游戏数据~<<<\n\n-戳回车键查看玩家信息并继续游戏")
302                 #展示所有玩家信息
303                 self.Show(self,self.player_amount)
304                 #初始化游戏,初始化方法为3
305                 self.InitGame(self,player_name,self.player_amount,3)
306             #若玩家选择不读取,则开始新游戏
307             else:
308                 self.Start(self)
309     #读取游戏的子程序
310     def __Read(self):
311         try:
312             #检验是否能正常读取游戏数据,若能读取则返回True
313             with open("save.txt","r"):
314                 return True
315         #否则将直接开始新游戏
316         except:
317             print(">>>系统未检测到游戏数据喔,新游戏将开始<<<")
318             self.Start(self)
319     #展示所有玩家信息的程序
320     #输入参数:{玩家数量}
321     def Show(self,player_amount):
322         #此Flag用于记录玩家金钱是否不足以进行下一局游戏,初始值为True
323         Flag = True
324         #对于所有玩家
325         for i in range(self.player_amount):
326             #展示玩家信息
327             print("\n>>>玩家{}:[{}]\n>>>庄家:{}\n>>>手牌:".format(i + 1,self.player_list[i].name,self.player_list[i].banker),end = "")
328             #若此玩家金钱不足,Flag将设定为False,游戏将结束
329             if int(self.player_list[i].money) <= 0:
330                 Flag = False
331             #展示玩家信息
332             for n in range(len(self.player_list[i].hand)):
333                 print(self.player_list[i].hand[n].suit + self.player_list[i].hand[n].rank,end = " ")
334             print("\n>>>手牌点数:{}\n>>>本轮下注:{}$\n>>>钱包余额:{}$".format(self.player_list[i].point,self.player_list[i].bet,self.player_list[i].money))
335         return Flag
336     #发奖子程序
337     #输入参数:{获奖者玩家编号,奖金,庄家编号}
338     def __Bouns(self,i,bouns,banker_number):
339         #若该名获奖者不是庄家
340         if not self.player_list[i].banker:
341             #从庄家的钱包中扣除该名获奖者在本轮中的下注金额,并将其加入奖池
342             self.player_list[banker_number].money -= self.player_list[i].bet
343             bouns += self.player_list[i].bet
344             print("\n>>>闲家获胜,庄家要额外付给他与他下注同样多的钱,总共{}$!".format(self.player_list[i].bet))
345         #发奖给获奖者
346         self.player_list[i].money += bouns
347         print(">>>玩家{}:[{}]共获得{}$奖金,钱包余额为{}$!".format(i + 1,self.player_list[i].name,bouns,self.player_list[i].money))
348     #补牌子程序
349     #输入参数:{要牌者玩家编号}
350     def __AugmentCard(self,i):
351         print("\n-玩家{}:[{}]抽到了{}{}:{}点!".format(i + 1,self.player_list[i].name,self.cards[0].suit,self.cards[0].rank,self.cards[0].value))
352         #从牌堆顶摸一张牌给玩家
353         self.player_list[i].hand.append(self.cards[0])
354         del self.cards[0]
355         #玩家得牌后计算该名玩家的手牌点数,若大于10.5则爆牌
356         if self.__calculate(self,i) > 10.5:
357             print(">>>目前的点数为{}!您爆了,神仙也救不了您!".format(self.player_list[i].point))
358             #修改不爆牌标记
359             self.player_list[i].inboom = False
360         #若未爆则对赌徒进行鼓励,增加赌场的预期收入
361         else:
362             print(">>>目前的点数为{}!再接再励哟!".format(self.player_list[i].point))
363     #玩家牌点计算器
364     #输入参数:{被计算牌点的玩家编号}
365     def __calculate(self,i):
366         #计算前先将记录玩家牌点的属性归零,因为稍后将给予新的数值
367         self.player_list[i].point = 0
368         #将玩家手中每张牌的点数加起来
369         for n in range(len(self.player_list[i].hand)):
370             self.player_list[i].point += self.player_list[i].hand[n].value
371         #返回该名玩家的牌点
372         return self.player_list[i].point
373     #下注子程序
374     #输入参数:{下注者编号,下注金额}
375     def __Bet(self,i,bet):
376         #判断该名玩家是否下假注(钱包里根本没那么多钱)
377         if (self.player_list[i].money - bet) >= 0:
378             #未超额,正常下注
379             self.player_list[i].money -= bet
380             self.player_list[i].bet = bet
381             print("\n>>>闲家{}:[{}]下了{}$,钱包还剩{}$!".format(i + 1,self.player_list[i].name,bet,self.player_list[i].money))
382             return True
383         #超额了,返回False给主程序,主程序将给予回应
384         else:
385             print(">>>您的钱不够,您只有{}$!请重新下注!".format(self.player_list[i].money))
386             return False
387     #玩家类
388     class Players:
389         #初始化方法,包含了玩家对象的9个属性
390         #9个属性:{序号,名称,手牌,庄家标记,要牌标记,不爆牌标记,下注,金钱,牌点}
391         def __init__(self,number,name,hand,banker,want,inboom,bet,money,point):
392            self.number = number
393            self.name = name
394            self.hand = hand
395            self.banker = banker
396            self.want = want
397            self.inboom = inboom
398            self.bet = bet
399            self.money = money
400            self.point = point
401     #扑克牌类
402     class Card:
403         #初始化方法,包含了扑克牌对象的3个属性
404         #3个属性:{花色,牌号,所代表的点数}
405         def __init__(self,suit,rank,value):
406            self.suit = suit
407            self.rank = rank
408            self.value = value
409         #创建一副全新的扑克牌
410         def InitCard(self):
411             #创建扑克牌盒子
412             self.cards = []
413             #创建花色
414             for suit in ["","","",""]:
415                 #创建牌号
416                 for rank in ["A","2","3","4","5","6","7","8","9","10","J","Q","K"]:
417                     #实例化扑克牌对象,并赋予属性,然后装进扑克牌盒子
418                     self.cards.append(self.Card(suit,rank,self.Calculate(rank)))
419             #引入随机模块
420             from random import shuffle as refresh
421             #洗牌
422             refresh(self.cards)
423 #游戏开始运行
424 Game.Process(Game)

 

试玩:

在这里插入图片描述

十点半游戏介绍

在这里插入图片描述

posted @ 2021-02-19 18:12  BugMiaowu2021  阅读(282)  评论(0编辑  收藏  举报