给出数组:
string [,] arr =新字符串[n,n]。 如何检查每一行,每一列以及两个对角线的元素是否相等?
这是一种井字游戏:编写一个控制台应用程序,以输入X和0的N个移动作为坐标作为输入日期。 (0,0)是左上角,(2,2)是右下角。第一行是移动数N,第二行是移动,每行一个。第一个动作是玩家的X动作,然后是玩家的0动作,然后是X动作,依此类推。应用程序将分析收到的动作并显示获胜者:X,0或如果没有获胜者则平局。 这是我尝试过的,但没有结果:
static void Main()
{
int numberOfMoves = Convert.ToInt32(Console.ReadLine());
const int size = 3;
string[,] boardGame = new string[size, size];
for (int i = 0; i < numberOfMoves; i++)
{
string strCoordinates = Console.ReadLine();
string[] lineCoordinates = strCoordinates.Split(' ');
int coordinateX = Convert.ToInt32(lineCoordinates[0]);
int coordinateY = Convert.ToInt32(lineCoordinates[1]);
const int value = 2;
boardGame[coordinateX, coordinateY] = i % value == 0 ? "X" : "0";
}
// CheckElements(boardGame); in construction
Console.Read();
}
static void CheckRows(int x, int y)
{
string[,] boardGame = new string[3, 3];
int cols = boardGame.GetLength(1);
const int value = 2;
for (int i = 0; i < cols; i++)
{
if ((boardGame[0, 0] == boardGame[0, 1] && boardGame[0, 1] == boardGame[0, value]) || (boardGame[1, 0] == boardGame[1, 1] && boardGame[1, 1] == boardGame[1, value]))
{
Console.WriteLine(boardGame[0, 0]);
}
if ((boardGame[1, 0] == boardGame[1, 1] && boardGame[1, 1] == boardGame[1, value]) || (boardGame[value, 0] == boardGame[value, 1] && boardGame[value, 1] == boardGame[value, value]))
{
Console.Write(boardGame[0, 0]);
}
}
Console.WriteLine(boardGame[x, y]);
}
static void CheckColumns(int x, int y)
{
string[,] boardGame = new string[3, 3];
int rows = boardGame.GetLength(0);
const int value = 2;
for (int i = 0; i < rows; i++)
{
if ((boardGame[0, 0] == boardGame[1, 0] && boardGame[1, 0] == boardGame[value, 0]) || (boardGame[0, 1] == boardGame[1, 1] && boardGame[1, 1] == boardGame[value, 1]))
{
Console.WriteLine(boardGame[0, 0]);
}
if ((boardGame[0, 1] == boardGame[1, 1] && boardGame[1, 1] == boardGame[value, 1]) || (boardGame[0, value] == boardGame[1, value] && boardGame[1, value] == boardGame[value, value]))
{
Console.WriteLine(boardGame[0, 1]);
}
}
Console.WriteLine(boardGame[x, y]);
}
static void CheckDiagonals(int x, int y)
{
string[,] boardGame = new string[3, 3];
int m = boardGame.Length;
const int value = 2;
for (int i = 0; i < m; i++)
{
m--;
for (int j = 0; j < m; j++)
{
if (boardGame[0, 0] == boardGame[1, 1] && boardGame[1, 1] == boardGame[value, value])
{
Console.WriteLine(boardGame[0, 0]);
}
}
}
Console.WriteLine(boardGame[x, y]);
}
答案 0 :(得分:1)
这显然是家庭作业,所以我不会为您做,但是我将遍历您的代码并在我认为有问题的地方以及需要如何更改的地方添加注释:
//i think this method should take the game board as a parameter, not x and y
//because your game oard is populated in the main as a variable that is not accessible anywhere
//outside the main
static void CheckRows(int x, int y)
{
//this should be an input parameter, rather than being declared here
string[,] boardGame = new string[3, 3];
//ok this gets the number of columns..
int cols = boardGame.GetLength(1);
//..but where is the same thing for rows? I know it's a square board but
//it's easy to code up the rows too, for ultimate flexibility
//what's this for? looks like you're limiting yourself to 3x3 boards?
const int value = 2;
//i'd have probably called this variable col, or c
//and I'd probably start it at 1...
for (int i = 0; i < cols; i++)
{
//you declared i but you don't use it? You have a loop that increments
//a number through 0, 1, 2, 3 ... just like you've hard coded here
//so think about what you hardcoded and how you could do that in a loop
// - see later for a hint
if ((boardGame[0, 0] == boardGame[0, 1] && boardGame[0, 1] == boardGame[0, value]) || (boardGame[1, 0] == boardGame[1, 1] && boardGame[1, 1] == boardGame[1, value]))
{
Console.WriteLine(boardGame[0, 0]);
}
//ok, so now you've moved onto hard coding row number 1, and hard coding
//a bunch of columns.. think about how you could use the variables you have
if ((boardGame[1, 0] == boardGame[1, 1] && boardGame[1, 1] == boardGame[1, value]) || (boardGame[value, 0] == boardGame[value, 1] && boardGame[value, 1] == boardGame[value, value]))
{
Console.Write(boardGame[0, 0]);
}
}
//what is this for?
Console.WriteLine(boardGame[x, y]);
}
好的,所以在那儿我谈到了提示。
当您检查单个数组中的每个元素是否相同时,最简单的操作是将每个元素与第一个元素进行比较:
int[] nums = new[]{2, 2, 2, 2, 2};
//get the first number
int first = nums[0]; //it's always at 0
//use a loop to check if all are the same. use a boolean to remember it
bool allSame = true; //be optimistic..
for(int i = 1; i < nums.Length; i++){ //start from second, not first
if(nums[i] != first){
allSame = false;
break;
}
}
您能看到我们如何设置此变量吗?它可以检查数组中的一千个条目,以查看它们是否相同。一旦任何元素与第一个元素都不相同,我们就将allSame
设置为false并停止循环(没有继续进行的点)
然后我们可以检查allSame的值,看看它是否相同
如果仅检查一个维度,则1D数组和2D数组在这里没有区别:
int[,] nums = new int[,]{{2,2,2},{3,4,5},{4,3,2}};
int first = nums[0,0];
for(int c = 1; c < nums.GetLength(1); c++){
if(nums[0, c] == first) ...
我们所做的只是将维度添加为硬编码的内容...第0行。列c是变量。
但是如果我们想使其成为变量,以便我们检查所有尺寸怎么办?
使用两个循环
for(int r = 0; r < nums.GetLength(0); r++){ //rows start from 0!
int first = nums[r, 0]; //row is variable, column is first
for(int c = 1; c < nums.GetLength(1); c++){ //cols start from 1!
if(nums[r, c] == first) //r will be 0, while c goes 1..3, then r will be 1 while c is 1..3 etc
我们添加行检查的全部工作是在检查单个列的位周围添加了另一个环绕,这为r
提供了递增值
当涉及到列填充时,逻辑是相同的,只是我们为每个c重复增加r(c为0,r从1..3出发,c为1,r为1..3, c是2,r是1..3)
在检查对角线时,它更简单;我们只需要一个以1开始的变量,因为这是我们要执行的检查:
x[0,0] compared to x[1,1]
x[0,0] compared to x[2,2]
x[0,0] compared to x[3,3]
x[0,0] compared to x[4,4]
..
这意味着您只能使用一个变量,因为数字重复:
for(int i = 0; i < ... )
if(x{0,0] == x[i,i])
祝你好运!
答案 1 :(得分:0)
鉴于方阵,有一种方法可以在单个循环中进行所有检查。 但是在进行优化之前,我们先清理和简化。
给出以下方阵,可能很难通过换位找到获胜者。
var input = new [,]{
{"x","x","x"},
{"x","x","o"},
{"x","o","o"},
};
但是,如果我们能够切成行,列和对角线。
找到更容易获得{"x","x","x"},
或{"x","x","o"}
的赢家。
根据您先前的问题b,您已经在2D数组上可以使用GetLength(1)
和GetLength(0)
来计算列数和行数。
在此示例中,第一行索引为:
{ (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;
}
对于列,我们自然会有相同的代码:
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)
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
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
现在,我们有了一种方法来获取2d数组的Slice,例如{"x","x","o"}
。我们需要比较数组中所有元素的方法,以发现它们是否相同。
我们将保存第一个元素的值。并检查其他所有条件是否都相等。
static string Winner(string[] source)
{
var val = source.First();
var isTheSame = source.Skip(1).All(x => x == val);
return isTheSame ? val : default(string);
}
小心,它将作为{"","",""}
上的赢家返回空值。
但是我们可以在最终检查中简单地排除这一点。
这是没有LinQ的其他版本。并正确处理空单元格的空字符串和默认值。 免责声明:此方法中使用的有效符号与小提琴输入不匹配。
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!")
}
}
所有方法的工作方式相同:循环行或列数。
但是在平方矩阵中,行数和列数是相同的。
为了获得所有行,我们将需要一个循环以便不写:
var r1 = GetRow(input, 0);
var r2 = GetRow(input, 1);
var r3 = GetRow(input, 2);
如果将“行数或列数”重命名为大小。在检查它是一个方矩阵之后。
每个方法都可以处于同一循环中。让我们尝试合并GetRow
和GetColumn
来说明:第一行和第一列的内容为col_row_index = 0;
。
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];
}
我们现在可以检查其中一个是否为赢家:
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
}
我让您对角线进行合并。并且您应该能够进行较小的修改就可以对整个电路板进行检查。