I wanted to count number of 0 and 1 from a 2d array with floodfill algorithm....But unfortunetly...it's showing the wrong result.
I have a matrix like this
0,1,1,0,1
1,0,1,1,0
1,0,1,1,0
1,0,1,1,0
1,0,1,1,0
It supposed to show number of 0 = 10 and 1 =15
but it showing number of 0 = 4 and 1 = 21
here is my code
int[][] input;
public static int[,] reult;
public static int count = 0,col,row;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string path;
OpenFileDialog file = new OpenFileDialog();
if (file.ShowDialog() == DialogResult.OK)
{
input = File.ReadLines(file.FileName)
.Skip(0)
.Select(l => l.Split(',')
.Select(n => int.Parse(n))
.ToArray())
.ToArray();
}
reult = JaggedToMultidimensional(input);
int p = reult.GetLength(0);
int q = reult.GetLength(1);
row = p-1;
col = q - 1;
int one = p * q;
int zero = apply(row, col);
label1.Text = "" + zero;
label2.Text = "" + (one - zero);
}
public T[,] JaggedToMultidimensional<T>(T[][] jaggedArray)
{
int rows = jaggedArray.Length;
int cols = jaggedArray.Max(subArray => subArray.Length);
T[,] array = new T[rows, cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
array[i, j] = jaggedArray[i][j];
}
}
return array;
}
private static int apply(int x, int y)
{
int currentColor = getValueAt(x, y);
if (currentColor == 0)
{
visit(x, y);
count++;
if (x < row) apply(x + 1, y);
if(y<col) apply(x, y + 1);
if(x>0) apply(x - 1, y);
if (y>0) apply(x, y - 1);
}
return count;
}
private static int getValueAt(int x, int y)
{
if (x < 0 || y < 0 || x > row || y > col)
{
return -1;
}
else
{
return reult[x,y];
}
}
private static void visit(int x, int y)
{
reult[x,y] = 1;
}
int zero = apply(row, col);
In your flood fill algorithm, you are only going in four direction and cover the area which match your criteria. And fortunately [row,col] index has 0 and it count all four 0 from [row, col]. Now think what if apply(row,col) have 1 on that row, col index.
To get this thing right, you need to loop through whole matrix and call apply(i,j) where ever you find an array[i,j]==0
Change this line
int zero = apply(row, col);
to
int zero = 0;
for(int i=0; i<=row; i++)
{
for(int j=0; j<=col; j++)
{
if(array[i][j]==0)
{
count =0;
zero+= apply(row, col);
}
}
}
Hope this helps.
Given the requirements you should change the search criteria to search for 0's and 1's.
What you need to do is to search within the rectangle so the border of the rectangle is limit for searching.
i.e.
int[] count = {0,0};
private static int apply(int x, int y)
{
int currentColor = getValueAt(x, y);
if (currentColor != -1)
{
visit(x, y);
count[currentColor]++;
if (x < row) apply(x + 1, y);
if(y<col) apply(x, y + 1);
if(x>0) apply(x - 1, y);
if (y>0) apply(x, y - 1);
}
return count;
}
and then change your visit function to set the cell to -1 instead to avoid visiting it twice.
You can also use linq if you want (I actually prefer):
OpenFileDialog fileDialog = new OpenFileDialog();
if (fileDialog.ShowDialog() == DialogResult.OK)
{
var lines = File.ReadLines(fileDialog.FileName);
var splittedValues = lines.Where(l => !string.IsNullOrEmpty(l)).Select(l => l.Split(',')).SelectMany(l => l).ToList();
var valCount = splittedValues.GroupBy(s => s).Select(s => new { val = s.Key, count = s.Count() }).ToList();
}
It will give you following result:
[0] { val= "0", count=10} [1] { val= "1", count=15}
Related
I have to find the winner of a 3x3 TicTacToe game player vs player. Firsty, I have to user input N (number of moves) and then N moves like (1 2) (0 1) etc. each on new line, X has the first move, 0 second move and so on. First number from bracket is representing the row index and second number representing column index. The program needs to return the winner X or 0, or draw if there is not a winner.
For example for the following input:
7
1 1
2 1
2 0
0 2
1 0
1 2
0 0
The output is : X
I've tried this code, but nothing is shown in console. Any hint would be really apreciated.
using System;
namespace ConsoleApp20
{
public class Program
{
public static string Tictactoe(int[,] moves)
{
int[] rowsValues = new int[3];
int[] columnsValues = new int[3];
int diagonalSum = 0;
int antiDiagonalSum = 0;
const int c1 = 3;
bool isFirstPlayer = true;
for (int i = 0; i < c1; i++)
{
int rowIndex = moves[i, 0];
int columnIndex = moves[i, 1];
int value = isFirstPlayer ? 1 : -1;
if (rowIndex == columnIndex)
{
diagonalSum += value;
}
if (columnIndex == c1 - rowIndex - 1)
{
antiDiagonalSum += value;
}
rowsValues[rowIndex] += value;
columnsValues[columnIndex] += value;
if (Math.Abs(diagonalSum) == c1 ||
Math.Abs(antiDiagonalSum) == c1 ||
Math.Abs(rowsValues[rowIndex]) == c1 ||
Math.Abs(columnsValues[columnIndex]) == c1)
{
return isFirstPlayer ? "X" : "0";
}
isFirstPlayer = !isFirstPlayer;
}
return "Draw";
}
public static void Main()
{
Tictactoe(ReadValues());
}
public static int[,] ReadValues()
{
int n = Convert.ToInt32(Console.ReadLine());
int[,] movesArr = new int[n, 2];
for (int i = 0; i < n; i++)
{
string[] moves = Console.ReadLine().Split();
int a = int.Parse(moves[0]);
int b = int.Parse(moves[1]);
movesArr[i, 0] = a;
movesArr[i, 1] = b;
}
return movesArr;
}
}
}
I have a bool [,] board that stores if the cell is alive or dead. The code I have provided is correctly telling me the total neighbors for each cell, the problem is I need to only count the alive neighbors. My thought was to have a check in the
if (WithinBounds (row, col) ) {
if (board[row, col] == true)
liveNeighbor++;
These are my two relevant methods for calculating total neighbors.
private int TotalLiveNeighbors(int x, int y)
{
int liveNeighbors = 0;
for (int row = x - 1; row <= x + 1; row++)
{
for (int col = y - 1; col <= y + 1; col++)
{
if (! (row == x && col == y))
{
if (WithinBounds(row, col)) {
liveNeighbors++;
}
}
}
}
return liveNeighbors;
}
public bool WithinBounds(int x, int y)
{
if (x < 0 || y < 0)
return false;
if (x >= 3 || y >= 3)
return false;
return true;
}
I was also working on a different approach that used an offset as so:
int[,] neighborLocations = { { -1,-1 }, { -1,0 }, { -1, +1 },
{ 0, -1}, { 0, +1 },
{+1, -1}, {+1, 0 }, { +1, +1 } };
int countAliveNeighbors (int x, int y) {
int count = 0;
foreach (int[] offset in neighborLocations) {
if (board.hasAliveNeighborsAt(x + offset[1], y + offset[0])
count++;
}
return count;
}
Not really sure if this would be more efficient than my first approach
assuming that the array is called 'alive'
if (alive[row,col] && WithinBounds(row, col))
I have a string array and have to fill up a DataGridView with it by picking a random next cell. I want to use all items of the array but avoid to pick a cell I already filled up. It is fine if there are empty cells but I have to use all items.
What I tried:
foreach (var item in myarray)
{
y = random.Next(0, 5);
x = random.Next(0, t.Rows.Count);
t.CurrentCell = t[y, x];
for (int j = 0; j < t.Columns.Count; j++)
{
for (int k = 0; k < t.Rows.Count; k++)
{
if (t.Rows[k].Cells[j].Value == null)
{
t.CurrentCell.Value = item;
}
}
}
}
Many thanks!
You can assign a number to each cell from left to right, like for 4x4 matrix each cell will be numbered from 0 to 15. After that you can shuffle 0...15 array of integers and iterate over that array by assigning a string to the corresponding cell which you can get by converting a number from array (cellNumber) back to coordinates like this:
(cellNumber / rowsCount, cellNumber % columnsCount).
Consider following source code:
private static Random rng = new Random();
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
public static (int x, int y) GetCoordinates(int cellNumber, int rowsCount, int columnsCount) {
return (cellNumber / rowsCount, cellNumber % columnsCount);
}
public static void Main()
{
var rowsCount = 4;
var columnsCount = 4;
var cellNumbers = Enumerable.Range(0,rowsCount*columnsCount - 1).ToList();
cellNumbers.Shuffle();
foreach (var cellCoordinates in cellNumbers.Select(x => GetCoordinates(x, rowsCount, columnsCount))) {
Console.WriteLine($"{cellCoordinates.x},{cellCoordinates.y}");
}
}
here will be my code for famous Knights Tour for 8x8 deck. So, the main idea of my code is: we will choose from Turns our destination, check it with isPossible and then go recursevly to it, marked this cell to '1'. So, check every cell, and if we will be in 64's cell - return true.
But my code goes to infinite recurssion, and I can't debug it, any recommendation will be greatly appreciated.
class Class1
{
static void Main(string[] args)
{
int x = 0;
int y = 0;
Console.WriteLine("Enter X and press enter");
x = Int32.Parse(Console.ReadLine());
Console.WriteLine("Enter Y and press enter");
y = Int32.Parse(Console.ReadLine());
TurnVariation Turns = new TurnVariation();
EmptyBoard Board = new EmptyBoard();
if (TryPut.Put(Board, x, y, Turns, 1, false))
{
Console.WriteLine("МОЖНА!!!!");
}
else
{
Console.WriteLine("NET!!");
}
}
}
public class TryPut : EmptyBoard
{
public static bool Put(EmptyBoard Board, int x, int y, TurnVariation Turns, int count, bool flag)
{
int tempX = 0;
int tempY = 0;
if (count >= 64)
{
Console.WriteLine("yeab");
return true;
}
for (int i = 0; i <= 7; i++)
{
tempX = x + Turns.Turns[i,0];
tempY = y + Turns.Turns[i,1];
//Console.WriteLine(count);
if (IsPossible(Board, tempX, tempY))
{
Board.Array[tempX, tempY] = 1;
flag = Put(Board, tempX, tempY, Turns, count+1, flag);
if (flag)
{
break;
}
Board.Array[tempX, tempY] = 0;
}
}
if (flag)
return true;
else
return false;
}
public static bool IsPossible(EmptyBoard Board, int x, int y)
{
if ((x < 0) || (x > 7) || (y < 0) || (y > 7))
return false;
if (Board.Array[x, y] == 1)
return false;
return true;
}
}
public class TurnVariation
{
public int[,] Turns = new int[8, 2];
public TurnVariation()
{
Turns[0, 0] = -2; Turns[0, 1] = 1;
Turns[1,0] = -2; Turns[1,1] = -1;
Turns[2,0] = -1; Turns[2,1] = 2;
Turns[3,0] = 1; Turns[3,1] = 2;
Turns[4,0] = 2; Turns[4,1] = 1;
Turns[5,0] = 2; Turns[5,1] = -1;
Turns[6,0] = 1; Turns[6,1] = -2;
Turns[7,0] = -1; Turns[7,1] = -2;
}
}
public class EmptyBoard
{
public const int N = 8;
public int[,] Array = new int[N, N];
public EmptyBoard()
{
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
Array[i, j] = 0;
}
}
I think your problem is that your testing for count<64, but you never assign to count. You just pass (by value!) 'Count + 1' to the put method. You are probably thinking that this will bewritten back to the count variable. But that is not the case...
Do note that debugging is the first skill you need to learn!
I'm a beginner in C#, trying to make a lottery form applicaton.
There are types, first when you have 5 tips ( otos bool ) and 5 tips ( hatos bool ).
And there are many types of how many numbers will be raffled (tiz, harminc, kilencven, negyvenot).
I tried to scan the numbers after the raffle with Array.Equals with this code:
for (int i = 0; i <= 4; i++)
{
for (int y = 0; y <= 4; y++)
{
if (Array.Equals(lottoszamok[i], lottoszamok[y]))
lottoszamok[i] = r.Next (1, ?);
}
}
but at this the number will be scanned with itself too, so it will be always equal.
here is my code by the way:
if (otos == true)
{
for (int i = 0; i <= 5; i++)
{
if (tiz == true)
{
lottoszamok[i] = r.Next(1, 10);
}
else if (harminc == true)
{
lottoszamok[i] = r.Next(1, 30);
}
else if (kilencven == true)
{
lottoszamok[i] = r.Next(1, 90);
}
else if (negyvenot == true)
{
lottoszamok[i] = r.Next(1, 45);
}
else if (egyeni == true)
{
lottoszamok[i] = r.Next(1, (egyeniertek + 1));
}
}
}
if (hatos == true)
{
for (int i = 0; i <= 6; i++)
{
if (tiz == true)
{
lottoszamok[i] = r.Next(1, 10);
}
else if (harminc == true)
{
lottoszamok[i] = r.Next(1, 30);
}
else if (kilencven == true)
{
lottoszamok[i] = r.Next(1, 90);
}
else if (negyvenot == true)
{
lottoszamok[i] = r.Next(1, 45);
}
else if (egyeni == true)
{
lottoszamok[i] = r.Next(1, (egyeniertek + 1));
}
}
}
If you're trying to pick numbers from a range 1..n without repetitions, you need to "shuffle" the numbers out:
int[] allPossibleNumbers = Enumerable.Range(1, maxNumber).ToArray();
int[] picked = new int[numberToPick];
for (int i = 0; i < numberToPick; i++)
{
int index = r.Next(i, maxNumber);
picked[i] = allPossibleNumbers[index];
allPossibleNumbers[index] = allPossibleNumbers[i];
}
where numberToPick is 5 if otos or 6 if hatos, and maxNumber depends on tiz, harminc, kilencven, negyvenot, egyeni and egyeniertek.
If your maxNumber is huge and you only want to pick a few numbers, the following doesn't require the whole range to be in memory at once:
Dictionary<int, int> outOfPlace = new Dictionary<int,int>();
int[] picked = new int[numberToPick];
for (int i = 0; i < numberToPick; i++)
{
int shuffleOut = outOfPlace.ContainsKey(i) ? outOfPlace[i] : i;
int index = r.Next(i, maxNumber);
picked[i] = 1 + (outOfPlace.ContainsKey(index) ? outOfPlace[index] : index);
outOfPlace[index] = shuffleOut;
outOfPlace.Remove(i);
}
Try this one!
if (i!=y && Array.Equals(lottoszamok[i], lottoszamok[y]))
I made it this way, if you want you could put swapping like method.
static void SwapInts(int[] array, int position1, int position2)
{
// Swaps elements in an array.
int temp = array[position1]; // Copy the first position's element
array[position1] = array[position2]; // Assign to the second element
array[position2] = temp; // Assign to the first element
}
static void Main()
{
Random rng = new Random();
int n = int.Parse(Console.ReadLine());
int[] intarray = new int[n];
for (int i = 0; i < n; i++)
{
// Initialize array
intarray[i] = i + 1;
}
// Exchange resultArray[i] with random element in resultArray[i..n-1]
for (int i = 0; i < n; i++)
{
int positionSwapElement1 = i + rng.Next(0, n - i);
SwapInts(intarray, i, positionSwapElement1);
}
for (int i = 0; i < n; i++)
{
Console.Write(intarray[i] + " ");
}
}
}
I spend many time to get this, but i believe i can do it, now it's done, By the Easier way in the word, this kill every think about Random not duplicate,very simply code without any philosophy or difficulty of Developers made ... (welcome to my work) that (BEST OF THE BEST):
Numbers between (1-10) without any duplicate, 1- MY WORK in C#
private void TenNumbersRandomly()
{
int[] a = new int[10];
Random r = new Random();
int x;
for (int i = 0; i < 10; i++)
{
x= r.Next(1, 11);
for (int j = 0; j <= i ; j++)
{
while (a[j] == x)
{
x = r.Next(1, 11);
j = 0;
}
}
a[i] = x;
tb1.Text += a[i]+"\n";
}
}
2- in VB some Different i also have it :
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim x As Integer, i As Integer, j As Integer
x = Int(Rnd() * 10) + 1
Label1.Text = ""
Dim a(9) As Integer
For i = 0 To 9
x = Int(Rnd() * 10) + 1
For j = 0 To i
While (a(j) = x)
x = Int(Rnd() * 10) + 1
j = 0
End While
Next j
a(i) = x
Label1.Text += a(i).ToString() + " "
Next i