【问题标题】:Is there a cleaner way to stay inside the bounds of an array?有没有更干净的方法可以留在数组的范围内?
【发布时间】:2014-11-06 21:09:33
【问题描述】:

我有一个二维整数数组,它表示我用来跟踪游戏中对象位置的地图。它被一个程序系统修改,该系统将更改其中的数字以放置不同的对象。我将每个 Int 的值设置为 0,1 或 2。看起来像这样:

00010
00100
02120
21200
12000

由于程序步骤在很大程度上依赖于随机化,我想进行几项检查,如果我尝试写入的数组位置超出了数组的边界,它将回退到地图的边缘而不是造成故障。例如我尝试在 [0,10] 中输入一个条目,它将默认为 [0,4]。 是的,我知道我应该小心确保我永远不会尝试在数组边界之外写入,但考虑到其他元素不会每次都发生。健全性检查似乎是谨慎的。

我想出的解决方案可行,但它似乎过于繁琐且冗长。有没有我不知道的更清洁的解决方案?

这是代码示例:

//Example of something randomly being written to the array
random r = new Random();
int xMax = field.GetLength(0);
field[mid(r.next(0,5), 0, xMax), 0] = 1; 

//Method for sanity bounds.
private static int mid(int target, int min, int max)
{
    //Target is the value we want
    //Min is the smallest possible value
    //Max is the largest possible value.

    if (target == min)
    {
        return min;
    }
    if (target == max)
    {
        return max;
    }
     if (target < max && target > min)
    {
        return target;
    }
    else if (target > max && target > min)
    {
        return max;
    }
    else if (target < min && target < max)
    {
        return min;
    }
    return min; //This shouldn't ever get trigger.  In here so compiler won't complain.
}

【问题讨论】:

  • 我没有你的问题的答案,但也许你方法中的最后一行 - return min - 如果它是未定义/意外的行为,应该抛出一个异常。
  • 如果你正在访问一个无效的索引,你应该希望你的程序崩溃,这样你就会意识到你有一个错误并且可以修复它,而不是简单地访问错误的数组值并掩盖问题,创建一个更难发现和诊断的错误。
  • @DanPantry 他不需要那样做。在这种情况下,他可以删除整个东西,让数组索引器抛出一个索引超出范围的异常。
  • @Servy - 我是在笼统地说 - 如果你正在解决编译器错误,你可能应该抛出异常:p
  • @DanPantry 这不会抑制编译时错误。它抛出异常。是的,我同意应该在这里抛出异常,但不是创建一个方法来抑制异常然后让它抛出异常,你可以首先不抑制异常和不创建新方法。

标签: c# arrays optimization


【解决方案1】:

你可以这样做:

public int mid(int target, int min, int max)
{
    return Math.max(min, Math.min(max, target));
}

此函数返回预期值中较小的值和最大界限中的最大值,确保返回有效值。


如果您使用的是矩形二维数组,您也可以在访问中使用%

array[index1 % array.length][index2 % array[0].length] = /* somevar */;

【讨论】:

  • 这真的很漂亮。谢谢。
【解决方案2】:

如果您希望索引按照您的描述“环绕”数组,这应该可以:

public void GetValidIndexForArrayFromRandomIndex(int index, string[] myArray)
{
    var upperBound = myArray.GetUpperBound(0);
    var lowerBound = myArray.GetLowerBound(0);

    while (index > upperBound)
    {
        index -= upperBound + 1;
    }
    while (index < lowerBound)
    {
        index += upperBound;
    }

    return index;
}

或者这应该做你上面的代码所做的:

// We really only need to test the upper and lower bounds. 
// If target is greater than max or less than min, then return the bound that it crossed
if (target > max) return max;
if (target < min) return min;

// Otherwise, it's within the bounds, so just return target.
return target;

或者你可以在一行中完成:

return (target > max) ? max : (target < min) ? min : target;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-30
    • 2022-08-11
    • 1970-01-01
    • 2020-02-26
    • 2015-03-08
    相关资源
    最近更新 更多