-
Notifications
You must be signed in to change notification settings - Fork 1
/
interimpython.py
217 lines (190 loc) · 7.44 KB
/
interimpython.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
import random
class UnoCard:
'''represents an Uno card
attributes:
rank: int from 0 to 9
color: string'''
def __init__(self, rank, color):
'''UnoCard(rank, color) -> UnoCard
creates an Uno card with the given rank and color'''
self.rank = rank
self.color = color
def __str__(self):
'''str(Unocard) -> str'''
return(str(self.color) + ' ' + str(self.rank))
def is_match(self, other):
'''UnoCard.is_match(UnoCard) -> boolean
returns True if the cards match in rank or color, False if not'''
return (self.color == other.color) or (self.rank == other.rank)
class UnoDeck:
'''represents a deck of Uno cards
attribute:
deck: list of UnoCards'''
def __init__(self):
'''UnoDeck() -> UnoDeck
creates a new full Uno deck'''
self.deck = []
for color in ['red', 'blue', 'green', 'yellow']:
self.deck.append(UnoCard(0, color)) # one 0 of each color
for i in range(2):
for n in range(1, 10): # two of each of 1-9 of each color
self.deck.append(UnoCard(n, color))
random.shuffle(self.deck) # shuffle the deck
def __str__(self):
'''str(Unodeck) -> str'''
return 'An Uno deck with '+str(len(self.deck)) + ' cards remaining.'
def is_empty(self):
'''UnoDeck.is_empty() -> boolean
returns True if the deck is empty, False otherwise'''
return len(self.deck) == 0
def deal_card(self):
'''UnoDeck.deal_card() -> UnoCard
deals a card from the deck and returns it
(the dealt card is removed from the deck)'''
return self.deck.pop()
def reset_deck(self, pile):
'''UnoDeck.reset_deck(pile) -> None
resets the deck from the pile'''
if len(self.deck) != 0:
return
self.deck = pile.reset_pile() # get cards from the pile
random.shuffle(self.deck) # shuffle the deck
class UnoPile:
'''represents the discard pile in Uno
attribute:
pile: list of UnoCards'''
def __init__(self, deck):
'''UnoPile(deck) -> UnoPile
creates a new pile by drawing a card from the deck'''
card = deck.deal_card()
self.pile = [card] # all the cards in the pile
def __str__(self):
'''str(UnoPile) -> str'''
return 'The pile has ' + str(self.pile[-1]) + ' on top.'
def top_card(self):
'''UnoPile.top_card() -> UnoCard
returns the top card in the pile'''
return self.pile[-1]
def add_card(self, card):
'''UnoPile.add_card(card) -> None
adds the card to the top of the pile'''
self.pile.append(card)
def reset_pile(self):
'''UnoPile.reset_pile() -> list
removes all but the top card from the pile and
returns the rest of the cards as a list of UnoCards'''
newdeck = self.pile[:-1]
self.pile = [self.pile[-1]]
return newdeck
class UnoPlayer:
'''represents a player of Uno
attributes:
name: a string with the player's name
hand: a list of UnoCards'''
def __init__(self, name, deck):
'''UnoPlayer(name, deck) -> UnoPlayer
creates a new player with a new 7-card hand'''
self.name = name
self.hand = [deck.deal_card() for i in range(7)]
def __str__(self):
'''str(UnoPlayer) -> UnoPlayer'''
return str(self.name) + ' has ' + str(len(self.hand)) + ' cards.'
def get_name(self):
'''UnoPlayer.get_name() -> str
returns the player's name'''
return self.name
def get_hand(self):
'''get_hand(self) -> str
returns a string representation of the hand, one card per line'''
output = ''
for card in self.hand:
output += str(card) + '\n'
return output
def has_won(self):
'''UnoPlayer.has_won() -> boolean
returns True if the player's hand is empty (player has won)'''
return len(self.hand) == 0
def draw_card(self, deck):
'''UnoPlayer.draw_card(deck) -> UnoCard
draws a card, adds to the player's hand
and returns the card drawn'''
card = deck.deal_card() # get card from the deck
self.hand.append(card) # add this card to the hand
return card
def play_card(self, card, pile):
'''UnoPlayer.play_card(card, pile) -> None
plays a card from the player's hand to the pile
CAUTION: does not check if the play is legal!'''
self.hand.remove(card)
pile.add_card(card)
def take_turn(self, deck, pile):
'''UnoPlayer.take_turn(deck, pile) -> None
takes the player's turn in the game
deck is an UnoDeck representing the current deck
pile is an UnoPile representing the discard pile'''
# print player info
print(self.name + ", it's your turn.")
print(pile)
print("Your hand: ")
print(self.get_hand())
# get a list of cards that can be played
topcard = pile.top_card()
matches = [card for card in self.hand if card.is_match(topcard)]
if len(matches) > 0: # can play
for index in range(len(matches)):
# print the playable cards with their number
print(str(index + 1) + ": " + str(matches[index]))
# get player's choice of which card to play
choice = 0
while choice < 1 or choice > len(matches):
choicestr = input("Which do you want to play? ")
if choicestr.isdigit():
choice = int(choicestr)
# play the chosen card from hand, add it to the pile
self.play_card(matches[choice - 1], pile)
else: # can't play
print("You can't play, so you have to draw.")
input("Press enter to draw.")
# check if deck is empty -- if so, reset it
if deck.is_empty():
deck.reset_deck(pile)
# draw a new card from the deck
newcard = self.draw_card(deck)
print("You drew: "+str(newcard))
if newcard.is_match(topcard): # can be played
print("Good -- you can play that!")
self.play_card(newcard,pile)
else: # still can't play
print("Sorry, you still can't play.")
input("Press enter to continue.")
def play_uno(numPlayers):
'''play_uno(numPlayers) -> None
plays a game of Uno with numPlayers'''
# set up full deck and initial discard pile
deck = UnoDeck()
pile = UnoPile(deck)
# set up the players
playerList = []
for n in range(numPlayers):
# get each player's name, then create an UnoPlayer
name = input('Player #' + str(n + 1) + ', enter your name: ')
playerList.append(UnoPlayer(name,deck))
# randomly assign who goes first
currentPlayerNum = random.randrange(numPlayers)
# play the game
while True:
# print the game status
print('-------')
for player in playerList:
print(player)
print('-------')
# take a turn
playerList[currentPlayerNum].take_turn(deck, pile)
# check for a winner
if playerList[currentPlayerNum].has_won():
print(playerList[currentPlayerNum].get_name() + " wins!")
print("Thanks for playing!")
break
# go to the next player
currentPlayerNum = (currentPlayerNum + 1) % numPlayers
play_uno(3)