Accessing rows/columns/diagonals of a 2d matrix C# - c#

I'd like to access the rows, cols and the diagonals of a 2d matrix. How can I do this correctly?
I'm planning to use this in a function where I will access a particular row, column or diagonal and then exit the nested loop.
I've tried the following example :
Considering a 2d matrix of chars :
char[,] board = { { 'O', 'O', 'O' }, { 'X', 'X', 'X' }, { 'O', 'O', 'O' } };
for (int i = 0; i < board.GetLength(0); i++)
{
for (int j = 0; j < board.GetLength(1); j++)
{
// for example the second row where all the values are X
if (board[i+1, j] == 'X' && board[i+1, j+1] == 'X' && board[i+1, j+2] == 'X')
{
Console.WriteLine(board[i+1, j]);
Console.WriteLine(board[i+1, j+1]);
Console.WriteLine(board[i+1, j+2]);
}
}
}

To read from the array in the method you want, omit the for loops and just access the array directly...
// Only X's
Console.Write(board[1, 0]);
Console.Write(board[1, 1]);
Console.WriteLine(board[1, 2]);
// Diagonal
Console.Write(board[0, 0]);
Console.Write(board[1, 1]);
Console.WriteLine(board[2, 2]);
Use the for loops if you want to iterate through and display all of the values contained within the array. Remove the i+1 or 2 and j+1 or 2 as these will end up exceeding the array's constraints and cause an error
for (int i = 0; i < board.GetLength(0); i++)
{
for (int j = 0; j < board.GetLength(1); j++)
{
Console.WriteLine(board[i, j]);
}
}
To search for winners, you can do something as simple as checking all 8 combinations:
if ((board[0, 0] == charToCompare && board[0, 1] == charToCompare && board[0, 2] == charToCompare) || //Row 1
(board[1, 0] == charToCompare && board[1, 1] == charToCompare && board[1, 2] == charToCompare) || //Row 2
(board[2, 0] == charToCompare && board[2, 1] == charToCompare && board[2, 2] == charToCompare) || //Row 3
(board[0, 0] == charToCompare && board[1, 0] == charToCompare && board[2, 0] == charToCompare) || //Col 1
(board[1, 0] == charToCompare && board[1, 1] == charToCompare && board[1, 2] == charToCompare) || //Col 2
(board[2, 0] == charToCompare && board[2, 1] == charToCompare && board[2, 2] == charToCompare) || //Col 3
(board[0, 0] == charToCompare && board[1, 1] == charToCompare && board[2, 2] == charToCompare) || //Diagonal Top to Bottom
(board[2, 0] == charToCompare && board[1, 1] == charToCompare && board[0, 2] == charToCompare)) //Diagonal Bottom to Top
{
Console.WriteLine("Winner");
}
Or to modify your original code with 1 for loop and the breaks, you can do like so. There are probably much better ways, but effectively you will need to implement a routine to check for the solutions you desire
char[,] board = { { 'X', 'O', 'O' }
, { 'X', 'X', 'O' }
, { 'O', 'X', 'X' } };
char charToCompare = 'X';
for (int i = 0; i < 3; i++)
{
if (board[i, 0] == charToCompare && board[i, 1] == charToCompare && board[i, 2] == charToCompare)
{
Console.WriteLine($"Winner Row {i}");
break;
}
if (board[0, i] == charToCompare && board[1, i] == charToCompare && board[2, i] == charToCompare)
{
Console.WriteLine($"Winner Column {i}");
break;
}
}
if (board[0, 0] == charToCompare && board[1, 1] == charToCompare && board[2, 2] == charToCompare)
{
Console.WriteLine("Winner diagonal top to bottom");
}
if (board[2, 0] == charToCompare && board[1, 1] == charToCompare && board[0, 2] == charToCompare)
{
Console.WriteLine("Winner diagonal bottom to top");
}

Related

How would I convert this if-code to a for-loop?

I was wondering how I could possibly convert this holy nest of if and && checks, into a simple for-loop?
Any solutions are appreciated, since I'm completely lost and my brain has given up.
if (localModulebytes[i + 1] == convertedByteArray[1]
&& localModulebytes[i + 2] == convertedByteArray[2]
&& localModulebytes[i + 3] == convertedByteArray[3]
&& localModulebytes[i + 4] == convertedByteArray[4]
&& localModulebytes[i + 5] == convertedByteArray[5]
&& localModulebytes[i + 6] == convertedByteArray[6]
&& localModulebytes[i + 7] == convertedByteArray[7]
&& localModulebytes[i + 8] == convertedByteArray[8]
&& localModulebytes[i + 9] == convertedByteArray[9]
)
{
// Code
similarities++;
}
I tried this code, which gave similaries that were way beyond the ones from my bee-nest to code:
for (var j = 1; j < 9; j++)
{
if (localModulebytes[i + j] == convertedByteArray[j])
{
similarities++;
}
}
That's because you increase the similarities more times in the loop. You can try something like this
var sim = true;
for (var j = 1; j < 9; j++) {
if (localModulebytes[i + j] != convertedByteArray[j]) {
sim = false;
break;
}
}
if(sim) similarities++;
GreenChicken's answer is the way to do this with a for loop, but there's also LINQ:
if (Enumerable.Range(1,9).All(j => localModulebytes[i + j] == convertedByteArray[j])) {
++similarities;
}
Which isn't necessarily better, but I'll offer the alternative.
To convert your initial code to a looped check, you could do something like:
var similar = true;
for ( var j = 1; j < 10; j++ )
if ( localModulebytes[i + j] != convertedByteArray[j] )
{
similar = false;
break;
}
if (similar) similarities++;
But, considering you used the variable name similarities I suspected you wanted to count how many of those items were the same, not all of the 9. Your follow-up comment showed my assumption to be incorrect.

Non square spiral matrix not printing correctly

I am having issues with this assignment I have. I am to print a spiral matrix which cannot be square, in other words the user should input the number of rows and columns.
Console.Write("Enter n: ");
int n = int.Parse(Console.ReadLine());
Console.Write("Enter m: ");
int m = int.Parse(Console.ReadLine());
int[,] matrix = new int[n,m];
int row = 0;
int col = 0;
string direction = "right";
int maxRotations = n * m;
for (int i = 1; i <= maxRotations; i++)
{
if (direction == "right" && (col > n - 1 || matrix[row, col] != 0))
{
direction = "down";
col--;
row++;
}
if (direction == "down" && (row > n - 1 || matrix[row, col] != 0))
{
direction = "left";
row--;
col--;
}
if (direction == "left" && (col < 0 || matrix[row, col] != 0))
{
direction = "up";
col++;
row--;
}
if (direction == "up" && row < 0 || matrix[row, col] != 0)
{
direction = "right";
row++;
col++;
}
matrix[row, col] = i;
if (direction == "right")
{
col++;
}
if (direction == "down")
{
row++;
}
if (direction == "left")
{
col--;
}
if (direction == "up")
{
row--;
}
}
// displej matrica
for (int r = 0; r < n; r++)
{
for (int c = 0; c < m ; c++)
{
Console.Write("{0,4}", matrix[r,c]);
}
Console.WriteLine();
}
Console.ReadLine();
}
My issue currently is that is not printing and at the same is printing in a spiral. In other words the spiral is kind of messed up.
If i run the code and enter 4 as the number of rows and 6 as the number of columns I get the following:
1 2 3 4 0 24
12 13 14 5 0 23
11 16 17 18 19 22
10 9 8 7 20 21
What am i doing wrong?
Your first two conditions check the same boundary (n):
if (direction == "right" && (col > n - 1 || matrix[row, col] != 0))
if (direction == "down" && (row > n - 1 || matrix[row, col] != 0))
I guess for "right" your boundary should be m.
if (direction == "right" && (col > m - 1 || matrix[row, col] != 0))
That's why it is "turning" early: n is 4. And that's exactly where it is turning. The rest are all follow-up errors.

Why won't my C# Recursion stop when it hits true?

I tried to make a function that finds the fastest route to the end of the array by making a recursion that chooses its path by first availability. for some reason, the recursion doesn't stop when it returns true. why?
static void Main(string[] args)
{
int[,] arr = new int[5, 5];
arr[0, 0] = 2;
if (PathFinder(arr, 0, 0))
{
printarr(arr);
}
}
static bool PathFinder(int[,] arr, int y,int x)
{
if (arr[arr.GetLength(0) - 1, arr.GetLength(1) - 1] == 2)
{
return true;
}
else
{
/////Right
if (x != arr.GetLength(1) - 1 && arr[y, x + 1] != 2 && arr[y, x + 1] == 0)
{
arr[y, x + 1] = 2;
printarr(arr);
Console.WriteLine("");
PathFinder(arr, y, x + 1);
}
/////Down
if (y != arr.GetLength(0) - 1 && arr[y + 1, x] != 2 && arr[y + 1, x] == 0)
{
arr[y + 1, x] = 2;
printarr(arr);
Console.WriteLine("");
PathFinder(arr, y + 1, x);
}
/////UP
if (y!=0 && arr[y-1,x]!=2 && arr[y - 1, x] == 0)
{
arr[y - 1, x] = 2;
printarr(arr);
Console.WriteLine("");
PathFinder(arr,y-1,x);
}
/////Left
if (x != 0 && arr[y, x-1] != 2 && arr[y, x - 1] == 0)
{
arr[y, x - 1] = 2;
printarr(arr);
Console.WriteLine("");
PathFinder(arr, y, x - 1);
}
return false;
}
}
static void printarr(int[,] arr)
{
for (int row = 0; row < arr.GetLength(0); row++)
{
for (int colom = 0; colom < arr.GetLength(1); colom++)
{
Console.Write(arr[row, colom] + " ");
}
Console.WriteLine("");
}
}
If you call a method that has a return type recursively without storing that return value, it will proceed after the call. You have called it by name PathFinder(... so when true is returned your recursive call doesn't pass it on. Change your code like this:
static bool PathFinder(int[,] arr, int y, int x)
{
if (arr[arr.GetLength(0) - 1, arr.GetLength(1) - 1] == 2)
{
return true;
}
else
{
/////Right
if (x != arr.GetLength(1) - 1 && arr[y, x + 1] != 2 && arr[y, x + 1] == 0)
{
arr[y, x + 1] = 2;
printarr(arr);
Console.WriteLine("");
return PathFinder(arr, y, x + 1);
}
/////Down
if (y != arr.GetLength(0) - 1 && arr[y + 1, x] != 2 && arr[y + 1, x] == 0)
{
arr[y + 1, x] = 2;
printarr(arr);
Console.WriteLine("");
return PathFinder(arr, y + 1, x);
}
/////UP
if (y != 0 && arr[y - 1, x] != 2 && arr[y - 1, x] == 0)
{
arr[y - 1, x] = 2;
printarr(arr);
Console.WriteLine("");
return PathFinder(arr, y - 1, x);
}
/////Left
if (x != 0 && arr[y, x - 1] != 2 && arr[y, x - 1] == 0)
{
arr[y, x - 1] = 2;
printarr(arr);
Console.WriteLine("");
return PathFinder(arr, y, x - 1);
}
return false;
}
}
This way, when you hit return true;, that value will be passed along all the way back the call stack and you won't continue processing until your return false;
Recursive calls to methods without a return type should have a return; statement somewhere so they can escape otherwise you'll hit a StackOverflowException.

While loop stuck at random points on the code [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
i need help, i had my friend to help me debug this code, and we found that the code stops at random points on the code, sometimes on first loop, sometimes on last loop and so on.
the code is just to make a 9x9 sudoku board with all the rules applied. when i tested each block separately it worked and printed a well done sudoku board, but the problem here is that is gets stuck somehow.
help will be appreciated.
int[,] helpblock = new int[10, 10];
int[,] helplines = new int[10, 10];
int[,] helpcols = new int[10, 10];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
helplines[i, j] = 0;
helpcols[i, j] = 0;
helpblock[i, j] = 0;
}
}
Random rnf = new Random();
int help1;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
help1 = rnf.Next(1, 10);
if (i == 0 || i == 1 || i == 2) {
if (j == 0 || j == 1 || j == 2) {
if (helplines[i, help1] != 0 || helpblock[0, help1] != 0 || helpcols[j, help1] != 0) {
while (helplines[i, help1] != 0 || helpblock[0, help1] != 0 || helpcols[j, help1] != 0) {
System.Threading.Thread.Sleep(1);
help1 = rnf.Next(1, 10);
}
}
map[i, j] = help1;
helplines[i, help1]++;
helpcols[j, help1]++;
helpblock[0, help1]++;
} else if (j == 3 || j == 4 || j == 5) {
if (helplines[i, help1] != 0 || helpblock[1, help1] != 0 || helpcols[j, help1] != 0) {
while (helplines[i, help1] != 0 || helpblock[1, help1] != 0 || helpcols[j, help1] != 0) {
System.Threading.Thread.Sleep(1);
help1 = rnf.Next(1, 10);
}
}
map[i, j] = help1;
helplines[i, help1]++;
helpcols[j, help1]++;
helpblock[1, help1]++;
} else if (j == 6 || j == 7 || j == 8) {
if (helplines[i, help1] != 0 || helpblock[2, help1] != 0 || helpcols[j, help1] != 0) {
while (helplines[i, help1] != 0 || helpblock[2, help1] != 0 || helpcols[j, help1] != 0) {
System.Threading.Thread.Sleep(1);
help1 = rnf.Next(1, 10);
}
}
map[i, j] = help1;
helplines[i, help1]++;
helpcols[j, help1]++;
helpblock[2, help1]++;
}
} else if (i == 3 || i == 4 || i == 5) {
if (j == 0 || j == 1 || j == 2) {
if (helplines[i, help1] != 0 || helpblock[3, help1] != 0 || helpcols[j, help1] != 0) {
while (helplines[i, help1] != 0 || helpblock[3, help1] != 0 || helpcols[j, help1] != 0) {
System.Threading.Thread.Sleep(1);
help1 = rnf.Next(1, 10);
}
}
map[i, j] = help1;
helplines[i, help1]++;
helpcols[j, help1]++;
helpblock[3, help1]++;
} else if (j == 3 || j == 4 || j == 5) {
if (helplines[i, help1] != 0 || helpblock[4, help1] != 0 || helpcols[j, help1] != 0) {
while (helplines[i, help1] != 0 || helpblock[4, help1] != 0 || helpcols[j, help1] != 0) {
System.Threading.Thread.Sleep(1);
help1 = rnf.Next(1, 10);
}
}
map[i, j] = help1;
helplines[i, help1]++;
helpcols[j, help1]++;
helpblock[4, help1]++;
} else if (j == 6 || j == 7 || j == 8) {
if (helplines[i, help1] != 0 || helpblock[5, help1] != 0 || helpcols[j, help1] != 0) {
while (helplines[i, help1] != 0 || helpblock[5, help1] != 0 || helpcols[j, help1] != 0) {
System.Threading.Thread.Sleep(1);
help1 = rnf.Next(1, 10);
}
}
map[i, j] = help1;
helplines[i, help1]++;
helpcols[j, help1]++;
helpblock[5, help1]++;
}
} else if (i == 6 || i == 7 || i == 8) {
if (j == 0 || j == 1 || j == 2) {
if (helplines[i, help1] != 0 || helpblock[6, help1] != 0 || helpcols[j, help1] != 0) {
while (helplines[i, help1] != 0 || helpblock[6, help1] != 0 || helpcols[j, help1] != 0) {
System.Threading.Thread.Sleep(1);
help1 = rnf.Next(1, 10);
}
}
map[i, j] = help1;
helplines[i, help1]++;
helpcols[j, help1]++;
helpblock[6, help1]++;
} else if (j == 3 || j == 4 || j == 5) {
if (helplines[i, help1] != 0 || helpblock[7, help1] != 0 || helpcols[j, help1] != 0) {
while (helplines[i, help1] != 0 || helpblock[7, help1] != 0 || helpcols[j, help1] != 0) {
System.Threading.Thread.Sleep(1);
help1 = rnf.Next(1, 10);
}
}
map[i, j] = help1;
helplines[i, help1]++;
helpcols[j, help1]++;
helpblock[7, help1]++;
} else if (j == 6 || j == 7 || j == 8) {
if (helplines[i, help1] != 0 || helpblock[8, help1] != 0 || helpcols[j, help1] != 0) {
while (helplines[i, help1] != 0 || helpblock[8, help1] != 0 || helpcols[j, help1] != 0) {
System.Threading.Thread.Sleep(1);
help1 = rnf.Next(1, 10);
}
}
map[i, j] = help1;
helplines[i, help1]++;
helpcols[j, help1]++;
helpblock[8, help1]++;
}
}
}
}
PrintSudoku(map);
This is not really an answer, but hopefully it will help you debug the program. Inside your for loops you have a whole bunch of if statements that look something like:
if (i == 0 || i == 1 || i == 2) {
if (j == 0 || j == 1 || j == 2) {
It looks like you are using this logic to determine which block you're in, because that's the one array that you are using a hard-coded value for the first index.
Instead of doing it this way, consider calculating the block using a formula based on the current row and column value.
Your grid currently looks something like this:
| 0 1 2 | 3 4 5 | 6 7 8 |
--+-------+-------+--------
0 | | | |
1 | [0] | [1] | [2] |
2 | | | |
--+-------+-------+--------
3 | | | |
4 | [3] | [4] | [5] |
5 | | | |
--+-------+-------+--------
6 | | | |
7 | [6] | [7] | [8] |
8 | | | |
---------------------------
What you might notice is that if you take the row number and do an integer division by 3, you will get the Block row number (0, 1, or 2). Multiplying this number by 3 gives you the first block in each row (0, 3, and 6). Now, if we take the current column and integer-divide that by 3, we will get the current block column (0, 1, or 2). Adding the "block row" to the "block column" then will give us the block index:
int block = ((row / 3) * 3) + (column / 3);
(Note that it looks like you could simplify this since row is being divided by three and then multiplied by three, but remember that integer division rounds down, so 2 / 3 == 0, not .6667)
By calculating the block this way, you can drastically reduce the number of lines you have to walk through.
Also, using some more meaningful variable names will help with the readability.
I simplified your code to something that I believe does the exact same thing. Maybe it will help your analysis:
int[,] blocks = new int[10, 10];
int[,] rows = new int[10, 10];
int[,] columns = new int[10, 10];
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
rows[i, j] = 0;
columns[i, j] = 0;
blocks[i, j] = 0;
}
}
Random rnd = new Random();
int randomNumber;
for (int row = 0; row < 9; row++)
{
for (int column = 0; column < 9; column++)
{
int block = ((row / 3) * 3) + (column / 3);
randomNumber = rnd.Next(1, 10);
while (rows[row, randomNumber] != 0 ||
blocks[block, randomNumber] != 0 ||
columns[column, randomNumber] != 0)
{
System.Threading.Thread.Sleep(1);
randomNumber = rnd.Next(1, 10);
}
map[row, column] = randomNumber;
rows[row, randomNumber]++;
columns[column, randomNumber]++;
blocks[block, randomNumber]++;
}
}
After playing with this, of course, I got interested in the problem. Below is what I came up with to solve it, which is pretty much a brute-force method:
Start with numbers 1-9 available for each row, column, and block
From the list of available numbers for a cell, assign one of them at random, one cell at a time
Remove that number from the available numbers for that row, column, and block
If we run into the case where there is no valid number available for the cell, reset everything and try again.
Notice there is potential that this will run and never finish, but in my testing it usually finds a solution in less than 400 tries (which is relatively fast from a user's point of view).
What I did differently was, instead of using arrays to store the row/column/block information, I decided to use a Dictionary<int, List<int>>, which stores the row/column/block index as the key, and the value for each key is a List of available numbers for that index.
Then in our loop, I just put the intersection of the available numbers left for the current row, column, and block into a List. Then I pick a random index in that list and assign that value to the cell (and remove it from the available items in that row, column, and block).
I also added some logging to find out how many times it failed before finding a solution.
Here's the code, which also prints the solution at the end:
static void Main()
{
int[,] map = new int[9, 9];
var blocks = new Dictionary<int, List<int>>();
var rows = new Dictionary<int, List<int>>();
var columns = new Dictionary<int, List<int>>();
// initialize lists of available numbers
for (int i = 0; i < 9; i++)
{
blocks.Add(i, new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
rows.Add(i, new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
columns.Add(i, new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
}
Random rnd = new Random();
int failCount = 0;
// For each row
for (int row = 0; row < 9; row++)
{
// For each column in this row
for (int column = 0; column < 9; column++)
{
// Calculate block based on current row and column
int block = ((row / 3) * 3) + (column / 3);
// Get set of available numbers for this cell by getting the intersection
// of available numbers for the row, column, and block
var availableItems =
rows[row].Intersect(
columns[column].Intersect(
blocks[block])).ToList();
// If we reach a point where there are no availableItems, then this is
// not a valid Sudoku pattern. Reset everything and try again
if (availableItems.Count == 0)
{
failCount++;
Console.WriteLine($"Failed {failCount} times. Trying again...");
// Reset to the first cell
row = 0;
column = 0;
block = 0;
// Initialize data
for (int i = 0; i < 9; i++)
{
blocks[i] = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
rows[i] = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
columns[i] = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
}
availableItems = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
}
// Grab a number from the available numbers by choosing a random index
var randomNumber = availableItems[rnd.Next(0, availableItems.Count)];
// Update our map with this item
map[row, column] = randomNumber;
// Remove this item from our lists
rows[row].Remove(randomNumber);
columns[column].Remove(randomNumber);
blocks[block].Remove(randomNumber);
}
}
// Print our Sudoku map:
Console.WriteLine(new string('-', 25));
for(int i = 0; i < 9; i++)
{
Console.Write("|");
for (int j = 0; j < 9; j++)
{
Console.Write($" {map[i, j]}");
if ((j + 1) % 3 == 0) Console.Write(" |");
}
Console.WriteLine();
if ((i + 1) % 3 == 0) Console.WriteLine(new string('-', 25));
}
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
Ouput:
These loops look deadly:
while (helplines[i, help1] != 0 || helpblock[5, help1] != 0 || helpcols[j, help1] != 0) {
System.Threading.Thread.Sleep(1);
help1 = rnf.Next(1, 10);
}
If the new value of help1 doesn't change the while condition to false, it will loop forever.

combobox1 to 2 selectedindex

I having trouble on combobox selectedindex. basically i wanted to disable the button1 when my textbox result is 1. but the problem is when the button1 get disable and i chose another option it wont enable back. so is there another way to do it? below is just showing some part of the coding.
double[,] arr;
public Form1()
{
arr = new double[3, 3];
for (int i = 0; i < 2; i++)
{
arr[0, 0] = 1;
arr[0, 1] = 0.79;
arr[0, 2] = 1.17;
arr[1, 0] = 1.26;
arr[1, 1] = 1;
arr[1, 2] = 1.08;
arr[2, 0] = 0.85;
arr[2, 1] = 0.93;
arr[2, 2] = 1;
}
void CreateArray()
{
if (comboBox1.SelectedIndex == -1 || comboBox2.SelectedIndex == -1)
return;
else if (comboBox1.SelectedIndex == 1 || comboBox2.SelectedIndex == 0)
{
button1.Enabled = false;
}
else if (comboBox1.SelectedIndex == 0 || comboBox2.SelectedIndex == 1)
{
button1.Enabled = false;
}
else if (comboBox1.SelectedIndex == 1 || comboBox2.SelectedIndex == 2)
{
button1.Enabled = false;
}
else
{
button1.Enabled = true;
}
If the second combobox has only 3 items then you will never be able to reach the final else clause where you reset the button to the enabled state.
This happens because you use the || logical OR operator and with only three items you will always take one of the else if condition before the final else

Categories