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

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.

Related

Index is not in array issues - C#

I'm currently in the process of making mine sweeper for a class project. I have got most of the fundamentals but when I click on an edge button, because it checks all buttons around it, the code crashes when there is no index value. E.g. When x is equal to 10 but the code calls for buttonArray[x + 1, y]. Its a null value and just crashes. Any Ideas on how to fix this? Code is included...
decimal MineCount = 0;
#region MineCount
if ((buttonArray[x + 1, y] != null) && (isMine[x + 1, y] == true))
{
isNeighbour[x, y] = true;
isBlank[x, y] = false;
MineCount += 1m;
}
if ((buttonArray[x + 1, y + 1] != null) && (isMine[x + 1, y + 1] == true))
{
isNeighbour[x, y] = true;
isBlank[x, y] = false;
MineCount += 1m;
}
if ((buttonArray[x + 1, y - 1] != null) && (isMine[x + 1, y - 1] == true))
{
isNeighbour[x, y] = true;
isBlank[x, y] = false;
MineCount += 1m;
}
if ((buttonArray[x, y + 1] != null) && (isMine[x, y + 1] == true))
{
isNeighbour[x, y] = true;
isBlank[x, y] = false;
MineCount += 1m;
}
if ((buttonArray[x, y - 1] != null) && (isMine[x, y - 1] == true))
{
isNeighbour[x, y] = true;
isBlank[x, y] = false;
MineCount += 1m;
}
if ((buttonArray[x - 1, y - 1] != null) && (isMine[x - 1, y - 1] == true))
{
isNeighbour[x, y] = true;
isBlank[x, y] = false;
MineCount += 1m;
}
if ((buttonArray[x - 1, y] != null) && (isMine[x - 1, y] == true))
{
isNeighbour[x, y] = true;
isBlank[x, y] = false;
MineCount += 1m;
}
if ((buttonArray[x - 1, y + 1] != null) && (isMine[x - 1, y + 1] == true))
{
isNeighbour[x, y] = true;
isBlank[x, y] = false;
MineCount += 1m;
}
You can use this function for this, instead of duplicate code.
The point of the function is to use limited boundaries.
void CountCells()
{
for(int ix = Math.Max(x - 1, 0); ix <= Math.Min(x + 1, isMine.GetLength(0)); ix++)
{
for(int iy = Math.Max(y - 1, 0); iy <= Math.Min(y + 1, isMine.GetLength(1)); iy++)
{
if ((buttonArray[ix,iy] != null) && isMine[ix,iy])
{
isNeighbour[ix, iy] = true;
isBlank[ix, iy] = false;
MineCount += 1m;
}
}
}
}
Hope it's can be helpfull!

Trying to check coordinates if they exist in the list so I could ignore

I with a team trying to make Tetris Attack/Panel de Pon. I did debug and saw that Debug.Log("Match?"); is not executable. Before foreach (Vector2Int n in exist) Debug working.
How could I change my script?
With this part of code, I am trying to get cells that match with each other horizontally and vertically.
private List<Vector2Int> FindCellNeighbor(int x, int y, List<Vector2Int> matching)
{
matching.Add(new Vector2Int(x, y));
List<Vector2Int> exist = new List<Vector2Int>();
foreach (Vector2Int n in exist)
{
if (!n.Equals(matching))
{
Debug.Log("Match?");
if (x >= 0 && x <= height && y >= 0 && y <= width) // checks if cell coordiantes hits the borders
{
if (data[x, y] == data[x + 1, y])
{
matching.AddRange(FindCellNeighbor(x + 1, y, matching));
exist = matching;
Debug.Log("x + 1");
}
if (data[x, y] == data[x - 1, y])
{
matching.AddRange(FindCellNeighbor(x - 1, y, matching));
exist = matching;
Debug.Log("x - 1");
}
if (data[x, y] == data[x, y + 1])
{
matching.AddRange(FindCellNeighbor(x, y + 1, matching));
exist = matching;
Debug.Log("y + 1");
}
if (data[x, y] == data[x, y - 1])
{
matching.AddRange(FindCellNeighbor(x, y - 1, matching));
exist = matching;
Debug.Log("y - 1");
}
}
}
}
return matching;
}
Full codes GitHub

Random movement of char in console c#

I made a maze game in a console application and by using keys I can control character to leave the maze. Now I want to figure out how to automate that process So that my character can go by random directions and try to find the way out. Here is my class.
The problem is in the randomMovement Method.
class Player: Maze
{
public int x = 1;
public int y = 1;
public string playerName;
public static void printMv() {
while (true)
{
for (int i = 0; i < 15; i++)
{
Console.Clear();
mazeDev();
Console.Write("0");
Thread.Sleep(1000);
}
}
}
public static void movementByUser()
{
int x = 1, y = 1;
while (true)
{
Console.Clear();
mazeDev();
Console.CursorLeft = x;
Console.CursorTop = y;
Console.Write("0");
ConsoleKeyInfo mv = Console.ReadKey();
if (mv.Key == ConsoleKey.Escape) break;
if (mv.Key == ConsoleKey.A && mazeBluePrint[y, x - 1] == 0) {
x--;
}
if (mv.Key == ConsoleKey.D && mazeBluePrint[y, x + 1] == 0)
{
x++;
}
if (mv.Key == ConsoleKey.W && mazeBluePrint[y - 1, x] == 0)
{
y--;
}
if (mv.Key == ConsoleKey.S && mazeBluePrint[y + 1, x] == 0)
{
y++;
}
}
}
public static void randomMovement()
{
Random randMove = new Random();
int x = 1;
int y = 1;
int irandom = randMove.Next(4);
Console.CursorLeft = x;
Console.CursorTop = y;
if (irandom == mazeBluePrint[y, x - 1])
{
x--;
printMv();
}
else if (irandom == mazeBluePrint[y, x + 1])
{
x++;
printMv();
}
else if (irandom == mazeBluePrint[y - 1, x])
{
y--;
printMv();
}
else
{
y++;
printMv();
}
}
}
}
Your problem probably is the direction evaluation. Try this:
public static void randomMovement()
{
Random randMove = new Random();
int x = 1;
int y = 1;
int irandom = randMove.Next(4);
Console.CursorLeft = x;
Console.CursorTop = y;
if (irandom == 0 && mazeBluePrint[y, x - 1] == 0)
{
x--;
printMv();
}
else if (irandom == 1 && mazeBluePrint[y, x + 1] == 0)
{
x++;
printMv();
}
else if (irandom == 2 && mazeBluePrint[y - 1, x] == 0)
{
y--;
printMv();
}
else if (mazeBluePrint [y + 1, x] == 0)
{
y++;
printMv();
}
}
However, this code still has a lot of weaknesses (e.g. you could walk out of the boundaries of the mazeBluePrint array, which would result in an exception).
EDIT
If you want to move in the other direction if the first didn't work, you could try something like this:
public static void randomMovement()
{
Random randMove = new Random();
int x = 1;
int y = 1;
Console.CursorLeft = x;
Console.CursorTop = y;
while (true)
{
int irandom = randMove.Next(4);
if (irandom == 0 && mazeBluePrint[y, x - 1] == 0)
{
x--;
printMv();
break;
}
else if (irandom == 1 && mazeBluePrint[y, x + 1] == 0)
{
x++;
printMv();
break;
}
else if (irandom == 2 && mazeBluePrint[y - 1, x] == 0)
{
y--;
printMv();
break;
}
else if (mazeBluePrint[y + 1, x] == 0)
{
y++;
printMv();
break;
}
}
}
However, this only moves one time, beginning from 1,1.

recursive stackoverflow minesweeper c#

I am writing a game of minesweeper. Below is code for 3 methods in minesweeper. The first method is to check all the spaces around the button pressed and to count how many bombs are around it. The next method is to be called recursively, in order that if the user pressed a button with 0 buttons around it, it will open all of the squares that also indicate 0 squares around it. The third method is to check that it will be in bound the check. The empty space recursive call is getting me a stackoverflow error, what am I doing wrong?
Thanks!
private int GameLogicChecker(int x, int y)
{
int count = 0;
if (_grid[x, y] != -1)
{
if (x + 1 < SizeX)
{ //Right
if (_grid[x + 1, y] == -1)
count++;
}
if (x - 1 > 0)
{ //Left
if (_grid[x - 1, y] == -1)
count++;
}
if (y + 1 < SizeY)
{ //Upper
if (_grid[x, y + 1] == -1)
count++;
}
if (y - 1 > 0)
{ //Lower
if (_grid[x, y - 1] == -1)
count++;
}
if (x + 1 < SizeX && y + 1 < SizeY)
{ //Right-Upper
if (_grid[x + 1, y + 1] == -1)
count++;
}
if (x + 1 < SizeX && y - 1 > 0)
{ //Right-Lower
if (_grid[x + 1, y - 1] == -1)
count++;
}
if (x - 1 > 0 && y + 1 < SizeY)
{ //Left-Upper
if (_grid[x - 1, y + 1] == -1)
count++;
}
if (x - 1 > 0 && y - 1 > 0)
{ //Left-Lower
if (_grid[x - 1, y - 1] == -1)
count++;
}
}
return count;
}
void OpenEmptySpace(int x, int y)
{
for (var k = -1; k <= 1; k++)
{
for (var l = -1; l <= 1; l++)
{
if (CheckBounds(x + k, y + l) && GameLogicChecker(x + k, y + l) == 0)
{
_buttons[x + k, y + l].Text = "0";
OpenEmptySpace(x + k, y + l);
}
}
}
}
private bool CheckBounds(int x, int y)
{
return x >= 0 && x < SizeX && y >= 0 && y < SizeY;
}
For k = 0 and l = 0, you are calling yourself again and again and again...
Thanks to #BenVoigt for pointing out that two zeroes adjacent to each other will also lead to infinite recursion. So, in order to solve that one method is to create a boolean grid too and set a particular cell's value to true if it has been run through once. Assuming the grid is called Explored, I've added the condition for it in the code below.
If you insist on your current code, try changing the condition to:
if (CheckBounds(x + k, y + l)
&& GameLogicChecker(x + k, y + l) == 0
&& !(k == 0 && l == 0)
&& !Explored[x + k, y + l])
{
Explored[x + k, y + l] = true;
_buttons[x + k, y + l].Text = "0";
OpenEmptySpace(x + k, y + l);
}
Here is another answer for you, rewriting your methods one-by-one following better coding practices. Like in the other answer, a boolean grid called Explored[SizeX, SizeY] has been assumed.
1. GameLogicChecker()
private int GameLogicChecker(int x, int y)
{
if (_grid[x, y] == -1) return 0;
int count = 0;
if (x + 1 < SizeX && _grid[x + 1, y] == -1) //Right
{
count++;
}
if (x - 1 > 0 && _grid[x - 1, y] == -1) //Left
{
count++;
}
if (y + 1 < SizeY && _grid[x, y + 1] == -1) //Upper
{
count++;
}
if (y - 1 > 0 && _grid[x, y - 1] == -1) //Lower
{
count++;
}
if (x + 1 < SizeX && y + 1 < SizeY && _grid[x + 1, y + 1] == -1) //Right-Upper
{
count++;
}
if (x + 1 < SizeX && y - 1 > 0 && _grid[x + 1, y - 1] == -1) //Right-Lower
{
count++;
}
if (x - 1 > 0 && y + 1 < SizeY && _grid[x - 1, y + 1] == -1) //Left-Upper
{
count++;
}
if (x - 1 > 0 && y - 1 > 0 && _grid[x - 1, y - 1] == -1) //Left-Lower
{
count++;
}
return count;
}
What's better? Quicker returning from the method for special case. Reduced nesting in If(...) blocks.
2. OpenEmptySpace()
public/private void OpenEmptySpace(int x, int y)
{
for (var deltaX = -1; deltaX <= 1; deltaX += 2)
{
for (var deltaY = -1; deltaY <= 1; deltaY += 2)
{
var thisX = x + deltaX;
var thisY = y + deltaY;
if (OpeningNotNeeded(thisX, thisY))
{
continue;
}
Explored[thisX, thisY] = true;
_buttons[thisX, thisY].Text = "0";
OpenEmptySpace(thisX, thisY);
}
}
}
private bool OpeningNotNeeded(int x, int y)
{
return !CheckBounds(x, y)
|| GameLogicChecker(x, y) != 0
|| Explored[x, y];
}
What's better? Properly named indexing variables in both loops. Properly written condition (+= 2 instead of ++). Reduced nesting in If(...). Easier to read method call in the If(...) instead of three predicates. Useful temporary variables added which make it clear what x + k and y + l were in the code written earlier.
3. CheckBounds() is written fine.

C# which is faster do/while or for?

I have a C# .NET 2.0 script and I want to know why the following code would be faster than a do while loop of the same kind.
private double getStop(double avgPrice, bool longTrading)
{
double stopS = 0.0;
double stopL = 0.0;
for (int i = 0; i < 13; i++)
{
if (i == 0 || i == 12)
{
stopS = 0.0;
stopL = 0.0;
}
else
{
if ((lines[i] - ((lines[i] - lines[i - 1]) / 2)) < avgPrice && avgPrice < (lines[i + 1] - ((lines[i + 1] - lines[i]) / 2)))
{
if (avgPrice < lines[i])
{
stopL = (lines[i] - ((lines[i] - lines[i - 1]) / 2));
stopS = lines[i];
} else {
stopL = lines[i];
stopS = (lines[i + 1] - ((lines[i + 1] - lines[i]) / 2));
}
}
}
}
if (longTrading)
{
return stopL;
} else {
return stopS;
}
}
Also, would it be faster just to explicitly state each if statement instead of doing them inside of a for loop?
Being that this was answered so fast, why would this run far slower than the above code?
private double getStop(double avgPrice, bool longTrading)
{
double stopS = 0.0;
double stopL = 0.0;
for (int i = 0; i < 13; i++)
{
if (i == 0 || i == 12)
{
stopS = 0.0;
stopL = 0.0;
skip = true;
}
if (!skip && (lines[i] - ((lines[i] - lines[i - 1]) / 2)) < avgPrice && avgPrice < (lines[i + 1] - ((lines[i + 1] - lines[i]) / 2)))
{
if (avgPrice < lines[i])
{
stopL = (lines[i] - ((lines[i] - lines[i - 1]) / 2));
stopS = lines[i];
} else {
stopL = lines[i];
stopS = (lines[i + 1] - ((lines[i + 1] - lines[i]) / 2));
}
}
}
skip = false;
}
if (longTrading)
{
return stopL;
} else {
return stopS;
}
}
The performance difference should be negligible, but the for loop is clearer so I would go with that.
They should be essentially equivalent. Your 'for' loop gets evaluated as:
int i = 0;
while (i < 13)
{
//all other stuff
i++;
};
loop variations aren't too much different, it depends on the context and the programming language.
But my opinion is, for statement don't do until the constaint(s) is/are matched, therefore it should be faster than do/while.

Categories