找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 10574|回复: 5

【Python】Python编的纸牌游戏

[复制链接]
发表于 2014-2-10 18:13:47 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
本帖最后由 Jack 于 2014-2-26 15:33 编辑

我貌似还没在这个版块发过贴,现在补上。。。
记得小时候我和我表哥经常会玩一种牌,叫做“七鬼二五三“,你们可能都没玩过,简单介绍一下。


因为是两个人玩的所以规则比较简单:
1.游戏需要两副扑克牌
2.七鬼二五三这5种牌比其他所有牌都大,其中7最大,3最小。
3.其他牌按牌面数字比大小
(即7>Joker>2>5>3>K>Q>J>10>9>8>6>4>A)
4.当数字相同时红色大于黑色
5.游戏开始时一人揭5张牌,随机确定谁先出牌。
6.只能一张一张出,出一张就马上揭一张,保持自己手中始终有5张牌
7.如果自己的牌压不住对方,就得扣一张牌
8.当所有牌揭完时谁扣的牌少谁就赢了,除非。。。
9.若有人在游戏过程中集齐了相同颜色的”七鬼二五三“,则直接获胜


我先放上无图形界面版的代码思路看得更清晰一些,回来有机会再发带图形界面版本的。


首先我创建了一个纸牌模块命名为cards,代码如下(我的Python版本:Python2.5.1):
  1. class Card:
  2.     def __init__(self, suit_id, rank_id):
  3.         self.rank_id = rank_id#rank是牌的符号,如“J”
  4.         self.suit_id = suit_id#suit是牌的花色,如“红桃”
  5.         
  6.         if self.rank_id == 1:                              
  7.             self.rank = "A"                              
  8.             self.value1 = 1#value是牌的值,比大小用的                                 
  9.         elif self.rank_id == 2:                           
  10.             self.rank = "4"                              
  11.             self.value1 = 3                                 
  12.         elif self.rank_id == 3:                           
  13.             self.rank = "6"                             
  14.             self.value1 = 5                                 
  15.         elif self.rank_id == 4:                           
  16.             self.rank = "8"                              
  17.             self.value1 = 7                                 
  18.         elif self.rank_id == 5:                       
  19.             self.rank = "9"               
  20.             self.value1 = 9
  21.         elif self.rank_id == 6:
  22.             self.rank = "10"
  23.             self.value1 = 11
  24.         elif self.rank_id == 7:
  25.             self.rank = "11"
  26.             self.value1 = 13
  27.         elif self.rank_id == 8:
  28.             self.rank = "12"
  29.             self.value1 = 15
  30.         elif self.rank_id == 9:
  31.             self.rank = "13"
  32.             self.value1 = 17
  33.         elif self.rank_id == 10:
  34.             self.rank = "3"
  35.             self.value1 = 19
  36.         elif self.rank_id == 11:
  37.             self.rank = "5"
  38.             self.value1 = 21
  39.         elif self.rank_id == 12:
  40.             self.rank = "2"
  41.             self.value1 = 23
  42.         elif self.rank_id == 14:
  43.             self.rank = "g"#g表示鬼,七鬼二五三的“鬼”
  44.             self.value1 = 25
  45.         elif self.rank_id == 13:
  46.             self.rank = "7"
  47.             self.value1 = 27
  48.         else:
  49.             self.rank = "RankError"                        
  50.             self.value1 = -1                                 

  51.         if self.suit_id == 1:
  52.             self.suit = "H"#H是黑桃——这是为了方便输入,将花色用拼音的首字母代替
  53.             self.value2 = 0#颜色为黑色的value2都为0
  54.         elif self.suit_id == 2:                           
  55.             self.suit = "h"#h是红桃
  56.             self.value2 = 1#颜色为红色的value2都为1
  57.         elif self.suit_id == 3:                             
  58.             self.suit = "m"#m是梅花
  59.             self.value2 = 0
  60.         elif self.suit_id == 4:                             
  61.             self.suit = "f"#f是方片,以上普通牌的花色
  62.             self.value2 = 1
  63.         elif self.suit_id == 5:
  64.             self.suit = "b"#b是黑色
  65.             self.value2 = 0
  66.         elif self.suit_id == 6:
  67.             self.suit = "r"#r是红色,这两个是区分大小王的
  68.             self.value2 = 1
  69.         else:                                               
  70.             self.suit = "SuitError"
  71.             self.value2 = -1
  72.                        
  73.         self.value = self.value1 + self.value2#牌的值=value1+value2,这也解释了为何我设定的value1都是奇数
  74.         self.name = self.suit + self.rank#牌的称呼是花色加符号,如红桃K显示为“hK”
复制代码


然后是主程序:
  1. import random
  2. from cards import Card
  3. ############################################################################################################################################
  4. #函数:初始化
  5. ############################################################################################################################################
  6. def init_cards():
  7.     global deck, p_hand, c_hand, up_card, nc_kou, np_kou, c_kou, p_kou
  8.     deck = []#此为待揭的牌
  9.     nc_kou=np_kou=0#电脑和玩家的扣牌数
  10.     c_kou=[]#电脑扣的牌
  11.     p_kou=[]#玩家扣的牌
  12.     for pear in range(2):#pear是“副”的意思,这里要用2副牌
  13.         for suit in range(1, 5):#suit是“花色”的意思,扑克牌共有4种花色
  14.             for rank in range(1, 14):#rank指牌的符号如“A”、“9”等
  15.                 next = Card(suit, rank)
  16.                 deck.append(next)
  17.     deck.append(Card(5,14))
  18.     deck.append(Card(6,14))#这两行是初始化比较特殊的大王和小王

  19.     p_hand = []#此为玩家手中的牌
  20.     for cards in range(0, 5):
  21.         card = random.choice(deck)
  22.         p_hand.append(card)
  23.         deck.remove(card)
  24.    
  25.     c_hand = []#此为电脑手中的牌   
  26.     for cards in range(0, 5):
  27.         card = random.choice(deck)
  28.         c_hand.append(card)
  29.         deck.remove(card)
  30. ############################################################################################################################################
  31. #函数:轮到玩家
  32. ############################################################################################################################################
  33. def player_turn():
  34.     global deck, p_hand, p_blocked, up_card, over, p_kou, np_kou, card1, p_hand1, pkou,cpou, c_hand, nc_kou, p_first_play,win
  35.     valid_play1 = False
  36.     print "你手中的牌:",
  37.     p_hand1 = p_hand[:]
  38.     p_hand_sorted = []#这两行将玩家的牌按从大到小的顺序排序

  39.     if Blocked:#Blocked为真则牌已被揭完,这种情况下玩家手中的牌会小于5张,因此排序时应特殊处理
  40.         for i in range(1,6-p_blocked):
  41.             card1 = p_hand1[0]
  42.             for card in p_hand1:
  43.                 if card1.value < card.value:
  44.                     card1 = card
  45.             p_hand_sorted.append(card1)
  46.             p_hand1.remove(card1)
  47.     else:   
  48.         for i in range(1,6):
  49.             card1 = p_hand1[0]
  50.             for card in p_hand1:
  51.                 if card1.value < card.value:
  52.                     card1 = card
  53.             p_hand_sorted.append(card1)
  54.             p_hand1.remove(card1)
  55.             
  56.     for card in p_hand_sorted:
  57.         print card.name,#打印出玩家手中的牌
  58.     if (p_hand_sorted[0].value==27 and p_hand_sorted[1].value==25 and p_hand_sorted[2].value==23 and p_hand_sorted[3].value==21 and p_hand_sorted[4].value==19)or(p_hand_sorted[0].value==28 and p_hand_sorted[1].value==26 and p_hand_sorted[2].value==24 and p_hand_sorted[3].value==22 and p_hand_sorted[4].value==20):
  59.         over+=1
  60.         win=1#判断是否为同颜色的七鬼二五三,若为真则本局结束,玩家获胜
  61.     else:
  62.         print "\n你想要做什么?",
  63.         response1 = raw_input ("出牌还是扣牌?" )
  64.         while not valid_play1:#valid是“合法”的意思,用while语句判断玩家的每次输入是否合法,若不合法则让玩家重新输入
  65.             if response1=="出牌":
  66.                 pkou=False
  67.                 valid_play1=True
  68.                 response2=raw_input("请输入你要出的牌:")
  69.                 valid_play2=False
  70.                 while not valid_play2:
  71.                     selected_card1 = None
  72.                     while selected_card1 == None:
  73.                         for card in p_hand:
  74.                             if response2==card.name:
  75.                                 selected_card1=card
  76.                         if selected_card1 == None:
  77.                             response2=raw_input("对不起,你手中没有这张牌,请重新输入:")
  78.                     if p_first_play==True:#若本局玩家第一个出牌,则不用和明牌比大小
  79.                         p_first_play=False
  80.                         valid_play2=True
  81.                         p_hand.remove(selected_card1)
  82.                         up_card=selected_card1
  83.                         print"你出了一张",selected_card1.name
  84.                         if len(deck)>0:
  85.                             card=random.choice(deck)
  86.                             p_hand.append(card)
  87.                             deck.remove(card)
  88.                             print"你揭到一张",card.name
  89.                         else:
  90.                             p_blocked+=1#p_blocked是牌揭完后轮到玩家的次数,通过这个可以知道玩家手中的牌数,是为了给玩家手中的牌排序用的
  91.                             if len(p_hand)==0:#玩家的牌出完了但电脑的牌还没出完,电脑只能将手中的牌全部扣掉
  92.                                 for card in c_hand:
  93.                                     c_kou.append(card)
  94.                                     nc_kou=nc_kou+1
  95.                                 over+=1
  96.                     else:#否则,玩家选择的牌必须大于明牌up_card(也就是电脑刚出的牌),才能出出去
  97.                         if ckou==True:#如果刚才电脑没有出牌而是扣了一张牌,则将明牌的值设为0
  98.                             up_card.value=0
  99.                         if selected_card1.value>up_card.value:
  100.                             valid_play2=True
  101.                             p_hand.remove(selected_card1)
  102.                             up_card=selected_card1
  103.                             print"你出了一张",selected_card1.name
  104.                             if len(deck)>0:#牌没被揭完
  105.                                 card=random.choice(deck)
  106.                                 p_hand.append(card)
  107.                                 deck.remove(card)
  108.                                 print"你揭到一张",card.name
  109.                             else:#牌已被揭完
  110.                                 p_blocked+=1#此处与上面一样
  111.                                 if len(p_hand)==0:
  112.                                     for card in c_hand:
  113.                                         c_kou.append(card)
  114.                                         nc_kou=nc_kou+1
  115.                                     over+=1
  116.                     if not valid_play2:
  117.                         response2=raw_input("对不起,你输入的牌没有对方出的牌大,请重新你输入:")
  118.             elif response1=="扣牌":
  119.                 valid_play1=True
  120.                 pkou=True
  121.                 response3=raw_input("请输入要扣的牌:")
  122.                 valid_play3=False
  123.                 while not valid_play3:
  124.                     selected_card2=None
  125.                     while selected_card2==None:
  126.                         for card in p_hand:
  127.                             if response3==card.name:
  128.                                 selected_card2=card
  129.                                 valid_play3=True
  130.                         if selected_card2==None:
  131.                             response3=raw_input("对不起,你手中没有这张牌,请重新输入:")         
  132.                     p_hand.remove(selected_card2)
  133.                     np_kou=np_kou+1
  134.                     p_kou.append(selected_card2)
  135.                     print"你扣了一张",selected_card2.name
  136.                     if len(deck)>0:
  137.                         card=random.choice(deck)
  138.                         p_hand.append(card)
  139.                         deck.remove(card)
  140.                         print"你揭到一张",card.name
  141.                     else:
  142.                         p_blocked+=1
  143.                         if len(p_hand)==0:
  144.                             over+=1
  145.                     if not valid_play3:
  146.                         response3=raw_input("对不起,你的输入不合法,请重新你输入:")
  147.             if not valid_play1:
  148.                 response1=raw_input("对不起,你的输入不合法,请重新你输入:")
  149.             
  150. ############################################################################################################################################
  151. #函数:轮到电脑
  152. ############################################################################################################################################
  153. def computer_turn():#与player_turn类似,只是不用判断输入是否合法,默认出比明牌大的最小的牌,扣最小的牌
  154.     global c_hand, deck, up_card, over, c_blocked, c_kou, nc_kou, pkou,ckou, p_hand, np_kou,c_first_play
  155.     suit_cards=[]
  156.     ckou=False
  157.     c_hand1 = c_hand[:]
  158.     c_hand_sorted = []

  159.     if Blocked:
  160.         for i in range(1,6-c_blocked):
  161.             card1 = c_hand1[0]
  162.             for card in c_hand1:
  163.                 if card1.value < card.value:
  164.                     card1 = card
  165.             c_hand_sorted.append(card1)
  166.             c_hand1.remove(card1)
  167.     else:   
  168.         for i in range(1,6):
  169.             card1 = c_hand1[0]
  170.             for card in c_hand1:
  171.                 if card1.value < card.value:
  172.                     card1 = card
  173.             c_hand_sorted.append(card1)
  174.             c_hand1.remove(card1)

  175.     if (c_hand_sorted[0].value==27 and c_hand_sorted[1].value==25 and c_hand_sorted[2].value==23 and c_hand_sorted[3].value==21 and c_hand_sorted[4].value==19)or(c_hand_sorted[0].value==28 and c_hand_sorted[1].value==26 and c_hand_sorted[2].value==24 and c_hand_sorted[3].value==22 and c_hand_sorted[4].value==20):
  176.         over+=1
  177.         win=2
  178.     else:   
  179.         if pkou==True or c_first_play==True:
  180.             best_play = c_hand[0]
  181.             for card in c_hand:
  182.                 if card.value < best_play.value:
  183.                     best_play = card
  184.             c_hand.remove(best_play)
  185.             up_card = best_play
  186.             print "电脑出了一张", best_play.name
  187.             if Blocked==True:
  188.                 nc_hand=0
  189.                 for card in c_hand:
  190.                     nc_hand=nc_hand+1
  191.                 print"电脑还剩下%i张牌"%nc_hand
  192.             if len(deck) >0:
  193.                 next_card = random.choice(deck)
  194.                 c_hand.append(next_card)
  195.                 deck.remove(next_card)
  196.             else:
  197.                 c_blocked+=1
  198.                 if len(c_hand)==0:
  199.                     for card in p_hand:
  200.                         p_kou.append(card)
  201.                         np_kou=np_kou+1
  202.                     over+=1
  203.         else:     
  204.             for card in c_hand:
  205.                 if card.value>up_card.value:
  206.                     suit_cards.append(card)
  207.             if len(suit_cards) > 0:
  208.                 best_play = suit_cards[0]
  209.                 for card in suit_cards:
  210.                     if card.value < best_play.value:
  211.                         best_play = card
  212.                 c_hand.remove(best_play)
  213.                 up_card = best_play
  214.                 print "电脑出了一张", best_play.name
  215.                 if len(deck) >0:
  216.                     next_card = random.choice(deck)
  217.                     c_hand.append(next_card)
  218.                     deck.remove(next_card)
  219.                 else:
  220.                     c_blocked+=1
  221.                     if len(c_hand)==0:
  222.                         over+=1
  223.             else:
  224.                 if len(c_hand)>0:
  225.                     selected_card=c_hand[0]
  226.                     for card in c_hand:
  227.                         if card.value<selected_card.value:
  228.                             selected_card=card
  229.                     c_hand.remove(selected_card)
  230.                     nc_kou=nc_kou+1
  231.                     c_kou.append(selected_card)
  232.                     print"电脑扣了一张牌"
  233.                     ckou=True
  234.                     if len(deck) >0:
  235.                         next_card = random.choice(deck)
  236.                         c_hand.append(next_card)
  237.                         deck.remove(next_card)
  238.                     else:
  239.                         c_blocked+=1
  240.                 else:
  241.                     print"电脑的牌出完了"
  242.                     over+=1
  243. ############################################################################################################################################
  244. #主循环
  245. ############################################################################################################################################
  246. done=False#done指的是整个游戏结束,退出程序
  247. p_total=c_total=0#玩家和电脑的大比分
  248. game_time=1#游戏局数
  249. while not done:
  250.     game_done=False#game_done指的是本局游戏结束
  251.     c_blocked=0#牌揭完后轮到电脑的次数
  252.     p_blocked=0#牌揭完后轮到玩家的次数
  253.     Blocked=False#牌被揭完
  254.     over=0#over>0时game_done
  255.     win=0#此为关于集齐同种颜色的七鬼二五三获胜的判断,win==1时玩家胜,win==2时电脑胜
  256.     init_cards()#初始化扑克牌
  257.     n=random.randint(0,2)#随机确定谁第一个出牌
  258.     if n==0:
  259.         p_first_play=True
  260.         c_first_play=False
  261.     else:
  262.         p_first_play=False
  263.         c_first_play=True
  264.     pkou=False
  265.     ckou=False
  266.     print"第%i局"%game_time
  267.     while not game_done:
  268.         if n==0:#此为玩家第一个出牌
  269.             player_turn()
  270.             if c_blocked+p_blocked >= 1:#判断牌是否揭完
  271.                 Blocked=True
  272.             if over>=1:#判断本局是否结束
  273.                 game_done=True
  274.             if not game_done:
  275.                 computer_turn()
  276.                 if c_blocked+p_blocked >= 1:
  277.                     Blocked=True
  278.                 if over>=1:
  279.                     game_done=True
  280.         else:#此为电脑第一个出牌
  281.             computer_turn()
  282.             if c_blocked+p_blocked >= 1:
  283.                 Blocked=True
  284.             if over>=1:
  285.                 game_done=True
  286.             if not game_done:
  287.                 player_turn()
  288.                 if c_blocked+p_blocked>=1:
  289.                     Blocked=True
  290.                 if over>=1:
  291.                     game_done=True
  292.         if Blocked:
  293.             print"牌已经被揭完了"
  294.         if game_done:
  295.             game_time+=1
  296.             if win==1:
  297.                 print"你因集齐了同花色的七鬼二五三而赢得了本局的胜利!"
  298.                 print"你扣了%i张牌,而电脑扣了%i张牌"%(np_kou,nc_kou)
  299.                 p_total+=1
  300.             elif win==2:
  301.                 print"你输了!电脑因集齐了同花色的七鬼二五三而赢得了本局的胜利!"
  302.                 print"你扣了%i张牌,而电脑扣了%i张牌"%(np_kou,nc_kou)
  303.                 c_total+=1
  304.             else:
  305.                 if np_kou<nc_kou:
  306.                     print"你赢了!"
  307.                     print"你扣了%i张牌,而电脑扣了%i张牌"%(np_kou,nc_kou)
  308.                     p_total+=1
  309.                 elif np_kou>nc_kou:
  310.                     print"你输了!"
  311.                     print"你扣了%i张牌,而电脑扣了%i张牌"%(np_kou,nc_kou)
  312.                     c_total+=1
  313.                 else:
  314.                     c_kou_p=p_kou_p=0
  315.                     for card in c_kou:
  316.                         c_kou_p+=card_value
  317.                     for card in p_kou:
  318.                         p_kou_p+=card_value
  319.                     if c_kou_p>p_kou_p:
  320.                         print"你赢了!"
  321.                         print"你和电脑都扣了%i张牌,但你扣的牌价值更小,所以你赢了。"%np_kou
  322.                         p_total+=1
  323.                     elif c_kou_p<p_kou_p:
  324.                         print"你输了!"
  325.                         print"你和电脑都扣了%i张牌,但电脑扣的牌价值更小,所以电脑赢了。"%np_kou
  326.                         c_total+=1
  327.                     else:
  328.                         print"你和电脑战平了!"
  329.                         print"千年一遇啊!你和电脑都扣了%i张牌,而且所扣的牌的价值也相等!但由于该游戏的程序设计者偏心人类,所以这一局算你赢了!"%nc_kou
  330.                         p_total+=1
  331.     play_again=raw_input("再玩一局(Y/N)?")
  332.     if play_again.lower().startswith('y'):#这句让你无论是输入“Y”还是“y”,甚至是“yes”都等价于“y”
  333.         done=False
  334.         print"到目前为止,你和电脑的比分为%i:%i"%(p_total,c_total)
  335.     else:
  336.         done=True
  337. print"最终比分:"
  338. print"你","\t","电脑"
  339. print p_total,"\t",c_total

  340. """变量名命名规律:除扣牌的“扣”字用的是拼音“kou”外,其余变量皆用英文,如电脑简称“c”,玩家简称“p”"""
复制代码




P.S.我个人非常喜欢Python,因为它无疑是我见过的最简洁最清晰的语言。



回复

使用道具 举报

发表于 2014-2-13 13:54:18 | 显示全部楼层
虽然你喜欢Python但是不给注释是个毛情况?
回复 赞! 靠!

使用道具 举报

 楼主| 发表于 2014-2-13 16:23:01 | 显示全部楼层
@0xAA55 ,注释加上了

点评

哟西  发表于 2014-2-13 16:25
回复 赞! 靠!

使用道具 举报

发表于 2021-11-25 10:53:15 | 显示全部楼层
主程序第37行为什么报错,显示无效语法
回复 赞! 靠!

使用道具 举报

发表于 2022-2-3 19:35:29 | 显示全部楼层
是不是可以借鉴逆向斗地主
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-21 22:38 , Processed in 0.036709 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表