Как исследовать массив для.Текстовое значение
Это для игры в крестики-нолики, где сетка может быть размером до любого числа (3x3 4x4 8x8 и т. д.)
Когда форма загружается, метод считывает размер сетки и заполняет форму таким количеством кнопок в 1-мерном массиве кнопок. Массив называется buttonArray.
С помощью только 1-мерного buttonArray и без использования LINQ, как я могу сравнить .Текстовые значения кнопок в buttonArray, чтобы увидеть, являются ли они "X" или " O " для функции CheckWinner ().
После создания сетки кнопок у меня есть обработчик событий для нажатия кнопок:
private void button_click(object sender, EventArgs e)
{
Button b = (Button)sender;
b.Text = "X";
b.Enabled = false;
CheckWinner(buttonArray);
}
Затем я вызываю свою функцию CheckWinner и передаю в массив buttonArray.
Опять же, я просто ищу примитивный способ проверки / сравнения значений без использования LINQ. Если я знаю длину каждой стороны сетки, я могу сказать, что для горизонтальных линий выигрыша я ищу столько кнопок в ряду с "X" в качестве их .Свойство text.
Итак, если у меня есть сетка 5x5, и я есть 25 кнопок в buttonArray, как я могу проверить каждые 5, начиная с 0 индекса сетки для их .Текстовые значения "X", а затем распечатать сообщение, если 5 в строке одинаковы, или" X " в этом случае.
for (int z = 0; z < root; z++) //increments the column to start on
{
vCount = 0; //Starts the win counter at zero when moving to the next column
for (int i = z; i < arrLength; i=i+root) //starts at the first column and increments it by root to test the next button in the column
{
string bText = buttonArray[i].Text;
if (bText == "X")
vCount++;
if (vCount == root)
{
MessageBox.Show("Vertical row winner found !");
break;
}
}
}//end of vertical column test
Я сделал вертикальный тест, как это? Но я думаю, что объединить их в одно было бы лучше.
3 ответа:
Предполагая, что вы хотите проверить , Если
Button.Text == "X"
вevery element of a horizontal row
. Следование-это очень простой способ...public void CheckWinner(Buttons[] buttonArray) { int arrLength = buttonArray.Length; int hCount = 0; //int vCount = 0; int root = (int)Math.Sqrt(Convert.ToDouble(arrLength)); for (int i = 0; i < arrLength ; i++) { string bText = buttonArray[i].Text; hCount = i % root == 0? 0 : hCount; if(bText == "X") hCount++; if(hCount == root) { Console.WriteLine("Horizontal row winner found !"); break; } } }
Для проверки виртикального и / или горизонтального победителя:
public void CheckWinner(Buttons[] buttonArray) { int arrLength = buttonArray.Length; int hCount = 0; Int vCount = 0; int root = (int)Math.Sqrt(Convert.ToDouble(arrLength)); for (int i = 0; i < root; i++) { hCount = 0; vCount = 0; for(int j = 0; j < root; j++) { if(buttonArray[ (i * root) + j ].Text == "X") hCount++; if(buttonArray[ i + (root * j) ].Text == "X") vCount++; } if( hCount + vCount == 2 * root) { Console.WriteLine("Horizontal and Virtical winner found !"); break; } else if ( hCount == root ) { Console.WriteLine("Horizontal winner found !"); break; } else if ( vCount == root ) { Console.WriteLine("Virtical winner found !"); break; } } }
Я брошу свой вариант в кольцо, хотя, похоже, все остальные ответы тоже работают. Моя-это базовая реализация. Он просто идет вдоль каждой строки и проверяет, есть ли у вас одинаковое значение в каждой строке. Вертикальная версия этого так же проста, как и перестановка моих двух петель for, а диагональ не намного сложнее.
Мне кажется, что главная хитрость этого вопроса состоит в том, чтобы просто показать понимание строк и столбцов массива и как имитировать заданный 2D массив только массив 1D.
Для горизонтального:
string CheckWinnerHorizontal(Button[] buttonArray) { int N = (int)Math.Sqrt(buttonArray.Length); for (int row = 0; row < N; ++row) { string winner = ""; for (int col = 0; col < N; ++col) { string value = buttonArray[row * N + col].Text; if (winner == "") { winner = value; } else if (winner != value) { winner = "none"; } } if (winner != "none" && winner != "") { return winner; } } return "";
Конечно, вы можете дать этому шанс - я сделаю by-rows здесь, by-cols должны быть очень похожи:
(правка-ха, очевидно, я не умею читать...но может остаться полезным ответом для других...поскольку я уже доказал, что не обращал внимания на операцию, позвольте мне расширить это и заполнить вертикальные/диагонали...)
(LINQPad-ready)
void Main() { // Quickish and very dirty way to generate the grid var lineLength = 3; var rnd = new Random(); var gridSrc = from r in Enumerable.Range(0, lineLength) from c in Enumerable.Range(0, lineLength) select new { Row = r, Col = c, Text = rnd.Next(0,2) > 0 ? "X" : "O" }; var grid = gridSrc.ToArray(); // ok, now for the query var horizontalWinners = // need the cell and it's index - this is one way to do that from cellTuple in grid.Select((cell, idx) => Tuple.Create(idx, cell)) let idx = cellTuple.Item1 let cell = cellTuple.Item2 // figure out which row its in let row = idx / lineLength // figure out which column its in let col = idx % lineLength // for rows, group by row # group cell by row into byRow // only count if all cells in that row are same where byRow.All(rowCell => rowCell.Text == "X") || byRow.All(rowCell => rowCell.Text == "O") // tell us what row (and who won) select new { byRow.Key, byRow.First().Text }; var verticalWinners = from cellTuple in grid.Select((cell, idx) => Tuple.Create(idx, cell)) let idx = cellTuple.Item1 let cell = cellTuple.Item2 let row = idx / lineLength let col = idx % lineLength group cell by col into byCol where byCol.All(colCell => colCell.Text == "X") || byCol.All(colCell => colCell.Text == "O") select new { byCol.Key, byCol.First().Text }; var topLeftBottomRightDiagonalWinners = from cellTuple in grid.Select((cell, idx) => Tuple.Create(idx, cell)) let idx = cellTuple.Item1 let cell = cellTuple.Item2 let row = idx / lineLength let col = idx % lineLength let fwdSlash = (row == col) group cell by fwdSlash into byDiag where byDiag.Key && byDiag.All(d => d.Text == byDiag.First().Text) select new { Text = byDiag.First().Text, Pos = string.Join("", byDiag.Select(c => Tuple.Create(c.Col, c.Row).ToString())) }; var topRightBottomLeftDiagonalWinners = from cellTuple in grid.Select((cell, idx) => Tuple.Create(idx, cell)) let idx = cellTuple.Item1 let cell = cellTuple.Item2 let row = idx / lineLength let col = idx % lineLength let backSlash = (row + col) == (lineLength - 1) group cell by backSlash into byDiag where byDiag.Key && byDiag.All(d => d.Text == byDiag.First().Text) select new { Text = byDiag.First().Text, Pos = string.Join("", byDiag.Select(c => Tuple.Create(c.Col, c.Row).ToString())) }; for(int r=0;r<lineLength;r++) { for(int c=0;c<lineLength;c++) { Console.Write(grid[r*lineLength+c].Text + " "); } Console.WriteLine(); } foreach(var row in horizontalWinners) { Console.WriteLine("{0} wins on row {1}", row.Text, row.Key); } foreach(var col in verticalWinners) { Console.WriteLine("{0} wins on col {1}", col.Text, col.Key); } foreach (var diag in topLeftBottomRightDiagonalWinners .Concat(topRightBottomLeftDiagonalWinners)) { Console.WriteLine("{0} wins on diagonal {1}", diag.Text, diag.Pos); } }