War card game

From Rosetta Code
(Redirected from War Card Game)
Task
War card game
You are encouraged to solve this task according to the task description, using any language you may know.

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:

Related tasks:


11l[edit]

Translation of: Python
UInt32 seed = 0
F nonrandom(n)
   :seed = (1664525 * :seed + 1013904223) [&] FFFF'FFFF
   R Int(:seed >> 16) % n

F nonrandom_shuffle(&x)
   L(i) (x.len - 1 .< 0).step(-1)
      V j = nonrandom(i + 1)
      swap(&x[i], &x[j])

V SUITS = [‘♣’, ‘♦’, ‘♥’, ‘♠’]
V FACES = [‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘10’, ‘J’, ‘Q’, ‘K’, ‘A’]
V DECK = multiloop(FACES, SUITS, (f, s) -> f‘’s)
V CARD_TO_RANK = Dict((0 .< DECK.len).map(i -> (:DECK[i], (i + 3) I/ 4)))

T WarCardGame
   [String] deck1, deck2, pending

   F ()
      V deck = copy(:DECK)
      nonrandom_shuffle(&deck)
      .deck1 = deck[0.<26]
      .deck2 = deck[26..]

   F gameover()
      ‘ game over who won message ’
      I .deck2.empty
         I .deck1.empty
            print("\nGame ends as a tie.")
         E
            print("\nPlayer 1 wins the game.")
      E
         print("\nPlayer 2 wins the game.")
      R 0B

   F turn()
      ‘ one turn, may recurse on tie ’
      I .deck1.empty | .deck2.empty
         R .gameover()

      V card1 = .deck1.pop(0)
      V card2 = .deck2.pop(0)
      V (rank1, rank2) = (:CARD_TO_RANK[card1], :CARD_TO_RANK[card2])
      print(‘#<10#<10’.format(card1, card2), end' ‘’)
      I rank1 > rank2
         print(‘Player 1 takes the cards.’)
         .deck1.extend([card1, card2])
         .deck1.extend(.pending)
         .pending.clear()
      E I rank1 < rank2
         print(‘Player 2 takes the cards.’)
         .deck2.extend([card2, card1])
         .deck2.extend(.pending)
         .pending.clear()
      E
         print(‘Tie!’)
         I .deck1.empty | .deck2.empty
            R .gameover()

         V card3 = .deck1.pop(0)
         V card4 = .deck2.pop(0)
         .pending.extend([card1, card2, card3, card4])
         print(‘#<10#<10’.format(‘?’, ‘?’)‘Cards are face down.’)
         R .turn()

      R 1B

V WG = WarCardGame()
L WG.turn()
   L.continue
Output:
7♦        10♦       Player 2 takes the cards.
10♥       K♥        Player 2 takes the cards.
7♥        6♣        Player 1 takes the cards.
8♦        5♥        Player 1 takes the cards.
4♥        3♥        Player 1 takes the cards.
A♣        9♣        Player 1 takes the cards.
6♠        4♦        Player 1 takes the cards.
K♣        3♠        Player 1 takes the cards.
A♠        7♣        Player 1 takes the cards.
10♠       J♥        Player 2 takes the cards.
J♦        Q♣        Tie!
?         ?         Cards are face down.
6♦        Q♠        Player 2 takes the cards.
...
5♠        4♦        Player 1 takes the cards.
Q♣        K♥        Player 2 takes the cards.
10♣       9♠        Tie!
?         ?         Cards are face down.
8♥        10♥       Player 2 takes the cards.
8♣        J♣        Player 2 takes the cards.
5♦        5♣        Player 1 takes the cards.
5♠        3♥        Player 1 takes the cards.
4♦        3♣        Player 1 takes the cards.
5♦        7♦        Player 2 takes the cards.
5♣        7♥        Player 2 takes the cards.
5♠        6♥        Player 2 takes the cards.
3♥        A♥        Player 2 takes the cards.
4♦        8♠        Player 2 takes the cards.
3♣        4♠        Player 2 takes the cards.

Player 2 wins the game.

AutoHotkey[edit]

suits := ["♠", "♦", "♥", "♣"]
faces := [2,3,4,5,6,7,8,9,10,"J","Q","K","A"]
deck := [], p1 := [], p2 := []
for i, s in suits
	for j, v in faces
		deck.Push(v s)
deck := shuffle(deck)
deal := deal(deck, p1, p2)
p1 := deal.1, p2 := deal.2

for i, v in p2
{
	if InStr(v, "A")
		p2[i] := p1[i], p1[i] := v
	if InStr(v, "K")
		p2[i] := p1[i], p1[i] := v
	if InStr(v, "Q")
		p2[i] := p1[i], p1[i] := v
	if InStr(v, "J")
		p2[i] := p1[i], p1[i] := v
}
MsgBox % war(p1, p2)
return
war(p1, p2){
	J:=11, Q:=11, K:=11, A:=12, stack := [], cntr := 0
	output := "------------------------------------------"
			. "`nRound#  	  Deal	  		Winner	P1	P1"
			. "`n------------------------------------------"
			. "`nround0  			  				26	26"

	while (p1.Count() && p2.Count()) {
		cntr++
		stack.Push(c1:=p1.RemoveAt(1)), stack.Push(c2:=p2.RemoveAt(1))
		r1:=SubStr(c1,1,-1)	,r2:=SubStr(c2,1,-1)
		v1:=r1<11?r1:%r1%	,v2:=r2<11?r2:%r2%
		output .= "`nround# " cntr "`t" SubStr(c1 "  n", 1, 4) "vs " SubStr(c2 "  ", 1, 4)
		if (v1 > v2){
			loop % stack.Count()
				p1.Push(stack.RemoveAt(1))
			output .= "`t`tP1 wins"
		}
		else if (v1 < v2){
			loop % stack.Count()
				p2.Push(stack.RemoveAt(1))
			output .= "`t`tP2 wins"
		}
		if (v1 = v2){
			output .= "`t`t**WAR**`t" P1.Count() "`t" P2.Count() 
			stack.Push(c1:=p1.RemoveAt(1)), stack.Push(c2:=p2.RemoveAt(1))
			if !(p1.Count() && p2.Count())
				break
			output .= "`nround# " ++cntr "`t(" SubStr(c1 "  ", 1, 3) ") - (" SubStr(c2 " ", 1, 3) ")"
			output .= "`tFace Dn" 
		}
		output .= "`t" P1.Count() "`t" P2.Count()
		if !Mod(cntr, 20)
		{
			MsgBox % output
			output := ""
		}
	}
	output .= "`n" (P1.Count() ? "P1 Wins" : "P2 Wins")
	output := StrReplace(output, " )", ") ")
	output := StrReplace(output, "  -", " -")
	return output
Output:
------------------------------------------
Round#  	  Deal	  		Winner	P1	P1
------------------------------------------
round0  			  				26	26
round# 1	J♣  vs 3♠  		P1 wins	27	25
round# 2	3♣  vs 10♦ 		P2 wins	26	26
round# 3	Q♣  vs 8♠  		P1 wins	27	25
round# 4	A♦  vs 7♠  		P1 wins	28	24
round# 5	J♥  vs 3♦  		P1 wins	29	23
round# 6	8♦  vs 4♦  		P1 wins	30	22
round# 7	4♥  vs 6♦  		P2 wins	29	23
round# 8	7♥  vs 4♠  		P1 wins	30	22
round# 9	A♠  vs 7♣  		P1 wins	31	21
round# 10	K♣  vs 10♠ 		P1 wins	32	20
round# 11	4♣  vs 8♥  		P2 wins	31	21
round# 12	6♠  vs 6♥  		**WAR**	30	20
round# 13	(A♥) - (9♠) 		Face Dn	29	19
round# 14	5♣  vs 2♥  		P1 wins	34	18
round# 15	A♣  vs 8♣  		P1 wins	35	17
round# 16	J♦  vs 6♣  		P1 wins	36	16
round# 17	Q♥  vs 9♣  		P1 wins	37	15
round# 18	10♥ vs 5♠  		P1 wins	38	14
round# 19	K♥  vs K♠  		**WAR**	37	13
round# 20	(Q♠) - (9♥) 		Face Dn	36	12
round# 21	K♦  vs 3♥  		P1 wins	41	11
round# 22	J♠  vs 2♦  		P1 wins	42	10
round# 23	5♥  vs 5♦  		**WAR**	41	9
round# 24	(2♣) - (7♦) 		Face Dn	40	8
round# 25	Q♦  vs 10♣ 		P1 wins	45	7
round# 26	9♦  vs 2♠  		P1 wins	46	6
round# 27	J♣  vs 3♣  		P1 wins	47	5
round# 28	3♠  vs 10♦ 		P2 wins	46	6
round# 29	Q♣  vs 4♥  		P1 wins	47	5
round# 30	8♠  vs 6♦  		P1 wins	48	4
round# 31	A♦  vs 4♣  		P1 wins	49	3
round# 32	7♠  vs 8♥  		P2 wins	48	4
round# 33	J♥  vs 3♠  		P1 wins	49	3
round# 34	3♦  vs 10♦ 		P2 wins	48	4
round# 35	8♦  vs 7♠  		P1 wins	49	3
round# 36	4♦  vs 8♥  		P2 wins	48	4
round# 37	7♥  vs 3♦  		P1 wins	49	3
round# 38	4♠  vs 10♦ 		P2 wins	48	4
round# 39	A♠  vs 4♦  		P1 wins	49	3
round# 40	7♣  vs 8♥  		P2 wins	48	4
round# 41	K♣  vs 4♠  		P1 wins	49	3
round# 42	10♠ vs 10♦ 		**WAR**	48	2
round# 43	(6♠) - (7♣) 		Face Dn	47	1
round# 44	6♥  vs 8♥  		P2 wins	46	6
round# 45	A♥  vs 10♠ 		P1 wins	47	5
round# 46	9♠  vs 10♦ 		P2 wins	46	6
round# 47	5♣  vs 6♠  		P2 wins	45	7
round# 48	2♥  vs 7♣  		P2 wins	44	8
round# 49	A♣  vs 6♥  		P1 wins	45	7
round# 50	8♣  vs 8♥  		**WAR**	44	6
round# 51	(J♦) - (9♠) 		Face Dn	43	5
round# 52	6♣  vs 10♦ 		P2 wins	42	10
round# 53	Q♥  vs 5♣  		P1 wins	43	9
round# 54	9♣  vs 6♠  		P1 wins	44	8
round# 55	10♥ vs 2♥  		P1 wins	45	7
round# 56	5♠  vs 7♣  		P2 wins	44	8
round# 57	K♥  vs 8♣  		P1 wins	45	7
round# 58	K♠  vs 8♥  		P1 wins	46	6
round# 59	Q♠  vs J♦  		**WAR**	45	5
round# 60	(9♥) - (9♠) 		Face Dn	44	4
round# 61	K♦  vs 6♣  		P1 wins	49	3
round# 62	3♥  vs 10♦ 		P2 wins	48	4
round# 63	J♠  vs 5♠  		P1 wins	49	3
round# 64	2♦  vs 7♣  		P2 wins	48	4
round# 65	5♥  vs 3♥  		P1 wins	49	3
round# 66	5♦  vs 10♦ 		P2 wins	48	4
round# 67	2♣  vs 2♦  		**WAR**	47	3
round# 68	(7♦) - (7♣) 		Face Dn	46	2
round# 69	Q♦  vs 5♦  		P1 wins	51	1
round# 70	10♣ vs 10♦ 		**WAR**	50	0
P1 Wins

Go[edit]

Translation of: Wren
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()
}
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!

J[edit]

Implementation:
DECK=: '2 3 4 5 6 7 8 9 10 J K Q A' (,' of ',])&.>/&cut '♣ ♦ ♥ ♠'
rank=: DECK {{ {."1 ($m)#:(,m) i. y }}
shuffle=: {~ ?~@#
deal=: _26 ]\ shuffle@,@DECK
cardwar=: {{
  TURNS=: 0
  'P1 P2'=: <each deal''
  while. 0<P1 *&# P2 do. turn TURNS=: TURNS+1 end.
  after=. ' after ',TURNS,&":' turn','s'#~1~:TURNS
  if. #P1 do. 'Player 1 wins', after
  elseif. #P2 do. 'Player 2 wins', after
  else. 'Tie',after end.
}}
plays=: {{ ((m)=: }.".m)](echo n,~(m,' plays '),;'nothing'&[^:(0=#@]){.".m)]({.".m) }}
turn=: {{
  c=. (b=. 'P2' plays''),(a =. 'P1' plays'')
  while. a =&rank b do.
    if. 0=P1 *&# P2 do. echo 'No more cards to draw' return. end.
    c=. c, (a=. 'P1' plays''),(b =. 'P2' plays''), 'P1' plays' face down', 'P2' plays' face down'
  end.    
  ('P',":1+a <&rank b) takes ({~ ?~@#)c-.a:
}}
takes=: {{
  (m)=: (".m),y
  echo m,' takes ',;(<' and ') _2}}.,(<', '),.y
  echo''
}}
Example run:
   cardwar''
P1 plays 6 of 
P2 plays 9 of 
P2 takes 6 of  and 9 of 

P1 plays K of 
P2 plays 6 of 
P1 takes K of  and 6 of 

P1 plays A of 
P2 plays A of 
P2 plays 5 of  face down
P1 plays J of  face down
P2 plays 2 of 
P1 plays J of 
P1 takes A of , J of , A of , 2 of , 5 of  and J of 

P1 plays 7 of 
P2 plays 10 of 
P2 takes 10 of  and 7 of 

(... many lines deleted ...)

P1 plays 2 of 
P2 plays 5 of 
P2 takes 2 of  and 5 of 

P1 plays K of 
P2 plays 4 of 
P1 takes 4 of  and K of 

P1 plays 3 of 
P2 plays 3 of 
P2 plays 2 of  face down
P1 plays 6 of  face down
P2 plays 5 of 
P1 plays K of 
P1 takes 6 of , K of , 5 of , 3 of , 3 of  and 2 of 

Player 1 wins after 86 turns

Julia[edit]

# 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()
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.

Lua[edit]

Library: LÖVE
-- main.lua
function newGame ()
	-- new deck
	local deck = {}
	for iSuit = 1, #CardSuits do
		for iRank = 1, #CardRanks do
			local card = {
				iSuit = iSuit,
				iRank = iRank,
				suit = CardSuits[iSuit],
				rank = iRank,
				name = CardRanks[iRank] .. CardSuits[iSuit]
			}
			local i = math.random (#deck + 1)
			table.insert (deck, i, card)
		end
	end
	
	-- new deal
	Players = {
		{index = 1, cards = {}},
		{index = 2, cards = {}},
	}
	for i = 1, #deck/#Players do
		for iPlayer = 1, #Players do
			table.insert (Players[iPlayer].cards, table.remove(deck))
		end
	end
	WarCards = {}
	Turn = 1
	Statistics = {}
end

function getHigherCard (cardA, cardB)
	if cardA.rank > cardB.rank then
		return cardA, 1
	elseif cardA.rank < cardB.rank then
		return cardB, 2
	else
		return nil
	end
end

function love.load()
	-- there is no card suits in the standard font
	CardSuits = {"@", "#", "$", "%"}
	CardRanks = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "V", "Q", "K", "A"}
	
	newGame ()
end

function love.draw()
	for iPlayer = 1, #Players do
		local player = Players[iPlayer]
		love.graphics.print ('Player '..player.index, 50*(iPlayer-1), 0)
		for iCard, card in ipairs (player.cards) do
			love.graphics.print (card.name, 50*(iPlayer-1), 14*iCard)
		end
	end
	for i = 1, math.min(40, #Statistics) do
		local str = Statistics[i]
		love.graphics.print (str, 150, 20+(i-1)*14)
	end
	
end

function makeTurn ()
	local card1 = table.remove (Players[1].cards)
	local card2 = table.remove (Players[2].cards)
	if card1 and card2 then
		table.insert (WarCards, 1, card1)
		table.insert (WarCards, math.random (1, 2), card2)
		local winCard, index = getHigherCard (card1, card2)
		if winCard then
			table.insert (Statistics, 1, Turn .. '	Player ' .. index .. ' get ' .. #WarCards .. ' cards: ' .. card1.name .. ' vs ' .. card2.name)
			
			for iCard = #WarCards, 1, -1 do
				table.insert (Players[index].cards, 1, table.remove (WarCards))
			end
		elseif (#Players[1].cards > 0) and (#Players[2].cards > 0) then
		-- start war
			table.insert (Statistics, 1, Turn .. '	War: ' .. card1.name .. ' vs ' .. card2.name)
			table.insert (WarCards, table.remove (Players[1].cards))
			table.insert (WarCards, table.remove (Players[2].cards))
		else
			local index = 2
			if #Players[1].cards == 0 then index = 1 end
			table.insert (Statistics, 1, Turn .. '	Player ' .. index .. ' has no cards for this war.')
--			GameOver = true
		end
		Turn = Turn + 1
	elseif GameOver then
		GameOver = false
		newGame ()
	else
		local index = 2
		if #Players[1].cards > #Players[2].cards then index = 1 end
		table.insert (Statistics, 1, Turn .. '	Player ' .. index .. ' wins the game!')
		GameOver = true
	end
end

function love.keypressed(key, scancode, isrepeat)
	if false then
	elseif key == "space" then
		makeTurn ()
	elseif scancode == "n" then
		GameOver = false
		newGame ()
	elseif scancode == "q" then
		local lastTurn = Turn
		while not (GameOver or (Turn > lastTurn + 10000-1)) do
			makeTurn ()
		end
	elseif key == "escape" then
		love.event.quit()
	end
	if #Statistics > 40 then
		local i = #Statistics, 40, -1 do
			table.remove (Statistics, i)
		end
	end
end

function love.mousepressed( x, y, button, istouch, presses )
	if button == 1 then -- left mouse button
		makeTurn ()
	elseif button == 2 then -- right mouse button
	end
end

Nim[edit]

We use module "playing_cards" from task https://rosettacode.org/wiki/Playing_cards.

import strformat
import playing_cards

const
  None = -1
  Player1 = 0
  Player2 = 1

type Player = range[None..Player2]

const PlayerNames: array[Player1..Player2, string] = ["Player 1", "Player 2"]

#---------------------------------------------------------------------------------------------------

proc `<`(a, b: Card): bool =
  ## Compare two cards by their rank, Ace being the greatest.
  if a.rank == Ace: false
  elif b.rank == Ace: true
  else: a.rank < b.rank

#---------------------------------------------------------------------------------------------------

proc displayRound(round: int; hands: openArray[Hand]; card1, card2: string; text: string) =
  ## Display text for a round.
  stdout.write &"Round {round:<4}     "
  stdout.write &"Cards: {hands[Player1].len:>2}/{hands[Player2].len:<2}     "
  stdout.write &"{card1:>3}    {card2:>3}    "
  echo text

#---------------------------------------------------------------------------------------------------

proc outOfCards(player: Player) =
  ## Display a message when a player has run out of cards.
  echo &"{PlayerNames[player]} has run out of cards."

#---------------------------------------------------------------------------------------------------

proc doRound(hands: var openArray[Hand]; num: Positive) =
  ## Execute a round.

  var stack1, stack2: seq[Card]
  var winner: Player = None

  while winner == None:
    let card1 = hands[Player1].draw()
    let card2 = hands[Player2].draw()
    stack1.add card1
    stack2.add card2
    if card1.rank != card2.rank:
      winner = if card1 < card2: Player2 else: Player1
      displayRound(num, hands, $card1, $card2, &"{PlayerNames[winner]} takes the cards.")
    else:
      # There is a war.
      displayRound(num, hands, $card1, $card2, "This is a war.")
      if hands[Player1].len == 0:
        winner = Player2
      elif hands[Player2].len == 0:
        winner = Player1
      else:
        # Add a hidden card on stacks.
        stack1.add hands[Player1].draw()
        stack2.add hands[Player2].draw()
        displayRound(num, hands, "  ?", "  ?", "Cards are face down.")
        # Check if each player has enough cards to continue the war.
        if hands[Player1].len == 0:
          Player1.outOfCards()
          winner = Player2
        elif hands[Player2].len == 0:
          Player2.outOfCards()
          winner = Player1

  # Update hands.
  var stack = stack1 & stack2
  stack.shuffle()
  hands[winner] = stack & hands[winner]


#———————————————————————————————————————————————————————————————————————————————————————————————————

var deck = initDeck()
deck.shuffle()

var hands = deck.deal(2, 26)
var num = 0
while true:
  inc num
  hands.doRound(num)
  if hands[Player1].len == 0:
    echo "Player 2 wins this game."
    break
  if hands[Player2].len == 0:
    echo "Player 1 wins this game."
    break
Output:

Example of a short game.

Round 1        Cards: 25/25     10♣     5♠    Player 1 takes the cards.
Round 2        Cards: 26/24      3♦     7♦    Player 2 takes the cards.
Round 3        Cards: 25/25     10♦    10♥    This is a war.
Round 3        Cards: 24/24       ?      ?    Cards are face down.
Round 3        Cards: 23/23      A♦     4♥    Player 1 takes the cards.
Round 4        Cards: 28/22      4♠     J♦    Player 2 takes the cards.
Round 5        Cards: 27/23      9♠     Q♣    Player 2 takes the cards.
Round 6        Cards: 26/24      A♣     2♦    Player 1 takes the cards.
Round 7        Cards: 27/23      Q♦     3♠    Player 1 takes the cards.
Round 8        Cards: 28/22      5♥     3♥    Player 1 takes the cards.
Round 9        Cards: 29/21      2♥     2♠    This is a war.
Round 9        Cards: 28/20       ?      ?    Cards are face down.
Round 9        Cards: 27/19      4♦    10♠    Player 2 takes the cards.
Round 10       Cards: 26/24      K♠     6♣    Player 1 takes the cards.
Round 11       Cards: 27/23      8♥     7♣    Player 1 takes the cards.
Round 12       Cards: 28/22      4♣     5♦    Player 2 takes the cards.
Round 13       Cards: 27/23      8♣     8♦    This is a war.
Round 13       Cards: 26/22       ?      ?    Cards are face down.
Round 13       Cards: 25/21      9♦     6♠    Player 1 takes the cards.
Round 14       Cards: 30/20      K♥     9♥    Player 1 takes the cards.
Round 15       Cards: 31/19      J♠     7♥    Player 1 takes the cards.
Round 16       Cards: 32/18      J♣     K♦    Player 2 takes the cards.
Round 17       Cards: 31/19      2♣     3♣    Player 2 takes the cards.
Round 18       Cards: 30/20      A♥     6♥    Player 1 takes the cards.
Round 19       Cards: 31/19      A♠     6♦    Player 1 takes the cards.
Round 20       Cards: 32/18      8♠     5♣    Player 1 takes the cards.
Round 21       Cards: 33/17     10♣     7♦    Player 1 takes the cards.
Round 22       Cards: 34/16      5♠     3♦    Player 1 takes the cards.
Round 23       Cards: 35/15      Q♥     4♠    Player 1 takes the cards.
Round 24       Cards: 36/14     10♦     J♦    Player 2 takes the cards.
Round 25       Cards: 35/15      Q♠     9♠    Player 1 takes the cards.
Round 26       Cards: 36/14      A♦     Q♣    Player 1 takes the cards.
Round 27       Cards: 37/13      4♥     4♦    This is a war.
Round 27       Cards: 36/12       ?      ?    Cards are face down.
Round 27       Cards: 35/11      2♦    10♠    Player 2 takes the cards.
Round 28       Cards: 34/16      A♣     2♠    Player 1 takes the cards.
Round 29       Cards: 35/15      Q♦     7♠    Player 1 takes the cards.
Round 30       Cards: 36/14      3♠     2♥    Player 1 takes the cards.
Round 31       Cards: 37/13      5♥     5♦    This is a war.
Round 31       Cards: 36/12       ?      ?    Cards are face down.
Round 31       Cards: 35/11      6♣     J♣    Player 2 takes the cards.
Round 32       Cards: 34/16      K♠     K♦    This is a war.
Round 32       Cards: 33/15       ?      ?    Cards are face down.
Round 32       Cards: 32/14      7♣     2♣    Player 1 takes the cards.
Round 33       Cards: 37/13      K♣     J♦    Player 1 takes the cards.
Round 34       Cards: 38/12      6♠    10♦    Player 2 takes the cards.
Round 35       Cards: 37/13      J♥    10♥    Player 1 takes the cards.
Round 36       Cards: 38/12      8♣     2♦    Player 1 takes the cards.
Round 37       Cards: 39/11      9♦     9♣    This is a war.
Round 37       Cards: 38/10       ?      ?    Cards are face down.
Round 37       Cards: 37/9       9♥    10♠    Player 2 takes the cards.
Round 38       Cards: 36/14      K♥     4♦    Player 1 takes the cards.
Round 39       Cards: 37/13      7♥     6♣    Player 1 takes the cards.
Round 40       Cards: 38/12      J♠     5♥    Player 1 takes the cards.
Round 41       Cards: 39/11      A♥     4♣    Player 1 takes the cards.
Round 42       Cards: 40/10      6♥     J♣    Player 2 takes the cards.
Round 43       Cards: 39/11      A♠     3♥    Player 1 takes the cards.
Round 44       Cards: 40/10      6♦     5♦    Player 1 takes the cards.
Round 45       Cards: 41/9       8♠    10♦    Player 2 takes the cards.
Round 46       Cards: 40/10      5♣     6♠    Player 2 takes the cards.
Round 47       Cards: 39/11      7♦     8♦    Player 2 takes the cards.
Round 48       Cards: 38/12     10♣     9♦    Player 1 takes the cards.
Round 49       Cards: 39/11      3♦    10♠    Player 2 takes the cards.
Round 50       Cards: 38/12      5♠     4♥    Player 1 takes the cards.
Round 51       Cards: 39/11      4♠     9♥    Player 2 takes the cards.
Round 52       Cards: 38/12      Q♥     9♣    Player 1 takes the cards.
Round 53       Cards: 39/11      Q♠     6♥    Player 1 takes the cards.
Round 54       Cards: 40/10      9♠     J♣    Player 2 takes the cards.
Round 55       Cards: 39/11      Q♣     8♠    Player 1 takes the cards.
Round 56       Cards: 40/10      A♦    10♦    Player 1 takes the cards.
Round 57       Cards: 41/9       A♣     5♣    Player 1 takes the cards.
Round 58       Cards: 42/8       2♠     6♠    Player 2 takes the cards.
Round 59       Cards: 41/9       Q♦     7♦    Player 1 takes the cards.
Round 60       Cards: 42/8       7♠     8♦    Player 2 takes the cards.
Round 61       Cards: 41/9       3♠     3♦    This is a war.
Round 61       Cards: 40/8        ?      ?    Cards are face down.
Round 61       Cards: 39/7       7♣     9♥    Player 2 takes the cards.
Round 62       Cards: 38/12      8♥     4♠    Player 1 takes the cards.
Round 63       Cards: 39/11      K♦     9♠    Player 1 takes the cards.
Round 64       Cards: 40/10      2♣     J♣    Player 2 takes the cards.
Round 65       Cards: 39/11      3♣     2♠    Player 1 takes the cards.
Round 66       Cards: 40/10      K♠     6♠    Player 1 takes the cards.
Round 67       Cards: 41/9       J♦     7♠    Player 1 takes the cards.
Round 68       Cards: 42/8       K♣     8♦    Player 1 takes the cards.
Round 69       Cards: 43/7      10♥    10♠    This is a war.
Round 69       Cards: 42/6        ?      ?    Cards are face down.
Round 69       Cards: 41/5       8♣     2♥    Player 1 takes the cards.
Round 70       Cards: 46/4       2♦     9♥    Player 2 takes the cards.
Round 71       Cards: 45/5       K♥     3♠    Player 1 takes the cards.
Round 72       Cards: 46/4       4♦     7♣    Player 2 takes the cards.
Round 73       Cards: 45/5       7♥     2♣    Player 1 takes the cards.
Round 74       Cards: 46/4       6♣     J♣    Player 2 takes the cards.
Round 75       Cards: 45/5       5♥     2♦    Player 1 takes the cards.
Round 76       Cards: 46/4       J♠     9♥    Player 1 takes the cards.
Round 77       Cards: 47/3       A♥     7♣    Player 1 takes the cards.
Round 78       Cards: 48/2       4♣     4♦    This is a war.
Round 78       Cards: 47/1        ?      ?    Cards are face down.
Round 78       Cards: 46/0       A♠     J♣    Player 1 takes the cards.
Player 1 wins this game.

Perl[edit]

There are two players, 'one' and 'two'. This shows each players hand as the game progresses.

#!/usr/bin/perl

use strict; # https://rosettacode.org/wiki/War_Card_Game
use warnings;
use List::Util qw( shuffle );

my %rank;
@rank{ 2 .. 9, qw(t j q k a) } = 1 .. 13; # for winner
local $_ = join '', shuffle
  map { my $f = $_; map $f.$_, qw( S H C D ) } 2 .. 9, qw( a t j q k );
substr $_, 52, 0, "\n"; # split deck into two parts
my $war = '';
my $cnt = 0;
$cnt++ while print( /(.*)\n(.*)/ && "one: $1\ntwo: $2\n\n" ),
  s/^((.).)(.*)\n((?!\2)(.).)(.*)$/ my $win = $war; $war = ''; # capture
    $rank{$2} > $rank{$5} ? "$3$1$4$win\n$6" : "$3\n$6$4$1$win" /e
  ||
  s/^(.{4})(.*)\n(.{4})(.*)$/ print "WAR!!!\n\n"; $war .= "$1$3";
    "$2\n$4" /e; # tie means war
print "player '", /^.{10}/ ? 'one' : 'two', "' wins in $cnt moves\n";
Output:
one: 8CqCaD5H6S2HjC9S7HjH8S4DqD5C6DkC4H9D3DqHtC7C8DtS6C4S
two: 5S8HaCaH2C6H3HaS7DjD3S2D5D9CkSkH9H4C2StDtHjSkD7SqS3C

one: qCaD5H6S2HjC9S7HjH8S4DqD5C6DkC4H9D3DqHtC7C8DtS6C4S8C5S
two: 8HaCaH2C6H3HaS7DjD3S2D5D9CkSkH9H4C2StDtHjSkD7SqS3C

one: aD5H6S2HjC9S7HjH8S4DqD5C6DkC4H9D3DqHtC7C8DtS6C4S8C5SqC8H
two: aCaH2C6H3HaS7DjD3S2D5D9CkSkH9H4C2StDtHjSkD7SqS3C

WAR!!!

one: 6S2HjC9S7HjH8S4DqD5C6DkC4H9D3DqHtC7C8DtS6C4S8C5SqC8H
two: 2C6H3HaS7DjD3S2D5D9CkSkH9H4C2StDtHjSkD7SqS3C

one: 2HjC9S7HjH8S4DqD5C6DkC4H9D3DqHtC7C8DtS6C4S8C5SqC8H6S2CaD5HaCaH
two: 6H3HaS7DjD3S2D5D9CkSkH9H4C2StDtHjSkD7SqS3C

... (skipped middle part to save lines)

one: kC7HkHqCqH9SjS5StD4D3S2HaD7S8H4CkS4SaHjD8D6H4H3HjC7CtH5DtC2DjH2C9D6D6C2S6SkDqD9H9C5HtS3D
two: 8C7DaCqSaS5C8S3C

one: 7HkHqCqH9SjS5StD4D3S2HaD7S8H4CkS4SaHjD8D6H4H3HjC7CtH5DtC2DjH2C9D6D6C2S6SkDqD9H9C5HtS3DkC8C
two: 7DaCqSaS5C8S3C

WAR!!!

one: qCqH9SjS5StD4D3S2HaD7S8H4CkS4SaHjD8D6H4H3HjC7CtH5DtC2DjH2C9D6D6C2S6SkDqD9H9C5HtS3DkC8C
two: qSaS5C8S3C

WAR!!!

one: 9SjS5StD4D3S2HaD7S8H4CkS4SaHjD8D6H4H3HjC7CtH5DtC2DjH2C9D6D6C2S6SkDqD9H9C5HtS3DkC8C
two: 5C8S3C

one: jS5StD4D3S2HaD7S8H4CkS4SaHjD8D6H4H3HjC7CtH5DtC2DjH2C9D6D6C2S6SkDqD9H9C5HtS3DkC8C9S5C7HkH7DaCqCqHqSaS
two: 8S3C

one: 5StD4D3S2HaD7S8H4CkS4SaHjD8D6H4H3HjC7CtH5DtC2DjH2C9D6D6C2S6SkDqD9H9C5HtS3DkC8C9S5C7HkH7DaCqCqHqSaSjS8S
two: 3C

one: tD4D3S2HaD7S8H4CkS4SaHjD8D6H4H3HjC7CtH5DtC2DjH2C9D6D6C2S6SkDqD9H9C5HtS3DkC8C9S5C7HkH7DaCqCqHqSaSjS8S5S3C
two: 

player 'one' wins in 117 moves

Phix[edit]

Shuffles on pickup to significantly shorten the games

with javascript_semantics
sequence deck = shuffle(tagset(52)),
         hand1 = deck[1..26],
         hand2 = deck[27..52],
         pending = {}
 
function pop1()
    integer res
    {res, hand1} = {hand1[1],hand1[2..$]}
    return res
end function

function pop2()
    integer res
    {res, hand2} = {hand2[1],hand2[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(hand1)=0 then
        if length(hand2)=0 then
            printf(1,"Game ends as a tie.\n")
            exit
        end if
        printf(1,"Player 2 wins the game.\n")
        exit
    elsif length(hand2)=0 then
        printf(1,"Player 1 wins the game.\n")
        exit
    end if
    integer c1 = pop1(),
            c2 = pop2(),
            r1 = show(c1),
            r2 = show(c2)
    if r1>r2 then
        printf(1,"Player 1 takes the cards.\n")
        hand1 &= shuffle(c1&c2&pending)
        pending = {}
    elsif r1<r2 then
        printf(1,"Player 2 takes the cards.\n")
        hand2 &= shuffle(c1&c2&pending)
        pending = {}
    else -- r1==r2
        printf(1,"Tie!\n")
        if length(hand1)!=0 and length(hand2)!=0 then
            pending &= shuffle(c1&c2&pop1()&pop2())
            printf(1,"??    ??    Cards are face down.\n")
        end if
    end if
end while
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[edit]

Translation of: Julia
""" 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
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.

Racket[edit]

Translation of: Julia
(and inspired by Raku's thnudergnat rules)
#lang racket

(define current-battle-length (make-parameter 3))

(define cards (string->list (string-append "🂢🂣🂤🂥🂦🂧🂨🂩🂪🂫🂭🂮🂡" "🂲🂳🂴🂵🂶🂷🂸🂹🂺🂻🂽🂾🂱"
                                           "🃂🃃🃄🃅🃆🃇🃈🃉🃊🃋🃍🃎🃁" "🃒🃓🃔🃕🃖🃗🃘🃙🃚🃛🃝🃞🃑")))

(define face (curry hash-ref (for/hash ((c cards) (i (in-naturals))) (values c (+ 2 (modulo i 13))))))

(define (print-draw-result turn-number d1 c1 d2 c2  (pending null))
  (printf "#~a\t~a ~a ~a\t~a|~a|~a~%" turn-number c1  c2 (length d1) (length pending)(length d2)))

(define (turn d1 d2 (n 1) (pending null) (battle 0))
  (match* (d1 d2)
    [('() '()) "Game ends in a tie!"]
    [(_ '()) "Player 1 wins."]
    [('() _) "Player 2 wins."]
    [((list c3 d1- ...) (list c4 d2- ...))
     #:when (positive? battle)
     (define pending+ (list* c3 c4 pending))
     (print-draw-result n d1- "🂠" d2- "🂠" "?" pending+)
     (turn d1- d2- (add1 n) pending+ (sub1 battle))]
    [((list (and c1 (app face r)) d1- ...) (list (and c2 (app face r)) d2- ...))
     (define pending+ (list* c1 c2 pending))
     (print-draw-result n d1- c1 d2- c2 #\= pending+)
     (turn d1- d2- (add1 n) pending+ (current-battle-length))]
    [((list (and c1 (app face r1)) d1- ...) (list (and c2 (app face r2)) d2- ...))
     (define spoils (shuffle (list* c1 c2 pending)))
     (define p1-win? (> r1 r2))
     (define d1+ (if p1-win? (append d1- spoils) d1-))
     (define d2+ (if p1-win? d2- (append d2- spoils)))
     (print-draw-result n d1+ c1 d2+ c2 (if p1-win? "←" "→"))
     (turn d1+ d2+ (add1 n))]))

(define (war-card-game)
  (call-with-values (λ () (split-at (shuffle cards) (quotient (length cards) 2)))
                    turn))

(displayln (war-card-game))
Output:
#1	🃉 ← 🃔	27|0|25
#2	🂡 ← 🃘	28|0|24
#3	🂹 → 🃁	27|0|25
#4	🃋 → 🂽	26|0|26
#5	🂫 ← 🂪	27|0|25
#6	🃒 → 🃛	26|0|26
#7	🃑 ← 🃖	27|0|25
#8	🂢 → 🂻	26|0|26
#9	🃍 ← 🃗	27|0|25
#10	🃊 → 🃝	26|0|26
#11	🃎 ← 🂳	27|0|25
#12	🃅 → 🂶	26|0|26
#13	🃙 ← 🂨	27|0|25
#14	🂦 → 🂺	26|0|26

...

#305	🂧 → 🂾	45|0|7
#306	🂦 = 🃖	44|2|6
#307	🂠 ? 🂠	43|4|5
#308	🂠 ? 🂠	42|6|4
#309	🂠 ? 🂠	41|8|3
#310	🃁 ← 🃃	50|0|2
#311	🂽 ← 🂧	51|0|1
#312	🃘 → 🂾	50|0|2
#313	🂷 → 🂾	49|0|3
#314	🂴 → 🃘	48|0|4
#315	🃊 → 🂾	47|0|5
#316	🂱 ← 🂷	48|0|4
#317	🃋 ← 🂴	49|0|3
#318	🃒 → 🃘	48|0|4
#319	🂶 → 🃊	47|0|5
#320	🂢 → 🂾	46|0|6
#321	🂺 ← 🃒	47|0|5
#322	🂩 ← 🃘	48|0|4
#323	🃛 ← 🂶	49|0|3
#324	🃝 ← 🃊	50|0|2
#325	🃞 = 🂾	49|2|1
#326	🂠 ? 🂠	48|4|0
Player 1 wins.

(And the draw-3 rules were meant to lead to short games hmm?)

Raku[edit]

The linked Bicycle cards site has slightly different rules for War! than how I used to play when I was but a lad. Implement it both ways.

Some rules are not nailed down very well. Here is how I interpreted it:

  • The values of the cards 2-10 are face value; Jack, Queen, King and Ace may effectively be treated as: 11, 12, 13 & 14.
  • Each player plays one card face up. The player whose card is the highest value takes both of the played cards and adds them to the bottom of his deck.
  • When one player runs out of cards and is not able to place enough cards to finish a round, he loses.
  • If both players play a card of the same value, it is then War!
    • Bicycle rules: each player then plays another card face down then another face up.
    • thundergnat rules: each player then plays three cards face down then another face up. (Tends to make for shorter games.)
    • If the final face-up cards are different, the player playing the higher value card takes all of the played cards and adds them to the bottom of his deck
    • If they are the same, continue with rounds of War! until one player plays a higher value war card or a player runs out of cards.
  • When the winning player picks up his cards. the cards are randomized when added to the bottom of his deck. (Cuts a typical game from multi thousands of rounds to multi hundreds of rounds)

Pass in which variant you want to play 2 down, (Bicycle), --war=2, 4 down (thundergnat), (default), --war=4 or 3 down (????) , --war=3. By default, there is a short delay (.1 seconds) between rounds so you can watch what is going on. Pass in a larger/smaller value to slow down or speed up how long the game takes. --sleep=0 or whatever.

In glorious ANSI color! (The output loses much when pasted in as text so show output as screenshot images.)

unit sub MAIN (:$war where 2..4 = 4, :$sleep = .1);

my %c = ( # convenience hash of ANSI colors
    red   => "\e[38;2;255;10;0m",
    blue  => "\e[38;2;05;10;200m",
    black => "\e[38;2;0;0;0m"
);

my @cards = flat (flat
     <🂢 🂣 🂤 🂥 🂦 🂧 🂨 🂩 🂪 🂫 🂭 🂮 🂡
      🃒 🃓 🃔 🃕 🃖 🃗 🃘 🃙 🃚 🃛 🃝 🃞 🃑>.map({ "{%c<black>}$_" }),
     <🂲 🂳 🂴 🂵 🂶 🂷 🂸 🂹 🂺 🂻 🂽 🂾 🂱
      🃂 🃃 🃄 🃅 🃆 🃇 🃈 🃉 🃊 🃋 🃍 🃎 🃁>.map({ "{%c<red>}$_" })
).batch(13).map({ .flat Z 2..14 })».map: { .[1] but .[0] };

my $back = "{%c<blue>}🂠";
my @won  = <👈 👉>;

sub shuffle (@cards) { @cards.pick: * }
sub deal    (@cards) { [@cards[0,*+2 … *], @cards[1,*+2 … *]] }

my ($rows, $cols) = qx/stty size/.words».Int; # get the terminal size
note "Terminal is only $cols characters wide, needs to be at least 80, 120 or more recommended."
  and exit if $cols < 80;

sub clean-up {
    reset-scroll-region;
    show-cursor;
    print-at $rows, 1, '';
    print "\e[0m";
    exit(0)
}

signal(SIGINT).tap: { clean-up() }

my @index  = ($cols div 2 - 5, $cols div 2 + 4);
my @player = (deal shuffle @cards)».Array;
my $lose   = False;

sub take (@player, Int $cards) {
    if +@player >= $cards {
        return @player.splice(0, $cards);
    }
    else {
         $lose = True;
         return @player.splice(0, +@player);
    }
}

use Terminal::ANSI;

clear-screen;
hide-cursor;
# Set background color
print "\e[H\e[J\e[48;2;245;245;245m", ' ' xx $rows * $cols + 1;

# Add header
print-at 1, $cols div 2 - 1, "{%c<red>}WAR!";
print-at 2, 1, '━' x $cols;

my $row = 3;
my $height = $rows - $row - 2;
set-scroll-region($row, $height);

# footer
print-at $height + 1, 1, '━' x $cols;

my $round = 0;
my @round;

loop {
    @round = [@player[0].&take(1)], [@player[1].&take(1)] unless +@round;
    print-at $row, $cols div 2, "{%c<red>}┃";
    print-at $row, @index[0], @round[0;0] // ' ';
    print-at $row, @index[1], @round[1;0] // ' ';
    if $lose {
        if @player[0] < @player[1] {
            print-at $row, $cols div 2 + 1, @won[1] unless +@round[1] == 1;
            print-at $height + 3, $cols div 2 - 10, "{%c<red>} Player 1 is out of cards "
        } else {
            print-at $row, $cols div 2 - 2, @won[0] unless +@round[0] == 1;
            print-at $height + 3, $cols div 2 - 10, "{%c<red>} Player 2 is out of cards "
        }

    }
    if (@round[0].tail // 0) > (@round[1].tail // 0) {
        print-at $row, $cols div 2 - 2, @won[0];
        @player[0].append: flat (|@round[0],|@round[1]).pick: *;
        @round = ();
    }
    elsif (@round[0].tail // 0) < (@round[1].tail // 0) {
        print-at $row, $cols div 2 + 1, @won[1];
        @player[1].append: flat (|@round[0],|@round[1]).pick: *;
        @round = ();
    }
    else {
        @round[0].append: @player[0].&take($war);
        @round[1].append: @player[1].&take($war);
        print-at $row, @index[0] - $_ * 2, ($_ %% $war) ?? @round[0; $_] !! $back for ^@round[0];
        print-at $row, @index[1] + $_ * 2, ($_ %% $war) ?? @round[1; $_] !! $back for ^@round[1];
        next
    }
    last if $lose;
    print-at $height + 2, $cols div 2 - 4,  "{%c<blue>} Round {++$round} ";
    print-at $height + 2, $cols div 2 - 40, "{%c<blue>} Player 1: {+@player[0]} cards ";
    print-at $height + 2, $cols div 2 + 21, "{%c<blue>} Player 2: {+@player[1]} cards ";
    sleep $sleep if +$sleep;
    if $row >= $height { scroll-up } else { ++$row }
}

# game over
print-at $height + 2, $cols div 2 - 40, "{%c<blue>} Player 1: {+@player[0] ?? '52' !! "{%c<red>}0"}{%c<blue>} cards ";
print-at $height + 2, $cols div 2 + 20, "{%c<blue>} Player 2: {+@player[1] ?? '52' !! "{%c<red>}0"}{%c<blue>} cards ";
clean-up;
Sample outout Bicycle:

Pass in :war=2 on the command line. See Bicycle variation (offsite png image)

Sample outout using defaults:

See thundergnat variation (offsite png image)

Wren[edit]

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.

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()
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!

XPL0[edit]

char    Deck(52),               \initial card deck (low 2 bits = suit)
        Stack(2, 52);           \each player's stack of cards (52 maximum)
int     Inx(2),                 \index to last card (+1) for each stack
        Top,                    \index to compared cards, = stack top if not war
        Card, N, I, J, P, T;
char    Suit, Rank;

proc    MoveCard(To, From);     \Move top card From Stack to bottom of To Stack
int     To, From;
int     Card, I;
[Card:= Stack(From, 0);         \take top Card from From Stack
for I:= 0 to Inx(From)-2 do     \shift remaining cards over
        Stack(From, I):= Stack(From, I+1);
if Inx(From) > 0 then           \remove From card from its Stack
        Inx(From):= Inx(From)-1;
Stack(To, Inx(To)):= Card;      \add Card to bottom of To Stack
if Inx(To) < 52 then            \remove From card from its Stack
        Inx(To):= Inx(To)+1;
];

[\\Suit:= "^C^D^E^F ";          \IBM OEM card symbols aren't displayable on RC
Suit:= "HDCS ";
Rank:= "23456789TJQKA ";        \T = 10
for Card:= 0 to 52-1 do         \make a complete deck of cards
        Deck(Card):= Card;
for N:= 0 to 10_000 do          \shuffle the deck by swapping random locations
        [I:= Ran(52);  J:= Ran(52);
        T:= Deck(I);  Deck(I):= Deck(J);  Deck(J):= T;
        ];
for N:= 0 to 52-1 do            \deal deck into two stacks
        [Card:= Deck(N);
        I:= N/2;
        P:= rem(0);
        Stack(P, I):= Card;
        ];
Inx(0):= 52/2;  Inx(1):= 52/2;  \set indexes to last card +1

loop    [for P:= 0 to 1 do      \show both stacks of cards
                [for I:= 0 to Inx(P)-1 do
                        [Card:= Stack(P, I);  ChOut(0, Rank(Card>>2))];
                CrLf(0);
                for I:= 0 to Inx(P)-1 do
                        [Card:= Stack(P, I);  ChOut(0, Suit(Card&3))];
                CrLf(0);
                ];
        if Inx(0)=0 or Inx(1)=0 then quit;      \game over

        Top:= 0;                \compare card ranks (above 2-bit suits)
        loop    [if Stack(0, Top)>>2 = Stack(1, Top)>>2 then
                        [Text(0, "War!");  CrLf(0);
                        Top:= Top+2;            \play a card down and a card up
                        ]
                else if Stack(0, Top)>>2 > Stack(1, Top)>>2 then
                        [for I:= 0 to Top do    \move cards to Stack 0
                                [MoveCard(0, 0);  MoveCard(0, 1)];
                        quit;
                        ]
                else    [for I:= 0 to Top do    \move cards to Stack 1
                                [MoveCard(1, 1);  MoveCard(1, 0)];
                        quit;
                        ];
                ];
        T:= ChIn(1);            \wait for keystroke (no key echo)
        CrLf(0);
        ];
]
]
Output:
578Q465J29A9437JTT59A662QJ
CCDDCCSHSHHDDCHCSDHCDHSHHS
KK8A975Q2A38J87T63K342TQK4
HCCCSDDCCSSSDHSHDHDDHDCSSS

78Q465J29A9437JTT59A662QJ
CDDCCSHSHHDDCHCSDHCDHSHHS
K8A975Q2A38J87T63K342TQK4K5
CCCSDDCCSSSDHSHDHDDHDCSSSHC

8Q465J29A9437JTT59A662QJ
DDCCSHSHHDDCHCSDHCDHSHHS
8A975Q2A38J87T63K342TQK4K5K7
CCSDDCCSSSDHSHDHDDHDCSSSHCCC
War!

65J29A9437JTT59A662QJ
CSHSHHDDCHCSDHCDHSHHS
75Q2A38J87T63K342TQK4K5K788AQ94
DDCCSSSDHSHDHDDHDCSSSHCCCCDCDSC

5J29A9437JTT59A662QJ
SHSHHDDCHCSDHCDHSHHS
5Q2A38J87T63K342TQK4K5K788AQ9476
DCCSSSDHSHDHDDHDCSSSHCCCCDCDSCDC
War!
War!

9437JTT59A662QJ55JQ229AA3
DDCHCSDHCDHSHHSSDHCSCHSHS
8J87T63K342TQK4K5K788AQ9476
SDHSHDHDDHDCSSSHCCCCDCDSCDC

. . .

K38562446952A7A2K4J4T7KJQ39976Q893ATK8JTT5Q562AQ87
DDSDSHHSDDSSDDCCSDHCSCCCSSHSSCCCCHSCHHDDHHDCHDHHDH
J3
SC

38562446952A7A2K4J4T7KJQ39976Q893ATK8JTT5Q562AQ87KJ
DSDSHHSDDSSDDCCSDHCSCCCSSHSSCCCCHSCHHDDHHDCHDHHDHDS
3
C
War!

62446952A7A2K4J4T7KJQ39976Q893ATK8JTT5Q562AQ87KJ3385
SHHSDDSSDDCCSDHCSCCCSSHSSCCCCHSCHHDDHHDCHDHHDHDSDCSD