How to fix Console Writing the name of the Class? [duplicate] - c#

This question already has answers here:
Class List Keeps Printing Out As Class Name In Console?
(4 answers)
Closed 3 years ago.
I am new to C# and I am struggling with this since hours and would appreciate your help.
I want to create a Polygon and Write down each position of the points.
Currently I have this:
-Class Point
class Point
{
private int x;
private int y;
public Point(int x2, int y2)
{
x = x2;
y = y2;
}
}
-Class Polygon
class Polygon
{
private Point[] Points;
public Polygon(params Point[] a)
{
Points = new Point[a.Length];
for (int i = 0; i < a.Length; i++)
{
Points[i] = a[i];
}
}
public Point this[int index]
{
get { return Points[index]; }
set { Points[index] = value;}
}
}
Now I have this in my main:
Polygon First= new Polygon(new Point(7,4), new Point(4,1), new Point(2, 1));
First[0] = new Point(3, 4);
Console.WriteLine("points of polygon ");
for (int i = 0; i < First.PointCounter; i++)
{
Console.WriteLine(First[i]);
}
But now instead of seeing each position of the Point after "points of polygon" I see this in my Console: https://imgur.com/Z5aVFMK
How it should look like: https://imgur.com/a/aFkdrEF
How it should look like: https://imgur.com/a/aFkdrEF

I added an override of ToString so that your Point class has the expected output when converted to string. An output like "x:3 y:4".
class Point
{
public int x { get; private set; }
public int y { get; private set; }
public Point(int x2, int y2)
{
x = x2;
y = y2;
}
public override string ToString()
{
return $"x:{x,-3} y:{y,-3}";
}
}
As it is now, it is a good candidate for becoming a struct instead of class.

C# is not "interpreted" like other languages, so the Console.WriteLine method won't guess what you're trying to have printed.
To give the result you're looking for, with your current code, you would have to provide public properties to your Point class:
public int X { get { return x;} set{ x = value;} }
public int Y { get { return y;} set{ y = value;} }
After which you could now access those properties in your for loop:
for (int i = 0; i < First.PointCounter; i++)
{
Console.WriteLine($"x:{First[i].X} y:{First[i].Y}");
}

Related

struct in C# doesn't work as expected

I'm working on a simple application and I'm a little confused. I have a simple struct Point with int x and int y. And I use it for Line
public class Line : Shape {
public Line() {
PointA = new Point(x: 0, y: 0);
PointB = new Point(x: 0, y: 0);
}
public Point PointA { get; set; }
public Point PointB { get; set; }
}
and somewhere
var line = new Line();
line.PointB = new Point(x: 4, y: 2);
Console.WriteLine($"Line start at {line.PointA.GetX()}:{line.PointA.GetY()}; end at {line.PointB.GetX()}:{line.PointB.GetY()}");
for (int i = 0; i < 10; i++) {
line.PointB.IncrementX();
line.PointB.IncrementY();
}
Console.WriteLine($"Line start at {line.PointA.GetX()}:{line.PointA.GetY()}; end at {line.PointB.GetX()}:{line.PointB.GetY()}");
Here need to increment x and y of Point but result doesn't change:
Line start at 0:0; end at 4:2
Line start at 0:0; end at 4:2
What I'm doing wrong? It seems strange. Are there some specific rules to use struct in C#. I know that this is a value type but I think it is a good for Point. All examples uses struct for Point. Please help?
Point:
public struct Point {
private int _x;
private int _y;
public Point(int x, int y)
: this() {
_x = x;
_y = y;
}
public void IncrementX() {
_x++;
}
public void IncrementY() {
_y++;
}
public int GetX() {
return _x;
}
public int GetY() {
return _y;
}
}
Struct is a value type. And it is passed by value (i.e. by creating copy of all fields) instead of passing reference to struct instance. So when you do
line.PointB.IncrementX()
When you call getter of PropertyB, it returns copy of Point which is stored at PropertyB backing field. And then you call increment on copy. Thus original value will stay unchanged.
Further reading: Value and Reference Types and especially Mutating Readonly Structs which says
mutable value types are evil. Try to always make value types
immutable.
What you can do if you want to actually move line point?
Change Point type to class. Then it will be passed by reference, and all methods will be called on original point which you store in Line.
Assign new (modified) point instance to line
I.e. you should store copy, change it and assign back
var point = line.PointB; // get copy
point.IncrementX(); // mutate copy
point.IncrementY();
line.PointB = point; // assign copy of copy
You can also make your Point struct immutable (the best thing you can do for value types):
public struct Point
{
public Point(int x, int y)
{
X = x;
Y = y;
}
public int X { get; }
public int Y { get; }
public Point IncrementX() => new Point(X + 1, Y);
public Point IncrementY() => new Point(X, Y + 1);
public Point Move(int dx, int dy) => new Point(X + dx, Y + dy);
}
And now changing location will look like
line.PointB = line.PointB.Move(1, 1);

2D-array as a class property - how to create them the C# way?

I am trying to create a class with a property that is a two-dimensional array. The array will hold various x,y coordinates on a grid (e.g. 0,1 or 3,7) and the size of the array is dependent on a class property called size.
How would you go about creating this array in C#? I have given my solution below, but having very little C# experience and coming from a Python background with some javascript knowledge, it feels like that there is a better solution to this problem.
Could one of you C# wizards enlighten me, please?
Thanks in advance for your help.
Here is my code:
public class Obj
{
int Size; // Defines length of array
int[,] Pos;
// constructor
public Obj(int size)
{
this.Size = size;
this.Pos = new int[size, 2];
}
public void set_coord(int index, int x, int y)
{
if (index >= this.Size) {
Console.WriteLine("Catch OutOfRangeException");
}
else
{
this.Pos[index, 0] = x;
this.Pos[index, 1] = y;
}
}
You could create a List instead of a class, and have an internal sub class to represent your points.
Like this
public class Obj{
int Size;
List<Point> Pos = new List<Point>();
public Obj(int size){
this.Size = size;
}
public set_coord(int index, int x, int y){
if(index >= this.Size){
Console.Writeline("Catch OutOfRangeException")
}else{
this.Pos.Add(new Point(x,y));
}
}
}
class Point{
int x = 0;
int y = 0;
public Point(int xCor, int yCor){
this.x = xCor;
this.y = yCor;
}
}
A struct is the ideal approach for this. A full blown class may not be necessary, but it depends.
https://msdn.microsoft.com/en-us/library/ah19swz4.aspx
public struct Coordinates
{
public int coordX;
public int coordY;
}
The property then in your class could be set like this:
var Obj = new Obj();
List<Coordinates> listOfCoords = new List<Coordinates>();
var coord = new Coordinates();
coord.X = 20;
coord.Y = 15
listOfCoords.Add(coord);
Obj.Pos = listOfCoords
Keep in mind that Structs cannot be inherited from, or inherit, other classes or structs, as well as a few other gotchas. If you need these features, or the data in your struct is prone to modification after it is created (in other words, the data is NOT immutable), consider a small class instead.
https://msdn.microsoft.com/en-us/library/0taef578.aspx

How to tie one variable to another

I have this bit of code:
Brick brick1= new Brick(parent.X - 1,parent.Y);
X & Y are integers,
Basiclly what i want to do is: when the x of the parent brick changes, the x of brick1 changes,where it dosnt matter the value of parent.X, brick1.X will always be equal to parent.X - 1
Is there an way of accomplishing this?
Assuming that Brick is not a struct you could do this. You could also do this through inheritance with a ChildBrick class but unless you need the added complication, at least in my mind, it is simpler to just allow Brick to have a parent that is a Brick and add a constructor for the parent. Then if you retrieve a value and it needs to be computed from the parent you just check for whether you have a parent and calculate accordingly.
class Brick
{
private Brick _parent;
private int _x;
private int _y;
Brick(Brick parent) {_parent = parent);}
Brick(int x, int y)
{
_x = x;
_y=y;
}
public int X
{
get
{
if (_parent != null) return _parent.X - 1;
return _x;
}
}
public int Y
{
get
{
if (_parent != null) return _parent.Y;
return _y;
}
}
}
Just make brick1 a derived class with a calculated read only property
public class childBrick: Brick
{
public new float X
{
get { return base.X - 1.0 }
private set { base.X = value; }
}
public static Brick Make( float x, float y)
{
return new childBrick
{
X = x;
Y = y;
}
}
}
use it like this
Brick brick1 = childBrick.Make(parent.X - 1,parent.Y);

Weird Behaviour when initiate a class

I'm working on a game, and I made all the building blocks. now I'm working on the game logic and rendering.
I have abstract Monster class and a class call GreenMonster that inherits from it.
Now the weird thing is, when I try to init a GreenMonster object.
when I do this:
private void initGreenMonsters()
{
for (int i = 0; i < greenMonsters.Length; i++)
{
greenMonsters[i] = new GreenMonster(new Point(0,40),new Size(40, 40));
}
}
every thing works like I planned and I can render the images on the form.
but when I try to init like that:
private void initGreenMonsters()
{
for (int i = 0; i < greenMonsters.Length; i++)
{
greenMonsters[i] = new GreenMonster();
greenMonsters[i].Position = new Point(0, 40);
greenMonsters[i].Size = new Size(40, 40);
}
}
I don't get any errors, and the app runs, but I can render the monsters.
This is the Monster class constructor and the Draw Method I use to draw a Monster:
public Monster(Point _startPosition,Size _size)
{
this.size = _size;
this.position = _startPosition;
}
public virtual void Draw(Graphics g)
{
Rectangle monsterRec = new Rectangle(position, size);
g.DrawImage(img, monsterRec);
}
and this is the GreenMonster class constructor:
public GreenMonster(Point _startPosition, Size _size)
: base(_startPosition, _size)
{
this.img = new Bitmap(SpaceInvadersGame.Properties.Resources.NormalMonster);
this.hp = 1;
this.speed = 1;
}
public GreenMonster()
{
this.img = new Bitmap(SpaceInvadersGame.Properties.Resources.NormalMonster);
this.hp = 1;
this.speed = 1;
}
the only thing that bothers me is, that when I'm looking at both ways I init the objects, it just looks the same..
I just can't find any different between in both of the ways.
someone have any idea how its different?
If you need more code so the question is more clear, I would be happy to add!
this is the Monster class and its properties
public abstract class Monster
{
protected Point position;
public Point Position { get { return position; } set { position = value; } }
protected Size size;
public Size Size { get { return size; } set { value = size; } }
public int speed;
protected Bitmap img;
protected int hp;
public int HP { get { return hp; } }
public void SetStartingPosition(int x, int y)
{
this.position = new Point(x, y);
}
public virtual void Draw(Graphics g)
{
Rectangle monsterRec = new Rectangle(position, size);
g.DrawImage(img, monsterRec);
}
}
You are setting your incoming value to the current size, rather than setting the current size to the incoming value, in the method below:
public Size Size { get { return size; } set { value = size; } }
should be
public Size Size { get { return size; } set { size = value; } }
Your code for Position looks OK though:
public Point Position { get { return position; } set { position = value; } }

overloading the indexer causes : "Minesweeper.Tile is a type but is used like a variable" error

I am making a minesweeper project in c# for fun and I wanted to store the new Tiles in a dictionary inside the Tile class so that when a Tile is initiated it is stored and can be accessed through Tile[coords] however I keep getting the above error. This is the code I am using for the Tile class (please don't comment on my conventions, I'm new to C# I'm a Java/Python programmer :p)
class Tile
{
private static Dictionary <Coords, Tile> tiles = new Dictionary <Coords, Tile> ();
public int numMinesAdjacents { get; set; }
public readonly bool isMine;
public readonly Coords position;
private Tile [] aAdjacents = new Tile [8];
public Tile(int x, int y, bool isMine = false)
{
this.isMine = isMine;
position = new Coords(x, y);
Tile[position] = this;
}
public void init()
{
calculateAdjacents();
calculateNumMinesAdjacent();
}
private void calculateAdjacents()
{
int i = 0;
for (int y = -1; y < 1; y++)
{
if ((position.y - y) < 0 || (position.y + y) > Math.Sqrt(Program.MAX_TILES)) continue;
for (int x = -1; x < 1; x++)
{
if ((position.x - x) < 0 || (position.x + x) > Math.Sqrt(Program.MAX_TILES)) continue;
aAdjacents [i] = Tile[position + new Coords(x, y)];
i++;
}
}
}
private void calculateNumMinesAdjacent()
{
int n = 0;
foreach (Tile pTile in aAdjacents)
{
if (pTile.isMine) n++;
}
numMinesAdjacents = n;
}
/*private static void add(Tile pTile)
{
tiles.Add(pTile.position, pTile);
}*/
public /*static - if I use static nothing is different*/ Tile this [Coords coords]
{
get { return tiles [coords]; }
}
}
if I call
Tile(0, 0);
Tile(0, 1);
and then
Tile[new Coords(0, 0)]
I get an error, I also get an error in the places in the class where Tile[] is used (constructor and calculateAdjacents) what is going wrong here?
Thanks,
Jamie
EDIT: Sorry I meant Tile[position] I was changing it back and mistyped. The problem is I overloaded this which should mean that Tile[coords] is legal even when called from another class
It's not clear what you expect this to mean:
Tile[this];
It's not a valid expression at the moment though.
C# doesn't support static indexers. For an instance indexer, you could use:
Tile tile = this[someCoordinate];
... although it's odd for an instance indexer to use a static member like this. It would be cleaner just to have a method:
public static Tile GetTile(Coords coords)
{
return tiles[coords];
}
Then you'd just call Tile.GetTile(...) elsewhere.
As a side-note, you should start following .NET naming conventions to make your code easier to understand. Also, I'd strongly recommend that you avoid public fields, even if they're read-only.

Categories