War card game
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
<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
<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
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!