修改2d数组元素的麻烦创建算法

时间:2019-04-19 17:05:23

标签: c# arrays

我在编辑2d char数组的值时遇到麻烦。

char[,] chrRaster = new char[4, 5];

将值添加到数组并将其打印到控制台后,我得到:

// Input example:
*****
**.**
*****
****.

我正在尝试创建一种算法,以将'。'旁边,下方或上方的每个'*'替换为'。'。然后将其打印到控制台。

// Output after algorithm example:
**.**
*...*
**.*.
***..

我尝试将2d char数组转换为2d字符串数组,然后使用IndexOf('*')替换'*'旁边,下方或上方的每个'.',并且还尝试了使用多个iffor循环来进行计算,没有任何运气。

 static void Main(string[] args)
        {
            // Variablen
            int intTestgeval = 0; // Number of times you want program to repeat 
            int intN = 0;         // Number of rows
            int intM = 0;         // Number of coloms
            char chrGrond;        // Used to store '*' or '.'
            char[,] chrRaster;    // 2d char array used to store all values 

            // Code
            try
            {
                intTestgeval = Int32.Parse(Console.ReadLine()); // Number of times program will repeat           

                if(intTestgeval > 150) // Program can not repeat more then 150 times 
                {
                    throw new Exception();
                }
            }
            catch (Exception)
            {                
                Environment.Exit(0);
            }

            intN = Controle(intN);                          // Number of rows ophalen
            intM = Controle(intM);                          // Number of Coloms ophalen

            chrRaster = new char[intN, intM];               // Initializing array with user input


            for (int intR = 0; intR < intTestgeval; intR++)  // Print 2d array to console
            {
                for(int intY = 0; intY < intN; intY++)
                {
                    for(int intZ = 0; intZ < intM; intZ++)
                    {
                        chrGrond = Convert.ToChar(Console.ReadKey().KeyChar);

                        chrRaster[intY, intZ] = chrGrond;
                    }
                    Console.WriteLine();
                }


                instorten[intR] = Instorten(chrRaster, intN, intM); // Ignore this part, that's another part of my assignment not related to my question.
            }
        }

        static int Controle( int intX )
        {
            try
            {
                intX = Int32.Parse(Console.ReadLine());

                if (intX > 150 || intX < 1) // Length of row and colom can not exceed 20 and can not go lower then 1
                {
                    throw new Exception();
                }
                return intX;
            }
            catch                           // Program will off if value does not meet requirements
            {
                Environment.Exit(0);
                return intX;
            }            
        }

  // It is this part of the program I need help with. This is what I tried but can't get any further
        static int Instorten(char[,] chrRaster, int intN, int intM)
        {
            for (int intY = 0; intY < intN; intY++)
            {
                for (int intZ = 0; intZ < intM; intZ++)
                {
                    if(chrRaster[intY, intZ] == '.' && chrRaster[intY, intZ + 1] == '*' || chrRaster[intY, intZ] == '*' && chrRaster[intY, intZ + 1] == '.')
                    {

                    }                    
                }
                Console.WriteLine();
            }
            int intm = 0;
            return intm;
        }        
    }

3 个答案:

答案 0 :(得分:0)

这是执行所需操作的算法。我试图在注释中解释我的代码。输出将与您要查找的内容匹配。

    static void Main(string[] args)
    {
        char STAR = '*';
        char DOT = '.';

        var input = new char[,]
        {
            { STAR,STAR,STAR,STAR,STAR},
            { STAR,STAR,DOT,STAR,STAR},
            { STAR,STAR,STAR,STAR,STAR},
            { STAR,STAR,STAR,STAR,DOT}
        };

        var output = new char[4, 5];

        // Copy each from input to output, checking if it touches a '.'
        for (int x = 0; x < 4; x++)
        {
            for (int y = 0; y < 5; y ++)
            {
                if (input[x, y] == STAR)
                {
                    var isDot = false;
                    // Check left
                    if (x > 0)
                        isDot = input[x - 1, y] == DOT;

                    // Check right
                    if (x < 3)
                        isDot = isDot || (input[x + 1, y] == DOT);

                    // Check above
                    if (y > 0)
                        isDot = isDot || (input[x, y - 1] == DOT);

                    // Check below
                    if (y < 4)
                        isDot = isDot || (input[x, y + 1]) == DOT;

                    output[x, y] = isDot ? DOT : STAR;
                }
                else
                {
                    output[x, y] = input[x, y];
                }
            }
        }

        // Print output
        for (int x = 0; x < 4; x ++)
        {
            for (int y = 0; y < 5; y ++)
            {
                Console.Write(output[x, y]);
            }
            Console.WriteLine();
        }

        Console.Read();
    }

答案 1 :(得分:0)

一种方法是复制数组,然后遍历数组,检查每个项目。如果该项目是'.',则更新该项目在原始数组中的邻居。

要确定邻居,我们只需在行中添加一个即可获得下一个邻居,从行中减去一个即可获得上一个邻居,类似地,我们可以通过对列值进行加/减来获得左右邻居。当然,在执行任何操作之前,我们需要确保我们位于数组的边界内。

我们可以使用这种逻辑编写一个方法,如下所示:

private static void ExposeDotNeighbors(char[,] input)
{
    if (input == null) return;

    // Make a copy of the input array that we can iterate over
    // so that we don't analyze items that we've already changed
    var copy = (char[,]) input.Clone();

    for (var row = 0; row <= copy.GetUpperBound(0); row++)
    {
        for (var col = 0; col <= copy.GetUpperBound(1); col++)
        {
            if (copy[row, col] == '.')
            {
                // Update neighbors in original array
                // Above = [row - 1, col], Below = [row + 1, col],
                // Left = [row, col - 1], Right = [row, col + 1]
                // Before updating, make sure we're inside the array bounds
                if (row > 0) input[row - 1, col] = '.';
                if (row < input.GetUpperBound(0)) input[row + 1, col] = '.';
                if (col > 0) input[row, col - 1] = '.';
                if (col < input.GetUpperBound(1)) input[row, col + 1] = '.';
            }
        }
    }
}

我们还可以编写一些帮助程序方法,这些方法将为我们提供初始数组并将其打印到控制台(也可以将一个标头写入控制台):

private static char[,] GetInitialArray()
{
    var initialArray = new char[4, 5];

    for (var row = 0; row <= initialArray.GetUpperBound(0); row++)
    {
        for (var col = 0; col <= initialArray.GetUpperBound(1); col++)
        {
            if ((row == 1 && col == 2) || (row == 3 && col == 4))
            {
                initialArray[row, col] = '.';
            }
            else
            {
                initialArray[row, col] = '*';
            }
        }
    }

    return initialArray;
}

private static void PrintArrayToConsole(char[,] input)
{
    if (input == null) return;

    for (var row = 0; row <= input.GetUpperBound(0); row++)
    {
        for (var col = 0; col <= input.GetUpperBound(1); col++)
        {
            Console.Write(input[row, col]);
        }

        Console.WriteLine();
    }
}

private static void WriteHeader(string headerText)
{
    if (string.IsNullOrEmpty(headerText))
    {
        Console.Write(new string('═', Console.WindowWidth));
        return;
    }

    Console.WriteLine('╔' + new string('═', headerText.Length + 2) + '╗');
    Console.WriteLine($"║ {headerText} ║");
    Console.WriteLine('╚' + new string('═', headerText.Length + 2) + '╝');
}

使用这些帮助器方法,我们可以编写如下代码:

private static void Main()
{
    var chrRaster = GetInitialArray();

    WriteHeader("Before");
    PrintArrayToConsole(chrRaster);

    ExposeDotNeighbors(chrRaster);

    WriteHeader("After");
    PrintArrayToConsole(chrRaster);

    GetKeyFromUser("\nDone! Press any key to exit...");
}

输出结果如下:

enter image description here


我注意到您似乎也正在从用户那里获取值,并使用try/catch块来验证输入。更好的方法可能是编写一个辅助方法,该方法接受一个表示用户“提示”的字符串,以及一个可用于验证输入的验证方法。这样,我们就可以继续要求用户输入,直到他们输入有效的内容为止。

下面是从用户那里获取整数和字符并允许调用方传递可用于验证的函数的方法。在用户输入有效输入之前,这些方法将不会返回:

private static char GetCharFromUser(string prompt, Func<char, bool> validator = null)
{
    char result;
    var cursorTop = Console.CursorTop;

    do
    {
        ClearSpecificLineAndWrite(cursorTop, prompt);
        result = Console.ReadKey().KeyChar;
    } while (!(validator?.Invoke(result) ?? true));

    Console.WriteLine();
    return result;
}

private static int GetIntFromUser(string prompt, Func<int, bool> validator = null)
{
    int result;
    var cursorTop = Console.CursorTop;

    do
    {
        ClearSpecificLineAndWrite(cursorTop, prompt);
    } while (!int.TryParse(Console.ReadLine(), out result) ||
                !(validator?.Invoke(result) ?? true));

    return result;
}

private static void ClearSpecificLineAndWrite(int cursorTop, string message)
{
    Console.SetCursorPosition(0, cursorTop);
    Console.Write(new string(' ', Console.WindowWidth));
    Console.SetCursorPosition(0, cursorTop);
    Console.Write(message);
}

然后我们可以重新编写我们的GetInitialArray方法,以使用这些方法从用户那里获取尺寸和值:

private static char[,] GetInitialArray()
{
    const int maxCols = 20;
    const int maxRows = 20;

    var numCols = GetIntFromUser(
        $"How many columns do you want (1 - {maxCols}): ",
        i => i > 0 && i <= maxCols);

    var numRows = GetIntFromUser(
        $"How many rows do you want (1 - {maxRows}): ",
        i => i > 0 && i <= maxRows);

    var initialArray = new char[numRows, numCols];

    for (var row = 0; row <= initialArray.GetUpperBound(0); row++)
    {
        for (var col = 0; col <= initialArray.GetUpperBound(1); col++)
        {
            initialArray[row, col] = GetCharFromUser(
                $"Enter value for [{row}, {col}] ('.' or '*'): ",
                c => c == '.' || c == '*');
        }
    }

    return initialArray;
}

现在我们的输出可能如下所示:

enter image description here

如果尝试,请注意您不能输入非法值。该程序仅等待您阅读说明并输入有效的数字或字符。 :)

答案 2 :(得分:0)

您可以这样:

using System;
public class chars
{
    public static void Main(string[] args)
    {
        char[,] charArray = new char[,] {{'*','*','*','*','*'}, 
                                         {'*','*','.','*','*'},
                                         {'*','*','*','*','*'},
                                         {'*','*','*','*','.'}};
        int[,] holdIndex = new int[4, 5];

        for(int i = 0; i<4; i++)  // get allindexes containing '.'
        {
            for(int j = 0; j<5; j++)
            {
                if(charArray[i,j] == '.')
                    holdIndex[i,j] = 1;
                else
                    holdIndex[i,j] = 0;
            }
        }

        for(int i = 0; i<4; i++)
        {
            for(int j = 0; j<5; j++)
            {
                if(holdIndex[i,j] == 1)
                {
                    if(i!=0)
                        charArray[i-1,j] = '.';  //up
                    if(j!=0)
                        charArray[i,j-1] = '.';  // left
                    if(j!=4)
                        charArray[i,j+1] = '.';  //right 
                    if(i!=3)
                        charArray[i+1,j] = '.';  //down
                }
            }
        }

        for(int i = 0; i<4; i++)
        {
            for(int j = 0; j<5; j++)
            {
                Console.Write(charArray[i,j]);
            }
            Console.WriteLine();
        }
        Console.Read();
    }
}