How to stop enum from going out of bounds? - c#

I'm still learning the ropes with C# programming. I am trying to write an application to solve Knight's Tour but have run into some grief when trying to get possible future positions for the knight.
For positions I am using a very simple struct:
public struct Position
{
public enum BoardRank { A = 1, B, C, D, E, F, G, H };
public BoardRank X;
public int Y;
}
In the knight class, my PossibleMoves() method begins like this:
public List<Position> PossibleMoves(Position position)
{
List<Position> positions = new List<Position>();
int[] multiply = new int[]{1, -1};
foreach (int times in multiply)
{
try{
Position possible = new Position();
possible.X = position.X + (Behaviour.X * times);
possible.Y = position.Y + (Behaviour.Y * times);
positions.Add(possible);
}
...
For position = A1 and times = -1, you can see how Behaviour.X could quickly fall out of bounds, but I assumed this would have been picked up by the try block.
I tried adding a {get; set;} on the enum declaration but that threw some useless syntax errors in VS2010.
Is there anything else I can try here to stop my enum from going out of bounds?

I assumed this would have been picked up by the try block.
Nope. Enums in C# are "named numbers" effectively. They're not a complete set of values for the type.
Is there anything else I can try here to stop my enum from going out of bounds?
You can use Enum.IsDefined to check whether a value exists in the original enum. I would personally stop using public fields, and instead make Position immutable - then validate the value in the constructor. You could also have methods such as WithX which returned a new value based on the current value with just X changing. While you've got public fields, you're never going to be able to trust that any particular value is valid though.

It may be useful to use modulo to keep the values within a specific range:
possible.X = (position.X + (Behaviour.X * times)) % ((int)BoardRank.H + 1);
This way I am not sure whether an enum is the best solution here, as we're working with integers anyway. The numbers must be a sequence with no gaps and you have to make sure you take the highest defined enum value plus one. Thus, if you add a I to your enum, you need to change the modul.
Here I have a very simple program to illustrate how it works:
enum Foo { A, B, C }
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i % ((int)Foo.C + 1));
}
}
As you see we take i modulo C + 1 which makes C's integer value the actual range maximum. This is the output:
0, 1, 2, 0, 1, 2, 0, 1, 2, 0

Related

Use an integer to test a combination of enum values

I have seen something like this in practice before, but I cannot find out what the name of this technique is called to be able to google it.
I want to achieve this:
public enum Directions
{
Top = 1,
Right = 2,
Bottom = 4,
Left = 8
}
And then generate a random combination of those directions:
int combinationOfDirections = Random.Range(1, 15);
.. so the minimum could be 1, and the max 15 (1 + 2 + 4 + 8).
What method could I use to test which combination of top, right, bottom and left were picked. Something like:
// 'includes' is just the English version of what I want to do
if(combinationOfDirections includes Directions.Bottom)
I'm sure it was something using a '|' or an '&'.. any help would be hot!
Thanks
You can do this to check if a direction was included:
public static bool isDirectionAvailable(Directions direction, int value)
{
return ((int)direction & value) != 0;
}
If you have a variable like that:
var dirs = (Directions)combinationsOfDirections;
You can check if a single directions is contained by using the HasFlag() method:
bool hasTop = dirs.HasFlag(Directions.Top);
To check if the values is exactly a specified combination, you can do:
bool isExactlyTopAndBottom = dirs == Directions.Top | Directions.Bottom;

Create a 2D Matrix X[][] with letters on X axis and numbers on Y Axis

I am trying to create a 2D matrix like given below.
I am not able to find a way, please help me out.
A pseudo code would be very helpful.
Normal x[3][5] 2D matrix :
[00][01][02][03][04]
[10][11][12][13][14]
[20][21][22][23][24]
What I want to create is x[C][5]
[A0][A1][A2][A3][A4]
[B0][B1][B2][B3][B4]
[C0][C1][C2][C3][C4]
This isn't quite the syntax you were looking for, but I think it'll suit your needs. In order to get the behavior you want, you'll need to create a class that stores a 2D matrix and overloads the [] operator to accept a char instead of an int
public class Matrix<T> {
private T[,] arr;
public Matrix(int x, int y) {
arr = new T[x, y];
}
public T this[char c, int i] {
get { return arr[c - 'A', i]; }
set { arr[c - 'A', i] = value; }
}
}
As you can see, the code is actually pretty simple. It takes advantage of the fact that the char datatype holds the ASCII value of its letter. By subtracting away 'A', we can use 'A' as 0, 'B' as 1, etc. Then you can call your Matrix using characters like so:
Matrix<int> m = new Matrix<int>(3,4); // Creates a 3 x 4 matrix of ints
m['B',3] = 4; // m[1,3] = 4
EDIT
If you wanted to, you could also modify the constructor to accept a char
public Matrix(char x, int y) {
arr = new T[x - 'A' + 1, y];
}
Note that the character you use to initialize, like an integer initializer for an array, is the number of entries and thus one greater than the highest index.
Matrix<int> m = new Matrix<int>('C',4); // Creates a 3 x 4 matrix of ints
m['B',3] = 4; // m[1,3] = 4

In C#, can multiplications inside of an array declaration/initialization cause mayhem?

I am going a bit crazy here with the following section of code
public static readonly float f = 1.25f;
public static void init(){
Debug.Log(f); // output: 1.25f
FLIPPER_CENTERS = new float[,] {
{ (20*f), (27*f) }, { FLIPPER_WIDTH - (20*f), (27*f)},
{ (6*f), (25*f) }, { MH_FLIPPER_WIDTH- (6*f), (25*f) },
{ (8), (15)}, { (SMALL_FLIPPER_WIDTH - 8), (15)},
{ (8), (20)}, { (67 - 8), (20)},
};
Debug.Log(FLIPPER_CENTERS[0,0]); // output: 0, expected 25;
}
If I print the values of the first element of that array, I get [0, 0]. The last two elements are [59, 20], as expected.
The first value is supposed to be [25, 33,75]. Which I can get if I substitute (20*f) for (20*1.25f).
{ (20*1.25f), (27*1.25f) }, { FLIPPER_WIDTH - (20*f), (27*f)},
So here is the problem: if I leave the multiplication by f in the array initialization, the values are 0. However, if I change f to 1.25f all is good.
I have tried to figure out what is going on, but to no avail. I am certain the value of f is 1.25f and not 0. Can anyone shed some light on this for me please?
Edit:
To prove that f is not 0, I've tried 20/f for the first element. That didn't throw an exception and the output was still 0.
Partial Solution
Changing f from readonly to const solves the problem. However, I would really much like to know why this is happening.
public const float f = 1.25f;
All this is running in Unity, it may have something to do with it.
I see this question is tagged Unity3D.
Is it possible that f is a public variable exposing it to be modified in the Unity Editor? If so, any value set in the editor will override a value set in the code during variable declaration. The value set during declaration is simply used as a default value for the Unity Editor.
If this is the case then someone could have set f to 0 in the editor causing it to be 0 when you do your math.
Edited Answer After Some Testing: 8/22/2013
I was able to repeat your problem when using Unity. It seems there is a bug in Unity that doesn't allow variables to be used during initialization of an array at declaration. Everything works properly if it is a standard C# project, however, so this is related to Unity only.
The problem has nothing to do with f being static or readonly, only that it is a variable. The following code does not work:
public void init()
{
float f = 1.25f;
float[,] FLIPPER_CENTERS = new float[,] {
{ (5+f), (27*f) }, { 30 - (20*f), (27*f)},
{ (6*f), (25*f) }, { 20 - (6*f), (25*f) },
{ (8), (15)}, { (10 - 8), (15)},
{ (8), (20)}, { (67 - 8), (20)},
};
Debug.Log(FLIPPER_CENTERS[0,0]); // Outputs 0 | Expected 6.25f
}
Anywhere the variable f is used in the array initialization will result in a 0. More specifically, it doesn't just set f = 0 it sets the whole expression to 0. For example, the first element in the array above, 5+f, would result in 0 - not 5. The elements with constants, however, evaluate normally (such as the last few elements). It seems if Unity is bailing out of the evaluation when it encounters a variable.
If, however, I define the array in one line and then set the elements later everything works normally. For example:
public void init()
{
float f = 1.25f;
float[,] FLIPPER_CENTERS = new float[8, 2];
FLIPPER_CENTERS[0, 0] = 20*f;
FLIPPER_CENTERS[0, 1] = 27*f;
FLIPPER_CENTERS[1, 0] = 30 - (20*f);
FLIPPER_CENTERS[1, 1] = 27*f;
FLIPPER_CENTERS[2, 0] = 6*f;
FLIPPER_CENTERS[2, 1] = 25*f;
FLIPPER_CENTERS[3, 0] = 20 - (6*f);
FLIPPER_CENTERS[3, 1] = 25*f;
FLIPPER_CENTERS[4, 0] = 8;
FLIPPER_CENTERS[4, 1] = 15;
FLIPPER_CENTERS[5, 0] = 10 - 8;
FLIPPER_CENTERS[5, 1] = 15;
FLIPPER_CENTERS[6, 0] = 8;
FLIPPER_CENTERS[6, 1] = 20;
FLIPPER_CENTERS[7, 0] = 67 - 8;
FLIPPER_CENTERS[7, 1] = 20;
Debug.Log(FLIPPER_CENTERS[0,0]); // Outputs 25.0f | Expected 25.0f
}
Just did some further testing and it seems that the problem is only present with multidimensional arrays. The following gives expected output:
public void init()
{
float f = 1.25f;
float[] FLIPPER_CENTERS = new float[] {
(f), (f * 2), (f * 3), (f * 4),
(f + 1), (f + 2), (f + 3), (f + 5)
};
Debug.Log(FLIPPER_CENTERS[0]); // Outputs 1.25f | Expected 1.25f
}
This certainly seems like a bug in Unity to me. It is generally recommended, however, that const be used over static readonly. Using const provides a performance benefit (albeit slight) since it is converted into a literal at compile time. In addition, using const will avoid this problem altogether.
I know you already figured out const works, just wanted to give you a little information that I discovered.

C#: Loop to find minima of function

I currently have this function:
public double Max(double[] x, double[] y)
{
//Get min and max of x array as integer
int xMin = Convert.ToInt32(x.Min());
int xMax = Convert.ToInt32(x.Max());
// Generate a list of x values for input to Lagrange
double i = 2;
double xOld = Lagrange(xMin,x,y);
double xNew = xMax;
do
{
xOld = xNew;
xNew = Lagrange(i,x,y);
i = i + 0.01;
} while (xOld > xNew);
return i;
}
This will find the minimum value on a curve with decreasing slope...however, given this curve, I need to find three minima.
How can I find the three minima and output them as an array or individual variables? This curve is just an example--it could be inverted--regardless, I need to find multiple variables. So once the first min is found it needs to know how to get over the point of inflection and find the next... :/
*The Lagrange function can be found here.** For all practical purposes, the Lagrange function will give me f(x) when I input x...visually, it means the curve supplied by wolfram alpha.
*The math-side of this conundrum can be found here.**
Possible solution?
Generate an array of input, say x[1,1.1,1.2,1.3,1.4...], get an array back from the Lagrange function. Then find the three lowest values of this function? Then get the keys corresponding to the values? How would I do this?
It's been a while since I've taken a numerical methods class, so bear with me. In short there are a number of ways to search for the root(s) of a function, and depending on what your your function is (continuous? differentiable?), you need to choose one that is appropriate.
For your problem, I'd probably start by trying to use Newton's Method to find the roots of the second degree Lagrange polynomial for your function. I haven't tested out this library, but there is a C# based numerical methods package on CodePlex that implements Newton's Method that is open source. If you wanted to dig through the code you could.
The majority of root finding methods have cousins in the broader CS topic of 'search'. If you want a really quick and dirty approach, or you have a very large search space, consider something like Simulated Annealing. Finding all of your minima isn't guaranteed but it's fast and easy to code.
Assuming you're just trying to "brute force" calculate this to a certain level of prcision, you need your algorithm to basically find any value where both neighbors are greater than the current value of your loop.
To simplify this, let's just say you have an array of numbers, and you want to find the indices of the three local minima. Here's a simple algorithm to do it:
public void Test()
{
var ys = new[] { 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5, 4, 3, 4, 5, 4 };
var indices = GetMinIndices(ys);
}
public List<int> GetMinIndices(int[] ys)
{
var minIndices = new List<int>();
for (var index = 1; index < ys.Length; index++)
{
var currentY = ys[index];
var previousY = ys[index - 1];
if (index < ys.Length - 1)
{
var neytY = ys[index + 1];
if (previousY > currentY && neytY > currentY) // neighbors are greater
minIndices.Add(index); // add the index to the list
}
else // we're at the last index
{
if (previousY > currentY) // previous is greater
minIndices.Add(index);
}
}
return minIndices;
}
So, basically, you pass in your array of function results (ys) that you calculated for an array of inputs (xs) (not shown). What you get back from this function is the minimum indices. So, in this example, you get back 8, 14, and 17.

Sorting ArrayList of shapes

I have an ArrayList of MCommand objects (cmdList) and I want to sort it so that shapes with closest points are next to each other in the ArrayList. For example, say I have three lines in the ArrayList:
line(xs, ys, zs, xe, ye, ze)
cmdList[0] = line1(1.3, 2.5, 3, 4, 5, 6)
cmdList[1] = line2(1, 5, 6.77, 7, 8, 2)
cmdList[2] = line3(1, 6, 3, 1, 1.1, 1)
Points that need to be close are LastPosition of line with BeginPosition of other line.
LastPosition of line is (xe, ye, ze) and BeginPosition of line is (xs, ys, zs).
I now do my sorting by executing a built in sorting:
cmdList.Sort(new MCommandComparer());
This is how my MCommand looks like and how i calculate distance of two points:
public abstract class MCommand
{
//...
public abstract Point3 LastPosition { get; }
public abstract Point3 BeginPosition { get; }
public double CompareTo(Object obj)
{
Point3 p1, p2;
p1 = this.BeginPosition;
p2 = ((MCommand)obj).LastPosition;
return Math.Sqrt(Math.Pow((p2.x - p1.x), 2) +
Math.Pow((p2.y - p1.y), 2) +
Math.Pow((p2.z - p1.z), 2));
}
}
This is the comparer i use:
public class MCommandComparer : IComparer
{
private MCommand prev;
double distanceFromPrev = 0;
double distanceFromCurr = 0;
public int Compare(object o1, object o2)
{
if ((MCommand)o2 == prev)
return 0;
if (prev != null)
distanceFromPrev = ((MCommand)o1).CompareTo(prev);
distanceFromCurr = ((MCommand)o1).CompareTo(o2);
prev = (MCommand)o2;
return (int)(distanceFromCurr - distanceFromPrev);
}
}
I've tried many ways and got lost... This doesnt sort shapes the way I want to. My question is, what I could be doing wrong? Should i try writing sorting from scratch? My ArrayList can contain couple thousands elements, and i need to have an efficient sort.
What could I be doing wrong?
You're assuming the elements will be presented to you in a particular order - you're remembering the "previous" element, which is a huge red flag.
The way various sorts work won't do this at all. Basically your comparer should be stateless. It sounds like you don't really have a total ordering here - there's no way of taking any two arbitrary elements and saying which should be before or after the other one.
I don't know exactly how you'd do whatever you need, but I don't think the standard sorting built into .NET is going to help you much.
You could make your MCommand class subscribe to IComparable. In doing this you would allow your list to sort your shapes without the need for additional Comparer Object. All the sorting functionality would be handled by the list and the objects within it.

Categories