My code generates characters 'L' into 2D-Array on random place, but I need program to check if there isn't 'L' already and if it is there, program should go through process of generation again. But there comes the problem, because Stackoverflowexception shows up. Does anybody have an idea how to change my code, or how to increase stack size?
(I have to mention, that I already tried increase stack size using Project Properties, but I don't have there Linker option. And also I'm new to programming, so I don't know how to use editbin or commands). Thanks in advance.
EDIT:
public void Generate()
{
Fill();
Fleet();
}
public void Fleet()
{
Ship2(Utility.R(1,9),Utility.R(1,9),Utility.R(4));
Ship3(Utility.R(1,9),Utility.R(1,9),Utility.R(4));
Ship3(Utility.R(1,9),Utility.R(1,9),Utility.R(4));
Ship4(Utility.R(1,9),Utility.R(1,9),Utility.R(4));
Ship5(Utility.R(1,9),Utility.R(1,9),Utility.R(4));
}
public void Ship2(int x, int y, int r)
{
if (r == 0)
{
CreateShip(x, y);
CreateShip(x, (y + 1));
}
if (r == 1)
{
CreateShip(x, y);
CreateShip(x, (y + -1));
}
if (r == 2)
{
CreateShip(x, y);
CreateShip((x-1), (y));
}
if (r == 3)
{
CreateShip(x, y);
CreateShip((x+1), (y));
}
}
public void CreateShip(int x, int y)
{
if (x <= 9 && y <= 9 && x >= 0 && y >= 0)
{
if (Board[x, y] == 'L')
{
Generate();
}
else
{
Board[x, y] = 'L';
}
}
else
{
Generate();
}
}
This is the important part of code.
What you can do is: If Creation fails pass back a bool and try again from scratch.
public void Generate()
{
Fill();
while(!Fleet())
{
// I assume Fill clears your board again?!
Fill();
}
}
public bool Fleet()
{
return Ship2(Utility.R(1,9),Utility.R(1,9),Utility.R(4)) &&
Ship3(Utility.R(1,9),Utility.R(1,9),Utility.R(4)) &&
Ship3(Utility.R(1,9),Utility.R(1,9),Utility.R(4)) &&
Ship4(Utility.R(1,9),Utility.R(1,9),Utility.R(4)) &&
Ship5(Utility.R(1,9),Utility.R(1,9),Utility.R(4));
}
public bool Ship2(int x, int y, int r)
{
if (r == 0)
{
return CreateShip(x, y) &&
CreateShip(x, (y + 1));
}
if (r == 1)
{
return CreateShip(x, y) &&
CreateShip(x, (y + -1));
}
if (r == 2)
{
return CreateShip(x, y) &&
CreateShip((x-1), (y));
}
if (r == 3)
{
return CreateShip(x, y) &&
CreateShip((x+1), (y));
}
return false;
}
public bool CreateShip(int x, int y)
{
if (x <= 9 && y <= 9 && x >= 0 && y >= 0)
{
if (Board[x, y] == 'L')
{
return false;
}
else
{
Board[x, y] = 'L';
}
}
else
{
return false;
}
return true;
}
Note: This will still not work, if the input parameters to CreateShip never change. You will now not see any Exception but the Generate method will never finish.
Related
I am trying to implement the algorithm described in the following http://repositorium.sdum.uminho.pt/bitstream/1822/6429/1/ConcaveHull_ACM_MYS.pdf
I am using the following class libraries. Loyc libs come from http://core.loyc.net/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Device.Location;
using Loyc.Collections;
using Loyc.Geometry;
using Loyc;
Here is the basic class
public class Hulls
{
private static List<Point<double>> KNearestNeighbors(List<Point<double>> points, Point<double> currentPoint, int k, out int kk)
{
kk = Math.Min(k, points.Count - 1);
var ret = points
.OrderBy(x => PointMath.Length(new Vector<double>(currentPoint.X - x.X, currentPoint.Y - x.Y)))
.Take(k)
.ToList();
return ret;
}
private static double Angle(Point<double> a, Point<double> b)
{
var ret = -Math.Atan2(b.Y - a.Y, b.X - a.X);
return NormaliseAngle(ret);
}
private static double NormaliseAngle(double a)
{
//while (a < b - Math.PI) a += Math.PI * 2;
//while (b < a - Math.PI) b += Math.PI * 2;
if (a < 0.0) { return a + Math.PI + Math.PI; }
return a;
}
private static List<Point<double>> SortByAngle(List<Point<double>> kNearest, Point<double> currentPoint, double angle)
{
//kNearest
// .Sort((v1, v2) => AngleDifference(angle, Angle(currentPoint, v1)).CompareTo(AngleDifference(angle, Angle(currentPoint, v2))));
//return kNearest.ToList();
kNearest = kNearest.OrderByDescending(x => NormaliseAngle(Angle(currentPoint, x) - angle)).ToList();
return kNearest;
}
private static bool CCW(Point<double> p1, Point<double> p2, Point<double> p3)
{
var cw = ((p3.Y - p1.Y) * (p2.X - p1.X)) - ((p2.Y - p1.Y) * (p3.X - p1.X));
return cw > 0 ? true : cw < 0 ? false : true; // colinear
}
private static bool _Intersect(LineSegment<double> seg1, LineSegment<double> seg2)
{
return CCW(seg1.A, seg2.A, seg2.B) != CCW(seg1.B, seg2.A, seg2.B) && CCW(seg1.A, seg1.B, seg2.A) != CCW(seg1.A, seg1.B, seg2.B);
}
private static bool Intersect(LineSegment<double> seg1, LineSegment<double> seg2)
{
if ((seg1.A.X == seg2.A.X && seg1.A.Y == seg2.A.Y)
|| (seg1.B.X == seg2.B.X && seg1.B.Y == seg2.B.Y))
{
return false;
}
if (_Intersect(seg1, seg2))
{
return true;
}
return false;
}
public IListSource<Point<double>> KNearestConcaveHull(List<Point<double>> points, int k)
{
points.Sort((a, b) => a.Y == b.Y ? (a.X > b.X ? 1 : -1) : (a.Y >= b.Y ? 1 : -1));
Console.WriteLine("Starting with size {0}", k.ToString());
DList<Point<double>> hull = new DList<Point<double>>();
var len = points.Count;
if (len < 3) { return null; }
if (len == 3) { return hull; }
var kk = Math.Min(Math.Max(k, 3), len);
var dataset = new List<Point<double>>();
dataset.AddRange(points.Distinct());
var firstPoint = dataset[0];
hull.PushFirst(firstPoint);
var currentPoint = firstPoint;
dataset.RemoveAt(0);
double previousAngle = 0;
int step = 2;
int i;
while ((currentPoint != firstPoint || step == 2) && dataset.Count > 0)
{
if (step == 5) { dataset.Add(firstPoint); }
var kNearest = KNearestNeighbors(dataset, currentPoint, k, out kk);
var cPoints = SortByAngle(kNearest, currentPoint, previousAngle);
var its = true;
i = 0;
while (its == true && i < cPoints.Count)
{
i++;
int lastPoint = 0;
if (cPoints[i - 1] == firstPoint)
{
lastPoint = 1;
}
int j = 2;
its = false;
while (its == false && j < hull.Count - lastPoint)
{
LineSegment<double> line1 = new LineSegment<double>(hull[step - 2], cPoints[i - 1]);
LineSegment<double> line2 = new LineSegment<double>(hull[step - 2 - j], hull[step - 1 - j]);
//its = LineMath.ComputeIntersection(line1, line2, out pfrac, LineType.Segment);
its = Intersect(line1, line2);
j++;
}
}
if (its == true)
{
return KNearestConcaveHull(points, kk + 1);
}
currentPoint = cPoints[i - 1];
hull.PushLast(currentPoint);
previousAngle = Angle(hull[step - 1], hull[step - 2]);
dataset.Remove(currentPoint);
step++;
}
bool allInside = true;
i = dataset.Count;
while (allInside == true && i > 0)
{
allInside = PolygonMath.IsPointInPolygon(hull, dataset[i - 1]);
i--;
}
if (allInside == false) { return KNearestConcaveHull(points, kk + 1); }
return hull;
}
}
The above is supposed to pick a new edge for the boundary based on the furthest right-hand turn from the previous edge going around the point set counterclockwise. The code seems to pick the correct first edge from the initial vertex which has the lowest y-value, but then does not pick the next edge correctly when the offset angle is nonzero. I think the issue is the SortByAngle or Angle. -atan2 would return the clockwise turn, correct? Possibly I should be adding the offset angle?
EDIT (SOLUTION): Found the issue after following Eric's helpful advice provided in the first comment to the question. It was SortByAngle and Angle:
private static double Angle(Point<double> a, Point<double> b)
{
var ret = Math.Atan2(b.Y - a.Y, b.X - a.X);
return NormaliseAngle(ret);
}
private static double NormaliseAngle(double a)
{
if (a < 0.0) { return a + Math.PI + Math.PI; }
return a;
}
private static List<Point<double>> SortByAngle(List<Point<double>> kNearest, Point<double> currentPoint, double angle)
{
//kNearest = kNearest.OrderByDescending(x => NormaliseAngle(Angle(currentPoint, x) - angle)).ToList();
kNearest.Sort((a, b) => NormaliseAngle(Angle(currentPoint, a) - angle) > NormaliseAngle(Angle(currentPoint, b) - angle) ? 1 : -1);
return kNearest;
}
You have some bug:
var kNearest = KNearestNeighbors(dataset, currentPoint, k, out kk);
Change the kk to just some var. You override the incrementation of that "kk" value, and then you're getting StackOverflow exceptions.
Change your code to the following:
int someVal;
var kNearest = KNearestNeighbors(dataset, currentPoint, k, out someVal);
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.
I'm trying to make a self-learning snake game and encountered an issue that I'm trying to resolve for the last several hours. Here is the code where I move the snake head:
public void moveTo()
{
int foodX = food.PosX / food.Width;
int foodY = food.PosY / food.Height;
Direction directionOfMaxForCurrentState= new Direction();
int currentX = head.PosX / head.Width;
int currentY = head.PosY / head.Height;
do
{
int tmpX = currentX;
int tmpY = currentY;
previousX = tmpX;
previousY = tmpY;
directionOfMaxForCurrentState = HighestQactionForState(currentX, currentY, previousX, previousY);
if (directionOfMaxForCurrentState == Direction.Up) { head.PosY -= head.Height; }
if (directionOfMaxForCurrentState == Direction.Down) { head.PosY += head.Height; }
if (directionOfMaxForCurrentState == Direction.Left) { head.PosX -= head.Width; }
if (directionOfMaxForCurrentState == Direction.Right) {head.PosX += head.Width; }
currentX = head.PosX / head.Width;
currentY = head.PosY / head.Height;
if (currentX == foodX && currentY == foodY) { snake.Clear(); head = new Cell(1, 1); snake.Add(head); }
} while (head.PosX == food.PosX && head.PosY == food.PosY);
}
And here is HighestQactionForState function:
public Direction HighestQactionForState(int x, int y, int px, int py)
{
var Qaround = new List<decimal>();
var actionsWithMax = new List<Direction>();
Direction toExclude = new Direction();
toExclude = directionToExclude(x, y, px, py);
foreach (Direction action in PosibleActionsForState(x, y).Where(a => a != toExclude).ToList())
{
if (action == Direction.Up && (double)Math.Abs(Q[Tuple.Create(x, y - 1, action)] - MaxQaroundState(x, y)) < 0.000000000000000000000001) actionsWithMax.Add(action);
if (action == Direction.Down && (double)Math.Abs(Q[Tuple.Create(x, y + 1, action)] - MaxQaroundState(x, y)) < 0.000000000000000000000001) actionsWithMax.Add(action);
if (action == Direction.Left && (double)Math.Abs(Q[Tuple.Create(x - 1, y, action)] - MaxQaroundState(x, y)) < 0.000000000000000000000001) actionsWithMax.Add(action);
if (action == Direction.Right && (double)Math.Abs(Q[Tuple.Create(x + 1, y, action)] - MaxQaroundState(x, y)) < 0.000000000000000000000001) actionsWithMax.Add(action);
}
return actionsWithMax.ElementAt(rnd.Next(actionsWithMax.Count));
}
So now when I put the breakpoint in the moveTo function I see that HighestQactionForState gets the right parameters, but in the HighestQactionForState function the parameters are not correct - px always has the same value as int x, and py is the same as y which causing the program to behave wrong. Any help would be appreciated!
If im not mistaken you should do this instead
directionOfMaxForCurrentState = HighestQactionForState(currentX, currentY, previousX, previousY);
previousX = currentX;
previousY = currentY;
You set previous values after you call method so by the meaning of variables they have values set in previous iteration.
Also there is no need for declaring extra temp variables. Your parameters are passed by value not by reference.
The Program Works for arrays upto 20x20 But for anything larger it throws an OutOfMemoryException.
Below is the code:
public static Point GetFinalPath(int x, int y) {
queue.Enqueue(new Point(x,y, null));
while(queue.Count>0) {
Point p = queue.Dequeue();
if (arr[p.x,p.y] == 9) {
Console.WriteLine("Found Destination");
return p;
}
if(IsOpen(p.x+1,p.y)) {
arr[p.x,p.y] = 1;
queue.Enqueue(new Point(p.x+1,p.y, p));
}
//similarly for the other directions
}
return null;
}
public int[,] SolutionMaze()
{
Point p = GetFinalPath(0, 0);
while (p.getParent() != null)
{
solvedarray[p.x, p.y] = 9;
p = p.getParent();
}
return solvedarray;
}
ok people here is the rest of the code
public static Queue<Point> queue=new Queue<Point>();
public static bool IsOpen(int x, int y)
{
//BOUND CHECKING
if ((x >= 0 && x < XMAX) && (y >= 0 && y < YMAX) && (arr[x,y] == 0 || arr[x,y] == 9))
{
return true;
}
return false;
}
public class Point
{
public int x;
public int y;
Point parent;
public Point(int x, int y, Point parent)
{
this.x = x;
this.y = y;
this.parent = parent;
}
public Point getParent()
{
return this.parent;
}
}
Assumes start to be 0,0 and final destination is set as 9 at the constructor.
Help me implement this for an array of size 500x500
Well, looking at your code I found one problem. You perform the wrong check. You should check if your point is already added to a queue. What do you do now? We'll, you are just marking processed cell as not open. It's easy to see that you can add to queue same node twice.
Let's follow my example:
1 | . .
0 | ! .
--+----
yx| 0 1
Queue: point (0,0)
We are starting at point(0,0). At this moment, we are adding points (0, 1) and (1,0) to our queue and mark point(0,0) as processed
1 | . .
0 | X !
--+----
yx| 0 1
Queue: point (0,1), point (1,0)
Now we dequeue point(0,1), marking it processed and adding point(1,1) to queue.
1 | ! .
0 | X X
--+----
yx| 0 1
Queue: point (1,0), point(1,1)
Now we dequeue point(1,0), marking it as processed and adding point(1,1) to queue:
1 | X !
0 | X X
--+----
yx| 0 1
Queue: point (1,1), point (1,1)
And now we have same point twice in a queue. And that is not your last problem. Your points have a reference to all it parents, so your previous points (doubled too) can't be processed with Garbage Collector.
Okay i found an answer to the OutOfMemory. Now the code works even for 500x500 matrix
As it turns out i just implemented a node list which keeps track of added nodes in queue using y*MAX_X_LENGTH + x formula
public static Queue<Point> queue=new Queue<Point>();
public SolveMaze(int[,] array,int staX,int staY,int finX,int finY)
{
//sets Destination as 9
arr = array;
XMAX = array.GetLength(0);
YMAX = array.GetLength(1);
finishY = finX; finishX = finY; startY = staX; startX = staY;
solvedarray = new int[XMAX, YMAX];
}
public static List<int> nodelist=new List<int>();
public void AddPointToQueueIfOpenAndNotAlreadyPresent(Point p,int direction)
{
if (nodelist.Contains(XMAX * p.y + p.x))
return;
else
{
switch(direction){
case 1:
//north
if (IsOpen(p.x, p.y - 1))
{
arr[p.x, p.y] = 1;
queue.Enqueue(new Point(p.x, p.y - 1, p));
nodelist.Add(XMAX * (p.y - 1) + p.x);
}
break;
case 0:
//east
if (IsOpen(p.x + 1, p.y))
{
arr[p.x, p.y] = 1;
queue.Enqueue(new Point(p.x + 1, p.y, p));
nodelist.Add(XMAX * (p.y) + p.x + 1);
}
break;
case 3:
//south
if (IsOpen(p.x, p.y + 1))
{
arr[p.x, p.y] = 1;
queue.Enqueue(new Point(p.x, p.y +1, p));
nodelist.Add(XMAX * (p.y + 1) + p.x);
}
break;
case 2:
//west
if (IsOpen(p.x - 1, p.y))
{
arr[p.x, p.y] = 1;
queue.Enqueue(new Point(p.x - 1, p.y, p));
nodelist.Add(XMAX * (p.y) + p.x-1);
}
break; }
}
}
public Point GetFinalPath(int x, int y) {
if (arr[finishX, finishY] == 0)
arr[finishX, finishY] = 9;
else
return null;
queue.Enqueue(new Point(x, y, null));
nodelist.Add(XMAX * y + x);
while(queue.Count>0) {
Point p = queue.Dequeue();
nodelist.Remove(p.y * XMAX + p.x);
if (arr[p.x,p.y] == 9) {
Console.WriteLine("Exit is reached!");
return p;
}
for (int i = 0; i < 4; i++)
{
AddPointToQueueIfOpenAndNotAlreadyPresent(p, i);
}
}
return null;
}
public static bool IsOpen(int x, int y)
{
//BOUND CHECKING
if ((x >= 0 && x < XMAX) && (y >= 0 && y < YMAX) && (arr[x,y] == 0 || arr[x,y] == 9))
{
return true;
}
return false;
}
public int[,] SolutionMaze()
{
Point p = GetFinalPath(startX, startY);
if(p!=null)
while (p.getParent() != null)
{
solvedarray[p.x, p.y] = 9;
p = p.getParent();
}
return solvedarray;
}
}
public class Point
{
public int x;
public int y;
Point parent;
public Point(int x, int y, Point parent)
{
this.x = x;
this.y = y;
this.parent = parent;
}
public Point getParent()
{
return this.parent;
}
}
Can someone explain what the use/meaning is of the following return statement: t > 1; (see last if statement last method)
the code is from a game called "Reversi" http://en.wikipedia.org/wiki/Reversi
This method checks if you enclose a stone of another player.
public bool allowed(int x, int y, bool player)
{
int color;
if(player == true) // true = player is blue.
color= 1;
else color= -1;
if(stone[x,y] != 0)
return false;
else
{
for (int dx = -1; dx <= 1; dx ++)
{
for (int dy = -1; dy <= 1; dy ++)
{
if (dx != 0 || dy != 0) // 0, 0 must be skipped, own stone.
{
if (close(color, x, y, dx, dy))
return true;
}
}
}
}
return false;
}
public bool close(int color, int x, int y, int dx, int dy)
{
int s;
int testx;
int testy;
for(int t=1; t<stone.Length;t++)
{
testx = x + t * dx;
testy = y + t * dy;
if(testx >= board.Width || testx <= 0 || testy >= board.Heigth|| testy <= 0)
return false;
s = stone[x + t * dx, y + t * dy];
if (s == 0) return false;
if (s == color) return t>1;
}
return true;
}
This code:
return t > 1;
Is equivalent to:
if (t > 1)
{
return true;
}
else
{
return false;
}
Except the latter approach is unnecessarily verbose and unfortunately quite common to see in real code.
Any expression to the right of a return statement is evaluated, and then the value is returned from the function.
In this case, t can either be greater than 1, or not - meaning it's either true or false - meaning either true or false will be returned, depending on the value of t.
It's exactly equivalent to:
if(t>1)
return true;
else
return false;
Returns true if t is greater than 1, otherwise it returns false.
return t > 1;
is same as
if (t > 1)
return true;
else
return false;
is same as
bool greaterThanOne;
if (t > 1)
greaterThanOne = true;
else
greaterThanOne =false;
return greaterThanOne;
return t>1 is equal to
if (t > 1)
{
return true;
}
else
{
return false;
}
Also there is an another using of return like;
static string AmIAwesome(bool b)
{
return b ? "Yes, I'm" : "No, I'm not";
}
Which is the same logic with first one.