更改我的变量会创建无限循环

问题描述 投票:0回答:3

我最近一直在学习Python,但是最近想做一个涉及2D数组的项目,所以我决定切换到C#(很抱歉,如果我的代码很差)

基本上我正在写一个为我做填字游戏的程序。

  • 我有i迭代顶部/底部
  • 我有j从左到右迭代

我发现i想要的第一个字母 - 让我们称之为“keyletter”

现在我需要查看它周围的所有8个空格。如果i/j位置是[1,2],我首先看[0,2]

在我的代码中,我想将i1更改为0,并打印,(如果这是正确的字母)第二个字母是:[0,2]

一旦我将i1更改为0并尝试打印,它就会吐出一百万次然后卡住了。

public static void Main(string[] args)
{
    string keyLetter = "g";
    string keyLetter2 = "b";
    string[,] crossword = new string[,] 
    { 
        { "a", "b", "c", "d" },
        { "e", "f", "g", "h" }, 
        { "a", "e", "b", "c" }, 
        { "i", "j", "k", "l" }
    };

    for (int i = 0; i < crossword.GetLength(0); i++)
    {
        for (int j = 0; j < crossword.GetLength(1); j++)
        {
            if (keyLetter == crossword[i, j])
            {
                Console.Write(keyLetter + " is [" + i + ", " + j + "]");
                Console.WriteLine();
                Console.WriteLine();
                Console.Write("i is: " + i);
                Console.WriteLine();
                Console.Write("j is: " + j);
                Console.WriteLine();

                if (keyLetter2 == crossword[i - 1, j])
                {
                    // i--;
                    Console.Write("[i/j] position for " + keyLetter2 + " is [" + i + 
                        ", " + j + "]");
                }
                else if (keyLetter2 == crossword[i + 1, j])
                {
                    Console.Write("[i/j] position for " + keyLetter2 + " is [" + i + 
                        ", " + j + "]");
                }
                /*
                else if (keyLetter2 == crossword[i + 1, j - 1])
                {
                    Console.Write("[i/j] position for " + keyLetter2 + " is [" + i + 
                        ", " + j + "]");
                }
                else if (keyLetter2 == crossword[i, j - 1])
                {
                    Console.Write("[i/j] position for " + keyLetter2 + " is [" + i + 
                        ", " + j + "]");
                }
                else if (keyLetter2 == crossword[i - 1, j - 1])
                {
                    Console.Write("[i/j] position for " + keyLetter2 + " is [" + i + 
                        ", " + j + "]");
                }
                else if (keyLetter2 == crossword[i + 1, j + 1])
                {
                    Console.Write("[i/j] position for " + keyLetter2 + " is [" + i + 
                        ", " + j + "]");
                }
                else if (keyLetter2 == crossword[i, j + 1])
                {
                    Console.Write("[i/j] position for " + keyLetter2 + " is [" + i + 
                        ", " + j + "]");
                }
                else if (keyLetter2 == crossword[i - 1, j + 1])
                {
                    Console.Write("[i/j] position for " + keyLetter2 + " is [" + i + 
                        ", " + j + "]");
                }*/

                Console.WriteLine();
            }
        }
    }
}    

我有它设置如下:

  • keyletter =“a”
  • keyletter2 =“b”
  • 等等

Loop problem picture

c#
3个回答
0
投票

问题在于声明

// if(keyLetter2 == crossword [i-1,j])

这里,如果矩阵是这样的

"

a b c

d e f

"

并且假设你想要搜索模式“ba”,那么很明显你会找到b,因此我将为0而j将为1.现在,你要做(i-1)将为-1(那里)没有负面索引),因此错误。

执行此操作的最佳方法是检查i或j是否已经为0。如果它们是0,那么你不需要i-1或j-1,你可以像“if(i!= 0)然后if(keyLetter2 == crossword [i-1,j])... “


0
投票

我看不到任何无限循环,但运行时异常(IndexOutOfRangeException)at

if (keyLetter2 == crossword[i-1, j]) {...}      // if i == 0
...
else if (keyLetter2 == crossword[i+1, j]) {...} // if i == crossword.GetLength(0) - 1

让我们摆脱这些异常并刷新循环:

for (int i = 0; i < crossword.GetLength(0); ++i)
  for (int j = 0; j < crossword.GetLength(1); ++j)
    if (keyLetter == crossword[i, j]) {
      // Keep you messages being readable with a help of string interpolation - $""
      Console.WriteLine(string.Join(Environment.NewLine,
        $"{keyLetter} is [{i}, {j}]",
         ""
        $"i is: {i}",
         "" 
        $"j is: {j}",
         ""
      ));

      // Do not repeat yourself: if you want 4 neighbors to test
      for (int neighbor = 0; neighbor < 4; ++neighbor) {
        int ii = i + (neighbor % 2) * (neighbor - 1);
        int jj = j + (1 - neighbor % 2) * (neighbor - 1);

        // Check indexes ii, jj before addressing [ii, jj]
        if (ii >= 0 && ii < crossword.GetLength(0) &&
            jj >= 0 && jj < crossword.GetLength(1) && 
            keyLetter2 == crossword[ii, jj]) {
          Console.Write($"[i/j] position for {keyLetter2} is [{i}, {j}]");

          // In case we want at most one neighbor; comment it out if we want all of them
          break;
        }
      }
    }

如果你有8(不是4)邻居检查

    ...
    bool found = false;

    for (int ii = Math.Max(0, i - 1); ii <= Math.Min(i + 1, crossword.GetLength(0)) && !found; ++ii) 
      for (int jj = Math.Max(0, j - 1); jj <= Math.Min(j + 1, crossword.GetLength(0)) && !found; ++jj) {
        if ((ii != i || jj != j) && keyLetter2 == crossword[ii, jj])) {
          Console.Write($"[i/j] position for {keyLetter2} is [{i}, {j}]");

          // In case we want at most one neighbor; comment it out if we want all of them 
          found = true;
        }
      }

0
投票

我会采取一种稍微不同的方法,即将“邻居搜索”委托给辅助方法。您可以将数组,应搜索其邻居的单元格以及您要搜索的值传递给此方法。

因为一个单元格项由两个整数坐标定义,并且因为有一个现有的Point结构,我们可以使用它有两个整数属性(XY),我用它来表示我们数组中的一个单元格。

辅助函数的工作原理是确定XY的最小值,我们正在搜索的邻居通过从1X值中减去Y。然后我们需要确保这个结果不小于0,以确保我们保持在数组的范围内。

同样,我们添加1来获取最大值,并确保它不大于数组的上限。

最后,我们在List<Point>中返回匹配列表(如果找到的话):

public static List<Point> GetNeighborMatches(string[,] grid, Point item, string valueToFind)
{
    var result = new List<Point>();

    // if our grid is empty or the item isn't in it, return an empty list
    if (grid == null || grid.Length == 0 ||
        item.X < 0 || item.X > grid.GetUpperBound(0) ||
        item.Y < 0 || item.Y > grid.GetUpperBound(1))
    {
        return result;
    }

    // Get min and max values of x and y for searching
    var minX = Math.Max(item.X - 1, 0);
    var maxX = Math.Min(item.X + 1, grid.GetUpperBound(0));
    var minY = Math.Max(item.Y - 1, 0);
    var maxY = Math.Min(item.Y + 1, grid.GetUpperBound(1));

    // Loop through all neighbors to find a match
    for (int x = minX; x <= maxX; x++)
    {
        for (int y = minY; y <= maxY; y++)
        {
            // Continue looping if we're on the 'item'
            if (x == item.X && y == item.Y) continue;

            // If this is a match, add it to our list
            if (grid[x, y] == valueToFind) result.Add(new Point(x, y));
        }
    }

    // Return all the matching neighbors
    return result;
}

现在我们可以在现有代码中使用这个辅助方法:

public static void Main(string[] args)
{
    string keyLetter = "g";
    string keyLetter2 = "b";
    string[,] crossword = new string[,]
    {
        { "a", "b", "c", "d" },
        { "e", "f", "g", "h" },
        { "a", "e", "b", "c" },
        { "i", "j", "k", "l" }
    };

    for (int i = 0; i < crossword.GetLength(0); i++)
    {
        for (int j = 0; j < crossword.GetLength(1); j++)
        {
            if (keyLetter == crossword[i, j])
            {
                // we found a match for our first letter!
                Console.WriteLine("The first value (" + keyLetter + ") is at [" + 
                    i + ", " + j + "]");

                // get neighboring matches for keyLetter2
                List<Point> matches = GetNeighborMatches(crossword, 
                    new Point(i, j), keyLetter2);

                // Output our matches if we found any
                if (matches.Any())
                {
                    foreach (var match in matches)
                    {
                        Console.WriteLine("The second value (" + keyLetter2 + 
                            ") is at [" + match.X + ", " + match.Y + "]");
                    }
                }
                else
                {
                    Console.WriteLine("No match was found for '" + keyLetter2 + 
                        "' near [" + i + ", " + j + "]");
                }
            }
        }
    }
}

产量

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.