Uno (card game)

From Rosetta Code
(Redirected from Uno (Card Game))
Uno (card game) is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
This page uses content from Wikipedia. The original article was at Uno (card game). The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance)


Your task here is to replicate or recreate the American Card Game: Uno, using ASCII art or using GUIs, it's up to you. This is for Uno's 50 year anniversary.

  1.   You must have 4 players, 3 of which's cards will not be shown, those 3 are bots, the 4th one is the player, those cards are visible
  2.   You must also have the pile to pick out cards
  3.   You must include the Official Rules
  4.   You must include the Penalties

Official Rules

The aim of the game is to be the first player to score 500 points, achieved (usually over several rounds of play) by being the first to play all of one's own cards and scoring points for the cards still held by the other players.

The deck consists of 108 cards: four each of "Wild" and "Wild Draw Four", and 25 each of four colors (red, yellow, green, blue). Each color consists of one zero, two each of 1 through 9, and two each of "Skip", "Draw Two", and "Reverse". These last three types are known as "action cards".

To start a hand, seven cards are dealt to each player, and the top card of the remaining deck is flipped over and set aside to begin the discard pile. The player to the dealer's left plays first unless the first card on the discard pile is an action or Wild card (see below). On a player's turn, they must do one of the following:

play one card matching the discard in color, number, or symbol play a Wild card, or a playable Wild Draw Four card (see restriction below) draw the top card from the deck, then play it if possible Cards are played by laying them face-up on top of the discard pile. Play proceeds clockwise around the table.

Action or Wild cards have the following effects:

Card Effect when played from hand Effect as first discard
Skip Next player in sequence misses a turn Player to dealer's left misses a turn
Reverse Order of play switches directions (clockwise to counterclockwise, or vice versa) Dealer plays first; play proceeds counterclockwise
Draw Two (+2) Next player in sequence draws two cards and misses a turn Player to dealer's left draws two cards and misses a turn
Wild Player declares the next color to be matched (may be used on any turn even if the player has matching color; current color may be chosen as the next to be matched) Player to dealer's left declares the first color to be matched and plays a card in it
Wild Draw Four/Draw Four Wild (+4 and wild) Player declares the next color to be matched; next player in sequence draws four cards and misses a turn. May be legally played only if the player has no cards of the current color (see Penalties). Return card to the deck, shuffle, flip top card to start discard pile
  • A player who draws from the deck must either play or keep that card and may play no other card from their hand on that turn.
  • A player may play a Wild card at any time, even if that player has other playable cards.
  • A player may play a Wild Draw Four card only if that player has no cards matching the current color. The player may have cards of a different color matching the current number or symbol or a Wild card and still play the Wild Draw Four card. A player who plays a Wild Draw Four may be challenged by the next player in sequence (see Penalties) to prove that their hand meets this condition.
  • If the entire deck is used during play, the top discard is set aside and the rest of the pile is shuffled to create a new deck. Play then proceeds normally.
  • It is illegal to trade cards of any sort with another player.
  • A player who plays their next-to-last-card must call "uno" as a warning to the other players. The first player to get rid of their last card ("going out") wins the hand and scores points for the cards held by the other players. Number cards count their face value, all action cards count 20, and Wild and Wild Draw Four cards count 50. If a Draw Two or Wild Draw Four card is played to go out, the next player in the sequence must draw the appropriate number of cards before the score is tallied. The first player to score 500 points wins the game. Penalties

  • If a player does not call "uno" after laying down their next-to-last card and is caught before the next player in sequence takes a turn (i.e., plays a card from their hand, draws from the deck, or touches the discard pile), they must draw two cards as a penalty. If the player is not caught in time (subject to interpretation) or remembers to call "uno" before being caught, they suffer no penalty.
  • If a player plays a Wild Draw Four card, the following player can challenge its use. The player who used the Wild Draw Four must privately show their hand to the challenging player, in order to demonstrate that they had no matching colored cards. If the challenge is correct, then the challenged player draws four cards instead. If the challenge is wrong, then the challenger must draw six cards; the four cards they were already required to draw plus two more cards,
  • It is optional to include the House Rules

    FreeBASIC

    Dim Shared As String deck(107)
    Dim Shared As String player1(108), player2(108)
    Dim Shared As String topCard
    Dim Shared As Integer currentPlayer
    
    Sub createDeck
        Dim colors(3) As String = {"Red", "Green", "Blue", "Yellow"}
        Dim values(12) As String = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Skip", "Reverse", "Draw Two"}
        Dim As Integer i, j, k
        For i = 0 To 3
            For j = 0 To 12
                deck(k) = colors(i) & " " & values(j)
                k += 1
                If j > 0 Then
                    deck(k) = colors(i) & " " & values(j)
                    k += 1
                End If
            Next j
        Next i
        deck(k) = "Wild"
        deck(k+1) = "Wild"
        deck(k+2) = "Wild"
        deck(k+3) = "Wild"
        deck(k+4) = "Wild Draw Four"
        deck(k+5) = "Wild Draw Four"
        deck(k+6) = "Wild Draw Four"
        deck(k+7) = "Wild Draw Four"
    End Sub
    
    Sub shuffleDeck
        Dim As Integer i, j
        Dim As String temp
        For i = 0 To 107
            j = Int(Rnd * 108)
            Swap deck(i), deck(j)
        Next i
    End Sub
    
    Sub dealCards
        For i As Integer = 0 To 6
            player1(i) = deck(i)
            player2(i) = deck(i+7)
        Next i
        topCard = deck(14)
        currentPlayer = 1
    End Sub
    
    Sub printCards(player() As String)
        For i As Integer = 0 To Ubound(player)
            If player(i) <> "" Then Print i+1; ". "; player(i)
        Next i
    End Sub
    
    Sub drawCard(player() As String)
        For i As Integer = 0 To Ubound(player)
            If player(i) = "" Then
                player(i) = deck(Ubound(deck))
                Redim Preserve deck(Ubound(deck) - 1) As String
                Exit Sub
            End If
        Next i
    End Sub
    
    Sub playCard2(player() As String, choice As Integer)
        topCard = player(choice - 1)
        For i As Integer = choice - 1 To Ubound(player) - 1
            player(i) = player(i + 1)
        Next i
        Redim Preserve player(Ubound(player) - 1)
    End Sub
    
    Sub playCard(player() As String, choice As Integer)
        topCard = player(choice - 1)
        If Right(topCard, 4) = "Skip" Then
            ' Skip the next player's turn
            currentPlayer = 3 - currentPlayer
        Elseif Right(topCard, 7) = "Reverse" Then
            ' Reverse the order of play
            ' (In a two-player game, this is the same as a Skip)
            currentPlayer = 3 - currentPlayer
        Elseif Right(topCard, 8) = "Draw Two" Then
            ' The next player must draw two cards
            If currentPlayer = 1 Then
                drawCard(player2())
                drawCard(player2())
            Else
                drawCard(player1())
                drawCard(player1())
            End If
        Elseif Left(topCard, 4) = "Wild" Then
            ' The player who played this card chooses the color
            ' (In this simplified version, the color is chosen randomly)
            Dim colors(3) As String = {"Red", "Green", "Blue", "Yellow"}
            topCard = colors(Int(Rnd * 4))
            If Right(topCard, 11) = "Draw Four" Then
                ' The next player must draw four cards
                If currentPlayer = 1 Then
                    drawCard(player2())
                    drawCard(player2())
                    drawCard(player2())
                    drawCard(player2())
                Else
                    drawCard(player1())
                    drawCard(player1())
                    drawCard(player1())
                    drawCard(player1())
                End If
            End If
        End If
        For i As Integer = choice - 1 To Ubound(player) - 1
            player(i) = player(i + 1)
        Next i
        Redim Preserve player(Ubound(player) - 1)
    End Sub
    
    Function checkGameOver(player() As String) As Integer
        Return Iif(Ubound(player), True, False)
    End Function
    
    Function isValidPlay(player() As String, choice As Integer) As Boolean
        Dim As String card = player(choice - 1)
        Return Iif((Left(card, Len(topCard)) = Left(topCard, Len(topCard)) Or Right(card, 4) = "Wild"), True, False)
    End Function
    
    Sub playGame2
        Dim As Integer i, choice, numCards
        Do
            Print "Top card: "; topCard
            If currentPlayer = 1 Then
                Print "Player 1's turn"
                printCards(player1())
                Print "Choose a card to play (0 to draw a card): ";
                Input choice
                If choice = 0 Then
                    drawCard(player1())
                Else
                    playCard(player1(), choice)
                End If
                Print
            Else
                Print "Player 2's turn"
                numCards = 0
                For i = 0 To Ubound(player2)
                    If player2(i) <> "" Then numCards += 1
                Next i
                choice = Int(Rnd * numCards) + 1
                Print "Computer plays card "; choice
                playCard(player2(), choice)
            End If
            If checkGameOver(player1()) <> 0 Then
                Print "Player 1 has won the game!"
                Exit Sub
            End If
            If checkGameOver(player2()) <> 0 Then
                Print "Player 2 has won the game!"
                Exit Sub
            End If
            currentPlayer = 3 - currentPlayer
        Loop
    End Sub
    
    Sub playGame
        Dim As Integer i, choice, numCards
        Do
            Print "Top card: "; topCard
            If currentPlayer = 1 Then
                Print !"\nPlayer 1's turn"
                printCards(player1())
                Print 
                Input "Choose a card to play (0 to draw a card): ", choice
                If choice = 0 Then
                    drawCard(player1())
                Elseif isValidPlay(player1(), choice) <> 0 Then
                    playCard(player1(), choice)
                    If Ubound(player1) = 0 Then
                        Print "Player 1 says UNO!"
                    End If
                Else
                    Print !"Invalid play. Please choose a valid card.\n"
                End If
                If Ubound(player1) = -1 Then
                    Print "Player 1 has won the game!"
                    Exit Sub
                End If
            Else
                Print !"\nPlayer 2's turn"
                numCards = 0
                For i = 0 To Ubound(player2)
                    If player2(i) <> "" And Left(player2(i), Len(topCard)) = topCard Then
                        choice = i + 1
                        Print "Computer plays card "; choice
                        playCard(player2(), choice)
                        If Ubound(player2) = 0 Then
                            Print "Player 2 says UNO!"
                        End If
                        Exit For
                    End If
                Next i
                If choice = 0 Then drawCard(player2())
    
                If Ubound(player2) = -1 Then
                    Print "Player 2 has won the game!"
                    Exit Sub
                End If
            End If
            currentPlayer = 3 - currentPlayer
        Loop
    End Sub
    
    '--- Programa Principal ---
    Randomize Timer
    createDeck()
    shuffleDeck()
    dealCards()
    playGame()
    End
    '--------------------------
    

    Julia

    See Uno_(Card_Game)/Julia.

    Phix

    See Uno_(Card_Game)/Phix.

    Python

    See Uno_(Card_Game)/Python.

    Wren

    See Uno_(Card_Game)/Wren.