Code should not nest more than 3 control flow statements - c#

I have to implement a bingo game and check for line, bingo or nothing for a given input where I get a 3x3 bingo card and next 15 numbers extracted.
I wrote the following function:
static int[,] ReadBingoCard(int rowsNumber, int columnNumber)
{
int[,] card = new int[rowsNumber, columnNumber];
for (int i = 0; i < rowsNumber; i++)
{
string[] array = Console.ReadLine().Split(' ');
for (int j = 0; j < columnNumber; j++)
{
card[i, j] = Convert.ToInt32(array[j]);
}
}
return card;
}
static int[] ReadNumbersExtracted(int numbersExtracted)
{
int[] numbers = new int[numbersExtracted];
for (int i = 0; i < numbersExtracted; i++)
{
numbers[i] = Convert.ToInt32(Console.ReadLine());
}
return numbers;
}
static bool CheckForBingo(int[,] bingoCard, int[] numbers)
{
int numMatchesFound = 0;
for (int row = 0; row < bingoCard.GetLength(0); row++)
{
for (int col = 0; col < bingoCard.GetLength(1); col++)
{
for (int numIndex = 0; numIndex < numbers.Length; numIndex++)
{
if (bingoCard[row, col] == numbers[numIndex])
{
numMatchesFound++;
break;
}
}
}
}
return numMatchesFound == bingoCard.Length;
}
static bool CheckForLine(int[,] bingoCard, int[] numbers)
{
for (int row = 0; row < bingoCard.GetLength(0); row++)
{
int colMatchesInRow = 0;
for (int col = 0; col < bingoCard.GetLength(1); col++)
{
for(int numIndex = 0; numIndex < numbers.Length; numIndex++)
{
if (bingoCard[row, col] != numbers[numIndex])
{
continue;
}
colMatchesInRow++;
break;
}
}
Due to some limitations of sonar analyzer I get the error:
S134 (Error) : Refactor this code to not nest more than 3 control flow statements for CheckForBingo function.
Is there a way to split this function to get rid of this error?

Just use for-each to iterate through your 2d array:
static bool CheckForBingo(int[,] bingoCard, int[] numbers)
{
int numMatchesFound = 0;
foreach (var number in bingoCard)
{
for (int numIndex = 0; numIndex < numbers.Length; numIndex++)
{
if (number == numbers[numIndex])
{
numMatchesFound++;
break;
}
}
}
return numMatchesFound == bingoCard.Length;
}
EDIT:
This is a refactored CheckForLine using a helper method to search for a values in an array
static bool CheckForLine(int[,] bingoCard, int[] numbers)
{
for (int row = 0; row < bingoCard.GetLength(0); row++)
{
int colMatchesInRow = 0;
for (int col = 0; col < bingoCard.GetLength(1); col++)
{
if (IsNumberContainedInArray(bingoCard[row, col],numbers))
{
colMatchesInRow++;
break;
}
}
}
}
}
static bool IsNumberContainedInArray(int numberToCheck, int[] numbers)
{
for (int numIndex = 0; numIndex < numbers.Length; numIndex++)
{
if (numberToCheck == numbers[numIndex])
{
return true;
}
}
return false;
}

Related

How to give the reverse diagonal rows and columns color in a 2D array in c#?

for school i have made an 2D array. All numbers that are diagonal needs to be the color red, which works. Now i want to print all reverse diagonal columns and rows yellow. Here is some code: In the method DisplayMatrixWithCross it has to be made.
using System.Data.Common;
namespace assignment1
{
internal class Program
{
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("invalid number of arguments!");
Console.WriteLine("usage: assignment[1-3] <nr of rows> <nr of columns>");
return;
}
int numberOfRows = int.Parse(args[0]);
int numberOfColumns = int.Parse(args[1]);
Program myProgram = new Program();
myProgram.Start(numberOfRows, numberOfColumns);
}
void Start(int numberOfRows, int numberOfColumns)
{
int[,] matrix = new int[numberOfRows, numberOfColumns];
InitMatrixLinear(matrix);
DisplayMatrix(matrix);
DisplayMatrixWithCross(matrix);
}
void InitMatrix2D(int[,] matrix)
{
int element = 1;
for (int r = 0; r < matrix.GetLength(0); r++)
{
for (int c = 0; c < matrix.GetLength(1); c++)
{
matrix[r, c] = element++;
}
}
}
void DisplayMatrix(int[,] matrix)
{
for (int r = 0; r < matrix.GetLength(0); r++)
{
for (int c = 0; c < matrix.GetLength(1); c++)
{
Console.Write($"{matrix[r, c]:00} ");
}
Console.WriteLine();
}
}
void InitMatrixLinear(int[,] matrix)
{
int element = 1;
for (int i = 0; i < matrix.Length; i++)
{
int r = (element - 1) / matrix.GetLength(0);
int c = (element - 1) % matrix.GetLength(1);
matrix[r, c] = element;
element++;
}
}
void DisplayMatrixWithCross(int[,] matrix)
{
Console.WriteLine();
for (int rows = 0; rows < matrix.GetLength(0); rows++)
{
for (int columns = 0; columns < matrix.GetLength(1); columns++)
{
if (rows == columns)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Write($"{matrix[rows, columns]:00} ");
}
/* else if ()
{
Console.BackgroundColor = ConsoleColor.Yellow;
}*/
else
{
Console.ForegroundColor = ConsoleColor.White;
Console.Write($"{matrix[rows, columns]:00} ");
}
}
Console.WriteLine();
}
}
}
}
Cant get it to work sadly, can anyone help
You can calculate the value that goes in each spot, no need to keep a separate counter variable:
void InitMatrix2D(int[,] matrix)
{
for (int r = 0; r < matrix.GetLength(0); r++)
{
for (int c = 0; c < matrix.GetLength(1); c++)
{
matrix[r, c] = (r * matrix.GetLength(1)) + (c + 1);
}
}
}
void InitMatrixLinear(int[,] matrix)
{
for (int i=0; i<matrix.Length; i++)
{
int r = i / matrix.GetLength(1);
int c = i % matrix.GetLength(1);
matrix[r, c] = (i+1);
}
}
Next, you can use matrix.Length to determine the correct amount of zeroes to pad your numbers with:
void DisplayMatrix(int[,] matrix)
{
int maxLength = matrix.Length.ToString().Length;
String numFormat = new string('0', maxLength);
for (int r = 0; r < matrix.GetLength(0); r++)
{
for (int c = 0; c < matrix.GetLength(1); c++)
{
Console.Write(matrix[r, c].ToString(numFormat) + " ");
}
Console.WriteLine();
}
}
Lastly, for the reverse diagonal, if the one-based row number plus the zero-based column number equals the number of columns, then you can change the background to yellow:
void DisplayMatrixWithCross(int[,] matrix)
{
int maxLength = matrix.Length.ToString().Length;
String numFormat = new string('0', maxLength);
Console.WriteLine();
for (int rows = 0; rows < matrix.GetLength(0); rows++)
{
for (int columns = 0; columns < matrix.GetLength(1); columns++)
{
Console.ResetColor();
if (rows == columns)
{
Console.ForegroundColor = ConsoleColor.Red;
}
if ((rows+1)+columns == matrix.GetLength(1))
{
Console.BackgroundColor = ConsoleColor.Yellow;
}
Console.Write(" " + matrix[rows, columns].ToString(numFormat));
}
Console.WriteLine();
}
}
My output:

Function contains multiple control flow statements

I wrote a code for a 3x3 bingo game. It check for line, bingo or nothing for a given input where I get a 3x3 bingo card and next 15 numbers extracted.
Basically I use a 2D user inputed array for the 3x3 bingo card, then I have a function which asks me to input 15 numbers. If all the numbers from the 3x3 bingo card are present in those 15 extracted numbers then I have "bingo". If I have numbers from a line but not all numbers then the program will output "line". And if i will not have bingo neither line the program will output "nothing".
I don't like the CheckForLine() function using 3 nested loops. I can't use Linq, due to Sonar analyzer limitation.
using System;
class Program
{
static void Main()
{
const int numberOfRows = 3;
const int numberOfColumnns = 3;
const int numbersExtracted = 15;
int[,] bingoCard = ReadBingoCard(numberOfRows, numberOfColumnns);
int[] numbers = ReadNumbersExtracted(numbersExtracted);
PrintResult(bingoCard, numbers);
}
static int[,] ReadBingoCard(int rowsNumber, int columnNumber)
{
int[,] card = new int[rowsNumber, columnNumber];
for (int i = 0; i < rowsNumber; i++)
{
string[] array = Console.ReadLine().Split(' ');
for (int j = 0; j < columnNumber; j++)
{
card[i, j] = Convert.ToInt32(array[j]);
}
}
return card;
}
static int[] ReadNumbersExtracted(int numbersExtracted)
{
int[] numbers = new int[numbersExtracted];
for (int i = 0; i < numbersExtracted; i++)
{
numbers[i] = Convert.ToInt32(Console.ReadLine());
}
return numbers;
}
static bool CheckForBingo(int[,] bingoCard, int[] numbers)
{
int numMatchesFound = 0;
foreach (var number in bingoCard)
{
for (int numIndex = 0; numIndex < numbers.Length; numIndex++)
{
if (number == numbers[numIndex])
{
numMatchesFound++;
break;
}
}
}
return numMatchesFound == bingoCard.Length;
}
static bool CheckForLine(int[,] bingoCard, int[] numbers)
{
for (int row = 0; row < bingoCard.GetLength(0); row++)
{
int colMatchesInRow = 0;
for (int col = 0; col < bingoCard.GetLength(1); col++)
{
for (int numIndex = 0; numIndex < numbers.Length; numIndex++)
{
if (bingoCard[row, col] != numbers[numIndex])
{
continue;
}
colMatchesInRow++;
break;
}
}
if (colMatchesInRow == bingoCard.GetLength(1))
{
return true;
}
}
return false;
}
static void PrintResult(int[,] bingoCard, int[] numbersExtracted)
{
if (CheckForBingo(bingoCard, numbersExtracted))
{
Console.WriteLine("bingo");
}
else if (CheckForLine(bingoCard, numbersExtracted))
{
Console.WriteLine("line");
}
else
{
Console.WriteLine("nothing");
}
}
}

C# how to do arithmetic operations on a 2d Array matrix

I've been toying with this code which prints a small matrix with negative and positive numbers,
I would like an efficient way to add together only the positive elements on the matrix and get the product of such elements also do the same but after a specific number, such as the highest on the matrix
static void Main(string[] args)
{
int row = 5;
int column = 5;
int[,] array = new int[row, column];
Random rand = new Random();
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
array[i, j] = rand.Next(-5, 10);
}
}
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
Console.Write(array[i, j].ToString() + " ");
}
Console.WriteLine(" ");
}
Console.ReadLine();
}
To filter and add positive matrix elements, you could do something like the following:
static void Main(string[] args)
{
const int rows = 5;
const int columns = 5;
var array = new int[rows, columns];
var rand = new Random();
int sum = 0;
bool numberSeen = false;
int numberToSee = 1;
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < columns; col++)
{
var cell = rand.Next(-5, 10);
if (!numberSeen && (cell == numberToSee))
{
numberSeen = true;
}
array[row, col] = cell;
if (numberSeen && (cell > 0))
{
sum += cell;
}
}
}
Console.WriteLine($"sum = {sum}");
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < columns; col++)
{
Console.Write(array[row, col].ToString() + " ");
}
Console.WriteLine(" ");
}
Console.ReadLine();
}

How to multiply a matrix in C#?

I cannot get this method to work. It intends to multiply a matrix by a given one. Could someone help me to correct it please?
class Matriz
{
public double[,] structure;
//Other class methods
public void multiplyBy(Matrix m)
{
if (this.structure.GetLength(1) == m.structure.GetLength(0))
{
Matriz resultant = new Matriz(this.structure.GetLength(0), m.structure.GetLength(1));
for (int i = 0; i < this.structure.GetLength(0) - 1; i++)
{
for (int j = 0; j < m.structure.GetLength(1) - 1; j++)
{
resultant.structure[i, j] = 0;
for (int z = 0; z < this.structure.GetLength(1) - 1; z++)
{
resultant.structure[i, j] += this.structure[i, z] * m.structure[z, j];
}
}
}
this.structure= resultant.structure;
}
else
{
Console.WriteLine("Selected matrixs cannot be multiply");
}
}
}
Read this MSDN Magazine article by James McCaffrey and use the code below as an extension method. They use a jagged array which is more convenient and sometimes faster than a 2D array. Change any data[i][j] to data[i,j] to make the code work with a 2D array.
public static double[] MatrixProduct(this double[][] matrixA,
double[] vectorB)
{
int aRows=matrixA.Length; int aCols=matrixA[0].Length;
int bRows=vectorB.Length;
if (aCols!=bRows)
throw new Exception("Non-conformable matrices in MatrixProduct");
double[] result=new double[aRows];
for (int i=0; i<aRows; ++i) // each row of A
for (int k=0; k<aCols; ++k)
result[i]+=matrixA[i][k]*vectorB[k];
return result;
}
public static double[][] MatrixProduct(this double[][] matrixA,
double[][] matrixB)
{
int aRows=matrixA.Length; int aCols=matrixA[0].Length;
int bRows=matrixB.Length; int bCols=matrixB[0].Length;
if (aCols!=bRows)
throw new Exception("Non-conformable matrices in MatrixProduct");
double[][] result=MatrixCreate(aRows, bCols);
for (int i=0; i<aRows; ++i) // each row of A
for (int j=0; j<bCols; ++j) // each col of B
for (int k=0; k<aCols; ++k)
result[i][j]+=matrixA[i][k]*matrixB[k][j];
return result;
}
public static double[][] MatrixCreate(int rows, int cols)
{
// creates a matrix initialized to all 0.0s
// do error checking here?
double[][] result=new double[rows][];
for (int i=0; i<rows; ++i)
result[i]=new double[cols];
// auto init to 0.0
return result;
}
This is the modified version of my method, as far as I've been testing this approach works fine.
public void multiplicarPor(Matriz m)
{
if (this.estructura.GetLength(1) == m.estructura.GetLength(0))
{
Matriz resultante = new Matriz(this.estructura.GetLength(0), m.estructura.GetLength(1));
for (int i = 0; i < this.estructura.GetLength(0); i++)
{
for (int j = 0; j < m.estructura.GetLength(1); j++)
{
resultante.estructura[i, j] = 0;
for (int z = 0; z < this.estructura.GetLength(1); z++)
{
resultante.estructura[i, j] += this.estructura[i, z] * m.estructura[z, j];
}
}
}
this.estructura = resultante.estructura;
}
else
{
Console.WriteLine("No se pueden multiplicar estas matrices");
}
}

Extension method for fill rectangular array in C#

I want write extension method for fill multidimensional rectangular array. I know how to do it for the array with a fixed number of measurements:
public static void Fill<T>(this T[] source, T value)
{
for (int i = 0; i < source.Length; i++)
source[i] = value;
}
public static void Fill<T>(this T[,] source, T value)
{
for (int i = 0; i < source.GetLength(0); i++)
for (int j = 0; j < source.GetLength(1); j++)
source[i, j] = value;
}
public static void Fill<T>(this T[,,] source, T value)
{
for (int i = 0; i < source.GetLength(0); i++)
for (int j = 0; j < source.GetLength(1); j++)
for (int k = 0; k < source.GetLength(2); k++)
source[i, j, k] = value;
}
Can I write one fill-method for all multidimensional rectangular array?
You can change the fixed dimension parameter to an Array parameter so you can put the extension on any Array. Then I used recursion to iterate through each position of the array.
public static void Fill<T>(this Array source, T value)
{
Fill(0, source, new long[source.Rank], value);
}
static void Fill<T>(int dimension, Array array, long[] indexes, T value)
{
var lowerBound = array.GetLowerBound(dimension);
var upperBound = array.GetUpperBound(dimension);
for (int i = lowerBound; i <= upperBound; i++)
{
indexes[dimension] = i;
if (dimension < array.Rank - 1)
{
Fill(dimension + 1, array, indexes, value);
}
else
{
array.SetValue(value, indexes);
}
}
}
Here's a solution that does not use recursion (and is less complex):
public static void FillFlex<T>(this Array source, T value)
{
bool complete = false;
int[] indices = new int[source.Rank];
int index = source.GetLowerBound(0);
int totalElements = 1;
for (int i = 0; i < source.Rank; i++)
{
indices[i] = source.GetLowerBound(i);
totalElements *= source.GetLength(i);
}
indices[indices.Length - 1]--;
complete = totalElements == 0;
while (!complete)
{
index++;
int rank = source.Rank;
indices[rank - 1]++;
for (int i = rank - 1; i >= 0; i--)
{
if (indices[i] > source.GetUpperBound(i))
{
if (i == 0)
{
complete = true;
return;
}
for (int j = i; j < rank; j++)
{
indices[j] = source.GetLowerBound(j);
}
indices[i - 1]++;
}
}
source.SetValue(value, indices);
}
}
This is modeled from the System.Array.ArrayEnumerator. This implementation should have a similar level of correctness as ArrayEnumerator and (based on a few spot checks) appears to function fine.

Categories