I have:
partial class StarSystem : AstroThreeNode
{
public static StarSystem SunSolarSystem()
{
return new StarSystem("Solar System", Planet.SunCenter(), Resources.Space, SolarSystem.ActiveForm.Bounds).AddPlanet(Planet.MercuryPlanet(), Planet.VenusPlanet(), Planet.EarthPlanet(), Planet.MarsPlanet(), Planet.JupiterPlanet(), Planet.SaturnPlanet(), Planet.UranusPlanet(), Planet.NeptunePlanet());
}
public StarSystem AddPlanet(params Planet[] planetsToAdd)
{
foreach (Planet planet in planetsToAdd)
{
distanceFromSun += (planets.Count > 0 ? planets[planets.Count - 1].Image.Width / 2 : 0) + planet.Image.Width / 2 + DISTANCE_BETWEEN_PLANETS;
planet.DistanceFromSun = distanceFromSun;
planet.RotationCenter = new PointF(bounds.Width / 2, bounds.Height / 2);
planets.Add(planet);
}
return this;
}
}
partial class Planet : AstroThreeNode
{
private const float SUN_SPEED = 0;
public static Planet SunCenter()
{
return new Planet("Слънце", Resources.Sun_, SUN_SPEED, CLOCKWISE);
}
public static Planet MercuryPlanet()
{
return new Planet("Меркурий", Resources.Mercury_, 4.0923f, Planet.CLOCKWISE);
}
public static Planet VenusPlanet()
{
return new Planet("Венера", Resources.Venus_, 1.6021f, Planet.COUNTERCLOCKWISE);
}
public static Planet EarthPlanet()
{
return new Planet("Земя", Resources.Earth_, 0.9856f, Planet.CLOCKWISE);
}
public static Planet MarsPlanet()
{
return new Planet("Марс", Resources.Mars_, 0.5240f, Planet.CLOCKWISE);
}
public static Planet JupiterPlanet()
{
return new Planet("Юпитер", Resources.Jupiter_, 0.0830f, Planet.CLOCKWISE);
}
public static Planet SaturnPlanet()
{
return new Planet("Сатурн", Resources.Saturn_, 0.0334f, Planet.CLOCKWISE);
}
public static Planet UranusPlanet()
{
return new Planet("Уран", Resources.Uranus_, 0.0117f, Planet.COUNTERCLOCKWISE);
}
public static Planet NeptunePlanet()
{
return new Planet("Нептун", Resources.Neptune_, 0.0059f, Planet.CLOCKWISE);
}
public Planet(string name, Image image, float distanceFromSun, float degreesAddedEachTick, bool clockwise, PointF rotationCenter, float angleInDegrees = 0)
{
this.Name = name;
this.Image = image; // here I set the Image but I get an exception later
this.DistanceFromSun = distanceFromSun;
this.degreesAddedEachTick = degreesAddedEachTick;
this.isClockwiseRotation = clockwise;
this.RotationCenter = rotationCenter;
this.angleInDegrees = angleInDegrees;
}
}
I get the exception here: distanceFromSun += (planets.Count > 0 ? planets[planets.Count - 1].Image.Width / 2 : 0) + planet.Image.Width / 2 + DISTANCE_BETWEEN_PLANETS;
For the planet.Image. I don't get it why do I get exception when I set the Image when I create a Planet.
EDIT: Here is the constructor for StarSystem :
public StarSystem(string name, Planet starSystemCenter, Image background, Rectangle bounds)
{
this.Name = name;
this.Background = background;
this.bounds = bounds;
planets = new List<Planet>(); //planets instanieted here
planets.Add(starSystemCenter); // note I dont get the exception on this call but on the other call where I add all other planest
}
EDIT 2:
Found my problem but I have to go to bed I will post the answer tomorrow.
It looks like you're never instantiating your 'Planets' object (probably a List<Planet>?)
Is it in your StarSystem code?
Presumably it would be something like
public class StarSystem
{
public List<Planet> planets {get; set;}
//Other code here
public StarSystem()
{
planets = new List<Planet>();
}
}
But that code is not in evidence in your post. That's what I find to be the most likely culprit.
Post Question Edit:
Okay, then the only thing that seems to leave is the .Image for one or more of your planets. When you debug, you should be able to watch your variables- I would set a break-point before it evaluates that expression, and look at the last object it added, and the next object it's going to try to add, and look for a null .Image
Try to have class members, local variables, and method parameters differ by more than capitalization. See Bad Naming Convention in the canonical NullReferenceException post linked above.
You create each planet with this constructor
public Planet(string name, Image image, float distanceFromSun, float degreesAddedEachTick, bool clockwise, PointF rotationCenter, float angleInDegrees = 0)
Yet you never check to make sure that image != null && image.Width != null (if width is a native int you don't need to, but if it is a Number you do need that check.
Related
I have a simple struct that looks like this:
public struct GridNeighbours
{
public static Vector2Int North = new Vector2Int(0, 1);
public static Vector2Int South = new Vector2Int(0, -1);
public static Vector2Int East = new Vector2Int(1, 0);
public static Vector2Int West = new Vector2Int(-1, 0);
}
Is there a way to "iterate" through each of these fields somehow with a for loop? Do structs by chance index their fields or something? It would make my code a lot cleaner if it was possible but I am not sure how to make it iterative.
Edit: due to this being used in a hot path in a game, is there a way to rewrite this so i can avoid reflection ?
This is not a duplicate since i need an alternative approach to avoid reflection.
public struct GridNeighbours {
public enum Cardinal { North, East, South, West }
public static Vector2Int[] Neighbours = { new Vector2Int(0, 1), new Vector2Int(1, 0), new Vector2Int(0, -1), new Vector2Int(-1, 0) };
public Vector2Int this[Cardinal dirn] {
get { return this[(int)dirn]; }
set { this[(int)dirn] = value; }
}
public Vector2Int this[int dirn] {
get { return Neighbours[dirn]; }
set { Neighbours[dirn] = value; }
}
}
Example use:
var cell = new GridNeighbours();
var NorthNeighbour = cell[Cardinal.North];
Assert(cell[Cardinal.South] == cell[2]); // This is true!
===
Alternatively, if you want "direct" properties:
public struct GridNeighbours {
public enum Cardinal { North, East, South, West }
public static Vector2Int[] Neighbours = { new Vector2Int(0, 1), new Vector2Int(1, 0), new Vector2Int(0, -1), new Vector2Int(-1, 0) };
public static Vector2Int North { get { return Neighbours[0]; } set { Neighbours[0] = value; } }
public static Vector2Int East { get { return Neighbours[1]; } set { Neighbours[1] = value; } }
public static Vector2Int South { get { return Neighbours[2]; } set { Neighbours[2] = value; } }
public static Vector2Int West { get { return Neighbours[3]; } set { Neighbours[3] = value; } }
}
Without using reflection I don't think you can do it given the signature you have there.
What you could do is to setup an indexer on the struct that would allow you to loop.
If you mean the possible values in the struct will not be known in the compile-time, then you can try using Reflection. More specifically, using Type.GetFields() or Type.GetProperties().
Example:
Type structType = typeof(GridNeighbours);
FieldInfo[] fields = structType.GetFields();
Foreach(FieldInfo field in fields)
{
//Do something
}
But keeping the fact in mind that there will always be four directions, why a simple GridNeighboursInstance.North is not a preference for you.
If you don't want to use a dynamic way so I can suggest you to use a static way! When you have only those four members and you want to iterate over them you need to implement an AsEnumerable method inside your struct something like this:
public static IEnumerable<Vector2Int> AsEnumerable()
{
for (var i = 0; i < 4; i++)
{
switch (i)
{
case 1:
yield return North;
break;
case 2:
yield return South;
break;
case 3:
yield return East;
break;
case 4:
yield return West;
break;
}
}
}
I think there are some better way, But HTH ;).
I am trying to solve or be pointed in the right direction. I am having difficulty determining where to place my Area formula in the Triangle Class (not the main). Area can only have a 'get' and not a 'set'.
Next issue is identifying the type of triangle based on the inputed side and if it is a 'right' triangle, appending the 'type' with '-right' for example (isosceles-right). I have an enum for the triangle types.
I'm not looking for the direct answer to solve this but rather some help and coaching to help better build my skills
Here is the class structure I have generated so far in C#, please keep in mind it is not complete.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TriangleCheck;
namespace TriangleCheck
{
public class Triangle
{
private StringBuilder _ErrorMsg;
private int[] _Sides;
private const int _nSides = 3;
private int _Area;
public Triangle(int[] Sides)
{
//Track amunt of errors recieved.
int nErrors = 0;
//Make sure ErrorMsg is cleared
_ErrorMsg = new StringBuilder();
//Did I get _nSides? If not, append to ErrorMsg and throw exception
if(Sides.Length != _nSides)
{
_ErrorMsg.Append(string.Format("Expected {0} sides but recieved {1}", _nSides, Sides.Length));
nErrors += 1;
}
//Is each side positive? If not, append to ErrorMsg and throw exception
for (int i = 0; i < Sides.Length; i++)
{
if (Sides[i] <= 0)
{
_ErrorMsg.Append(string.Format("{0} side is not a postive integer", Sides[i]));
nErrors += 1;
}
}
//Set input from user to private property _Sides
_Sides = Sides;
_Area = Area;
}
public int Area
{
get { return _Area; }
private set
{
int parameter =
}
}
public string ErrorMsg
{
get
{ return ErrorMsg.ToString();}
}
public bool IsRight
{
get
{
return ;
}
}
public int Sides
{
get
{ return _Sides; }
set
{
if (value > 0)
{
_Sides = value;
}
else
throw new ArgumentOutOfRangeException("Value must be postive!");
}
}
public TriangleTypes TriangleTypes
{
get
{
throw new System.NotImplementedException();
}
set
{
}
}
public void ScaleUp(int[] ScaleFactor)
{
throw new System.NotImplementedException();
}
public override string ToString()
{
return "A Triangle with sides " + _Sides + " is Type: " + TriangleTypes + " with Area:" + Area;
}
}
}
You mention that you can't set the Area property... it looks like you're trying to enforce that by making a private set, but why not just exclude the set leaving it as a read-only property?
The Area formula could go a couple places; the key is that it is derived from the sides but only matters when someone asks for it. So you could reasonably:
Apply the formula and update internal state every time sides changes
Apply the formula and return the value every time someone does a get operation on Area
Remember the point of getter and setter being functions is that they could contain logic to execute (to fully update internal state in setter, or to calculate the value of a read-only derived property).
More sophisticated patterns exist if performance of the area calculation were very worrisome, but I wouldn't get into that at this point.
As for determining if the triangle is right... if it is, which side must be the hypotenuse? What relationship do you know between the length of the hypotenuse and the lengths of the other sides, if the triangle is right?
using System;
namespace ConsoleApp
{
class Program
{
static void Main()
{
var t = new Triangle(2, 3, 5);
//var Triangle = new Triangle(2); // won't compile as no Triangle constructor can be found that takes 1 integer
//var Triangle = new Triangle(2, 3, 5, 7); // won't compile as no Triangle constructor can be found that takes 4 integers
//var Triangle = new Triangle(2, -3, 5); // won't compile as the 2nd value is negative - and we've asked for unsigned for all 3 values
Console.WriteLine("The triangle ({0}, {1}, {2}) has an area of {3}.", t.A, t.B, t.C, t.area());
Console.ReadKey();
}
}
public class Triangle
{
public uint A { get; set; }
public uint B { get; set; }
public uint C { get; set; }
public Triangle(uint a, uint b, uint c)
{
this.A = a;
this.B = b;
this.C = c;
}
public uint area()
{
return A * B * C; // this needs fixing ...
}
}
}
Isn't this roughly what you are trying to achieve with your Triangle class - a way of stopping it being used incorrectly with too few or incorrect types of arguments. This one only allows 3 positive (uint) integers. Nothing else will comple - which is what you want. Sorry if I have misunderstood.
For my program, I created a new class called FinishedPiece with a number of public variables available to my main program. For example:
class FinishedPiece
{
private double _PieceLength;
public double PieceLength
{
get { return _PieceLength; }
set { _PieceLength = value; }
}
}
This all works fine, because then I can declare a new FinishedPiece and add properties:
FinishedPiece piece = new FinishedPiece();
piece.PieceLength = 48.25;
My question is, how do the same with an enum? If I do
public enum Cut
{
Angle = 0,
Straight = 1,
AngleThenStraight = 2,
StraightThenAngle = 3
};
then I'd like to change it something like this: piece.Cut = Cut.Angle; but I can only change it by declaring a new FinishedPiece.Cut object:
FinishedPiece.Cut cut = new FinishedPiece.Cut();
cut = FinishedPiece.Cut.Angle;
How do I make an enum available inside a variable so I can do piece.Cut = Cut.Angle? To me it would make sense to do something like this, but it doesn't appear to work.
public int Cut
{
get { return _Cut; }
set { _Cut = value; }
}
private enum _Cut
{
Angle = 0,
Straight = 1,
AngleThenStraight = 2,
StraightThenAngle = 3
};
Thanks in advance! Let me know if my question is unclear and I'll try to help as best as I can.
How do I make an enum available inside a variable so I can do
piece.Cut = Cut.Angle?
Just define another property of type Cut in your class like:
public Cut Cut { get; set; }
Then you can do:
FinishedPiece piece = new FinishedPiece();
piece.PieceLength = 48.25;
piece.Cut = Cut.Angle; //like this
So your class would like like:
class FinishedPiece
{
private double _PieceLength;
public double PieceLength
{
get { return _PieceLength; }
set { _PieceLength = value; }
}
public Cut Cut { get; set; }
}
Consider using Auto-Implemented properties, if you have only simple set and get
Like this:
class FinishedPiece
{
private double _PieceLength;
public double PieceLength
{
get { return _PieceLength; }
set { _PieceLength = value; }
}
private Cut _Cut;
public Cut Cut
{
get { return _Cut; }
set { _Cut = value; }
}
}
public enum Cut
{
Angle = 0,
Straight = 1,
AngleThenStraight = 2,
StraightThenAngle = 3
};
Then you can do:
var piece = new FinishedPiece();
piece.Cut = Cut.AngleThenStraight;
You can try this:
private enum Cut
{
//if you dont want to use any of these values as defaults
//just add another value and in your class private member
//assign it like for example a value called None
Angle = 0,
Straight = 1,
AngleThenStraight = 2,
StraightThenAngle = 3
};
public class FinishedPiece
{
//give it a default,if like stated in the enum you dont want
//any of those values create a None and place it here as default.
private Cut cutObj = Cut.Angle;
public Cut CutObj
{
get { return cutObj; }
set { cutObj = value; }
}
}
Then in your calling code...
FinishedPiece piece = new FinishedPiece();
//if you dont want the default change it...
piece.CutObj = Cut.Straight;
Here is the code below.
I am trying to make it so that when I click on the nextButton button it cycles to the next 3 numbers in my textfile. I cant figure out ow, what i have here should work :[
namespace GPSProject
{
class dataPoints
{
public int Count { get { return Points.Count; } }
List<dataPoint> Points;
//string p;
public dataPoints(/*string path*/)
{
Points = new List<dataPoint>();
// p = path;
TextReader tr = new StreamReader(/*p*/"C:/Test.txt");
string input;
while ((input = tr.ReadLine()) != null)
{
string[] bits = input.Split(',');
dataPoint a = new dataPoint(bits[0], bits[1], bits[2]);
Points.Add(a);
}
tr.Close();
}
internal dataPoint getItem(int p)
{
if (p < Points.Count)
{
return Points[p];
}
else
return null;
}
}
}
Above is the class that breaks down the textfile into inidividual numbers.
namespace GPSProject
{
public partial class Form1 : Form
{
private int count;
internal dataPoints myDataPoints;
public Form1()
{
myDataPoints = new dataPoints();
InitializeComponent();
}
private void buttonNext_Click(object sender, EventArgs e)
{
{
count++;
if (count == (myDataPoints.Count))
{
count = 0;
}
dataPoint a = myDataPoints.getItem(count);
textBoxLatitude.Text = a.CurLatitude;
textBoxLongtitude.Text = a.CurLongtitude;
textBoxElevation.Text = a.CurElevation;
}
}
}
}
Above is the Windows form
namespace GPSProject
{
class dataPoint
{
private string latitude;
private string longtitude;
private string elevation;
public dataPoint() //Overloaded incase no value available
{
latitude = "No Latitude Specified";
longtitude = "No Longtitude Specified";
elevation = "No Elevation Specified";
}
public dataPoint(string Latitude, string Longtitude, string Elevation)
{
// TODO: Complete member initialization
this.latitude = Latitude;
this.longtitude = Longtitude;
this.elevation = Elevation;
}
public string CurLongtitude { get { return this.longtitude; } }
public string CurLatitude { get { return this.latitude; } }
public string CurElevation { get { return this.elevation; } }
}
}
And finally this is the class the holds the numbers. The numbers i am trying to get the textboxes to show are cycles of CurLongtitude/Latitue/Elevation
First thing to do would be to create a proper vessle for your data: the DataPoint Entity:
class DataPoint
{
// Option 1: Field + read only property
private string _latitude;
public string Latitude { get { return _latitude; } }
// Option 2: Property + compiler generated field
public string Longitude { get; private set; }
public string Elevation { get; private set; }
// Constructor
public DataPoint(string latitude, string longtitude, string elevation)
{
// Internally in this class we use fields
_latitude = latitude;
// Unless we use property option 2
this.Longitude = longitude;
this.Elevation = elevation;
}
}
Next we could add a static method to the DataPoint class to load the data points from disk:
public static List<DataPoint> LoadFromFile (string filename)
{
// The .NET framework has a lot of helper methods
// be sure to check them out at MSDN
// Read the contents of the file into a string array
string[] lines = File.ReadAllLines(filename);
// Create the result List
List<DataPoint> result = new List<DataPoint>();
// Parse the lines
for (string line in lines)
{
string[] bits = line.Split(',');
// We're using our own constructor here
// Do watch out for invalid files, resulting in out-of-index Exceptions
DataPoint dataPoint = new DataPoint(bits[0], bits[1], bits[2]);
result.Add(dataPoint);
}
return result;
}
Now that we have all the building blocks. Let's make the application:
public partial class Form1 : Form
{
private int _index;
private List<DataPoint> _dataPoints;
public Form1()
{
// Since this is a simple test application we'll do the call here
_dataPoints = DataPoint.LoadFromFile(#"C:\Test.txt");
InitializeComponent();
}
private void buttonNext_Click(object sender, EventArgs e)
{
// Cycle the data points
_index++;
if (_index == _dataPoints.Count)
{
_index = 0;
}
// Get the specific data point
DataPoint dataPoint = _dataPoints[_index];
// The empty texts are UI only, so we could check them here
if (dataPoint.Latitude == null || dataPoint.Latitude == "")
{
textBoxLatitude.Text = "No Latitude Specified";
}
else
{
textBoxLatitude.Text = dataPoint.Latitude;
}
// A shorter, inline version
textBoxLongtitude.Text = String.IsNullOrEmpty(dataPoint.Longitude) ? "No Longitude Specified" : dataPoint.Longitude;
// Or if we don't care about empty texts
textBoxElevation.Text = dataPoint.Elevation;
}
}
Of course there are lots of ways to make the code even shorter, or to use modern techniques like LINQ, but I've tried not to go too far from your existing code. I haven't tried the code, I typed it here on SO :)
Also please be careful in how you format your code. Proper casing and following standards makes your code a lot easier to read by others.
MSDN has a lot of good examples and extensive documentation on the .NET Framework classes.
This is minor, I know, but let's say that I have a class Character and a class Ability (mostly because that's what I'm working on). Class Character has six abilities (so typical D&D...). basically:
public class Character
{
public Character()
{
this.Str = new Ability("Strength", "Str");
this.Dex = new Ability("Dexterity", "Dex");
this.Con = new Ability("Constitution", "Con");
this.Int = new Ability("Intelligence", "Int");
this.Wis = new Ability("Wisdom", "Wis");
this.Cha = new Ability("Charisma", "Cha");
}
#region Abilities
public Ability Str { get; set; }
public Ability Dex { get; set; }
public Ability Con { get; set; }
public Ability Int { get; set; }
public Ability Wis { get; set; }
public Ability Cha { get; set; }
#endregion
}
and
public class Ability
{
public Ability()
{
Score = 10;
}
public Ability(string Name, string Abbr)
: this()
{
this.Name = Name;
this.Abbr = Abbr;
}
public string Name { get; set; }
public string Abbr { get; set; }
public int Score { get; set; }
public int Mod
{
get
{
return (Score - 10) / 2;
}
}
}
When actually using these ability properties in future code, I'd like to be able to default to just the score, like so:
//Conan hits someone
int damage = RollDice("2d6") + Conan.Str;
//evil sorcerer attack drains strength
Conan.Str = 0;
rather than:
//Conan hits someone
int damage = RollDie("2d6") + Conan.Str.Score;
//evil sorcerer attack drains strength
Conan.Str.Score = 0;
Now, the first case can be taken care of with an implicit conversion:
public static implicit operator int(Ability a)
{
return a.Score;
}
Can anybody help me with the reverse? Implicit conversion like this:
public static implicit operator Ability(int a)
{
return new Ability(){ Score = a };
}
will replace the entire attribute rather than just the score of the attribute—not the desired result...
The best you can do is increment the score by adding these methods to Ability.
public static Ability operator + (Ability lhs, int score)
{
lhs.Score += score;
return lhs;
}
public static Ability operator - (Ability lhs, int score)
{
lhs.Score -= score;
return lhs;
}
public static implicit operator int(Ability rhs)
{
return rhs.Score;
}
and using them like:
static void Main(string[] args)
{
Character evil = new Character(); //Str.Sccore=10
evil.Str += 10; //cast spell for Str.Sccore=20
evil.Str -= evil.Str; //death with Str.Sccore=0
}
First, keep your implicit conversion:
public static implicit operator Ability(int a)
{
return new Ability(){ Score = a };
}
Then in your character class: Add a private Ability attribute for str, and change the getter and the setter of the Str property as follows:
private Ability str;
public Ability Str
{
get
{
return this.str;
}
set
{
if (value.Name == "")
{
this.str.Score = value.Score;
}
else
{
this.str = value;
}
}
}
There you go :)
You could also use:
if(string.IsNullOrWhiteSpace(value.Name))
instead of
if (value.Name == "")
If you are compiling to .NET 4.0 version
EDIT: I gave you a solution that does exactly what you wanted to, but What ja72 wrote is also a good suggestion with operators + and -; you can add his solution to mine (or mine to him, whatever), it will work just fine. You will then be able to write:
Character Jax = new Character(); // Str.Score = 10
Character Conan = new Character(); // Str.Score = 10
Jax.Str = 2000; // Str.Score = 2000;
Conan.Str += 150; // Str.Score = 160
Another option is to replace the properties with delegates like this
public class Character
{
public Character()
{
...
}
#region Abilities
...
#endregion
public Func<int> Strength
{
get { return () => Str.Score; }
set { Str.Score = value(); }
}
}
and use it like this
Character evil = new Character(); //Str.Sccore=10
// fist spell hits
evil.Strength = () => 5; //set Str.Score=5
// second spell hits
evil.Strength = () => 0; //set Str.Score=5
if (evil.Strength() == 0)
{
// dead
}
Perhaps you could make Ability abstract and then derive new classes from Ability for each of the sub-classes: Strength, ...
The constructor for the Strength class would look something like this:
public Strength () : base ("Strength", "Str") { ...}
Now the ability properties off a Character would be strongly typed and the implicit conversions could turn a value like 5 into a Strength object with a value of 5. This would also prevent you from accidentally storing a Dexterity in a Strength property, for example.
[Assuming the name and abbreviations are in fact fixed for all objects of that type.]