Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Import
- from random import randint, sample, shuffle
- class uno:
- def __init__(self):
- self.pile = []
- self.stack = self.deck()
- self.playerHands = {} # A dictionary containing each player's hand
- self.gameOrder = [] # A list containing each player's name, which are also the keys for the dictionary above
- self.numberOfPlayers = 0
- self.counter = 0
- self.lastPlayedCard = None
- self.clockwise = True
- self.endGame = False
- # Main Program
- self.initGame()
- while True:
- self.gameRound()
- if self.endGame:
- break
- if self.clockwise:
- self.counter += 1
- elif not self.clockwise:
- self.counter -= 1
- self.whoIsPlayingNextRound()
- # ███ ███ █████ ██ ███ ██ ███████ ██ ██ ███ ██ ██████ ████████ ██ ██████ ███ ██ ███████
- # ████ ████ ██ ██ ██ ████ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ████ ██ ██
- # ██ ████ ██ ███████ ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███████
- # ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
- # ██ ██ ██ ██ ██ ██ ████ ██ ██████ ██ ████ ██████ ██ ██ ██████ ██ ████ ███████
- def initGame(self):
- """ Initialise the game """
- self.numberOfPlayers = int(input('Please input the number of players in your game : '))
- while (10 < self.numberOfPlayers) or (self.numberOfPlayers < 2):
- self.numberOfPlayers = int(input('Please input the number of players in your game (2 min|10 max) : '))
- maxNumberCards = int(108 / self.numberOfPlayers)
- numberCardsHands = int(input("Input the number of cards you want in each player's hand at the begining of the game (< {}) : ".format(maxNumberCards)))
- while (maxNumberCards <= numberCardsHands) or (numberCardsHands <= 1):
- numberCardsHands = int(input("Input the number of cards you want in each player's hand at the begining of the game (< {}) : ".format(maxNumberCards)))
- playerNames = []
- for i in range(self.numberOfPlayers):
- names = input("Input the name of the player {} : ".format(i))
- while names in playerNames:
- names = input("Input the name of the player {} (You can't use the same name twice) : ".format(i))
- playerNames.append(names)
- for j in playerNames:
- self.playerHands[j] = []
- for k in range(self.numberOfPlayers):
- self.currentPlayer = playerNames[k]
- self.draw(numberCardsHands)
- ans = ['y', 'Y', 'n', 'N']
- keepOrder = input('The current direction of rotation is defined by the order in which you entered the name of the players, do you want to randomize it? [Y/N] ')
- while keepOrder not in ans:
- keepOrder = input('The current direction of rotation is defined by the order in which you entered the name of the players, do you want to randomize it? [Y/N] ')
- self.gameOrder = list(playerNames)
- if keepOrder in ['y', 'Y']:
- shuffle(self.gameOrder)
- self.currentPlayer = self.gameOrder[0]
- self.draw(1, True) # Put a random card of the deck on top of the pile
- self.lastPlayedCard = self.pile[0]
- def deck(self):
- """ Create an already shuffled deck of cards """
- deck = sample(range(1, 109), 108)
- return deck
- def draw(self, numCard, init=False):
- """ Draw X cards and append them in the hand of the player """
- for i in range(numCard):
- r = randint(0, len(self.stack) - 1)
- drawnCard = self.stack[r]
- self.stack.pop(self.stack.index(drawnCard))
- if not init:
- self.playerHands[self.currentPlayer].append(drawnCard)
- elif init:
- self.pile.append(drawnCard)
- return
- return drawnCard
- def automaticallyDraw(self):
- print("You don't have any card to match the one on the pile.")
- print('The game will automatically draw cards until you can play.')
- counter = 0
- while True:
- if not self.stack:
- self.refillStack()
- dc = self.draw(1)
- canPlayThisCard = self.setDownVerification(dc)
- counter += 1
- if canPlayThisCard:
- self.pile.append(dc)
- self.playerHands[self.currentPlayer].remove(dc)
- self.lastPlayedCard = dc
- print('You drew {} cards before being able to play. The last one has been played for you automatically.')
- break
- def refillStack(self):
- """ Refill the stack with the cards in the pile (Called when the stack becomes empty) """
- lastCard = self.pile[-1]
- self.pile.pop(self.pile.index(lastCard))
- self.stack += list(self.pile)
- shuffle(self.stack)
- self.pile = [lastCard]
- def showPlayerHand(self, victory=False):
- """ Display the hand of the player in the console """
- if not victory:
- handText = list(self.playerHands[self.currentPlayer])
- handTitle = "---- {}'s hand ----".format(self.currentPlayer)
- print(handTitle)
- for i in range(len(handText)):
- handText[i] = '[{}] {}'.format(i, self.convertToText(handText[i]))
- print ('\n'.join(handText))
- print('-' * len(handTitle))
- elif victory:
- self.gameOrder.remove(self.playerHands[self.currentPlayer])
- for e in self.gameOrder:
- handText = list(self.playerHands[e])
- print("{}'s hand:'")
- for i in range(len(handText)):
- handText[i] = '[{}] {}'.format(i, self.convertToText(handText[i]))
- print ('\n'.join(handText))
- def countCardsToDraw(self):
- """ Count the number of 'Draw Two' and 'Wild Draw Four' cards that follow each other
- to determine the number of cards that the player needs to draw """
- i = -1
- drawTwo = 0
- wildDrawFour = 0
- while True:
- x = self.convertToNumber(self.pile[i])
- if x == 10:
- drawTwo += 1
- i -= 1
- elif x == 14:
- wildDrawFour += 1
- i -= 1
- elif i+1 == -len(self.pile):
- break
- else:
- break
- total = (drawTwo * 2) + (wildDrawFour * 4)
- return total
- print('countCardsToDraw total =',total)
- def playableCards(self):
- """ Return a list of index of playable cards (-> pc) in the player's hand """
- pc = []
- for i in range(len(self.playerHands[self.currentPlayer])):
- x = self.setDownVerification(self.playerHands[self.currentPlayer][i])
- if x:
- pc.append(i)
- return pc
- def chooseCard(self):
- """ Ask the player which card he wants to play """
- self.showPlayerHand()
- pc = self.playableCards()
- playingCard = self.convertToText(self.lastPlayedCard)
- print('The last card in the pile is [{}]'.format(playingCard))
- x = int(input("Please choose a valid card to play: "))
- while True:
- if x in pc:
- break
- else:
- x = int(input("This card isn't valid, please choose a valid card to play: "))
- return self.playerHands[self.currentPlayer][x]
- def whoIsPlayingNextRound(self):
- """ Save in an instance variable the name / key of the player that is playing the current round """
- index = self.counter % self.numberOfPlayers
- self.currentPlayer = self.gameOrder[index]
- # ██████ ██████ ███ ██ ██ ██ ███████ ██████ ███████ ██ ██████ ███ ██ ███████ ██ ██ ███ ██ ██████ ████████ ██ ██████ ███ ██ ███████
- # ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ████ ██ ██
- # ██ ██ ██ ██ ██ ██ ██ ██ █████ ██████ ███████ ██ ██ ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███████
- # ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
- # ██████ ██████ ██ ████ ████ ███████ ██ ██ ███████ ██ ██████ ██ ████ ██ ██████ ██ ████ ██████ ██ ██ ██████ ██ ████ ███████
- def convertToColor(self, i):
- """ Return the color of a card based on her position in the deck """
- if (1 <= i <= 25):
- return 'Yellow'
- elif (26 <= i <= 50):
- return 'Blue'
- elif (51 <= i <= 75):
- return 'Green'
- elif (76 <= i <= 100):
- return 'Red'
- def convertToNumber(self, i):
- """ Return the number / function of a card based on her position in the deck """
- if i > 100:
- if (100 < i <= 104):
- return 13
- if (104 < i <= 108):
- return 14
- else:
- mod = i % 25
- if mod not in [0, 24]:
- return (mod // 2)
- else:
- return 12
- def convertToText(self, ind, returnText=True):
- """ Return the color and number / function of a card """
- color = self.convertToColor(ind)
- number = self.convertToNumber(ind)
- if number >= 10:
- if number == 10:
- number = 'Draw Two'
- elif number == 11:
- number = 'Reverse'
- elif number == 12:
- number = 'Skip'
- elif not returnText:
- return None, None
- elif number == 13:
- return 'Wild'
- elif number == 14:
- return 'Wild Draw Four'
- if (returnText):
- # Formated to be printed in the console
- text = '{} - {}'.format(number, color)
- return text
- else:
- # Return separately the color and the number / function of a card
- return color, number
- # ██ ██ ███████ ██████ ██ ███████ ██ ██████ █████ ████████ ██ ██████ ███ ██ ███████ ██ ██ ███ ██ ██████ ████████ ██ ██████ ███ ██ ███████
- # ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ████ ██ ██
- # ██ ██ █████ ██████ ██ █████ ██ ██ ███████ ██ ██ ██ ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███████
- # ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
- # ████ ███████ ██ ██ ██ ██ ██ ██████ ██ ██ ██ ██ ██████ ██ ████ ██ ██████ ██ ████ ██████ ██ ██ ██████ ██ ████ ███████
- def setDownVerification(self, card):
- """ Verify, for a given card, if it can be played or not based on the rules """
- lastCard = self.pile[-1]
- numLastCard = self.convertToNumber(lastCard)
- numCard = self.convertToNumber(card)
- lastCardColor, lastCardNumber = self.convertToText(lastCard, False)
- cardColor, cardNumber = self.convertToText(card, False)
- # Case 1 -> card = Wild Draw Four
- if numCard == 14:
- return True
- # Case 2 -> card = Wild
- elif (numCard == 13) and (numLastCard not in [10, 14]):
- return True
- # Case 3 -> Same color
- elif (lastCardColor == cardColor) and (lastCardColor is not None) and (cardColor is not None) and (numLastCard is not 10):
- return True
- # Case 4 -> Same number or 'function'
- elif (cardNumber == lastCardNumber) and (lastCardNumber is not None) and (cardNumber is not None):
- return True
- # Case 5 -> The last card is a 'Draw Two' or a 'Wild Draw Four' and the player don't have one of these cards
- elif numLastCard in [10, 14]:
- return 'forcedDraw'
- # Case 6 -> The player cannot play
- else:
- return False
- def playOrDraw(self):
- """ Verify that the player has at least one playable card in his hand """
- forcedDrawList = []
- for i in range(len(self.playerHands[self.currentPlayer])):
- x = self.setDownVerification(self.playerHands[self.currentPlayer][i])
- forcedDrawList.append(x)
- if x:
- # The player can play
- pc = self.playableCards()
- return True, pc
- # The player is forced to draw because of a 'Draw Two' or a 'Wild Draw Four'
- if all(e == 'forcedDraw' for e in forcedDrawList):
- cardsToDraw = self.countCardsToDraw()
- return False, cardsToDraw
- else:
- # The player needs to draw
- return False, -1
- def victory(self):
- """ Check if the hand of a player is empty (Which also means that he won) """
- if not self.playerHands[self.currentPlayer]:
- return True
- self.endGame = True
- return False
- def gameRound(self):
- play, cards = self.playOrDraw()
- print(play, cards)
- if play:
- c = self.chooseCard()
- self.pile.append(c)
- self.playerHands[self.currentPlayer].remove(c)
- self.lastPlayedCard = c
- win = self.victory()
- if win:
- print('{} won this game! Congratulation :)'.format(self.currentPlayer))
- print('The hands of the remaining players will be displayed below')
- self.showPlayerHand(True)
- return
- elif not play:
- if cards != -1:
- print("Because there's one or multiple Draw Two / Wild Draw Four cards on the pile, you need to draw {} cards.".format(cards))
- self.draw(cards)
- print('The cards have been drawn for you automatically')
- play, cards = self.playOrDraw()
- if (not play) and (cards == -1):
- self.automaticallyDraw()
- elif cards == -1:
- self.automaticallyDraw()
- uno = uno();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement