如何从integer()类型变量获取特定值?及解决二十一点游戏手牌计算的System.IndexOutOfRangeException异常
解决二十一点手牌计算的数组越界问题与Integer数组取值疑问
让我们一步步拆解你的问题,先搞定那个烦人的数组越界异常,再解答你关于Integer数组的疑问。
一、先解决System.IndexOutOfRangeException异常
你的异常根源完全出在这行代码上:
value += p.getHand(i).getValue(i)
这里犯了一个逻辑混淆的错误:你把遍历手牌的循环变量i,同时当成了getValue()返回的Integer数组的索引,但这两个索引完全没有关联:
- 循环变量
i是手牌列表的索引(从0到手牌总数-1) getValue()返回的数组是单张牌的可选数值(比如Ace是{1,11},2是{2},JQK是{10}),它的长度最多是2(只有Ace有两个值)
举个实际例子:当你遍历到第二张牌(i=1),如果这张牌是2,它的getValue()数组长度只有1,此时访问getValue(1)就会直接超出数组的合法索引范围(数组只有索引0),触发越界异常。
修复后的基础版check函数
如果只是想先实现基础的手牌总值计算(暂时把Ace按最小数值1计算),可以直接取数组的第一个元素:
Public Shared Function check(p As Player) As Integer Dim value As Integer = 0 For i = 0 To p.length() - 1 ' 取每张牌数值数组的第一个元素 value += p.getHand(i).getValue()(0) Next Return value End Function
进阶版:符合二十一点规则的Ace双值处理
二十一点中Ace可以灵活切换1或11(尽量不爆牌),我们可以优化逻辑来实现这个规则:
Public Shared Function check(p As Player) As Integer Dim total As Integer = 0 Dim aceCount As Integer = 0 ' 第一步:先按最小数值计算所有牌,统计Ace的数量 For Each card In p.getHand() Dim cardValues = card.getValue() If cardValues.Length = 2 Then ' 判定是Ace牌 aceCount += 1 total += cardValues(0) ' 先按1计算 Else total += cardValues(0) End If Next ' 第二步:尝试把Ace从1换成11,只要总价值不超过21就替换 While aceCount > 0 AndAlso total + 10 <= 21 total += 10 aceCount -= 1 End While Return total End Function
二、关于Integer()类型变量的取值疑问
Integer()在VB.NET里是整数数组,要获取里面的元素需要用索引访问,格式是数组变量(索引):
- 数组的索引从0开始,最大合法索引是
数组.Length - 1 - 比如Ace牌的数值数组是
{1,11},取1用values(0),取11用values(1) - 必须确保索引在合法范围内,否则就会触发你遇到的
IndexOutOfRangeException
举个简单的示例代码:
' Ace牌的数值数组 Dim aceValues() As Integer = {1, 11} Dim minAceValue As Integer = aceValues(0) ' 得到1 Dim maxAceValue As Integer = aceValues(1) ' 得到11 ' 2牌的数值数组 Dim twoValues() As Integer = {2} Dim cardValue As Integer = twoValues(0) ' 得到2
额外的小建议
为了让代码更符合.NET的命名规范,你可以做两个小调整:
- 把Player类里的
length()方法改成只读属性:
Public ReadOnly Property HandCount As Integer Get Return hand.Count End Get End Property
调用时用p.HandCount代替p.length(),代码可读性更强。
- 把Card类的
getValue()属性改成Values,和.NET的属性命名风格保持统一。
内容的提问来源于stack exchange,提问作者It was me DIO
相关产品推荐
相关产品推荐

