繁体   English   中英

if else 逻辑有什么更好的方法来实现这个?

[英]What would be a better way to implement this if else logic?

老实说,我想不出更好的标题,因为这是一个基于场景的问题:

我们有一个 Battleships 游戏,我们想要求玩家提供一对坐标,以便在网格上设置他们的一艘船(更具体地说,是船的起点和终点)。 假设坐标已经正确给出并且船在网格平面的范围内,我们只需要检查船是否与当前在网格平面上的任何其他船发生碰撞。

上下文:Grid 有一个 Content 属性,它可以是 ShipContent 或 EmptyContent。

CollisionChecker() 方法循环遍历先前给定的坐标对之间的空间(请注意,这些坐标不能是对角线,这也被假定为事先检查过的)。

玩家想把他们的战舰放在 A1 和 A4 之间。 由于字母相等,我们循环遍历 1 到 4,很简单。 但是,玩家可以按照他们的顺序分别输入 A4 和 A1。 这两种情况在逻辑上都可以正常工作,但如果不进行相应处理,它们可能会导致 OutOfBound 异常和/或不正确的循环。

最后一点上下文,CoordinateLetter 是一个枚举,其中包含整个英文字母表。

static bool CollisionChecker(Grid[][] gridPlane, CoordinateLetter coordinateLetter1, CoordinateLetter coordinateLetter2, int coordinateNumber1, int coordinateNumber2)
    {
        bool lettersEqual = coordinateLetter1 == coordinateLetter2;
        bool cL1Bigger = coordinateLetter1 > coordinateLetter2;
        bool cN1Bigger = coordinateNumber1 > coordinateNumber2;
        if (lettersEqual && cN1Bigger)
            for (int num = coordinateNumber2; num <= coordinateNumber1; num++)
            {
                // Assume that if it collides, it returns false
            }
        else if (lettersEqual && !cN1Bigger)
        {
            for (int num = coordinateNumber1; num <= coordinateNumber2; num++)
            {
                // Assume that if it collides, it returns false
            }
        }
        else if (!lettersEqual && cL1Bigger)
        {
            for (int num = (int)coordinateLetter2; num <= (int)coordinateLetter1; num++)
            {
                // Assume that if it collides, it returns false
            }
        }
        else
        {
            for (int num = (int)coordinateLetter1; num <= (int)coordinateLetter2; num++)
            {
                // Assume that if it collides, it returns false
            }
        }
        return true;
    }

这段代码让我脊背发凉。 如果其他情况是这样的,我不喜欢链接。 有什么更好的方法来实现这一点?

您可以使代码更易于遵循和维护,也许在命名上更合乎逻辑。

但有时你会做你必须做的事。

这只是我在玩弄它...

    static bool CollisionChecker(Grid[][] gridPlane, CoordinateLetter gridRow1, CoordinateLetter gridRow2, int gridCol1, int gridCol2)
    {
        bool sameRow = (gridRow1 == gridRow2);
        
        if (!(sameRow || (gridCol1 == gridCol2)))
            throw new ArgumentException("Diagonal not allowed!");
        
        if (sameRow)
        {
            int row = (int)gridRow1;
            int start = Math.Min(gridCol1, gridCol2);
            int end   = Math.Max(gridCol1, gridCol2);

            for (int i = start; i <= end; i++)
            {
                //Check gridPlane[row][i]
            }
        }
        else //Same column
        {
            int col = gridCol1;
            int start = Math.Min((int)gridRow1, (int)gridRow2);
            int end   = Math.Max((int)gridRow1, (int)gridRow2);

            for (int i = start; i <= end; i++)
            {
                //Check gridPlane[i][col]
            }
        }

        return true;
    }

您在这里真正要做的是在两个向量之间进行插值,因此您无需明确处理每种情况,只需使用它们的归一化差异来逐步遍历网格。 让我解释得更好。

首先,让我们用数字替换坐标系中的字母(只是为了让事情更简单),这样 A1 = (1; 1)、B4 = (2; 4) 等等。 想象一下,您正在尝试将 go 从 E1 到 A1,或 X = (5; 1) 到 Y = (1; 1)。 要在一个 go 中完成这一旅程,您需要从 X 的第一个分量中删除 4 个单位,这在数学上可以写为 X + (-4; 0) = Y。重新排列它为我们提供了找到任何之间差异的公式两个向量:Y - X = (-4; 0),也就是说,只需从目标 position (Y) 中减去起始 position (X)。

但是你不想在一个 go 中完成这个旅程,你想以小步骤检查另一艘船是否阻挡了你。 现在,因为你在一个离散的 integer 网格中(即你在 position 1 或 2 中,你不能在 position 中,而错过了最长的步骤 1.5) way 的长度为 1。因此,如果您的点之间的差异为 (-4; 0),则您需要 (-1; 0) 的步长。 如果差为 (0; 5),则需要 (0; 1) 的步长。 这种在保持方向不变的情况下获取向量并将其减少到长度 1 的过程称为归一化 由于您的向量将始终是轴对齐的(即您不会沿对角线行走),您可以作弊并在每个组件上使用Math.sign而不是进行“完整”向量归一化。

把它们放在一起会给你这样的东西(考虑这个伪代码,我什至不知道它是否会编译):

int diffX = (int)coordinateLetter2 - (int)coordinateLetter1;
int diffY = coordinateNumber2 - coordinateNumber1;

int stepX = Math.sign(diffX);
int stepY = Math.sign(diffY);

CoordinateLetter currentX = coordinateLetter1;
int currentY = coordinateNumber1;
while (currentX != coordinateLetter2 || currentY != coordinateNumber2)
{
    if (HasCollision(currentX, currentY))
        return false;

    currentX += stepX;
    currentY += stepY;
}

return true;

我还建议创建一个结构来保存 position 的两个坐标(字母和数字),以便您可以直接在 position 上而不是在其组件上进行操作。 这使得推理二维码变得更容易。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM