C# doesn't (unlike Delphi) has a cartesian point class so I went ahead and wrote one. All code public domain blah blah blah. Should work on Mono as well:
/* Sample Point Class for C# for use in Roguelikes. By Dave Moore (starbog@NOSPAMgmail.com) */
/* All Code here is Public Domain - no copyright whatsoever, use it however you want */
using System;
namespace Map
{
// List of cardinal directions useful in offset and coordinate calculations
enum CardinalDirection { None = -1, N = 0, NE = 1, E = 2, SE = 3, S = 4, SW = 5, W = 6, NW = 7 };
// Point Class to handle Map Functions
class Point
{
// Default Constructor
public Point()
{
// Set the internal values
this.x = 0;
this.y = 0;
}
// Standard Constructor
public Point(int X, int Y)
{
// Set the internal values
this.x = X;
this.y = Y;
}
// Limit the values of the point to an additional supplied arbitrary
// bounds - useful when working with calculated values
public Point(int X, int Y, int Min, int Max)
{
// Set the internal values
this.x = X;
this.y = Y;
// Limit the x value if necessary
if (this.x > Max) { this.x = Max; }
else if (this.x < Min) { this.x = Min; }
// Limit the y value if necessary
if (this.y > Max) { this.y = Max; }
else if (this.y < Min) { this.y = Min; }
}
// Copy Constructor - we need to use this because unlike C++ we cannot
// overload the assignment operator
public Point(Point P2)
{
// If we have a valid reference
if ((object)P2 != null)
{
// Set the internal values
this.x = P2.X;
this.y = P2.Y;
}
}
// Override the ToString method
public override string ToString()
{
return string.Format("[{0},{1}]", this.x, this.y);
}
// Overload the equality operator
public static bool operator ==(Point P1, Point P2)
{
// If we have a valid reference
if ((object)P1 == null) { return false; }
if ((object)P2 == null) { return false; }
// Check for full equality on both values
return (P1.x == P2.x && P1.y == P2.y);
}
// Overload the non-equality operator
public static bool operator !=(Point P1, Point P2)
{
// If we have a valid reference
if ((object)P1 == null) { return false; }
if ((object)P2 == null) { return false; }
// Check for inequality on either values
return (P1.x != P2.x || P1.y != P2.y);
}
// Overload the equals operator
public override bool Equals(System.Object P2)
{
// If we have a valid reference
if ((object)P2 == null) { return false; }
// Check we can cast the incoming object to a Point
Point p = P2 as Point;
if ((System.Object)p == null) { return false; }
// Check for full equality on both values
return (this.x == p.x && this.y == p.y);
}
// Provide a custom GetHashCode function (needed when the Equals operator is
// overridden
public override int GetHashCode()
{
// Use XOR
return this.x ^ this.y;
}
// Provide an equivalent of an assignment operator
public void Set(Point P2)
{
// If we have a valid reference
if ((object)P2 != null)
{
// Set the internal values
this.x = P2.X;
this.y = P2.Y;
}
}
// Provide another equivalent of an assignment operator
public void Set(int X, int Y)
{
// Set the internal values
this.x = X;
this.y = Y;
}
// Return the euclidean distance between two points
public int DistanceTo(Point P2)
{
// If we have a valid reference
if ((object)P2 == null) { return -1; }
// Return the distance (as an int, rounded down)
return (int)Math.Sqrt((this.x - P2.x) * (this.x - P2.x) +
(this.y - P2.y) * (this.y - P2.y));
}
// get the difference between two points
public void SetFromOffset(Point P1, Point P2)
{
// Set the default values
this.X = 0;
this.Y = 0;
// If we have a valid reference
if ((object)P1 == null) { return; }
if ((object)P2 == null) { return; }
// Get the offsets
this.X = (P1.x - P2.x);
this.Y = (P1.y - P2.y);
}
// Return the difference between two points optionally limiting the
// values returned
public void SetFromOffset(Point P1, Point P2, int Min, int Max)
{
// Set the default values
this.X = 0;
this.Y = 0;
// If we have a valid reference
if ((object)P1 == null) { return; }
if ((object)P2 == null) { return; }
// Get the offsets
this.X = (P1.x - P2.x);
this.Y = (P1.y - P2.y);
// Limit the x value if necessary
if (this.X > Max) { this.X = Max; }
else if (this.X < Min) { this.X = Min; }
// Limit the y value if necessary
if (this.Y > Max) { this.Y = Max; }
else if (this.Y < Min) { this.Y = Min; }
}
// Get the direction of one point from another as an enum
public CardinalDirection DirectionTo(Point P2)
{
// If we have a valid reference
if ((object)P2 == null) { return CardinalDirection.None; }
// Set up an offset array to convert the offsets of the two points
// into a direction
Point[] Directions = new Point[8];
Directions[(int)CardinalDirection.N] = new Point(0, -1);
Directions[(int)CardinalDirection.NE] = new Point(1, -1);
Directions[(int)CardinalDirection.E] = new Point(1, 0);
Directions[(int)CardinalDirection.SE] = new Point(1, 1);
Directions[(int)CardinalDirection.S] = new Point(0, 1);
Directions[(int)CardinalDirection.SW] = new Point(-1, 1);
Directions[(int)CardinalDirection.W] = new Point(-1, 0);
Directions[(int)CardinalDirection.NW] = new Point(-1, -1);
// Get the offset from one point to another
Point P = new Point();
P.SetFromOffset(this, P2, -1, 1);
// Find the matching direction
int Index = 0;
foreach (Point Item in Directions)
{
if (Item == P) { return (CardinalDirection)Index; }
else { Index++; }
}
// Return the null value just in case
return CardinalDirection.None;
}
// Check if two points are adjacent to each other
public bool Adjacent(Point P2)
{
// Test if the points are 1 square apart
return (this.DistanceTo(P2) == 1);
}
// Private data members
private int x;
private int y;
// Publically accessible properties
public int X
{
get { return this.x; }
set { this.x = value; }
}
public int Y
{
get { return this.y; }
set { this.y = value; }
}
}
}
And here's a console test app as well:
/* Sample Point Class for C# for use in Roguelikes. By Dave Moore (starbog@NOSPAMgmail.com) */
/* All Code here is Public Domain - no copyright whatsoever, use it however you want */
using System;
using System.Text;
using Map;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Point P1 = new Point(10, 11);
Point P2 = new Point(24, 20);
Point P3 = new Point(100, 5);
System.Console.WriteLine("C# Point Class Demo\n*******************\n");
System.Console.WriteLine("Defined P1 as (10, 11), P2 as (24, 20) and P3 as (100, 5)\n");
System.Console.WriteLine("Standard Constructor & ToString(): P1 = " + P1.ToString() + ", P2 = " + P2.ToString() + ", P3 = " + P3.ToString());
Point P5 = new Point(999, -999, -9, 9);
System.Console.WriteLine("Limit Constructor: P5 = (999, -999, -9, 9): P5 = " + P5.ToString());
Point P4 = new Point(P1);
System.Console.WriteLine("Copy Constructor (P4->P1): P4 = " + P4.ToString() + "\n");
System.Console.WriteLine("==: P1 == P2 = " + (P1 == P2).ToString());
System.Console.WriteLine("!=: P1 != P2 = " + (P1 != P2).ToString());
System.Console.WriteLine("Equals(): P1.Equals(P2) = " + (P1.Equals(P2)).ToString());
Point P6 = new Point(66, 66);
P6.Set(P3);
System.Console.WriteLine("(Assignment Operator) Set(): P6 = (66, 66), P6.Set(P3); P6 = " + P6.ToString());
Point P7 = new Point(77, 77);
P7.Set(7, 7);
System.Console.WriteLine("(Direct Set Operator) Set(): P7 = (77, 77), P7.Set(7, 7); P7 = " + P7.ToString() + "\n");
System.Console.WriteLine("DistanceTo(): P1.Distance(P2) = " + (P1.DistanceTo(P2)).ToString());
System.Console.WriteLine("Adjacent(): P1.Adjacent(P2) = " + (P1.Adjacent(P2)).ToString());
Point P8 = new Point(88, 88);
P8.SetFromOffset(P1, P2);
System.Console.WriteLine("SetFromOffSet(): P8 = (88, 88), P8.SetFromOffset(P1, P2) = " + P8.ToString());
Point P9 = new Point(99, 99);
P9.SetFromOffset(P2, P1);
System.Console.WriteLine("SetFromOffSet(): P9 = (99, 99), P9.SetFromOffset(P2, P1) = " + P9.ToString());
Point P10 = new Point(10, 10);
P10.SetFromOffset(P1, P2, -1, 1);
System.Console.WriteLine("SetFromOffSet(): P10 = (10, 10), P10.SetFromOffset(P1, P2, -1, 1) = " + P10.ToString() + "\n");
System.Console.WriteLine("DirectionTo(): P2.DirectionTo(P1) = " + P2.DirectionTo(P1).ToString());
System.Console.WriteLine("DirectionTo(): P1.DirectionTo(P2) = " + P1.DirectionTo(P2).ToString());
Console.ReadKey(true);
}
}
}
Enjoy!
Best,
P.