Wrong parameters passed to function C# - c#

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.

Related

Concave Hull implementation

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);

OutOfMemoryException For Maze Solver of Large Dimensions

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;
}
}

Go Board Game - Recursive board group check

Creating a Go Board Game but I'm stuck at checking the board for groups of stones that have been surrounded. To do this I thought I'd need to come up with some recursive functionality:
(Updated)
public List<Point> FindSurrounded(Board board, Point p, Player player, List<Point> group)
{
int[,] b = board.board;
for (int dx = -1; dx <= 1; dx++){
for (int dy = -1; dy <= 1; dy++)
{
//check if group allready contain this spot
if (p.X + dx < board.width && p.Y + dy < board.height && p.X + dx > 0 && p.Y + dy > 0 && (dy == 0 || dx == 0) && !(dy == 0 && dx == 0) && !group.Contains(new Point(p.X + dx, p.Y + dy)))
{
// is the spot empty
if (b[p.X + dx, p.Y + dy] == 0)
return null;
//check the suroundings of this spot and add them to the group
//if(b[p.X + dx, p.Y + dy] != player.Identifier)// is there an enemy on this spot
// return new List<Point>();
if (b[p.X + dx, p.Y + dy] != player.Identifier)
{
group.Add(new Point(p.X + dx, p.Y + dy));
List<Point> temp = FindSurrounded(board, new Point(p.X + dx, p.Y + dy), player, new List<Point>());
if (temp == null)
return null;
//group.AddRange(temp);
}
}
}
}
return group;
}
This code however gives me a System.StackOverFlowException error when I put a stone that surrounds stones of the opponent. The error would concern the following line:
if (p.X + dx < board.width && p.Y + dy < board.height && p.X + dx > 0 && p.Y + dy > 0 && (dy == 0 || dx == 0) && !(dy == 0 && dx == 0) && !group.Contains(new Point(p.X + dx, p.Y + dy)))
But I have no idea why.
Does anyone know a way in which I can check whether a group of stones on the board is surrounded?
Thanks in advance!
Best regards,
Skyfe.
EDIT: Forgot to mention I still have to create an array to temporarily store all found stones that form a group together in order to remove them from the board when they're surrounded.
Answer to the specific question:
Does anyone know a way in which I can check whether a group of stones on the board is surrounded?
Try this approach:
Board b;
int N, M; // dimensions
int timer;
int[,] mark; // assign each group of stones a different number
int[,] mov = // constant to look around
{
{ 0, -1 }, { 0, +1 },
{ -1, 0 }, { +1, 0 }
};
// Checks for a group of stones surrounded by enemy stones
// Returns the first group found or null if there is no such group.
public List<Point> CheckForSurrounded()
{
mark = new int[N,M];
for (int i = 0; i < b.SizeX; ++i)
for (int j = 0; j < b.SizeX; ++j)
if (mark[i, j] == 0) // not visited
{
var l = Fill(i, j);
if (l != null)
return l;
}
return null;
}
// Marks all neighboring stones of the same player in cell [x,y]
// Returns the list of stones if they are surrounded
private List<Point> Fill(int x, int y)
{
int head = 0;
int tail = 0;
var L = new List<Point>();
mark[x, y] = ++timer;
L.Add(new Point(x,y));
while (head < tail)
{
x = L[head].X;
y = L[head].Y;
++head;
for (int k = 0; k < 4; ++k)
{
// new coords
int xx = x + mov[k,0];
int yy = y + mov[k,1];
if (xx >= 0 && xx < N && yy >= 0 && yy < M) // inside board
{
if (mark[xx, yy] == 0) // not visited
{
if (b[xx, yy].IsEmpty) // if empty square => not surrounded
return null;
if (b[xx, yy].IsMine)
{
L.Add(new Point(xx,yy)); // add to queue
mark[xx, yy] = timer; // visited
++tail;
}
}
}
}
}
// the group is surrouneded
return L;
}
This method doesn't use recursion so you don't have to deal with stack overflow (the exception not the site).
You could do it with code that does something like this.
pseudocode
isSurrounded(stone){
//mark that you have seen the stone before
stone.seen = true;
//check if all the surrounding spots are surrounded
for(spot in surrounded.getSpotsAround){
//An empty spot means the stone is not surrounded
if(spot = empty){
return false;
}
else{
//don't recheck stones you have seen before or opponents stones
if(spot.stone.seen != true || !stone.belongsToOpponent){
//recursively call this method, if it returns false your stone is not surrounded
if(!isSurrounded(spot.stone){
return false;
}
}
}
}
//if all of the surrounding stones are surrounded,seen already, or belong to other players, this stone is surrounded
return true;
}
Then you would have to remove all the stones where seen = true or reset seen on all stones.
I came up with this
(Updated)
public List<Point> FindSurrounded(int[,] b, Point p, Player player, List<Point> group)
{
for (int dx = -1; dx <= 1; dx++){
for (int dy = -1; dy <= 1; dy++)
{
//check if group allready contain this spot
if ((dy == 0 || dx == 0) && !(dy == 0 && dx == 0) && !group.Contains(new Point(p.X + dx, p.Y + dy))
{
// is the spot empty
if( b[p.X + dx, p.Y + dy] == 0)
return null;
if(b[p.X + dx, p.Y + dy] == player.Identifier)// is this your own stone
{
//If this is my stone add it to the list and check for it
group.Add( new Point( p.X + dx, p.Y + dy ) );
List<Point> temp = removeSurrounded(b, new Point(p.X + dx, p.Y + dy), player, group);
if(temp == null)
return null;
}
}
}
}
return group;
}
This returns null if there is any empty spot near your group else it will return a list of Points which represents your group.
Afterwards you can remove them like that
List<Point> group = FindSurrounded(b, p, player, new List<Point>());
if(group != null)
foreach(Point point in group)
b[point.x, point.y] = 0;

What does it mean when a method returns t > 1 as a boolean?

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.

how can i drag a 2d level array from a txt file

i am working on improving this tower defence gtame that i finished from this tutorial http://xnatd.blogspot.com/ i now wish to load the levels from a text file but not quite sure how i would do this using a streamreader, any tips? heres the source code for my level class;
public class Level
{
protected int temperature;
protected int levelNo;
private Queue<Vector2> waypoints = new Queue<Vector2>();
public Queue<Vector2> Waypoints
{
get
{
return waypoints;
}
}
int[,] map = new int[,]
{
{0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,},
{0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,},
{0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,},
{0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,},
{0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,},
{0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,},
{0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,},
{0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,},
{0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,},
{0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,},
{0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,},
{0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,},
{0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,},
{0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,},
{0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,},
{0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,},
};
public int Temperature // get the width of the level (how many numbers are in a row)
{
get
{
return temperature;
}
}
public int LevelNo // get the width of the level (how many numbers are in a row)
{
get
{
return levelNo;
}
set
{
levelNo = value;
}
}
public int Width // get the width of the level (how many numbers are in a row)
{
get
{
return map.GetLength(1);
}
}
public int Height // get the height of our level (how many numbers are there in a column)
{
get
{
return map.GetLength(0);
}
}
public int GetIndex(int cellX, int cellY) // return the index of the requested cell.
{
if (cellX < 0 || cellX > Width - 1 || cellY < 0 || cellY > Height - 1)
{
return 0;
}
else
{
return map[cellY, cellX];
}
}
public List<Texture2D> tileTextures = new List<Texture2D>(); // list to contain all the textures
/// <summary>
/// CONSTRUCTOR NEW LEVEL
/// </summary>
public Level()
{
SetWayPoints(map);
this.temperature = 1000;
this.levelNo = 2;
}
private void SetWayPoints(int[,] map)
{
int currentPosVal = map[0, 0];
int lPos = 0;
int rPos = 0;
int uPos = 0;
int dPos = 0;
int storedXPos = 99;
int storedYPos = 99;
int endstoredXPos = 99;
int endstoredYPos = 99;
int lastY = 0;
int lastX = 0;
//Search top ROW for start
for (int i = 0; i < Width; i++)
{
currentPosVal = map[0, i];
if (currentPosVal == 1)
{
storedXPos = i;
storedYPos = 0;
waypoints.Enqueue(new Vector2(storedXPos, storedYPos) * 32);
lastX = storedXPos;
lastY = storedYPos;
break;
}
}
//if start not set
if (storedXPos == 99 && storedXPos == 99)
{
//look in 1st coloum for start
for (int i = 0; i < Height; i++)
{
currentPosVal = map[i, 0];
if (currentPosVal == 1)
{
storedXPos = 0;
storedYPos = i;
waypoints.Enqueue(new Vector2(storedXPos, storedYPos) * 32);
lastX = storedXPos;
lastY = storedYPos;
break;
}
}
}
//search end COLOUM for end
for (int i = 0; i < Height; i++)
{
currentPosVal = map[i, Width - 1];
if (currentPosVal == 1)
{
endstoredXPos = Width - 1;
endstoredYPos = i;
}
}
//If end not set look in bottom row for end
if (endstoredXPos == 99 && endstoredYPos == 99)
{
for (int i = 0; i < Width; i++)
{
currentPosVal = map[7, i];
if (currentPosVal == 1)
{
endstoredXPos = i;
endstoredYPos = Height - 1;
}
}
if (endstoredXPos == 99 && endstoredYPos == 99)
{
}
}
// start midlle loop
while (true)
{
lPos = 0;
rPos = 0;
uPos = 0;
dPos = 0;
//If current pos is not down the left hand edge
if (storedXPos > 0) { lPos = map[storedYPos, storedXPos - 1]; }
//If current pos square is not down the right hand edge
if (storedXPos < Width - 1) { rPos = map[storedYPos, storedXPos + 1]; }
//If current pos square is not in the top row
if (storedYPos > 0) { uPos = map[storedYPos - 1, storedXPos]; }
//If current pos square is not in the bottom row
if (storedYPos < Height - 1) { dPos = map[storedYPos + 1, storedXPos]; }
if (lPos == 1 && (lastX != storedXPos - 1 || lastY != storedYPos))
{
lastX = storedXPos;
lastY = storedYPos;
storedXPos--;
waypoints.Enqueue(new Vector2(storedXPos, storedYPos) * 32);
}
else if (rPos == 1 && (lastX != storedXPos + 1 || lastY != storedYPos))
{
lastX = storedXPos;
lastY = storedYPos;
storedXPos++;
waypoints.Enqueue(new Vector2(storedXPos, storedYPos) * 32);
}
else if (dPos == 1 && (lastX != storedXPos || lastY != storedYPos + 1))
{
lastX = storedXPos;
lastY = storedYPos;
storedYPos++;
waypoints.Enqueue(new Vector2(storedXPos, storedYPos) * 32);
}
else if (uPos == 1 && (lastX != storedXPos || lastY != storedYPos - 1))
{
lastX = storedXPos;
lastY = storedYPos;
storedYPos--;
waypoints.Enqueue(new Vector2(storedXPos, storedYPos) * 32);
}
if (storedXPos == endstoredXPos && storedYPos == endstoredYPos)
{
break;
}
}
}
public void AddTexture(Texture2D texture) // method adds a texture to our texture list.
{
tileTextures.Add(texture);
}
//Reads number from array, store its value in textureIndex, Use textureIndex to get the texture from tileTextures,
public void Draw(SpriteBatch batch) //Draw appropiate texture, Repeat through all elements of the array
{
int textureIndex;
Texture2D texture;
for (int x = 0; x < Width; x++)
{
for (int y = 0; y < Height; y++)
{
if (levelNo == 0)
{
textureIndex = map[y, x];
if (textureIndex == -1)
continue;
texture = tileTextures[textureIndex];
batch.Draw(texture, new Rectangle(x * 32, y * 32, 32, 32), Color.White);
}
if (levelNo > 0)
{
textureIndex = map[y, x];
textureIndex += (levelNo * 2);
if (textureIndex == -1)
continue;
texture = tileTextures[textureIndex];
batch.Draw(texture, new Rectangle(x * 32, y * 32, 32, 32), Color.White);
}
}
}
}
}
}
Since C# is compiled and can't do evals like scripted languages can (not that you should be doing that anyway) you should probably use streamreader to read the data from file (formatted perhaps as delimited text: csv or tsv)
Assuming you're loading something similar to the map you have up there then a map file could look something like
0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0
0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0
0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0
0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0
0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0
0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0
0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0
0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0
0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0
0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0
0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0
0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0
0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0
0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0
0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0
0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1
where you would then loop through the file and read each line
As each line is read in, you can then split the line by "," to create a 1d array which can then be assigned to an index in the 2d array. Loop for each line to create the entire 2d map array
Take a look at this if you need help splitting strings in C#; note that the sample code splits at spaces " " and that you should use s.Split(','); for csv
With a file that small i would use:
File.ReadAllLines , and after readling it loop over the lines with a foreach loop.

Categories