fork download
  1. #!/usr/bin/env python3
  2.  
  3. from functools import reduce
  4. from itertools import groupby, zip_longest
  5. from random import randint, sample
  6. from sys import argv, exit
  7.  
  8. class Card(object):
  9. '''トランプのオブジェクト'''
  10. def __init__(self, suit, number):
  11. self.suit = suit
  12. self.number = number
  13.  
  14. def __repr__(self):
  15. return f"[{self.suit}:{self.number}]"
  16.  
  17. def drawCard(player1, player2, pos):
  18. '''カードを引く'''
  19. card = player2[pos]
  20. return card, [card] + player1, player2[:pos] + player2[pos + 1:]
  21.  
  22. def discardPair(player):
  23. '''カードを捨てる'''
  24. p = [j[0] for j in [list(i) for key, i in \
  25. groupby(sorted(player, key = lambda x: x.number), \
  26. key = lambda x: x.number)] if len(j) != 2]
  27. return list(set(player) - set(p)), p
  28.  
  29. def selectCard(num):
  30. '''num枚のカードから引くカードを決める'''
  31. return randint(0, num - 1)
  32.  
  33. def dealCards(deck, n):
  34. '''カードを配る'''
  35. i = len(deck) // n
  36. acc = [deck[x:x + i] for x in range(0, len(deck), i)]
  37. return [i[0] + [i[1]] if i[1] != None else i[0] for i in \
  38. zip_longest(acc[:-1], acc[-1])]
  39.  
  40. def shuffle_list(lst, n):
  41. '''カードシャッフルする'''
  42. return reduce(lambda x, y: sample(x, len(lst)), range(n), lst)
  43.  
  44. # メッセージ
  45.  
  46. message = {"inputSelectCard" : "何枚目のカードを引きますか? (0 〜 {0})\n",
  47. "showNumCard" : "プレイヤー{0}のカード: {1}枚\n",
  48. "showCards" : "プレイヤー{0}のカード: {1}\n",
  49. "showDiscardCards" : "プレイヤー{0}が捨てたカード: {1}\n",
  50. "showDrawCard" : "プレイヤー{0} -> プレイヤー{1} : {2}\n",
  51. "showResult" : "プレイヤー{0}の負けです...\n"}
  52.  
  53. def showCards(players):
  54. '''手持ちのカードを表示する文字列'''
  55. return "".join([message["showCards"].format(i, getCardsStr(j))\
  56. if i == 0 \
  57. else message["showNumCard"].format(i, len(j))\
  58. for i, j in enumerate(players)])
  59.  
  60. def showDiscardCards(id, cards):
  61. '''捨てられたカードを表示する文字列'''
  62. if cards == []:
  63. return ""
  64. else:
  65. return message["showDiscardCards"].format(id, getCardsStr(cards))
  66.  
  67. def showDrawCard(id1, id2, card):
  68. '''カードの交換状況を表示する文字列'''
  69. return message["showDrawCard"].format(id1, id2, getCardStr(card))
  70.  
  71. def showResult(id):
  72. '''ゲームの結果を表示する文字列'''
  73. return message["showResult"].format(id)
  74.  
  75. def getCardsStr(cards):
  76. '''Cardオブジェクトのリストを文字列に変換'''
  77. return "".join([getCardStr(i) for i in cards])
  78.  
  79. def getCardStr(card):
  80. '''Cardオブジェクトを文字列に変換'''
  81. return "{0}".format(card)
  82.  
  83. def make_deck():
  84. '''トランプのカードを作成する'''
  85. return [Card("J", "0")] + [Card(i, "A" if j == 1 else "J" if j == 11 \
  86. else "Q" if j == 12 else "K" if j == 13 \
  87. else str(j)) for i in \
  88. ("D", "H", "S", "C") for j in \
  89. range(1, 14)]
  90.  
  91. class World(object):
  92. '''環境'''
  93. def __init__(self, card, clist, discarded, pair, id1, id2, players):
  94. self.card = card
  95. self.clist = clist
  96. self.discarded = discarded
  97. self.pair = pair
  98. self.id1 = id1
  99. self.id2 = id2
  100. self.players = players
  101.  
  102. # read
  103.  
  104. def read(w):
  105. id1, id2, players = w.id1, w.id2, w.players
  106. k = len(players[id2])
  107. if id1 == 0:
  108. return int(input(message["inputSelectCard"].format(k - 1)))
  109. else:
  110. return selectCard(k)
  111.  
  112. # eval
  113.  
  114. def world_go(exp, w):
  115. clist, id1, id2, players = w.clist, w.id1, w.id2, w.players
  116. player1, player2 = players[id1], players[id2]
  117. card, player1, player2 = drawCard(player1, player2, exp)
  118. discarded, player1 = discardPair(player1)
  119. players = insert(id1, player1, insert(id2, player2, players))
  120. new_id1 = next_id(clist, id1 + 1, players)
  121. new_id2 = next_id(clist, new_id1 + 1, players)
  122. return World(card, clist, discarded,
  123. [id1, id2], new_id1, new_id2, players)
  124.  
  125. # print
  126.  
  127. def display(w):
  128. card, discarded, pair, players = w.card, w.discarded, w.pair, w.players
  129. head, tail = pair[0], pair[1]
  130. print(showDrawCard(tail, head, card) + \
  131. showDiscardCards(head, discarded) + \
  132. showCards(players), end ="")
  133. return w
  134.  
  135. def is_game_ends(w):
  136. '''ゲーム終了判定'''
  137. return w.id1 == w.id2
  138.  
  139. # 補助関数
  140.  
  141. def insert(i, player, players):
  142. head, tail = players[:i], players[i:]
  143. return head + [player] + tail[1:]
  144.  
  145. def next_id(clist, i, players):
  146. while True:
  147. pos = clist[i % len(clist)]
  148. player = players[pos]
  149. if player != []:
  150. return pos
  151. i += 1
  152.  
  153. # 初期化
  154.  
  155. def initialize(n):
  156. players = dealCards(shuffle_list(make_deck(), 7), n)
  157. print(showCards(players), end = "")
  158. lst = [discardPair(i) for i in players]
  159. discarded = [i[0] for i in lst]
  160. players = [i[1] for i in lst]
  161. [print(showDiscardCards(i, j), end = "") for i, j in enumerate(discarded)]
  162. print(showCards(players), end = "")
  163. return World(False, list(range(n)), [], [], 0, 1, players)
  164.  
  165. if __name__ == '__main__':
  166. '''REPL'''
  167. w = initialize(int(argv[1]))
  168. while True:
  169. if is_game_ends(w):
  170. print(showResult(w.id1))
  171. exit()
  172. try:
  173. w = display(world_go(read(w), w))
  174. except IndexError:
  175. print("不正な入力です")
  176. except ValueError:
  177. print("不正な入力です")
  178. finally:
  179. w
  180.  
Runtime error #stdin #stdout #stderr 0.21s 23904KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
Traceback (most recent call last):
  File "./prog.py", line 167, in <module>
IndexError: list index out of range