Module quickpython.examples.uno
/games/uno.py
Copyright (c) 2019 ShineyDev
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
View Source
"""
/games/uno.py
Copyright (c) 2019 ShineyDev
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
__authors__ = [("shineydev", "contact@shiney.dev")]
__maintainers__ = [("shineydev", "contact@shiney.dev")]
__version_info__ = (2, 0, 0, "final", 0)
__version__ = "{0}.{1}.{2}{3}{4}".format(
*[str(n)[0] if (i == 3) else str(n) for (i, n) in enumerate(__version_info__)]
)
import os
import random
import colorama
import pyfiglet
CARD_COLORS = ["Blue", "Green", "Red", "Yellow"]
CARD_NAMES = [
"0",
"1",
"1",
"2",
"2",
"3",
"3",
"4",
"4",
"5",
"5",
"6",
"6",
"7",
"7",
"8",
"8",
"9",
"9",
"Reverse",
"Skip",
"+2",
]
START_HAND = 7
COLOR_FORMATS = {
"Blue": colorama.Fore.BLUE,
"Green": colorama.Fore.GREEN,
"Red": colorama.Fore.RED,
"Yellow": colorama.Fore.YELLOW,
}
class Card:
def __init__(self, color: str, name: str):
"""
initializes a `Card` object
"""
self.color = color
self.name = name
def format(self) -> str:
"""
formats the card with cli color codes
returns:
:: str :: the formatted card
"""
if self.color != "Wild":
return "{}{}{}".format(COLOR_FORMATS[self.color], self.short_name, colorama.Fore.RESET)
return self.short_name
def is_wild(self) -> bool:
"""
checks whether the `Card` object is a wildcard
returns:
:: bool :: whether the `Card` object is a wildcard
"""
if self.color == "Wild":
return True
return False
@property
def short_name(self) -> str:
"""
generates a short name for the `Card` object
returns:
:: str :: the `Card` object's short name
"""
return "{}{}".format(self.color[:1:], self.name[:1:])
class Deck:
def __init__(self):
"""
initializes a `Deck` object
"""
self.deck = list()
self.in_play = list()
self.in_pile = list()
# add color cards
for color in CARD_COLORS:
for name in CARD_NAMES:
self.deck.append(Card(color, name))
# add wildcards
for i in range(4):
for name in ["Change", "+4"]:
self.deck.append(Card("Wild", name))
self.shuffle()
def flip(self):
"""
flips `self.in_pile` back over into `self.deck`
"""
if not self.deck:
self.deck = self.in_pile
self.in_pile = list()
def is_empty(self) -> bool:
"""
checks whether `self.deck` is empty
returns:
:: bool :: whether `self.deck` is empty
"""
if len(self.deck) == 0:
return True
return False
def reset(self):
"""
re-builds `self.deck`, `self.in_play` and `self.in_pile` and calls `self.shuffle`
"""
self.deck = list()
self.in_play = list()
self.in_pile = list()
for color in CARD_COLORS:
for name in CARD_NAMES:
self.deck.append(Card(color, name))
for i in range(4):
for name in ["Change", "+4"]:
self.deck.append(Card("Wild", name))
self.shuffle()
def shuffle(self):
"""
shuffles `self.deck`
"""
random.shuffle(self.deck)
class Hand:
def __init__(self, deck: Deck):
"""
initializes a `Hand` object
"""
self.deck = deck
self.hand = list()
def __len__(self) -> int:
"""
utilized by built-in `len` function
"""
return len(self.hand)
def generate(self):
"""
fills `self.hand` up to len( `START_HAND` )
"""
for i in range(START_HAND):
card = self.deck.deck.pop()
self.hand.append(card)
self.deck.in_play.append(card)
def reset(self):
"""
sets `self.hand` to an empty list
"""
self.hand = list()
class Player:
def __init__(self, name: str, deck: Deck):
"""
initializes a `Player` object
"""
self.name = name
self.deck = deck
self.hand = Hand(self.deck)
def is_winner(self) -> bool:
"""
checks whether the `Player` has won the game
returns:
:: bool :: whether the `Player` has won the game
"""
if len(self.hand) == 0:
return True
return False
class Uno:
def __init__(self, player_count: int):
"""
initializes an `Uno` object
"""
self.player_count = player_count
def game(self):
"""
starts the game
"""
self.deck = Deck()
self.players = list()
self.current_player = 0
self.clockwise = True
self.message = ""
self.color = None
for i in range(self.player_count):
self.players.append(Player("P{}".format(i + 1), self.deck))
self.players[i].hand.generate()
card = self.deck.deck.pop()
self.top_card = card
self.deck.in_pile.append(card)
if len(self.players) == 2:
players = [self.players[0].name, self.players[1].name, "--", "--"]
elif len(self.players) == 3:
players = [
self.players[0].name,
self.players[1].name,
self.players[2].name,
"--",
]
elif len(self.players) == 4:
players = [
self.players[0].name,
self.players[1].name,
self.players[2].name,
self.players[3].name,
]
while not any([player.is_winner() for player in self.players]):
cls()
if self.color:
color = COLOR_FORMATS[self.color]
else:
color = ""
if self.current_player == 0:
pointers = ["/\\", " ", " ", " "]
elif self.current_player == 1:
pointers = [" ", ">", " ", " "]
elif self.current_player == 2:
pointers = [" ", " ", "\\/", " "]
elif self.current_player == 3:
pointers = [" ", " ", " ", "<"]
print(
"""
{4} left in deck
{0}
{8}
{3} {11} {5}{6}{7} {9} {1}
{10}
{2}
""".format(
*players,
len(self.deck.deck),
color,
self.top_card.format(),
colorama.Fore.RESET,
*pointers
)
)
print()
if self.message:
print(self.message)
print()
self.message = ""
print(self.players[self.current_player].name)
for card in self.players[self.current_player].hand.hand:
print(card.format(), end=" ")
print()
print()
card = input("choose a card to place;\n> ").strip().upper()
if card == "+":
if self.deck.is_empty():
self.deck.flip()
card = self.deck.deck.pop()
self.players[self.current_player].hand.hand.append(card)
self.deck.in_play.append(card)
continue
try:
card_index = int(card)
if card_index not in range(1, len(self.players[self.current_player].hand.hand) + 1):
self.message = (
"card must be an integer in range 1 - {0} or the card name".format(
len(self.players[self.current_player].hand.hand)
)
)
continue
card = self.players[self.current_player].hand.hand[card_index - 1]
except (ValueError) as e:
if card not in [
card.short_name for card in self.players[self.current_player].hand.hand
]:
self.message = (
"card must be an integer in range 1 - {0} or the card name".format(
len(self.players[self.current_player].hand.hand)
)
)
continue
card = self.players[self.current_player].hand.hand[
[card.short_name for card in self.players[self.current_player].hand.hand].index(
card
)
]
if card.color == "Wild":
pass
elif self.top_card.color == "Wild":
if card.color != self.color:
self.message = "you can't place that card"
continue
elif card.color == self.top_card.color:
pass
elif card.name == self.top_card.name:
pass
else:
self.message = "you can't place that card"
continue
card = self.players[self.current_player].hand.hand.pop(
self.players[self.current_player].hand.hand.index(card)
)
self.top_card = card
self.deck.in_play.remove(card)
self.deck.in_pile.append(card)
add_cards = 0
skip_player = False
reverse = False
color = ""
if self.top_card.name == "Change":
self.color = ""
while self.color not in ["Blue", "Green", "Red", "Yellow"]:
cls()
print(
"""
{4} left in deck
{0}
{8}
{3} {11} {5}{6}{7} {9} {1}
{10}
{2}
""".format(
*players,
len(self.deck.deck),
color,
self.top_card.format(),
colorama.Fore.RESET,
*pointers
)
)
print()
if self.message:
print(self.message)
print()
self.message = ""
print(self.players[self.current_player].name)
for card in self.players[self.current_player].hand.hand:
print(card.format(), end=" ")
print()
print()
self.color = input("choose a color;\n> ").strip().capitalize()
elif self.top_card.name == "+4":
self.color = ""
while self.color not in ["Blue", "Green", "Red", "Yellow"]:
cls()
print(
"""
{4} left in deck
{0}
{8}
{3} {11} {5}{6}{7} {9} {1}
{10}
{2}
""".format(
*players,
len(self.deck.deck),
color,
self.top_card.format(),
colorama.Fore.RESET,
*pointers
)
)
print()
if self.message:
print(self.message)
print()
self.message = ""
print(self.players[self.current_player].name)
for card in self.players[self.current_player].hand.hand:
print(card.format(), end=" ")
print()
print()
self.color = input("choose a color;\n> ").strip().capitalize()
add_cards = 4
skip_player = True
elif self.top_card.name == "+2":
add_cards = 2
skip_player = True
elif self.top_card.name == "Skip":
skip_player = True
elif self.top_card.name == "Reverse":
reverse = True
if reverse:
self.clockwise = not self.clockwise
if len(self.players) == 2:
# we don't want to change the player
continue
if self.clockwise:
next_player = self.current_player + 1
else:
next_player = self.current_player - 1
if next_player > (len(self.players) - 1):
next_player -= len(self.players)
elif next_player < 0:
next_player += len(self.players)
if add_cards:
for i in range(add_cards):
if self.deck.is_empty():
self.deck.flip()
card = self.deck.deck.pop()
self.players[next_player].hand.hand.append(card)
self.deck.in_play.append(card)
if skip_player:
if self.clockwise:
next_player = self.current_player + 2
else:
next_player = self.current_player - 2
if next_player > (len(self.players) - 1):
next_player -= len(self.players)
elif next_player < 0:
next_player += len(self.players)
self.current_player = next_player
winner = [player for player in self.players if player.is_winner()][0]
cls()
print()
print(
"""
{4} left in deck
{0}
{8}
{3} {11} {5}{6}{7} {9} {1}
{10}
{2}
""".format(
*players,
len(self.deck.deck),
color,
self.top_card.format(),
colorama.Fore.RESET,
*pointers
)
)
print()
print("{0} wins!".format(winner.name))
def start(self):
"""
calls `self.game` in a 'would you like to play again?' loop
"""
choice = "y"
while choice.startswith("y"):
cls()
print(pyfiglet.figlet_format("Uno"))
print()
input("enter to play\nctrl + c to quit to main menu\n\n")
self.game()
choice = input("\nwould you like to play again?\n> ").strip()
if __name__ == "__main__":
players = None
while not isinstance(players, int):
cls()
players = input("players;\n> ")
try:
players = int(players)
except (ValueError) as e:
pass
game = Uno(players)
game.start()
Variables
CARD_COLORS
CARD_NAMES
COLOR_FORMATS
START_HAND
Classes
Card
class Card(
color: str,
name: str
)
View Source
class Card:
def __init__(self, color: str, name: str):
"""
initializes a `Card` object
"""
self.color = color
self.name = name
def format(self) -> str:
"""
formats the card with cli color codes
returns:
:: str :: the formatted card
"""
if self.color != "Wild":
return "{}{}{}".format(COLOR_FORMATS[self.color], self.short_name, colorama.Fore.RESET)
return self.short_name
def is_wild(self) -> bool:
"""
checks whether the `Card` object is a wildcard
returns:
:: bool :: whether the `Card` object is a wildcard
"""
if self.color == "Wild":
return True
return False
@property
def short_name(self) -> str:
"""
generates a short name for the `Card` object
returns:
:: str :: the `Card` object's short name
"""
return "{}{}".format(self.color[:1:], self.name[:1:])
Instance variables
short_name
generates a short name for the Card
object
returns:
:: str :: the Card
object's short name
Methods
format
def format(
self
) -> str
formats the card with cli color codes
returns: :: str :: the formatted card
View Source
def format(self) -> str:
"""
formats the card with cli color codes
returns:
:: str :: the formatted card
"""
if self.color != "Wild":
return "{}{}{}".format(COLOR_FORMATS[self.color], self.short_name, colorama.Fore.RESET)
return self.short_name
is_wild
def is_wild(
self
) -> bool
checks whether the Card
object is a wildcard
returns:
:: bool :: whether the Card
object is a wildcard
View Source
def is_wild(self) -> bool:
"""
checks whether the `Card` object is a wildcard
returns:
:: bool :: whether the `Card` object is a wildcard
"""
if self.color == "Wild":
return True
return False
Deck
class Deck(
)
View Source
class Deck:
def __init__(self):
"""
initializes a `Deck` object
"""
self.deck = list()
self.in_play = list()
self.in_pile = list()
# add color cards
for color in CARD_COLORS:
for name in CARD_NAMES:
self.deck.append(Card(color, name))
# add wildcards
for i in range(4):
for name in ["Change", "+4"]:
self.deck.append(Card("Wild", name))
self.shuffle()
def flip(self):
"""
flips `self.in_pile` back over into `self.deck`
"""
if not self.deck:
self.deck = self.in_pile
self.in_pile = list()
def is_empty(self) -> bool:
"""
checks whether `self.deck` is empty
returns:
:: bool :: whether `self.deck` is empty
"""
if len(self.deck) == 0:
return True
return False
def reset(self):
"""
re-builds `self.deck`, `self.in_play` and `self.in_pile` and calls `self.shuffle`
"""
self.deck = list()
self.in_play = list()
self.in_pile = list()
for color in CARD_COLORS:
for name in CARD_NAMES:
self.deck.append(Card(color, name))
for i in range(4):
for name in ["Change", "+4"]:
self.deck.append(Card("Wild", name))
self.shuffle()
def shuffle(self):
"""
shuffles `self.deck`
"""
random.shuffle(self.deck)
Methods
flip
def flip(
self
)
flips self.in_pile
back over into self.deck
View Source
def flip(self):
"""
flips `self.in_pile` back over into `self.deck`
"""
if not self.deck:
self.deck = self.in_pile
self.in_pile = list()
is_empty
def is_empty(
self
) -> bool
checks whether self.deck
is empty
returns:
:: bool :: whether self.deck
is empty
View Source
def is_empty(self) -> bool:
"""
checks whether `self.deck` is empty
returns:
:: bool :: whether `self.deck` is empty
"""
if len(self.deck) == 0:
return True
return False
reset
def reset(
self
)
re-builds self.deck
, self.in_play
and self.in_pile
and calls self.shuffle
View Source
def reset(self):
"""
re-builds `self.deck`, `self.in_play` and `self.in_pile` and calls `self.shuffle`
"""
self.deck = list()
self.in_play = list()
self.in_pile = list()
for color in CARD_COLORS:
for name in CARD_NAMES:
self.deck.append(Card(color, name))
for i in range(4):
for name in ["Change", "+4"]:
self.deck.append(Card("Wild", name))
self.shuffle()
shuffle
def shuffle(
self
)
shuffles self.deck
View Source
def shuffle(self):
"""
shuffles `self.deck`
"""
random.shuffle(self.deck)
Hand
class Hand(
deck: quickpython.examples.uno.Deck
)
View Source
class Hand:
def __init__(self, deck: Deck):
"""
initializes a `Hand` object
"""
self.deck = deck
self.hand = list()
def __len__(self) -> int:
"""
utilized by built-in `len` function
"""
return len(self.hand)
def generate(self):
"""
fills `self.hand` up to len( `START_HAND` )
"""
for i in range(START_HAND):
card = self.deck.deck.pop()
self.hand.append(card)
self.deck.in_play.append(card)
def reset(self):
"""
sets `self.hand` to an empty list
"""
self.hand = list()
Methods
generate
def generate(
self
)
fills self.hand
up to len( START_HAND
)
View Source
def generate(self):
"""
fills `self.hand` up to len( `START_HAND` )
"""
for i in range(START_HAND):
card = self.deck.deck.pop()
self.hand.append(card)
self.deck.in_play.append(card)
reset
def reset(
self
)
sets self.hand
to an empty list
View Source
def reset(self):
"""
sets `self.hand` to an empty list
"""
self.hand = list()
Player
class Player(
name: str,
deck: quickpython.examples.uno.Deck
)
View Source
class Player:
def __init__(self, name: str, deck: Deck):
"""
initializes a `Player` object
"""
self.name = name
self.deck = deck
self.hand = Hand(self.deck)
def is_winner(self) -> bool:
"""
checks whether the `Player` has won the game
returns:
:: bool :: whether the `Player` has won the game
"""
if len(self.hand) == 0:
return True
return False
Methods
is_winner
def is_winner(
self
) -> bool
checks whether the Player
has won the game
returns:
:: bool :: whether the Player
has won the game
View Source
def is_winner(self) -> bool:
"""
checks whether the `Player` has won the game
returns:
:: bool :: whether the `Player` has won the game
"""
if len(self.hand) == 0:
return True
return False
Uno
class Uno(
player_count: int
)
View Source
class Uno:
def __init__(self, player_count: int):
"""
initializes an `Uno` object
"""
self.player_count = player_count
def game(self):
"""
starts the game
"""
self.deck = Deck()
self.players = list()
self.current_player = 0
self.clockwise = True
self.message = ""
self.color = None
for i in range(self.player_count):
self.players.append(Player("P{}".format(i + 1), self.deck))
self.players[i].hand.generate()
card = self.deck.deck.pop()
self.top_card = card
self.deck.in_pile.append(card)
if len(self.players) == 2:
players = [self.players[0].name, self.players[1].name, "--", "--"]
elif len(self.players) == 3:
players = [
self.players[0].name,
self.players[1].name,
self.players[2].name,
"--",
]
elif len(self.players) == 4:
players = [
self.players[0].name,
self.players[1].name,
self.players[2].name,
self.players[3].name,
]
while not any([player.is_winner() for player in self.players]):
cls()
if self.color:
color = COLOR_FORMATS[self.color]
else:
color = ""
if self.current_player == 0:
pointers = ["/\\", " ", " ", " "]
elif self.current_player == 1:
pointers = [" ", ">", " ", " "]
elif self.current_player == 2:
pointers = [" ", " ", "\\/", " "]
elif self.current_player == 3:
pointers = [" ", " ", " ", "<"]
print(
"""
{4} left in deck
{0}
{8}
{3} {11} {5}{6}{7} {9} {1}
{10}
{2}
""".format(
*players,
len(self.deck.deck),
color,
self.top_card.format(),
colorama.Fore.RESET,
*pointers
)
)
print()
if self.message:
print(self.message)
print()
self.message = ""
print(self.players[self.current_player].name)
for card in self.players[self.current_player].hand.hand:
print(card.format(), end=" ")
print()
print()
card = input("choose a card to place;\n> ").strip().upper()
if card == "+":
if self.deck.is_empty():
self.deck.flip()
card = self.deck.deck.pop()
self.players[self.current_player].hand.hand.append(card)
self.deck.in_play.append(card)
continue
try:
card_index = int(card)
if card_index not in range(1, len(self.players[self.current_player].hand.hand) + 1):
self.message = (
"card must be an integer in range 1 - {0} or the card name".format(
len(self.players[self.current_player].hand.hand)
)
)
continue
card = self.players[self.current_player].hand.hand[card_index - 1]
except (ValueError) as e:
if card not in [
card.short_name for card in self.players[self.current_player].hand.hand
]:
self.message = (
"card must be an integer in range 1 - {0} or the card name".format(
len(self.players[self.current_player].hand.hand)
)
)
continue
card = self.players[self.current_player].hand.hand[
[card.short_name for card in self.players[self.current_player].hand.hand].index(
card
)
]
if card.color == "Wild":
pass
elif self.top_card.color == "Wild":
if card.color != self.color:
self.message = "you can't place that card"
continue
elif card.color == self.top_card.color:
pass
elif card.name == self.top_card.name:
pass
else:
self.message = "you can't place that card"
continue
card = self.players[self.current_player].hand.hand.pop(
self.players[self.current_player].hand.hand.index(card)
)
self.top_card = card
self.deck.in_play.remove(card)
self.deck.in_pile.append(card)
add_cards = 0
skip_player = False
reverse = False
color = ""
if self.top_card.name == "Change":
self.color = ""
while self.color not in ["Blue", "Green", "Red", "Yellow"]:
cls()
print(
"""
{4} left in deck
{0}
{8}
{3} {11} {5}{6}{7} {9} {1}
{10}
{2}
""".format(
*players,
len(self.deck.deck),
color,
self.top_card.format(),
colorama.Fore.RESET,
*pointers
)
)
print()
if self.message:
print(self.message)
print()
self.message = ""
print(self.players[self.current_player].name)
for card in self.players[self.current_player].hand.hand:
print(card.format(), end=" ")
print()
print()
self.color = input("choose a color;\n> ").strip().capitalize()
elif self.top_card.name == "+4":
self.color = ""
while self.color not in ["Blue", "Green", "Red", "Yellow"]:
cls()
print(
"""
{4} left in deck
{0}
{8}
{3} {11} {5}{6}{7} {9} {1}
{10}
{2}
""".format(
*players,
len(self.deck.deck),
color,
self.top_card.format(),
colorama.Fore.RESET,
*pointers
)
)
print()
if self.message:
print(self.message)
print()
self.message = ""
print(self.players[self.current_player].name)
for card in self.players[self.current_player].hand.hand:
print(card.format(), end=" ")
print()
print()
self.color = input("choose a color;\n> ").strip().capitalize()
add_cards = 4
skip_player = True
elif self.top_card.name == "+2":
add_cards = 2
skip_player = True
elif self.top_card.name == "Skip":
skip_player = True
elif self.top_card.name == "Reverse":
reverse = True
if reverse:
self.clockwise = not self.clockwise
if len(self.players) == 2:
# we don't want to change the player
continue
if self.clockwise:
next_player = self.current_player + 1
else:
next_player = self.current_player - 1
if next_player > (len(self.players) - 1):
next_player -= len(self.players)
elif next_player < 0:
next_player += len(self.players)
if add_cards:
for i in range(add_cards):
if self.deck.is_empty():
self.deck.flip()
card = self.deck.deck.pop()
self.players[next_player].hand.hand.append(card)
self.deck.in_play.append(card)
if skip_player:
if self.clockwise:
next_player = self.current_player + 2
else:
next_player = self.current_player - 2
if next_player > (len(self.players) - 1):
next_player -= len(self.players)
elif next_player < 0:
next_player += len(self.players)
self.current_player = next_player
winner = [player for player in self.players if player.is_winner()][0]
cls()
print()
print(
"""
{4} left in deck
{0}
{8}
{3} {11} {5}{6}{7} {9} {1}
{10}
{2}
""".format(
*players,
len(self.deck.deck),
color,
self.top_card.format(),
colorama.Fore.RESET,
*pointers
)
)
print()
print("{0} wins!".format(winner.name))
def start(self):
"""
calls `self.game` in a 'would you like to play again?' loop
"""
choice = "y"
while choice.startswith("y"):
cls()
print(pyfiglet.figlet_format("Uno"))
print()
input("enter to play\nctrl + c to quit to main menu\n\n")
self.game()
choice = input("\nwould you like to play again?\n> ").strip()
Methods
game
def game(
self
)
starts the game
View Source
def game(self):
"""
starts the game
"""
self.deck = Deck()
self.players = list()
self.current_player = 0
self.clockwise = True
self.message = ""
self.color = None
for i in range(self.player_count):
self.players.append(Player("P{}".format(i + 1), self.deck))
self.players[i].hand.generate()
card = self.deck.deck.pop()
self.top_card = card
self.deck.in_pile.append(card)
if len(self.players) == 2:
players = [self.players[0].name, self.players[1].name, "--", "--"]
elif len(self.players) == 3:
players = [
self.players[0].name,
self.players[1].name,
self.players[2].name,
"--",
]
elif len(self.players) == 4:
players = [
self.players[0].name,
self.players[1].name,
self.players[2].name,
self.players[3].name,
]
while not any([player.is_winner() for player in self.players]):
cls()
if self.color:
color = COLOR_FORMATS[self.color]
else:
color = ""
if self.current_player == 0:
pointers = ["/\\", " ", " ", " "]
elif self.current_player == 1:
pointers = [" ", ">", " ", " "]
elif self.current_player == 2:
pointers = [" ", " ", "\\/", " "]
elif self.current_player == 3:
pointers = [" ", " ", " ", "<"]
print(
"""
{4} left in deck
{0}
{8}
{3} {11} {5}{6}{7} {9} {1}
{10}
{2}
""".format(
*players,
len(self.deck.deck),
color,
self.top_card.format(),
colorama.Fore.RESET,
*pointers
)
)
print()
if self.message:
print(self.message)
print()
self.message = ""
print(self.players[self.current_player].name)
for card in self.players[self.current_player].hand.hand:
print(card.format(), end=" ")
print()
print()
card = input("choose a card to place;\n> ").strip().upper()
if card == "+":
if self.deck.is_empty():
self.deck.flip()
card = self.deck.deck.pop()
self.players[self.current_player].hand.hand.append(card)
self.deck.in_play.append(card)
continue
try:
card_index = int(card)
if card_index not in range(1, len(self.players[self.current_player].hand.hand) + 1):
self.message = (
"card must be an integer in range 1 - {0} or the card name".format(
len(self.players[self.current_player].hand.hand)
)
)
continue
card = self.players[self.current_player].hand.hand[card_index - 1]
except (ValueError) as e:
if card not in [
card.short_name for card in self.players[self.current_player].hand.hand
]:
self.message = (
"card must be an integer in range 1 - {0} or the card name".format(
len(self.players[self.current_player].hand.hand)
)
)
continue
card = self.players[self.current_player].hand.hand[
[card.short_name for card in self.players[self.current_player].hand.hand].index(
card
)
]
if card.color == "Wild":
pass
elif self.top_card.color == "Wild":
if card.color != self.color:
self.message = "you can't place that card"
continue
elif card.color == self.top_card.color:
pass
elif card.name == self.top_card.name:
pass
else:
self.message = "you can't place that card"
continue
card = self.players[self.current_player].hand.hand.pop(
self.players[self.current_player].hand.hand.index(card)
)
self.top_card = card
self.deck.in_play.remove(card)
self.deck.in_pile.append(card)
add_cards = 0
skip_player = False
reverse = False
color = ""
if self.top_card.name == "Change":
self.color = ""
while self.color not in ["Blue", "Green", "Red", "Yellow"]:
cls()
print(
"""
{4} left in deck
{0}
{8}
{3} {11} {5}{6}{7} {9} {1}
{10}
{2}
""".format(
*players,
len(self.deck.deck),
color,
self.top_card.format(),
colorama.Fore.RESET,
*pointers
)
)
print()
if self.message:
print(self.message)
print()
self.message = ""
print(self.players[self.current_player].name)
for card in self.players[self.current_player].hand.hand:
print(card.format(), end=" ")
print()
print()
self.color = input("choose a color;\n> ").strip().capitalize()
elif self.top_card.name == "+4":
self.color = ""
while self.color not in ["Blue", "Green", "Red", "Yellow"]:
cls()
print(
"""
{4} left in deck
{0}
{8}
{3} {11} {5}{6}{7} {9} {1}
{10}
{2}
""".format(
*players,
len(self.deck.deck),
color,
self.top_card.format(),
colorama.Fore.RESET,
*pointers
)
)
print()
if self.message:
print(self.message)
print()
self.message = ""
print(self.players[self.current_player].name)
for card in self.players[self.current_player].hand.hand:
print(card.format(), end=" ")
print()
print()
self.color = input("choose a color;\n> ").strip().capitalize()
add_cards = 4
skip_player = True
elif self.top_card.name == "+2":
add_cards = 2
skip_player = True
elif self.top_card.name == "Skip":
skip_player = True
elif self.top_card.name == "Reverse":
reverse = True
if reverse:
self.clockwise = not self.clockwise
if len(self.players) == 2:
# we don't want to change the player
continue
if self.clockwise:
next_player = self.current_player + 1
else:
next_player = self.current_player - 1
if next_player > (len(self.players) - 1):
next_player -= len(self.players)
elif next_player < 0:
next_player += len(self.players)
if add_cards:
for i in range(add_cards):
if self.deck.is_empty():
self.deck.flip()
card = self.deck.deck.pop()
self.players[next_player].hand.hand.append(card)
self.deck.in_play.append(card)
if skip_player:
if self.clockwise:
next_player = self.current_player + 2
else:
next_player = self.current_player - 2
if next_player > (len(self.players) - 1):
next_player -= len(self.players)
elif next_player < 0:
next_player += len(self.players)
self.current_player = next_player
winner = [player for player in self.players if player.is_winner()][0]
cls()
print()
print(
"""
{4} left in deck
{0}
{8}
{3} {11} {5}{6}{7} {9} {1}
{10}
{2}
""".format(
*players,
len(self.deck.deck),
color,
self.top_card.format(),
colorama.Fore.RESET,
*pointers
)
)
print()
print("{0} wins!".format(winner.name))
start
def start(
self
)
calls self.game
in a 'would you like to play again?' loop
View Source
def start(self):
"""
calls `self.game` in a 'would you like to play again?' loop
"""
choice = "y"
while choice.startswith("y"):
cls()
print(pyfiglet.figlet_format("Uno"))
print()
input("enter to play\nctrl + c to quit to main menu\n\n")
self.game()
choice = input("\nwould you like to play again?\n> ").strip()