为什么卡片在 Javascript ES6 "Game of War" 中丢失?

Why are cards being lost in Javascript ES6 "Game of War"?

为了更好地理解 Javascript ES6 和一般的面向对象编程,我决定尝试编写一个简单的游戏 War.

乍一看,游戏似乎 运行 不错......它总是 return 获胜玩家的名字,因为它是一个机会游戏,所以 return 任何给定的玩家大约有 50% 的时间。

然而,仔细检查后发现有些地方非常不对劲。 问题是在每个连续的回合中,游戏中的纸牌总数都在减少,而不是保持在恒定的 52。

该游戏使用五个不同的 类,全部列在下面,以及一个 war.js 文件来实例化游戏并记录获胜者。

可以在以下位置找到源文件:https://github.com/johncmunson/war

运行与node war.js

的比赛

Card.js

class Card {
    constructor(rank, suit) {
        this.rank = rank
        this.suit = suit
    }
}

module.exports = Card

Deck.js

const Card = require('./Card.js')

class Deck {
    constructor() {
        const suits = [1, 2, 3, 4]
        const ranks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
        this.cards = ranks.map(
            rank => suits.map(
                suit => new Card(rank, suit)
            )
        ).reduce(
            (cum, cur) => cum.concat(cur),
            []
        )
    }

    shuffle() {
        let currentIndex = this.cards.length
        let tempValue, randomIndex
        while (0 !== currentIndex) {
            randomIndex = Math.floor(Math.random() * currentIndex)
            currentIndex -= 1
            tempValue = this.cards[currentIndex]
            this.cards[currentIndex] = this.cards[randomIndex]
            this.cards[randomIndex] = tempValue
        }
    }

    deal(players) {
        let currentIndex = 0
        while (this.cards.length) {
            let dealtCard = this.cards.pop()
            players[currentIndex].receiveCard(dealtCard)
            if (currentIndex === players.length - 1) {
                currentIndex = 0
            } else {
                currentIndex += 1
            }
        }
    }
}

module.exports = Deck

Player.js

class Player {
    constructor(name) {
        this.name = name
        this.cards = []
        this.battleCard = null
    }

    playCard() {
        this.battleCard = this.cards.shift()
    }

    receiveCard(card) {
        this.cards.push(card)
    }

    winBattle(battleCard, potCards) {
        this.cards.push(battleCard)
        if (potCards.length) {
            for (let card of potCards) {
                this.cards.push(card)
            }
        }
    }

    tie(pot) {
        let burnCards = this.cards.length <= 3 ?
            this.cards.splice(0, this.cards.length) :
            this.cards.splice(0, 3)
        pot.receiveBurnCards(burnCards)
        pot.receiveBattleCard(this.battleCard)
    }
}

module.exports = Player

Pot.js

class Pot {
    constructor() {
        this.cards = []
    }

    receiveBattleCard(card) {
        this.cards.push(card)
    }

    receiveBurnCards(burnCards) {
        for (let card of burnCards) {
            this.cards.push(card)
        }
    }

    reset() {
        this.cards = []
    }
}

module.exports = Pot

Game.js

const Card = require('./Card.js')
const Deck = require('./Deck.js')
const Player = require('./Player.js')
const Pot = require('./Pot.js')

class Game {
    constructor(player1, player2, numberRounds) {
        this.player1 = new Player(player1)
        this.player2 = new Player(player2)
        this.rounds = numberRounds
        this.deck = new Deck()
        this.pot = new Pot()
    }

    _compare(card1, card2) {
        const rank1 = card1.rank === 1 ? 14 : card1.rank
        const rank2 = card2.rank === 1 ? 14 : card2.rank
        return rank2 - rank1
    }

    _battle() {
        this.player1.playCard()
        this.player2.playCard()
        const result = this._compare(this.player1.battleCard,                                         
        this.player2.battleCard)
        if (result < 0) {
            this.player1.winBattle(this.player2.battleCard, this.pot.cards)
            this.pot.reset()
        } else if (result > 0) {
            this.player2.winBattle(this.player1.battleCard, this.pot.cards)
            this.pot.reset()
        } else {
            this.player1.tie(this.pot)
            this.player2.tie(this.pot)
        }
    }

    _getWinner() {
        if (this.player1.cards.length > this.player2.cards.length) {
            return this.player1.name
        } else if (this.player1.cards.length < this.player2.cards.length) {
            return this.player2.name
        } else {
            return 'Tie!'
        }
    }

    play() {
        this.deck.shuffle()
        this.deck.deal([this.player1, this.player2])
        if (this.rounds) {
            while (this.rounds !== 0) {
                this._battle()
                this.rounds -= 1
                console.log('Number of Cards: ', this.pot.cards.length + this.player1.cards.length + this.player2.cards.length)
            }
        } else {
            while (this.player1.cards.length && this.player2.cards.length) {
                this._battle()
                console.log('Number of Cards: ', this.pot.cards.length + this.player1.cards.length + this.player2.cards.length)
            }
        }
        return this._getWinner()
    }
}

module.exports = Game

war.js

const Game = require('./Game.js')
const war = new Game('George', 'Abe')
console.log(war.play())

控制台输出

Number of Cards:  52
Number of Cards:  51
Number of Cards:  50
Number of Cards:  49
Number of Cards:  48
Number of Cards:  47
Number of Cards:  47
Number of Cards:  46
Number of Cards:  45
Number of Cards:  45
Number of Cards:  44
Number of Cards:  43
Number of Cards:  42
Number of Cards:  41
Number of Cards:  40
Number of Cards:  39
Number of Cards:  38
Number of Cards:  37
Number of Cards:  36
Number of Cards:  35
Number of Cards:  34
Number of Cards:  33
Number of Cards:  32
Number of Cards:  31
Number of Cards:  30
Number of Cards:  29
Number of Cards:  28
Number of Cards:  27
Number of Cards:  26
Number of Cards:  25
Number of Cards:  24
Number of Cards:  23
Number of Cards:  22
Number of Cards:  21
Number of Cards:  20
Number of Cards:  19
Number of Cards:  18
George

那是因为赢家也应该保留自己的卡。

在 Player.js 你应该添加

 winBattle(battleCard, potCards) {
    this.cards.push(this.battleCard) // this one
    this.cards.push(battleCard)
    if (potCards.length) {
        for (let card of potCards) {
            this.cards.push(card)
        }
    }
}