且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

检查2D数组中某些元素是否相等C#Sharp

更新时间:2023-11-26 08:44:34

鉴于方阵,有一种方法可以在单个循环中进行所有检查. 但是在进行优化之前,我们先清理和简化.

Given a square matrix there is a way to do all the check in a single loop. But before going for optimisation let's clean up and simplify.

给出以下方阵,可能很难通过换位找到获胜者.

Given the following square matrix, It may be hard to make all commutation to find the winner.

var input = new [,]{
    {"x","x","x"},
    {"x","x","o"},
    {"x","o","o"},
};

但是,如果我们能够切成行,列和对角线. 在给定{"x","x","x"},{"x","x","o"}的情况下,更容易找到赢家.

But if we were able to slice into Rows, Column, and Diagonals . It will be easier to to find a winner given {"x","x","x"}, or {"x","x","o"}.

根据您先前的问题b,您已经在2D数组上可以使用GetLength(1)GetLength(0)来计算列数和行数.

Based on your previous questionb you already that on a 2D array we can num the number of Cols and Rows using GetLength(1) and GetLength(0).

在此示例中,第一行索引为:
{ (0,0), (0,1), (0,2) }.

For this example the first row indexes are :
{ (0,0), (0,1), (0,2) }.

static string[] GetRow(string[,] source, int rowNumber)
{
    var rows = source.GetLength(0);
    var result = new string[rows];
    for (int i = 0; i < rows; i++)
    {
        result[i] = source[rowNumber, i];
    }
    return result;
}

自然,对于列,我们将具有相同的代码:

Naturally for columns we will have the same code:

static string[] GetColumn<T>(string[,] source, int columnNumber)
{
    var cols = source.GetLength(1);
    var result = new string[cols];
    for (int i = 0; i < cols; i++)
    {
        result[i] = source[i, columnNumber];
    }
    return result;
}

对角线

使用 https://en.wikipedia.org/wiki/Main_diagonal.
主要对角线索引将为{(0,0) , (1,1), (2,2)}.
看起来像是同一循环,但带有(i,i)

Diagonals

Lets name the diagonal using https://en.wikipedia.org/wiki/Main_diagonal.
The main diagonal indexes will be {(0,0) , (1,1), (2,2)}.
It's look like the same loop but with (i,i)

string[] GetSquareMatrixMainDiagonal(string[,] source)
{// {(0,0) , (1,1), (2,2)}

    var cols = source.GetLength(0);
    var rows = source.GetLength(1);
    if (cols != rows) // diagonal will not work on not square matrix.
        throw new ArgumentException($"2D Array [{rows},{cols}], is not a Square matrix");

    var result = new string[rows];
    for (int i = 0; i < rows; i++)
    {
        result[i] = source[i, i];
    }
    return result;
}

对于对角线索引将为{(0,2) , (1,1), (2,0)}.
行从0开始递增. 1> 2.
而专栏做的恰恰相反. 2> 1> 0

For the Anti Diagonal indexes will be {(0,2) , (1,1), (2,0)}.
Rows is incrementing from 0 > 1 > 2.
While columns are doing the contrary. 2 > 1 > 0

static string[] GetSquareMatrixAntiDiagonal(string[,] source)
{
    var cols = source.GetLength(0);
    var rows = source.GetLength(1);
    if (cols != rows) throw new ArgumentException($"2D Array [{rows},{cols}], is not a Square matrix");

    var result = new string[rows];
    var row = 0;
    var col = rows - 1;
    for (int i = 0; i < rows; i++)
    {
        result[i] = source[row++, col--];
    }
    return result;
}

以下是获取行,列和对角线的简单示例:
https://dotnetfiddle.net/FjPIqY

Here a simple example of getting Rows, Columns and Diagonals:
https://dotnetfiddle.net/FjPIqY

现在,我们有了一种方法来获取像{"x","x","o"}这样的2d数组的Slice.我们需要比较数组中所有元素的方法,以发现它们是否相同. 我们将保存第一个元素的值.并检查其他所有条件是否都相等.

Now that we have a way to get Slice of the 2d array like {"x","x","o"}. We need way to compare all the elment of an array to find if they are the same. We will save the value of the first element. And check if All the others are equals to it.

static string Winner(string[] source)
{
    var val = source.First();
    var isTheSame = source.Skip(1).All(x => x == val);
    return isTheSame ? val : default(string);
}    

小心,这将返回空值作为{"","",""}上的赢家. 但是我们可以在最终检查中简单地排除这一点.

Carefull this will return empty value as a winner on {"","",""}. But we can simply rules this one out in the final check.

这是没有LinQ的另一个版本.并正确处理空单元格的空字符串和默认值. 免责声明:此方法中使用的有效符号与小提琴输入不匹配.

Here is an other version without LinQ. And proper handling of empty string and default value fo an empty cell. Disclaimer: valid symbols used in this method does not match the fiddle input.

static bool CheckWinner(string[] source, out string winnerSymbol)
{
    winnerSymbol= "-"; // "-", arbitrary representation of an empty cell. 1 char for simple layout.
    
    var firstVal = source[0];
    for(int i = 1; i < source.Length; i++){ 
        if(source[i] != firstVal){
            return false;
        }
    }
    
    // Will be nice to have valid Symbols in an array.
    if(firstVal!= "0" && firstVal != "X"){      
        return false;
    }
    
    winnerSymbol = firstVal;
    return true;
}

static void ExampleUsageOf_CheckWinner(){
    var winInput= new []{"0","0","0"};  
    var looseInput= new []{"0","0","X"};


    if(CheckWinner(winInput, out string winnerSymbol)){
        Console.WriteLine( winnerSymbol +"is a Winner in winInput")
    }
    else{
        Console.WriteLine( "No winner in winInput!")
    }
    
    
    if(CheckWinner(looseInput, out string winnerSymbol)){
        Console.WriteLine( winnerSymbol +"is a Winner in looseInput")
    }
    else{
        Console.WriteLine( "No winner in looseInput!")
    }
} 

重新分解

所有方法的工作方式相同:循环行或列数. 但是在平方矩阵中,行数和列数是相同的..
为了获得所有行,我们将需要一个循环以便不写:

Re Factorisation

All methode work the same way: A loop on number of rows or columns. But in a square matric number of rows and column are the same..
In order to get All the row we will need a loop in order to not write:

var r1 = GetRow(input, 0);
var r2 = GetRow(input, 1);
var r3 = GetRow(input, 2);

如果您重命名行数或列数",变成大小.在检查它是一个方矩阵之后. 每个方法都可能处于同一循环中.让我们尝试合并GetRowGetColumn进行说明:在第一行和第一列中使用col_row_index = 0;.

If you rename the "number of rows or columns" into size. After checking that it's a square matrix. Every methods may be able to be in the same loop. Let try to merge GetRow and GetColumn to illustrate: with col_row_index = 0; for the first row and column.

var size = source.GetLength(0);

var currentColumn = new string[size]; // old result variable
var currentRow = new string[size];    // old result variable

for (int i = 0; i < size; i++)
{
    currentColumn[i] = source[i, col_row_index];
    currentRow[i] = source[col_row_index, i];
}

我们现在可以检查其中一个是否是获胜者:

We now can check if one of them is the winner :

var winnerC = Winner(currentColumn);
var winnerR = Winner(currentColumn);

if(winnerC != ""){
    // Stop everything! We have a winner 
    // Console.WriteLine + Break, if we are in a loop.
    // Set a boolean to true, if we use some State machine.
    // Return if we are in method
}

if(winnerR != ""){ // Same
}

示例.

我让您对角线进行合并.并且您应该能够进行较小的修改就可以对整个电路板进行检查.

I let you do the merge for the diagonal. And you should be able to do the whole board checking with minor modification.