运行函数几次后索引未定义

Undefined index after running function a few times

本文关键字:几次 索引 未定义 函数 运行      更新时间:2023-09-26

所以我试图在javascript中创建我自己的Blackjack用于学习目的,即使代码总体上工作,我也遇到了一个奇怪的错误。

在点击Deal html按钮后,调用函数deal(),我会得到playerHand[i] undefineddealerHand[i]未定义的错误,分别在114行或118行,下面发布的代码。

我注意到,如果我非常快地点击按钮,不管什么原因,也会发生这种情况。我怀疑这与内存优化有关,所以我使用delete命令在游戏回合之间重置这些数组,但错误仍然存在。

那么,为什么我的数组在使用后会中断呢?

谢谢。

JS:

var deck = [];
var dealerHand = [];
var playerHand = [];
var dscore = 0;
var pscore = 0;
var turn = 0;
function Card(suit, src) {
    this.src = src;
    this.suit = getSuit(suit);
    this.value = getValue(src);
};
function getSuit(suit) {
    if (suit == 1) return "Clubs";
    if (suit == 2) return "Diamonds";
    if (suit == 3) return "Hearts";
    if (suit == 4) return "Spades";
};
function getValue(src) {
    if (src == 1) return 11;
    if (src < 10) return src;
    else return 10;
};
function createDeck() {
    for (i=1; i<=4; i++) {
        for(j=1; j<=13; j++) {
            var card = new Card(i, j);
            deck.push(card);
        };
    };
};
function getCard() {
    var rand = Math.floor(Math.random()*deck.length);
    deck.splice(rand,1);
    return deck[rand];
};
function deal() {
    if(turn == 0) {
        dealerHand.push(getCard());
        playerHand.push(getCard());
    };
    dealerHand.push(getCard());
    playerHand.push(getCard());
};
function stand() {
    dealerHand.push(getCard());
};
function clearBoard () {
    $('#player').html("");
    $('#dealer').html("");
};
function resetDeck () {
    delete deck;
    deck = [];
};
function resetHands () {
    delete dealerHand;
    delete playerHand;
    dealerHand = [];
    playerHand = [];
};
function resetScore () {
    pscore = 0;
    dscore = 0;
};
function isAce (arr) {
    for(i=0; i<arr.length; i++) {
        if (arr[i].src == 1) return true;
        else return false;
    };
}
function updateScore() {
    resetScore();
    if (playerHand.length > 0 && dealerHand.length > 0) {
        for(i=0; i<playerHand.length; i++) {
            pscore += playerHand[i].value;
        };
        for(i=0; i<dealerHand.length; i++) {
            dscore += dealerHand[i].value;
        };
        //Regra do Às
        if(pscore > 21 && isAce(playerHand)) {
            pscore -= 10;
        };
        if(dscore > 21 && isAce(dealerHand)) {
            dscore -= 10;
        };
    } else {
        pscore = 0;
        dscore = 0;
    };
};
function showScore () {
    $('#pscore').html("<p>Player Score: " + pscore + "</p>");
    $('#dscore').html("<p>Dealer Score: " + dscore + "</p>");
};
function showCards () {
    for(i=0; i<playerHand.length; i++) {
        var div = $("<div>");
        var img = $("<img>");
        img.attr('src', 'img/cards/' + playerHand[i].suit + '/' + playerHand[i].src + '.png');
        div.append(img);
        $('#player').append(div);
    };
    for(i=0; i<dealerHand.length; i++) {
        var div = $("<div>");
        var img = $("<img>");
        img.attr('src', 'img/cards/' + dealerHand[i].suit + '/' + dealerHand[i].src + '.png');
        div.append(img);
        $('#dealer').append(div);
    };
};
function cleanUp () {
    if (pscore == 21) {
        alert("Blackjack!");
        newGame();
    };
    if (pscore > 21) {
        alert("Bust!");
        newGame();
    };
    if (dscore == 21) {
        alert("You lost!");
        newGame();
    };
    if (dscore > 21) {
        alert("You won!");
        newGame();
    };
};
function newGame () {
    turn = 0;
    clearBoard();
    resetHands();
    resetScore();
    showScore();
    resetDeck();
    createDeck();
};
function gameTurn () {
    clearBoard();
    updateScore();
    showCards();
    showScore();
    cleanUp();
    turn++;
};
$(document).ready(function() {
    newGame();
    $('#deal').on('click', function(){
        deal();
        gameTurn();
    });
    $('#stand').on('click', function(){
        stand();
        gameTurn();
    });
});
CSS:

body {
    background: url(../img/greenbg.png);
}
.holder { 
    width:800px;
    margin:auto;
}
.clearfix { 
    clear:both;
}
#pscore, #dscore {
    color: white;
    margin: 10px;
    display: block;
    font-size: 1.2rem;
    text-shadow: 0 0 5px #000;
}
.container {
    width: 600px;
    height: 300px;
    margin: 10px;
}
div img {
    float: left;
    margin: 10px;
}
div button {
    margin: 10px;
}
HTML:

<html>
    <head>
        <div class="holder clearfix">
            <div id="dscore"><p>Dealer Score: 0</p>
            </div>
            <div id="dealer" class="container">
            </div>
            <div id="pscore"><p>Player Score: 0</p>
            </div>
            <div id="player" class="container">
            </div>
            <div class="">
                <button id="deal">Deal</button>
                <button id="stand">Stand</button>
            </div>
        </div>
    </body>
</html>

这个函数有问题,这可能是原因:

function getCard() {
    var rand = Math.floor(Math.random()*deck.length);
    deck.splice(rand,1);
    return deck[rand];
};
如前所述,它是移除一张牌,然后返回现在在牌组中该位置的牌。如果rand是数组中的最后一个元素,那么在那个位置上不再有一张牌,所以它将返回undefined

您应该返回被删除的卡本身的值,splice调用结果的一部分:

function getCard() {
    var rand = Math.floor(Math.random() * deck.length);
    var pick = deck.splice(rand, 1);
    return pick[0];
};

注。学习用于数组的现代ES5实用函数是值得的。例如,可以这样重写isAce函数,以避免在测试第一个元素之后总是使用return的错误:

function isAce(arr) {
    return arr.some(function(n) {
        return n === 1;
    });
};

或者更清楚地说:

function isAce(card) {
    return card === 1;        // test a single card
};
function holdsAce(hand) {
    return hand.some(isAce);  // test an array (or hand) of cards
};