Exchanging variables between 2 classes - c#

Whenever I call the method Draw in Sprite, it won't draw it because X, Y, Width and Height are 0. :(
code:
class Sprite
{
protected int Y;// { get; set; }
protected int X;// { get; set; } { get; set; }
protected int Width;// { get; set; } { get; set; }
public int Height;// { get; set; } { get; set; }
protected Image image;// { get; set; } { get; set; }
public Sprite()
{
}
public void Draw(Graphics drawArea)
{
Image sImage = Image.FromFile("alien.jpg");
drawArea.Clear(Color.White);
drawArea.DrawImage(sImage, X, Y, Width, Height);
}
}
class User:Sprite
{
public User()
{
}
public User(int width, int height, int userWidth, int userHeight)
{
Sprite sprite = new Sprite();
Image UserImage = Image.FromFile("alien.jpg");
X = width;
Y = height;
Width = userWidth;
Height = userHeight;
image = UserImage;
}
}
ps: sprite.Draw is declared in another method in another class, but that all should work just fine.
Thanks for helping and probably saving me hours of time :)
Nick
EDIT
here is the subclass which gives the parameter and other stuff.
Alien mAlien;
User mUser;
protected int mLevel;
public gameLogic()
{
}
public gameLogic(int width, int height, int level)
{
mUser = new User(width / 2, height - 30, 30, 30);
mAlien = new Alien(width / 2, 5, 30, 30, "alien.jpg", 10 * level);
mLevel = level;
}
public void drawAll(Graphics drawArea)
{
Sprite sprite = new Sprite();
sprite.Draw(drawArea);
}
Im sorry for all these errors that'll probably occur, Im a new student :)

Try this:
public User(int width, int height, int userWidth, int userHeight)
{
Sprite sprite = new Sprite();
Image UserImage = Image.FromFile("alien.jpg");
sprite.X = width;
sprite.Y = height;
sprite.Width = userWidth;
sprite.Height = userHeight;
sprite.image = UserImage;
}
In order to access the fields of the sprite, you have to specify which Sprite object you are modifying. This is done by writing the name of the variable followed by .
EDIT: Just realized that there is another problem - your User class is inheriting from the Sprite class. Apparently your users are sprites, according to the comments, so you'll want to never instantiate a Sprite, and just use the User class instead:
class User:Sprite
{
public User(int width, int height, int userWidth, int userHeight)
{
Image UserImage = Image.FromFile("alien.jpg");
X = width;
Y = height;
Width = userWidth;
Height = userHeight;
image = UserImage;
}
}
Then instead of calling draw on a sprite in the other file, use the following:
User user = new User(x, y, width, height)
...
user.draw();
The key here is to make sure you are using new User... and not new Sprite - even if you are assigning to a Sprite variable e.g. Sprite s = new User(...);.
Then just make sure you call draw on the same object - the user.draw line. If you want to check that you're doing it right, try making Sprite abstract - abstract class Sprite - that way there will be compile errors if you try to instantiate Sprite instead of User.
EDIT 2: Ok, all you really need to do is change your calling code:
public void drawAll(Graphics drawArea)
{
mUser.draw(drawArea);
mAlien.draw(drawArea);
}

You are missing trailing '}' for both your classes, Sprite and User. Second you should call the base-Constructor in User's constructor:
public User(int width, int height, int userWidth, int userHeight)
: base(width, height, userWidth, userHeight, Image.FromFile("alien.jpg"))
{
}
Also you need to create a constructor for your base class which accepts these parameters.

Related

How to calculate area using Open closed principle C#

I am working with Open Closed principle of SOLID in C#. I have abstract class Shape which i want to used to calculate the area of different shapes. How to call areaCalculator class and how to pass different shapes. Here is my code.
public abstract class Shape
{
public abstract double Area();
}
public class Rectangle : Shape
{
public double Height { get; set; }
public double Width { get; set; }
public override double Area()
{
return Height * Width;
}
}
public class AreaCalculator
{
public double TotalArea(Shape[] shapes)
{
double area = 0;
foreach (var objShapes in shapes)
{
area += objShapes.Area();
}
return area;
}
}
I want to call areaCalculator class to calculate the area.
AreaCalculator _obj = new AreaCalculator();
Shape[] _shapes = new Shape[2];
var _result = _obj.TotalArea(_shapes);
Console.WriteLine(_result);
Console.ReadLine();
You need to create the rectangle objects and set their height and width for the calculation. If not the _shapes list is empty. Find below a sample of working code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShapesStacjOverflow {
public abstract class Shape {
public abstract double Area();
}
public class Rectangle : Shape {
public double Height { get; set; }
public double Width { get; set; }
public override double Area() {
return Height * Width;
}
}
public class AreaCalculator {
public double TotalArea(Shape[] shapes) {
double area = 0;
foreach (var objShapes in shapes) {
area += objShapes.Area();
}
return area;
}
}
class Program {
static void Main(string[] args) {
AreaCalculator _obj = new AreaCalculator();
Shape[] _shapes = new Shape[2];
Rectangle rectangle1 = new Rectangle {
Width = 2,
Height = 3
};
Rectangle rectangle2 = new Rectangle {
Width = 1,
Height = 1
};
_shapes[0] = rectangle1;
_shapes[1] = rectangle2;
var _result = _obj.TotalArea(_shapes);
Console.WriteLine(_result);
Console.ReadLine();
}
}
}
Returning 7 as a result.
If you want to create other child shapes, those should override the Area() method, so for each of the objects created in the list, the corresponding Area() method would be applied.
Hope that helps.

Linking instances of two classes together

Programming newbie here and I've been breaking my head over this for several hours now.
I can make a coordinate object but then I want to make a dot object that can access the coordinate fields from a Coordinate object. How do I "link" these two classes together? And do you have any recommendations for good YouTube videos that explain what I'm missing here? Thanks!
class Coordinate
{
public int X { get; private set; } = 0;
public int Y { get; private set; } = 0;
public Coordinate(int x, int y)
{
x = X;
y = Y;
}
}
class Dot
{
public string color { get; set; }
public Dot(string color, Dot dot)
{
this.Color = color;
}
}
class Program
{
static void Main(string[] args)
{
Coordinate coor1 = new Coordinate(2, 3);
Dot dot1 = new Dot("Blue", coor1);
}
Here is what you are searching for a "linking" your classes. In object-oriented programming this is called composition.
That way you can use functionality and data of Coordinate-instance inside your Dot class.
class Coordinate
{
public int X { get; private set; }
public int Y { get; private set; }
public Coordinate(int x, int y)
{
X = x;
Y = y;
}
}
class Dot
{
public Coordinate coord { get; private set; }
public string color { get; set; }
public Dot(string color, Coordinate coord)
{
this.color = color;
this.coord = coord;
}
}
class Program
{
static void Main(string[] args)
{
Coordinate coor1 = new Coordinate(2, 3);
Dot dot1 = new Dot("Blue", coor1);
Console.WriteLine(dot1.coord.X);
}
}
Note: I also fixed possible typo in Coordinate-constructor (setting X=x and Y=y..)

Is there a way to add additional values to the rectangle struct?

I want to add additional values to a rectangle. Like a "Name" string for example.
Something like this:
Rectangle MyRectangle = new Rectangle(Y, X, Width, Height, Name)
Is this possible?
There is two overload constructor function in Rectangle class.
public Rectangle(Point location, Size size);
public Rectangle(int x, int y, int width, int height);
But there isn't a constructor function parameter new Rectangle([int], [int], [int], [int], [string]) in Rectangle class.
You can try to use composite public Rectangle rect { get; set; } property in the class.
Then use constructor function to set Rectangle object and Name
public class CustomerRectangle
{
public Rectangle Rect { get; set; }
public string Name { get; set; }
public CustomerRectangle(int llx, int lly, int urx, int ury,string name)
{
Rect = new Rectangle(llx, lly, urx, ury);
Name = name;
}
}
then you can use
CustomerRectangle MyRectangle = new CustomerRectangle (Y, X, Width, Height, Name);
//MyRectangle.Name; use Name property
//MyRectangle.Rect; use Rectangle
I assume you are using a constructor from the System.Drawing namespace:
https://learn.microsoft.com/en-us/dotnet/api/system.drawing.rectangle?view=netframework-4.7.2
It is not possible to add an extra field to that structure. What you can do is create your own class or structure which does contain more .
public class NamedRectangle
{
public string Name { get; set; }
public double X { get; set; }
public double Y { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public NamedRectangle(double x, double y, double width, double height, string name)
{
Name = name;
X = x;
Y = y;
Width = width;
Height = height;
}
}
I've seen others have contributed good examples, but in case of Cannot inherit from sealed type error, following example might help you:
public class myRectangle
{
private Rectangle newRectangle = new Rectangle();
private string name;
public myRectangle Rectangle(Int32 Y, Int32 X, Int32 Height, Int32 Width, string name )
{
newRectangle.Y = Y;
newRectangle.X = X;
newRectangle.Height = Height;
newRectangle.Width = Width;
this.name = name;
return this;
}
}

returning actual Height and Width to wpf rectangle after dynamic change

I have an app with the main window which contains a rectangle and a button that leads to another window in which the user enters information. After entering info, user clicks on a button and it returns him to the main window and changes the size accordingly. What I am trying to achieve is to return the ActualHeight and ActualWidth to the rectangle if a user presses the button in the main window again, kind of a refresh of rectangle.
All the code is in the Main Window Button click event. If you need any specific information about the code, i will gladly give it to you.
private void buttonStart_Click(object sender, RoutedEventArgs e)
{
Questionnaire q = new Questionnaire();
q.ShowDialog();
var size = q.textBoxNumberOfEmployees.Text;
if (int.Parse(size) > 5 && int.Parse(size) < 15)
{
Rect1.Height = Rect1.ActualHeight - 10;
Rect1.Width = Rect1.ActualWidth - 5;
}
else if (int.Parse(size) > 15 && int.Parse(size) < 30)
{
Rect1.Height = Rect1.ActualHeight - 15;
Rect1.Width = Rect1.ActualWidth - 10;
}
else if (int.Parse(size) > 30 && int.Parse(size) < 100)
{
Rect1.Height = Rect1.ActualHeight - 30;
Rect1.Width = Rect1.ActualWidth - 15;
}
else
{
Rect1.Height = Rect1.ActualHeight;
Rect1.Width = Rect1.ActualWidth;
}
You can store the original height and width of rectangle in variables in form load. Use those variables to make rectangle to original size bebore opening new window in button click.
Following code goes at the top inside your form.
private int rect1width;
private int rect1height;
In your form__load you write this at the end.
rect1width = Rect1.ActualWidth;
rect1height = Rect1.ActualHeight;
In your button click code following code goes at top.
Rect1.Width = rect1width;
Rect1.Height = rect1height;
Here is some seemingly long code, but it uses an MVC type design pattern and compounds with the state pattern. The only thing really missing to make it true MVC is Observers and observable interfaces that would subscribe to the Questionnaire.
public interface RectangleState
{
int myHeight { get; set; }
int myWidth { get; set; }
}
public class RectangleModel
{
private static Rectangle Rect1;
public RectangleModel(Rectangle rect1 )
{
Rect1 = rect1;
}
private RectangleState state;
public RectangleState State
{
get
{
return state;
}
set
{
state = value;
ModifyState(value.myHeight, value.myWidth);
}
}
private void ModifyState(int Height, int Width)
{
Rect1.Height = Height;
Rect1.Width = Width;
}
}
public class SmallState : RectangleState
{
public int myHeight { get; set; } = 20;
public int myWidth { get; set; } = 80;
}
public class MediumState : RectangleState
{
public int myHeight { get; set; } = 25;
public int myWidth { get; set; } = 90;
}
public class LargeState : RectangleState
{
public int myHeight { get; set; } = 35;
public int myWidth { get; set; } = 120;
}
public class NormalState : RectangleState
{
public int myHeight { get; set; } = 30;
public int myWidth { get; set; } = 100;
}
Now all you need to do is plug in the conditions:
RectangleModel RM = new RectangleModel(myRectangle); // store this in your class as property;
int size = 0;
int.TryParse(q.textBoxNumberOfEmployees.Text, out size);
if (size > 5 && size < 15)
{
RM.State = new SmallState();
}
else if (size > 15 && size < 30)
{
RM.State = new MediumState();
}
else if (size > 30 && size < 100)
{
RM.State = new LargeState();
}
else
{
RM.State = new NormalState();
}
If later you decide you want to change the default values on any of these you can change them. If you wish to add a new Rectangle shape or size you can add it. If you wish to create an adapter to further modify the rectangle, you can do so. This is a nice pattern. I know the answer looks overdone, but I think you will find it works solidly and is quite flexible when plugged into the code that accesses your questionaire.

Creating multiple / multinode properties in class

I would like to understand and make my own classes in the way like the common rectangle:
Rectangle r1 = new Rectangle();
Size s = r1.Size;
int size = r1.Size.Width;
I don't want to use methods, just simple property values.
public partial class Rectangle
{
private Size _size;
public Size Size
{
get { return _size; }
set { _size = value; }
}
}
So how to create the Width, Height, etc. properties?
And if i would like to create longer chain? e.g.:
r1.Size.Width.InInches.Color.
etc.
Probably you'll find yourself saying: I knew it.
Class properties can be associations with other classes:
public class Size
{
public Size(double width, double height)
{
Width = width;
Height = height;
}
public double Width { get; }
public double Height { get; }
}
Now you'll be able to get rectangle's size as follows: rect1.Size.Width.
About providing the size unit, I wouldn't create an InInches property, but I would create an enumeration:
public enum Unit
{
Inch = 1,
Pixel
}
...and I would add a property to Size as follows:
public class Size
{
public Size(double width, double height, Unit unit)
{
Width = width;
Height = height;
Unit = unit;
}
public double Width { get; }
public double Height { get; }
public Unit Unit { get; }
}
...and if you need to perform conversions, you could easily implement them in Size too:
public class Size
{
public Size(double width, double height, Unit unit)
{
Width = width;
Height = height;
Unit = unit;
}
public double Width { get; }
public double Height { get; }
public Unit Unit { get; }
public Size ConvertTo(Unit unit)
{
Size convertedSize;
switch(unit)
{
case Unit.Inch:
// Calc here the conversion from current Size
// unit to inches, and return
// a new size
convertedSize = new Size(...);
break;
case Unit.Pixel:
// Calc here the conversion from current Size
// unit to pixels, and return
// a new size
convertedSize = new Size(...);
break;
default:
throw new NotSupportedException("Unit not supported yet");
break;
}
return convertedSize;
}
}
What you call chain is what in object-oriented programming is called composition.
Thus, you can associate Size with other class, and associate another class to the other one, and so on...

Categories

Resources