Vue.js 战斗 - 确认框覆盖重置功能

Vue.js Battle - confirm box overrides reset function

我目前正在学习 Udemy 的 Vue.js 教程。我已经到达您正在构建战斗网络应用游戏的部分。完成后,我决定练习我的重构并遇到了这个错误。

当你点击攻击按钮然后确认框出现询问你是否想再玩时,它似乎在我的日志数组中添加了一个额外的项目而不是完全重置游戏。

我怀疑这是因为按下攻击按钮的速度太快,然后在 运行 一个 addToLog() 之前出现确认框,然后它在之后运行它。

或者这可能是我的错误代码。哈哈

请注意,我知道在确认框中单击取消也会出现错误。

index.html

<!DOCTYPE html>
<html>

<head>
    <title>Monster Slayer</title>
    <script src="https://npmcdn.com/vue/dist/vue.js"></script>
    <link rel="stylesheet" href="css/foundation.min.css">
    <link rel="stylesheet" href="css/app.css">
</head>

<body>
    <div id="app">
        <section class="row">
            <div class="small-6 columns">
                <h1 class="text-center">YOU</h1>
                <div class="healthbar">
                    <div class="healthbar text-center" style="background-color: green; margin: 0; color: white;" :style="{width: playerHealth + '%'}">
                        {{ playerHealth }}
                    </div>
                </div>
            </div>
            <div class="small-6 columns">
                <h1 class="text-center">BADDY</h1>
                <div class="healthbar">
                    <div class="healthbar text-center" style="background-color: green; margin: 0; color: white;" :style="{width: computerHealth + '%'}">
                        {{ computerHealth }}
                    </div>
                </div>
            </div>
        </section>
        <section class="row controls" v-if="!isRunning">
            <div class="small-12 columns">
                <button id="start-game" @click="startGame">START GAME</button>
            </div>
        </section>
        <section class="row controls" v-else>
            <div class="small-12 columns">
                <button id="attack" @click="attack">ATTACK</button>
                <button id="special-attack" @click="specialAttack">SPECIAL ATTACK</button>
                <button id="heal" @click="heal">HEAL</button>
                <button id="restart" @click="restart">RESTART</button>
            </div>
        </section>
        <section class="row log" v-if="turns.length > 0">
            <div class="small-12 columns">
                <ul>
                    <li v-for="turn in turns" :class="{'player-turn': turn.isPlayer, 'monster-turn': !turn.isPlayer}">
                        {{ turn.text }}
                    </li>
                </ul>
            </div>
        </section>
    </div>
    <script src="app.js"></script>
</body>

</html>

css/app.css

.text-center {
    text-align: center;
}

.healthbar {
    width: 80%;
    height: 40px;
    background-color: #eee;
    margin: auto;
    transition: width 500ms;
}

.controls,
.log {
    margin-top: 30px;
    text-align: center;
    padding: 10px;
    border: 1px solid #ccc;
    box-shadow: 0px 3px 6px #ccc;
}

.turn {
    margin-top: 20px;
    margin-bottom: 20px;
    font-weight: bold;
    font-size: 22px;
}

.log ul {
    list-style: none;
    font-weight: bold;
    text-transform: uppercase;
}

.log ul li {
    margin: 5px;
}

.log ul .player-turn {
    color: blue;
    background-color: #e4e8ff;
}

.log ul .monster-turn {
    color: red;
    background-color: #ffc0c1;
}

button {
    font-size: 20px;
    background-color: #eee;
    padding: 12px;
    box-shadow: 0 1px 1px black;
    margin: 10px;
}

#start-game {
    background-color: #aaffb0;
}

#start-game:hover {
    background-color: #76ff7e;
}

#attack {
    background-color: #ff7367;
}

#attack:hover {
    background-color: #ff3f43;
}

#special-attack {
    background-color: #ffaf4f;
}

#special-attack:hover {
    background-color: #ff9a2b;
}

#heal {
    background-color: #aaffb0;
}

#heal:hover {
    background-color: #76ff7e;
}

#restart {
    background-color: #ffffff;
}

#restart:hover {
    background-color: #c7c7c7;
}

app.js

new Vue({
    el: app,
    data: {
        playerHealth: 100,
        computerHealth: 100,
        isRunning: false,
        turns: [],
    },
    methods: {
        startGame: function() {
            this.isRunning = true;
            this.playerHealth = 100;
            this.computerHealth = 100;
            this.clearLog();
        },
        attackController: function(attacker, maxRange, minRange) {
            let receiver = this.setReceiver(attacker);
            let damage = 0;
            if (attacker === 'player') {
                damage = this.randomDamage(maxRange, minRange);
                this.computerHealth -= damage;
            }
            if (attacker === 'computer') {
                damage = this.randomDamage(maxRange, minRange);
                this.playerHealth -= damage;
            }
            this.addToLog(attacker, receiver, damage);
            if (this.checkWin()) {
                return;
            }
        },
        attack: function() {
            this.attackController('player', 10, 3);
            this.attackController('computer', 10, 3);
        },
        specialAttack: function() {
            this.attackController('player', 30, 5);
            this.attackController('computer', 30, 5);
        },
        heal: function() {
            if (this.playerHealth <= 90) {
                this.playerHealth += 10;
            } else {
                this.playerHealth = 100;
            }
            this.turns.unshift({
                isPlayer: true,
                text: 'Player heals for ' + 10,
            });
        },
        randomDamage: function(max, min) {
            return Math.floor(Math.random() * max, min);
        },
        checkWin: function() {
            if (this.computerHealth <= 0) {
                this.alertBox('YOU WIN! New Game?');
            } else if (this.playerHealth <= 0) {
                this.alertBox('LOSER!!! New Game?');
            }
            return false;
        },
        alertBox: function(message) {
            if (confirm(message)) {
                this.isRunning = false;
                this.startGame();
            } else {
                this.isRunning = false;
            }
            return true;
        },
        restart: function() {
            this.isRunning = false;
            this.startGame();
        },
        addToLog: function(attacker, receiver, damage) {
            this.turns.unshift({
                isPlayer: attacker === 'player',
                text: attacker + ' hits ' + receiver + ' for ' + damage,
            });
        },
        clearLog: function() {
            this.turns = [];
        },
        setReceiver: function(attacker) {
            if (attacker === 'player') {
                return 'computer';
            } else {
                return 'player';
            }
        },
        damageOutput: function(attacker, health) {
            if (attacker === 'player') {
                damage = this.randomDamage(maxRange, minRange);
                this.computerHealth -= damage;
            }
        },
    },
});

Github 回购是 here 如果你愿意的话。谢谢!

你的attack(和specialAttack)两个玩家的函数攻击:

    attack: function() {
        this.attackController('player', 10, 3);
        this.attackController('computer', 10, 3);
    },

目前,它会在每次 attackController 调用时检查是否获胜。因此,当第一个攻击者 (player) 获胜时,游戏重置并且第二个玩家攻击。

所以,我的建议是,将 checkWinattackController 移到 attack 函数中:

    attack: function() {
        this.attackController('player', 10, 3);
        this.attackController('computer', 10, 3);
        this.checkWin();
    },

specialAttack

Code/JSFiddle: https://jsfiddle.net/acdcjunior/wwc1xnyc/10/


注意,当玩家获胜时,在上面的代码中,即使游戏结束,计算机仍会"strike back"。如果你想停止它,让 checkWin return 如果游戏结束:

    checkWin: function() {
        if (this.computerHealth <= 0) {
            this.alertBox('YOU WIN! New Game?');
            return true;
        } else if (this.playerHealth <= 0) {
            this.alertBox('LOSER!!! New Game?');
            return true;
        }
        return false;
    },

并在 attack(和 specialAttack)中添加一个 if

    attack: function() {
        this.attackController('player', 10, 3);
        if (this.checkWin()) return;
        this.attackController('computer', 10, 3);
        this.checkWin();
    },

已更新 fiddle:https://jsfiddle.net/acdcjunior/wwc1xnyc/13/