War card game: Difference between revisions

From Rosetta Code
Content added Content deleted
mNo edit summary
Line 189: Line 189:
c3, c4 = popfirst!(d1), popfirst!(d2)
c3, c4 = popfirst!(d1), popfirst!(d2)
println(rpad("?", 10), rpad("?", 10), "Cards are face down.")
println(rpad("?", 10), rpad("?", 10), "Cards are face down.")
turn!(d1, d2, push!(pending, c1, c2, c3, c4))
return turn!(d1, d2, push!(pending, c1, c2, c3, c4))
end
end
return true
return true

Revision as of 22:00, 27 December 2020


War 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.

War Card Game

Simulate the card game War. Use the Bicycle playing card manufacturer's rules. Show a game as played. User input is optional.

References:

  • Bicycle card company War game site. [[1]]     (This site leaves a cookie.)
  • Wikipedia entry. [[2]]

Related tasks:


Go

Translation of: Wren

<lang go>package main

import (

   "fmt"
   "math/rand"
   "time"

)

var suits = []string{"♣", "♦", "♥", "♠"} var faces = []string{"2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A"} var cards = make([]string, 52) var ranks = make([]int, 52)

func init() {

   for i := 0; i < 52; i++ {
       cards[i] = fmt.Sprintf("%s%s", faces[i%13], suits[i/13])
       ranks[i] = i % 13
   }

}

func war() {

   deck := make([]int, 52)
   for i := 0; i < 52; i++ {
       deck[i] = i
   }
   rand.Shuffle(52, func(i, j int) {
       deck[i], deck[j] = deck[j], deck[i]
   })
   hand1 := make([]int, 26, 52)
   hand2 := make([]int, 26, 52)
   for i := 0; i < 26; i++ {
       hand1[25-i] = deck[2*i]
       hand2[25-i] = deck[2*i+1]
   }
   for len(hand1) > 0 && len(hand2) > 0 {
       card1 := hand1[0]
       copy(hand1[0:], hand1[1:])
       hand1[len(hand1)-1] = 0
       hand1 = hand1[0 : len(hand1)-1]
       card2 := hand2[0]
       copy(hand2[0:], hand2[1:])
       hand2[len(hand2)-1] = 0
       hand2 = hand2[0 : len(hand2)-1]
       played1 := []int{card1}
       played2 := []int{card2}
       numPlayed := 2
       for {
           fmt.Printf("%s\t%s\t", cards[card1], cards[card2])
           if ranks[card1] > ranks[card2] {
               hand1 = append(hand1, played1...)
               hand1 = append(hand1, played2...)
               fmt.Printf("Player 1 takes the %d cards. Now has %d.\n", numPlayed, len(hand1))
               break
           } else if ranks[card1] < ranks[card2] {
               hand2 = append(hand2, played2...)
               hand2 = append(hand2, played1...)
               fmt.Printf("Player 2 takes the %d cards. Now has %d.\n", numPlayed, len(hand2))
               break
           } else {
               fmt.Println("War!")
               if len(hand1) < 2 {
                   fmt.Println("Player 1 has insufficient cards left.")
                   hand2 = append(hand2, played2...)
                   hand2 = append(hand2, played1...)
                   hand2 = append(hand2, hand1...)
                   hand1 = hand1[0:0]
                   break
               }
               if len(hand2) < 2 {
                   fmt.Println("Player 2 has insufficient cards left.")
                   hand1 = append(hand1, played1...)
                   hand1 = append(hand1, played2...)
                   hand1 = append(hand1, hand2...)
                   hand2 = hand2[0:0]
                   break
               }
               fdCard1 := hand1[0] // face down card
               card1 = hand1[1]    // face up card
               copy(hand1[0:], hand1[2:])
               hand1[len(hand1)-1] = 0
               hand1[len(hand1)-2] = 0
               hand1 = hand1[0 : len(hand1)-2]
               played1 = append(played1, fdCard1, card1)
               fdCard2 := hand2[0] // face down card
               card2 = hand2[1]    // face up card
               copy(hand2[0:], hand2[2:])
               hand2[len(hand2)-1] = 0
               hand2[len(hand2)-2] = 0
               hand2 = hand2[0 : len(hand2)-2]
               played2 = append(played2, fdCard2, card2)
               numPlayed += 4
               fmt.Println("? \t? \tFace down cards.")
           }
       }
   }
   if len(hand1) == 52 {
       fmt.Println("Player 1 wins the game!")
   } else {
       fmt.Println("Player 2 wins the game!")
   }

}

func main() {

   rand.Seed(time.Now().UnixNano())
   war()

}</lang>

Output:

Sample game (abridged):

9♠	Q♣	Player 2 takes the 2 cards. Now has 27.
7♠	6♠	Player 1 takes the 2 cards. Now has 26.
3♠	2♣	Player 1 takes the 2 cards. Now has 27.
A♠	2♦	Player 1 takes the 2 cards. Now has 28.
K♠	Q♥	Player 1 takes the 2 cards. Now has 29.
6♥	7♦	Player 2 takes the 2 cards. Now has 24.
2♥	T♣	Player 2 takes the 2 cards. Now has 25.
3♦	4♠	Player 2 takes the 2 cards. Now has 26.
Q♦	K♣	Player 2 takes the 2 cards. Now has 27.
7♥	5♠	Player 1 takes the 2 cards. Now has 26.
T♠	K♥	Player 2 takes the 2 cards. Now has 27.
A♦	9♣	Player 1 takes the 2 cards. Now has 26.
5♦	5♥	War!
? 	? 	Face down cards.
5♣	2♠	Player 1 takes the 6 cards. Now has 29.

......

6♣	3♣	Player 1 takes the 2 cards. Now has 50.
3♥	T♥	Player 2 takes the 2 cards. Now has 3.
K♥	8♠	Player 1 takes the 2 cards. Now has 50.
Q♣	T♥	Player 1 takes the 2 cards. Now has 51.
3♦	3♥	War!
Player 2 has insufficient cards left.
Player 1 wins the game!

Julia

<lang julia># https://bicyclecards.com/how-to-play/war/

using Random

const SUITS = ["♣", "♦", "♥", "♠"] const FACES = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" ] const DECK = vec([f * s for s in SUITS, f in FACES]) const rdict = Dict(DECK[i] => div(i + 3, 4) for i in eachindex(DECK))

deal2(deck) = begin d = shuffle(deck); d[1:2:51], d[2:2:52] end

function turn!(d1, d2, pending)

   (isempty(d1) || isempty(d2)) && return false
   c1, c2 = popfirst!(d1), popfirst!(d2)
   r1, r2 = rdict[c1], rdict[c2]
   print(rpad(c1, 10), rpad(c2, 10))
   if r1 > r2
       println("Player 1 takes the cards.")
       push!(d1, c1, c2, pending...)
       empty!(pending)
   elseif r1 < r2
       println("Player 2 takes the cards.")
       push!(d2, c2, c1, pending...)
       empty!(pending)
   else # r1 == r2
       println("Tie!")
       (isempty(d1) || isempty(d2)) && return false
       c3, c4 = popfirst!(d1), popfirst!(d2)
       println(rpad("?", 10), rpad("?", 10), "Cards are face down.")
       return turn!(d1, d2, push!(pending, c1, c2, c3, c4))
   end
   return true

end

function warcardgame()

   deck1, deck2 = deal2(DECK)
   while turn!(deck1, deck2, []) end
   if isempty(deck2)
       if isempty(deck1)
           println("Game ends as a tie.")
       else
           println("Player 1 wins the game.")
       end
   else
       println("Player 2 wins the game.")
   end

end

warcardgame()

</lang>

Output:
5♦        3♥        Player 1 takes the cards.
8♥        K♥        Player 2 takes the cards.
5♠        K♦        Player 2 takes the cards.
3♦        6♥        Player 2 takes the cards.
9♣        J♠        Player 2 takes the cards.
8♦        2♦        Player 1 takes the cards.
J♣        5♥        Player 1 takes the cards.
3♠        4♥        Player 2 takes the cards.
9♥        A♣        Player 2 takes the cards.
9♠        9♦        Tie!
?         ?         Cards are face down.     
A♠        4♦        Player 1 takes the cards.
5♣        Q♠        Player 2 takes the cards.
6♦        8♠        Player 2 takes the cards.
4♣        10♦       Player 2 takes the cards.
4♠        2♥        Player 1 takes the cards.
Q♦        K♣        Player 2 takes the cards.
A♥        2♣        Player 1 takes the cards.
Q♣        2♠        Player 1 takes the cards.
10♥       6♣        Player 1 takes the cards.

... many other lines ...

10♥       Q♣        Player 2 takes the cards.
4♣        5♦        Player 2 takes the cards.
A♣        8♦        Player 1 takes the cards.
9♣        2♣        Player 1 takes the cards.
Q♥        Q♣        Tie!
?         ?         Cards are face down.
Q♠        5♦        Player 1 takes the cards.
8♥        4♣        Player 1 takes the cards.
Player 1 wins the game.

Phix

Shuffles on pickup to significantly shorten the games <lang Phix>sequence deck = shuffle(tagset(52)),

        hands = {deck[1..26],deck[27..52]},
        pending = {}

function pop(integer hand)

   integer res
   {res, hands[hand]} = {hands[hand][1],hands[hand][2..$]}
   return res

end function

function show(integer c)

   integer r = remainder(c-1,13)+1,
           s = floor((c-1)/13)+1
   printf(1,"%s    ",{"23456789TJQKA"[r]&"SHDC"[s]})
   return r

end function

while true do

   if length(hands[1])=0 then
       if length(hands[2])=0 then
           printf(1,"Game ends as a tie.\n")
           exit
       end if
       printf(1,"Player 2 wins the game.\n")
       exit
   elsif length(hands[2])=0 then
       printf(1,"Player 1 wins the game.\n")
       exit
   end if
   integer c1 = pop(1),
           c2 = pop(2),
           r1 = show(c1),
           r2 = show(c2)
   if r1>r2 then
       printf(1,"Player 1 takes the cards.\n")
       hands[1] &= shuffle(c1&c2&pending)
       pending = {}
   elsif r1<r2 then
       printf(1,"Player 2 takes the cards.\n")
       hands[2] &= shuffle(c1&c2&pending)
       pending = {}
   else -- r1==r2
       printf(1,"Tie!\n")
       if length(hands[1])!=0 and length(hands[2])!=0 then
           pending &= shuffle(c1&c2&pop(1)&pop(2))
           printf(1,"??    ??    Cards are face down.\n")
       end if
   end if

end while</lang>

Output:
9H    3C    Player 1 takes the cards.
AD    KD    Player 1 takes the cards.
3D    KS    Player 2 takes the cards.
...
2H    9S    Player 2 takes the cards.
KC    7H    Player 1 takes the cards.
5C    JS    Player 2 takes the cards.
3S    3D    Tie!
??    ??    Cards are face down.
8D    2H    Player 1 takes the cards.
2C    JS    Player 2 takes the cards.
JD    5C    Player 1 takes the cards.
6D    2C    Player 1 takes the cards.
QD    JS    Player 1 takes the cards.
Player 1 wins the game.

Python

Translation of: Julia

<lang python>""" https://bicyclecards.com/how-to-play/war/ """

from numpy.random import shuffle

SUITS = ['♣', '♦', '♥', '♠'] FACES = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'] DECK = [f + s for f in FACES for s in SUITS] CARD_TO_RANK = dict((DECK[i], (i + 3) // 4) for i in range(len(DECK)))


class WarCardGame:

   """ card game War """
   def __init__(self):
       deck = DECK.copy()
       shuffle(deck)
       self.deck1, self.deck2 = deck[:26], deck[26:]
       self.pending = []
   def turn(self):
       """ one turn, may recurse on tie """
       if len(self.deck1) == 0 or len(self.deck2) == 0:
           return self.gameover()
       card1, card2 = self.deck1.pop(0), self.deck2.pop(0)
       rank1, rank2 = CARD_TO_RANK[card1], CARD_TO_RANK[card2]
       print("{:10}{:10}".format(card1, card2), end=)
       if rank1 > rank2:
           print('Player 1 takes the cards.')
           self.deck1.extend([card1, card2])
           self.deck1.extend(self.pending)
           self.pending = []
       elif rank1 < rank2:
           print('Player 2 takes the cards.')
           self.deck2.extend([card2, card1])
           self.deck2.extend(self.pending)
           self.pending = []
       else:  #  rank1 == rank2
           print('Tie!')
           if len(self.deck1) == 0 or len(self.deck2) == 0:
               return self.gameover()
           card3, card4 = self.deck1.pop(0), self.deck2.pop(0)
           self.pending.extend([card1, card2, card3, card4])
           print("{:10}{:10}".format("?", "?"), 'Cards are face down.', sep=)
           return self.turn()
       return True
   def gameover(self):
       """ game over who won message """
       if len(self.deck2) == 0:
           if len(self.deck1) == 0:
               print('\nGame ends as a tie.')
           else:
               print('\nPlayer 1 wins the game.')
       else:
           print('\nPlayer 2 wins the game.')
       return False


if __name__ == '__main__':

   WG = WarCardGame()
   while WG.turn():
       continue

</lang>

Output:
8♠        K♠        Player 2 takes the cards.
3♠        8♥        Player 2 takes the cards.
K♣        4♠        Player 1 takes the cards.
Q♦        J♣        Player 1 takes the cards.
5♦        6♦        Player 2 takes the cards.
A♥        Q♣        Player 1 takes the cards.
10♣       5♥        Player 1 takes the cards.
J♦        7♣        Player 1 takes the cards.
K♥        Q♠        Player 1 takes the cards.
2♦        2♣        Player 1 takes the cards.
10♠       9♥        Player 1 takes the cards.
9♠        3♦        Player 1 takes the cards.
A♠        A♦        Tie!
?         ?         Cards are face down.
3♥        8♦        Player 2 takes the cards.
5♣        2♠        Player 1 takes the cards.
J♠        4♦        Player 1 takes the cards.
2♥        7♦        Player 2 takes the cards.

... et cetera ...

A♣        4♣        Player 1 takes the cards.
7♣        3♣        Player 1 takes the cards.
9♠        A♦        Player 2 takes the cards.
6♦        Q♠        Player 2 takes the cards.
7♦        3♦        Player 1 takes the cards.
5♥        2♥        Player 1 takes the cards.
A♣        A♥        Player 2 takes the cards.
4♣        10♣       Player 2 takes the cards.
7♣        10♥       Player 2 takes the cards.
3♣        5♦        Player 2 takes the cards.
7♦        K♦        Player 2 takes the cards.
3♦        8♣        Player 2 takes the cards.
5♥        J♦        Player 2 takes the cards.
2♥        6♥        Player 2 takes the cards.

Player 2 wins the game.

Wren

Library: Wren-queue

I've assumed that if a player runs out of cards during a 'war', then the other player automatically wins the game. The Bicycle card company's rules don't appear to cover this eventuality

I've also assumed that if a player wins a round, his/her own cards (in the order played) are added back to the bottom of his/her hand before the other player's cards. <lang ecmascript>import "random" for Random import "/queue" for Deque

var rand = Random.new() var suits = ["♣", "♦", "♥", "♠"] var faces = ["2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A" ] var cards = List.filled(52, null) for (i in 0..51) cards[i] = "%(faces[i%13])%(suits[(i/13).floor])" var ranks = List.filled(52, 0) for (i in 0..51) ranks[i] = i % 13

var war = Fn.new {

   var deck = List.filled(52, 0)
   for (i in 0..51) deck[i] = i
   rand.shuffle(deck)
   var hand1 = Deque.new()
   var hand2 = Deque.new()
   for (i in 0..25) {
       hand1.pushFront(deck[2*i])
       hand2.pushFront(deck[2*i+1])
   }
   while (hand1.count > 0 && hand2.count > 0) {
       var card1 = hand1.popFront()
       var card2 = hand2.popFront()
       var played1 = [card1]
       var played2 = [card2]
       var numPlayed = 2
       while (true) {
           System.write("%(cards[card1])\t%(cards[card2])\t")
           if (ranks[card1] > ranks[card2]) {
               hand1.pushAllBack(played1)
               hand1.pushAllBack(played2)
               System.print("Player 1 takes the %(numPlayed) cards. Now has %(hand1.count).")
               break
           } else if (ranks[card1] < ranks[card2]) {
               hand2.pushAllBack(played2)
               hand2.pushAllBack(played1)
               System.print("Player 2 takes the %(numPlayed) cards. Now has %(hand2.count).")
               break
           } else {
               System.print("War!")
               if (hand1.count < 2) {
                   System.print("Player 1 has insufficient cards left.")
                   hand2.pushAllBack(played2)
                   hand2.pushAllBack(played1)
                   hand2.pushAllBack(hand1)
                   hand1.clear()
                   break
               }
               if (hand2.count < 2) {
                   System.print("Player 2 has insufficient cards left.")
                   hand1.pushAllBack(played1)
                   hand1.pushAllBack(played2)
                   hand1.pushAllBack(hand2)
                   hand2.clear()
                   break
               }
               played1.add(hand1.popFront()) // face down card
               card1 = hand1.popFront()      // face up card
               played1.add(card1)
               played2.add(hand2.popFront()) // face down card
               card2 = hand2.popFront()      // face up card
               played2.add(card2)
               numPlayed = numPlayed + 4
               System.print("? \t? \tFace down cards.")
           }
       }
   }
   if (hand1.count == 52) {
       System.print("Player 1 wins the game!")
   } else {
       System.print("Player 2 wins the game!")
   }

}

war.call()</lang>

Output:

Sample game (abridged):

Q♥	9♠	Player 1 takes the 2 cards. Now has 27.
3♦	T♦	Player 2 takes the 2 cards. Now has 26.
8♣	A♥	Player 2 takes the 2 cards. Now has 27.
3♠	Q♠	Player 2 takes the 2 cards. Now has 28.
J♠	4♥	Player 1 takes the 2 cards. Now has 25.
3♣	7♣	Player 2 takes the 2 cards. Now has 28.
9♦	2♠	Player 1 takes the 2 cards. Now has 25.
7♥	K♦	Player 2 takes the 2 cards. Now has 28.
5♥	A♠	Player 2 takes the 2 cards. Now has 29.
2♦	K♠	Player 2 takes the 2 cards. Now has 30.
5♠	5♣	War!
? 	? 	Face down cards.
4♣	T♣	Player 2 takes the 6 cards. Now has 33.
A♦	9♥	Player 1 takes the 2 cards. Now has 20.
T♥	9♣	Player 1 takes the 2 cards. Now has 21.
K♣	Q♣	Player 1 takes the 2 cards. Now has 22.
4♦	A♣	Player 2 takes the 2 cards. Now has 31.
7♠	7♦	War!
? 	? 	Face down cards.
8♦	J♣	Player 2 takes the 6 cards. Now has 34.

.....

T♠	7♦	Player 1 takes the 2 cards. Now has 10.
7♠	J♣	Player 2 takes the 2 cards. Now has 43.
4♣	4♥	War!
? 	? 	Face down cards.
2♠	2♣	War!
? 	? 	Face down cards.
3♦	9♠	Player 2 takes the 10 cards. Now has 48.
5♠	5♣	War!
? 	? 	Face down cards.
T♠	T♥	War!
Player 1 has insufficient cards left.
Player 2 wins the game!