【问题标题】:Trying to remove a card from a deck BlackJack getting IndexOutOfRange exception [duplicate]试图从牌组 BlackJack 中移除一张牌,得到 IndexOutOfRange 异常 [重复]
【发布时间】:2014-02-09 08:00:58
【问题描述】:

我正在用 C# 创建一个小 BlackJack 应用程序。我能够向庄家和玩家发一手牌,然后为玩家打牌。但是一旦我这样做了,当庄家手牌值小于 17 时,庄家应该从牌堆中抽一张牌。

这是从套牌类中的套牌中获取单张牌:

public Card GetCard()
{
    int r0 = rndCard.Next(0, cardsInDeck_.Count - 1);
    cardsInDeck_.RemoveAt(r0);
    return cardsInDeck_[r0];
}

当我点击“留下”并且经销商激活时,我在最后一行收到此错误

Index was out of range. Must be non-negative and less than the size of the collection

这是我在表单上的“停留”方法

 private void buttonStay_Click(object sender, EventArgs e)        
 {          
    while (dealer.GetValue() < 17) 
    {
        dealer.CardsInDealerHand.Add(deck.GetCard());

    }

    dealerHandValue_ = dealer.GetValue();

    if (dealerHandValue_ > 21)
    {
        Win();

    }
    else
    {
        WinCondition();
    }
 }

我一般是编程新手,但我认为我的套牌或经销商有问题。

我将不胜感激。

【问题讨论】:

  • 这是你的宝贝吗?
  • 不,不是,我目前正在为大学放暑假,我认为这是一个很好的练习,但我被困住了。

标签: c# indexoutofboundsexception


【解决方案1】:

我注意到的第一件事是:您在访问卡片并将其归还之前将卡片从卡片组中取出,导致您的索引失控。在某些情况下,这可能会“起作用”,因为它不会抛出,但你不会取回正确的牌。在其他情况下,您最终可能会超出列表的界限。

考虑:你的“套牌”中有 6 件物品,而你选择了最后一件。您当前的逻辑是:

cardsInDeck_.RemoveAt(r0);  # Remove the item at index 5; now we have 5 items (0-based indexing)
return cardsInDeck_[r0]; # Try to get the item at index 5, but it's no longer there!

即使您没有选择最后一个索引,您实际上也会得到错误的卡片。例如,如果您有:

{ A, J, 5, 10, 2 }

...在你的牌组中,你选择了索引 2,你应该拿回 5。由于您首先移除卡片然后访问列表索引,因此您实际上会取回 10。

您需要先获取卡片的引用,然后将其从卡组中取出并返回引用:

public Card GetCard()
{
    int r0 = rndCard.Next(0, cardsInDeck_.Count - 1);
    var chosenCard = cardsInDeck_[r0];
    cardsInDeck_.RemoveAt(r0);
    return chosenCard;
}

在尝试获取另一张卡之前检查cardsInDeck_.Count 的零值可能是个好主意,也许是在GetCard() 或while 循环中。如果你只发两​​只手(一只给玩家,一只给庄家),那么这在数学上当然不是你会遇到的情况。否则,如果有多位玩家,您需要以某种方式处理这种情况(例如,您可以通过重新填充 cardsInDeck 来添加第二副牌)。

【讨论】:

  • 我刚试过这个,但程序崩溃了
  • minValue' 不能大于第一行的 maxValue
  • @user3230102:这似乎意味着牌组是空的(例如,cardsInDeck_.Count - 1 必须是 -1,小于 0),但我不能告诉你为什么会这样您显示的代码。无论哪种方式,GetCard() 中的当前逻辑都将是错误的。听起来您遇到了多个错误。
  • 这是否意味着卡组中的卡片列表没有填充?
  • @user3230102:要么一开始没有填充,要么被清空并且没有重新填充。同样,我无法根据目前的情况来判断。但是,如果列表根本没有被填充,那么我看不出你会如何得到你的问题中的错误,因为一个空列表将导致调用Random.Next(0, -1),给你错误在你的评论中。它会导致无法获得索引错误(至少在第一次调用时)。
【解决方案2】:

函数 rndCard.Next 将 r0 设置为负值或大于 cardsInDeck_ 大小的值

    int r0 = rndCard.Next(0, cardsInDeck_.Count - 1);

【讨论】:

  • 你知道我该如何解决这个问题吗,visual studio 说这条线是问题所在,但我认为 rndCard.Next 的参数将给出一个介于 0 和卡片列表大小之间的值甲板
  • 对不起,我对C#或一般编程不是很熟悉,你的意思是卡组中的卡片列表/
  • Stack Overflow 不是调试服务。如果我找到了错误的来源,请将答案标记为正确。您需要研究调试技术并了解对象上的函数如何返回值。
【解决方案3】:

问题:您正在尝试从 cardsInDeck_ 中删除项目,而不检查其 Count 。如果您在某个时刻继续从cardsInDeck_ 中删除项目,则Count 变为 如果 Count 为零,则无法删除任何项目。

解决方案:在从cardsInDeck_删除项目之前,您需要检查它的Count,只有当它的Count大于零时才应该删除项目。

替换这个:

cardsInDeck_.RemoveAt(r0);

有了这个:

if(cardsInDeck_.Count>0)
{
cardsInDeck_.RemoveAt(r0);
}

【讨论】:

  • 它说不是所有的代码路径都返回一个值然后它不能正确编译。
  • 计数为零怎么办?我会以某种方式停止该方法吗?
  • @user3230102: 是的,因为如果 cardsInDeck_ 的计数为零,您就无法从 cardsInDeck_ 中删除项目。
【解决方案4】:

异常消息: “索引超出范围。必须为非负数且小于集合的大小” 是这里的问题,因为如果甲板是空的,那么

int r0 = rndCard.Next(0, cardsInDeck_.Count - 1); Next 的第二个参数是一个排他的上限。 因此,如果 Count 为 0,那么您要求的是 int >= 0 && 如果 count 为 1,则您要求 int >= 0 &&

另外,我建议您遵循标准 C# 命名约定。 Microsoft 的建议是一个很好的起点

msdn C# style guide

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 2015-04-27
    • 2013-03-19
    • 1970-01-01
    相关资源
    最近更新 更多