I'm working on a app on C# Visual Studio '13, and I just hit a brickwall - a newbie brickwall I bet. I have a class - lets say it's a car class. It isn't, but it's a decent example for this question.
Now, I'd like to create - I'm not sure this is the right terminology - templates, from which I'd like to create instances. These created instances will be stored in a List<Car> object.
Let's just say the car class has name, model year and mileage attributes. I'd like to be able to create a template, where I can call up a constructor to create a car with a preset name and model year, but a randomized mileage - and have a couple of different ones. Maybe use it in a constructor in such a way, that I have a few sets of presets - or templates - e.g. '99 BMW, '03 Merc and a '79 Lada. When I call the constructor, I'd like it to pick one of these templates, and add a random mileage.
The adding random mileage is not a problem. Matter of fact, there is no problem with building this other than the fact that for the life of me, I can't figure out how to do templates in a constructor.
One of the easiest solutions for some hardcoded, predefined instance values is the factory pattern. For the following Car class:
public class Car
{
public string Model { get; private set; }
public int Year { get; private set; }
public Color Color { get; private set; }
public int Mileage { get; private set; }
// ...
public Car(string model, int year, Color color, int mileage)
{
Model = model;
Year = year;
Color = color;
Mileage = mileage;
}
}
you can create CarFactory as suggested by Henk Holterman in his comment. For example:
public class CarFactory
{
public CarFactory()
{
random = new Random();
}
public Car CreateBMW99WithRandomMileage(Color color)
{
return new Car("BMW", 1999, color, random.Next());
}
public Car Create03BlackMerc(int mileage)
{
return new Car("Mercedes", 2003, Colors.Black, mileage);
}
public Car Create79Lada(Color color, int mileage)
{
return new Car("Lada", 1979, color, mileage);
}
// ...
private Random random;
}
As you can see you have many possibilities when choosing which attributes to fix, which should be random, and which can be left out as configurable.
Another, similar, pattern you can employ here is the prototype pattern.
Here is how you can combine these two patterns to create a random car:
public class CarFactory
{
public CarFactory()
{
random = new Random();
black99BMW = new Car("BMW", 1999, Colors.Black, 0);
black03Merc = new Car("Mercedes", 2003, Colors.Black, 0);
black79Lada = new Car("Lada", 1979, Colors.Black, 0);
// ...
allCars = new Car[] { black99BMW, black03Merc, black79Lada };
}
public Car CreateBMW99WithRandomMileage(Color color)
{
return black99BMW.Clone(color, random.Next());
}
public Car Create03BlackMerc(int mileage)
{
return black03Merc.Clone(Colors.Black, random.Next());
}
public Car Create79Lada(Color color, int mileage)
{
return black79Lada.Clone(color, mileage);
}
public Car CreateRandomCar()
{
var index = random.Next(allCars.Length);
Color color = // pick random color
int mileage = random.Next();
return allCars[index].Clone(color, mileage);
}
private Car black99BMW;
private Car black03Merc;
private Car black79Lada;
private Car[] allCars;
}
Possibilities are countless - this is just a simple example, and does not necessary fit your scenario best. However, usually and especially for beginners, it is better to implement something to see how does it work, to see its advantages and flaws with your own eyes, and then try to improve it.
Related
I am sorry if the question isn't too clear, but I did'nt know
how else to phrase it.
I am attempting to create a card game which contains the following classes
The suits are Red, Blue, Green, and Yellow and depending on the suit
the value is the product of the cards number and the suit multiplier
red = 1
blue = 2
green = 3
yellow = 4
abstract class Card;
public class Deck
{
private List<Card> deckList;
}
public class RedCard : Card, suit
{
private int number;
public int Getvalue()
{
return number;
}
}
interface suit
{
int GetValue();
}
is there a way to encapsulate the Card subclasses so
that the Deck constructor does not need to know what
kind of cards can be added to the deck.
The aim is to make sure that the Deck class does not need
to be altered if I add another suit/card subclass in the future
If you think about this in real world terms, you have a Deck that has instances of Card in it. The types of attributes or physical properties of the cards in the deck are all the same, they all have a Suit and a Number and in your business case they all have a Value as well. From a structural point of view they are identical, all that changes are the values for each of the properties.
If every Card has the same attributes, and the same behaviours, then there is no reason to create further sub-classes or even interfaces of these Cards.
In software design, we use inheritance and composition (Interfaces) to add attributes and behaviours to the base implementation; or to change existing behaviours. It is an anti-pattern to inherit from a Card just to change the values of the attributes and doing so can elad to confusion down the track. You really need to separate the concept of structure vs content. If the structure and beahviour
On top of this you have defined a list of suits and have declared that they have specific integer values, in C# we can encapsulate such fixed lists using an enum.
public enum Suit : int
{
Red = 1,
Blue = 2,
Green = 3,
Yellow = 4
}
public class Deck
{
private List<Card> deckList;
}
public class Card
{
public Suit Suit { get; private set; }
public int Number { get; private set; }
public Card (Suit suit, int number)
{
this.Suit = suit;
this.Number = number;
}
public int Value { get { return (int)Suit * Number; } }
}
We can now create a method to generate a deck of cards for us, based on some fixed criteria, I'll call this from the constructor for this demo:
public class Deck
{
private const int LENGTH_OF_SUIT = 10;
private List<Card> deckList = new List<Card>();
public Deck()
{
BuildDeck();
}
private void BuildDeck()
{
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
for(int number = 1 ; number <= LENGTH_OF_SUIT; number ++)
{
deckList.Add(new Card(suit, number));
}
}
}
}
This simple structure is one way to encapsulates the requirements listed in the original post, you can play with this here: https://dotnetfiddle.net/BnhGGG
If the number of suits can change at runtime, then an enum is NOT a good fit, then you would need a class to represent the Suit:
public class Suit
{
public string Name { get;set; }
public int Value { get;set; }
}
But note that the Card class doesn't need to change much:
public class Card
{
public Suit Suit { get; private set; }
public int Number { get; private set; }
public Card (Suit suit, int number)
{
this.Suit = suit;
this.Number = number;
}
public int Value { get { return Suit.Value * Number; } }
}
To build the deck we would need additional information, like what suits to build:
public class Deck
{
private const int LENGTH_OF_SUIT = 10;
private List<Card> deckList = new List<Card>();
public Deck(Suit[] suits)
{
BuildDeck(suits);
}
private void BuildDeck(Suit[] suits)
{
foreach (Suit suit in suits)
{
for(int number = 1 ; number <= LENGTH_OF_SUIT; number ++)
{
deckList.Add(new Card(suit, number));
}
}
}
}
Finally, if we need to get all the Cards of a specific Suit we could add a method that does this for us to the Deck
public List<Card> GetCardsOfSuit(Suit suit)
{
return deckList.Where(x => x.Suit == suit).ToList();
}
There are many other ways to implement the same or similar logic, this is but one example.
You may have started off in your learning using Vehicle and then created sub classes for Car and MotorCycle. Often the example is that Vehicle has a property for Wheels and the Car has 4 Wheels and the MotorCycle has 2.
That model alone is flawed as a learning tool, it can lead you to assume that the reason behind subclassing was to change the value of a fixed property. This example has been overly simplified, fundamentally there are other attributes and behaviours that give us real world, anc conceptual reasons to classify these objects into their own class definition.
It was an example devised because in the real world classification of Cars and MotorCycles separately is very logical and it is easy to comprehend that they are both types of Vehicles.
If we start to talk about Color of a Vehicle, then we are closer to the concept of a Suit of a Card. you can have a Red Car and a Red MotorCycle, but the color is only one of the attributes of that physical object, we do not now create a new class definition to represent RedCar and RedMotorCycle... Red is simply the Value of the Color property.
A better inheritance example
The example of an Animal that has sub classes of Bird and Fish makes it easier to show the similarities (what is inherited) and the differences in the types of attributes and beahviours encapsulated by the class definitions:
We can have a count of eyes for all animals, and some type of animals by definition will only have a fixed number of eyes. So we can use eyes to show overriding fixed values. But it doesn't make sense to have a property on Animal to store the number of wings, because that is part of the definition that makes an animal a bird and no other type of animal will have wings at all. We wouldn't store the fact that a bird has any number of wings because All birds have 2 wings by definition. We would not normally even bother to record that fact in our model, because it is a constant value and not likely to be of any use to us. But Flight is a behaviour common to birds, but not all birds can fly! Now we can start to talk about behaviours.
In this model we will capture 2 types of real world behaviours as properties, we wont specifically add any c# behaviours in these definitions, but it is a better tool to enable new developers to relate these abstract c# concepts to the real world.
public class Animal
{
public string Name { get; set; }
/// <summary>Number of Eyes</summary>
/// <remarks>Not all animals have eyes, use 0 to represent no eyes</remarks>
public virtual int Eyes { get; set; };
public string override ToString()
{
return $"{Name} - Eyes:{Eyes}";
}
}
/// <summary>Vertebrates have a spine, but are also `Chordates`, they have "Camera Eyes" that are specifically 2 eyes using lenses to focus an image.</summary>
/// <remarks>http://www.madsci.org/posts/archives/1999-02/920061344.Ev.r.html#:~:text=This%20is%20the%20same%20process%20at%20work%20in,they%20retained%20the%20trait%20from%20a%20common%20ancestor.</remarks>
public class Vertebrate : Animal
{
public override sealed int Eyes { get { return 2; } set{/*Force only 2 eyes, ignore setter*/} }
}
public class Bird : Vertebrate
{
/// <summary>Not all birds can fly: penguins, emus and ostriches are some examples </summary>
public bool CanFly { get;set; }
public override string ToString()
{
return base.ToString() + $", CanFly :{CanFly}";
}
}
public class Fish : Vertebrate
{
/// <summary>Fun fact, not all fish can swim backwards! Sharks is one example</summary>
public bool CanSwimBackwards { get;set; }
public override string ToString()
{
return base.ToString() + $", CanSwimBackwards :{CanSwimBackwards}";
}
}
What we've shown here is a simple inheritance model that shows different properties being added to the base class we can use these to add some Animals to a list:
List<Animal> myFavouriteAnimals = new List<Animal>();
myFavouriteAnimals.Add(new Animal { Name = "Worm", Eyes = 0 });
myFavouriteAnimals.Add(new Bird { Name = "Hawk", CanFly = true; });
myFavouriteAnimals.Add(new Bird { Name = "Penguin", CanFly = false; });
myFavouriteAnimals.Add(new Fish { Name = "Eel", CanSwimBackwards = true; });
myFavouriteAnimals.Add(new Fish { Name = "Shark", CanSwimBackwards = false; });
foreach(var animal in myFavouriteAnimals)
{
Console.WriteLine(animal.ToString());
}
This would produce the following result:
Try it out here: https://dotnetfiddle.net/n6jgHO
Worm - Eyes:0
Hawk - Eyes:2, CanFly: True
Penguin - Eyes:2, CanFly: False
Eel - Eyes:2, CanSwimBackwards: True
Shark - Eyes:2, CanSwimBackwards: False
There's a little bit of syntactic sugar in that example but hopefully it helps to explain better scenarios for using inheritance other than just changing the value of an attribute defined in the base class.
I am currently making a simple console based RPG dungeon game, I am still fairly new to C#, I took a visual basic course in school, and I have played around with unity for about a month.
My problem is, that I am programming the first battle that the player will encounter. I have constructed a few weapons, and I want to be able to call the persons current weapon with a separate string, for example, My current weapon is the dagger, or the object wp1, I want my "weapon" to be attached to wp1 in some way, so that I can do something like,
Console.WriteLine("Damage: " + weapon.dmg); rather than hardcoding wp1.dmg, so that later in the game making process, when the player has the opportunity to purchase a better weapon, I can do it with variables, for example, the player now has the shortsword (wp2)
private string weapon = "wp2";
...
Console.WriteLine("Damage: " + weapon.dmg);
I have tried to simply put,
String weapon = wp1;
then call weapon.dmg, but this doesn't work because it thinks i'm trying to call
weapon.dmg, and not wp1.dmg
//players base damage
int damage = 0;
//players strength attribute
int strength = 0;
//weapon constructor
class wp
{
public int dmg;
public int cost;
public string name;
public wp(int d, int c, string n)
{
dmg = d;
cost = c;
name = n;
}
}
//three weapons that are constructed
wp wp1 = new wp(1, 25, "dg");
wp wp2 = new wp(3, 100, "ss");
wp wp3 = new wp(5, 250, "ls");
//the current weapon string
public string weapon = "wp1";
void attack()
{
//calculates damage based off of the players damage, strength, and weapon
int newDamage = damage * strength + (weapon.dmg);
}
Expected result:
the program should use the player's current weapon's damage value
Actual result, the program tries to find the dmg value of the weapon, but that is not possible because "weapon" is just a string, so it throws an error
As I said in a comment above, get into good habits now, as a beginner and you won't have to break those habits later. Let's see how we might design your system. Start off with a well-designed class hierarchy. Let's say we have three kinds of weapons: swords, daggers, and clubs. The stuff they have in common goes into an abstract base class:
abstract class Weapon
{
What do they have in common? Damage, cost, and a name. So make abstract, read-only properties for those:
public abstract int Damage { get; }
public abstract decimal Cost { get; }
public abstract string Name { get; }
}
Now make some derived classes. Are you planning on extending them further? If not, seal them:
sealed class Sword : Weapon
{
public override int Damage => 10;
public override decimal Cost => 12.5m;
public override string Name => "normal sword";
}
And so on.
Now do the same for player. Let's say that we can change a player's weapon, but not their name. So Name should be a read-only property, and Weapon should be a read-write property:
sealed class Player
{
public string Name { get; private set; }
public Weapon Weapon { get; set; }
public int Strength { get; private set; }
public int BaseDamage { get; private set; }
public Player(string name, Weapon weapon, int strength, int baseDamage)
{
this.Name = name;
this.Weapon = weapon;
this.Strength = strength;
this.BaseDamage = baseDamage;
}
}
Now we can make some weapons:
Weapon weapon1 = new Sword();
Weapon weapon2 = new Dagger();
Weapon weapon3 = new Club();
Player fighter = new Player("Bob", weapon3, 5, 10);
Or, better:
var weapons = new List<Weapon> { new Sword(), new Dagger(), new Club() };
// weapons is indexed 0, 1, 2.
Player fighter = new Player("Bob", weapons[2], 5, 10);
And now if you have a Player in hand:
static void Attack(Player p)
{
int damage = p.BaseDamage * p.Strength + p.Weapon.Damage;
string text = $"Player {p.Name} attacks with {p.Weapon.Name}";
No strings for referencing objects! Do not use strings for anything except text. References to objects should be references to objects, not strings.
Now, for advanced players only, there are times when you do need to look something up by a string. The way you do that in C# is:
var d = new Dictionary<string, Weapon> {
{ "weapon1", new Sword() },
{ "weapon2", new Dagger() },
{ "weapon3", new Club() }
};
Weapon w = d["weapon1"]; // w is a Sword.
But do not do this by default. That's not the normal way to refer to something in C#.
one way to achieve what you want:
if(weapon=="wp1")
//use wp1 object here.
But a Better way would be to put your 3 wp's into a list or array (since you literally hardcoded a list of 3 objects). Then wp1 would be at
wpArray[0];
New here, I've been learning c# for about a month.
Anyway, I've been searching StackOverflow for a couple of days now and couldn't find a specific answer to my problem...
//Here's my Class
public class Guy
{
public static int ID { get; set; }
public static int LifeExpectancy { get; set; }
public static bool Living { get; set; }
public Guy(int id, int lifeExpectancy, bool living)
{
ID = id;
LifeExpectancy = lifeExpectancy;
Living = living;
}
}
What I'm trying to do is create a specific number of "someGuy" objects to then put them into a public list using this method...
public static List<Guy> Guys = new List<Guy>();
public static void makeSomeGuys(int howManyGuys)
{
for (int i = 0, i <= howManyGuys; i++)
{
int id = i;
int lifeExpectancy = 80;
bool alive = true;
Guys.Add(New Guy(id, lifeExpectancy, alive));
Console.WriteLine("Made a new Guy {0}", id);
}
return;
}
Questions in order of importance:
How do I access a specific object as well as its parameters? (Accessing from the list "Guys".)
How do I access an object from this list in another class? (Not that I absolutely need to, I'm curious)
Can I search for an object in a list by using its parameters? (As opposed to doing something like... humanPopulation[number])
Should I create a new list for objects that have had their parameters modified? (As opposed to leaving it in the original list)
Is it possible to remove items from a list? (Just in general, is that a thing people do? if so, why?)
I really only need the first question answered. The rest of them are just a bonus. Thanks!
First you need to remove the static modifier from the properties of the Guy class, i.e.:
public int ID { get; set; }
public int LifeExpectancy { get; set; }
public bool Living { get; set; }
because static causes the property to be an attribute of the class itself, rather than the instances of the class (the individual 'guys').
To access life expectancy of the first guy (the zeroth):
Console.WriteLine(Guys[0].LifeExpectancy);
To access life expectancy of the fifth guy:
Console.WriteLine(Guys[4].LifeExpectancy);
using System;
using System.Collections.Generic;
using System.Linq;
namespace test
{
public class Guy
{
private int m_ID;
private int m_LifeExpectancy;
private bool m_Living;
public int ID
{
get { return m_ID; }
set { m_ID = value; }
}
public int LifeExpectancy
{
get { return m_LifeExpectancy; }
set { m_LifeExpectancy = value; }
}
public bool Living
{
get { return m_Living; }
set { m_Living = value; }
}
public Guy(int id, int lifeExpectancy, bool living)
{
ID = id;
LifeExpectancy = lifeExpectancy;
Living = living;
}
}
public class MyFactory
{
public IList<Guy> MakeSomeGuys(int howManyGuys)
{
IList<Guy> localGuys = new List<Guy>();
for (int i = 0; i <= howManyGuys; i++)
{
int id = i;
int lifeExpectancy = 80;
bool alive = true;
localGuys.Add(new Guy(id, lifeExpectancy, alive));
Console.WriteLine("Made a new Guy {0}", id);
}
return localGuys;
}
}
public class program
{
public void Main()
{
MyFactory mf = new MyFactory();
IList<Guy> guys = mf.MakeSomeGuys(5);
//How do I access a specific object as well as its parameters? (Accessing from the list "Guys".)
int GetFirstGuyId = guys.FirstOrDefault().ID; //LEARN LINQ
//How do I access an object from this list in another class? (Not that I absolutely need to, I'm curious)
//you need to learn about object oriented encapsulation for better understanding.
//Can I search for an object in a list by using its parameters? (As opposed to doing something like...humanPopulation[number])
Guy guyById = guys.Where(g => g.ID == 5).FirstOrDefault(); // returns the first match (need to learn lambda expression)
//Should I create a new list for objects that have had their parameters modified? (As opposed to leaving it in the original list)
// you need to learn about passing values by value / reference (by reference you already changing the original!).
//Is it possible to remove items from a list? (Just in general, is that a thing people do? if so, why?)
//yes
guys.Remove(guyById);
}
}
}
You're likely new to C# and OO programming, so I've included some good links in this answer.
Regarding question 1 only:
Firstly, your Guy class properties aren't properly encapsulated. Make sure you properly scope the ID, LifeExpectancy and Living properties like shown in this article.
If you'd like to access a specific item, that is, a Guy with a particular ID, you'd be better off using an associative container like Dictionary.
If you're happy with the List container, you need to use the Find method on Guys as shown in the example at the link. You'll notice the term Predicate in the documentation, this link will elaborate.
If I have a class, let's say Car.
class Car {
private Color m_Color;
private int m_Passengers;
}
Now, when I have this class at this state, I'm implementing this on X number of places in my software. Later on, my boss says he also want to store the max speed of the car. By all means, he is a nice guy and should have his property added.
class Car {
private Color m_Color;
private int m_Passengers;
private int m_MaxSpeed;
}
With this workflow, we might have something like this after a while
class Car {
private Color m_Color;
private int m_Passengers;
private int m_MaxSpeed;
private int m_Year;
private List<Seats> m_Seats;
private DateTime m_LatestCHeckup;
private double m_GasUsage;
}
Which is ok, but the 1st and 2nd version of the class is already implemented with fewer properties. How can I make sure, that if I add a property on a object that property must be used on all other objects initiated from the same class?
EDIT:
To clear it up.
I use this for my first car:
Car c = new Car();
c.m_Color = Color.White;
c.m_Passengers = 4;
and this for my 2nd car:
Car c2 = new Car();
c2.m_Color = Color.White;
c2.m_Passengers = 4;
c2.m_MaxSpeed=200;
and 3rd car
Car c3 = new Car();
c3.m_Color = Color.Green;
c3.m_Passengers = 8;
c3.m_MaxSpeed=180;
c3.m_Year = 2000;
c3.m_Seats = mySeatList;
c3.m_LatestCheckup = Datetime.Now;
c3.m_GasUsage=1.8;
I want to make sure that GasUsage is added on c and c2 when I've added it to the class. But c and c2 was created long time ago when GasUsage didnt exist. How do I prevent an object to not have all properties used? I might have one class, but 2000 objects.
The reason I want this behaviour is because I might loop through all the car objects and calculate for example how much gas they've used. Or similiar. If not all objects have a value in GasUsage that calc would fail.
If you have required properties that need to be initialised you should declare them in the constructor. Any optional values can be made into properties.
If you add any required properties to your Car class you should add them to the constructor, then the compilation will fail until previously-created values are fixed.
From your comment it looks like you want to add an interface with all the declared properties, then make them all constructor parameters in your implementing class:
public interface ICar {
Color Color { get; }
int Passengers { get; }
...
double GasUsage { get; }
}
class Car : ICar {
public Car(Color color, int passengers, int maxSpeed, ..., double gasUsage) {
this.m_Color = color;
this.m_Passengers = passengers;
...
this.m_GasUsage
}
private Color m_Color;
private int m_Passengers;
}
The initialization of the class instances could also be done with an constructor that demands all properties; all instatiations would then become syntactically incorrect as soon as a new property is added.
Assuming that 'Property must be used' means that you expect the instantiated objects to set a value for each of the new properties then you either change the constructor to require the new properties, set a default value for the new properties or raise an exception if a method on the object is called that requires a value to be set.
First version of the car class:
class Car
{
public Car(Color mColor, int mPassengers)
{
m_Color = mColor;
m_Passengers = mPassengers;
}
private Color m_Color;
private int m_Passengers;
}
Second version of the car class with constructor that has default value:
class Car
{
public Car(Color mColor, int mPassengers, int mMaxSpeed = 130)
{
m_Color = mColor;
m_Passengers = mPassengers;
m_MaxSpeed = mMaxSpeed;
}
private Color m_Color;
private int m_Passengers;
private int m_MaxSpeed;
}
greetings, im am new to programming and at the moment developing a clone of the game battleships. i need to implement a fleet of 5 ships. this is what i have done so far:
class Cell holds the status of a table cell:
public class Cell
{
// class for holding cell status information
public enum cellState
{
WATER,
SCAN,
SHIPUNIT,
SHOT,
HIT
}
public Cell()
{
currentCell = cellState.WATER;
}
public Cell(cellState CellState)
{
currentCell = CellState;
}
public cellState currentCell { get; set; }
}
class GridUnit holds table cell info:
public class GridUnit
{
public GridUnit()
{
Column = 0;
Row = 0;
}
public GridUnit(int column, int row)
{
Column = column;
Row = row;
}
public int Column { get; set; }
public int Row { get; set; }
}
finally class Shipunit contains both the above classes and acts as a wrapper for state info of an individual cell:
public class ShipUnit
{
public GridUnit gridUnit = new GridUnit();
public Cell cell = new Cell(Cell.cellState.SHIPUNIT);
}
at the moment i am thinking about implementing the fleet info in a Jagged Array like this:
ShipUnit[][] Fleet = new ShipUnit[][]
{
new ShipUnit[] {ShipUnit,ShipUnit,ShipUnit,ShipUnit,ShipUnit},
new ShipUnit[] {ShipUnit,ShipUnit,ShipUnit,ShipUnit},
new ShipUnit[] {ShipUnit,ShipUnit,ShipUnit}
new ShipUnit[] {ShipUnit,ShipUnit,ShipUnit}
new ShipUnit[] {ShipUnit,ShipUnit}
};
i realize the last bit of code does not work. it is only for presenting the idea.
but the problem being i need a field that states what type of ship each line of jagged array represent and i dont think it is practical to state this info in every cell information.
so i would like some ideas of implementation of this issue from you.
thank you.
class Ship
{
ShipUnit[] shipUnits;
string type;
public Ship(int length, string type)
{
shipUnits = new ShipUnit[length];
this.type = type;
}
}
Ship[] fleet = new Ship[5];
fleet[0] = new Ship(5, "Carrier");
fleet[1] = new Ship(4, "Battleship");
fleet[2] = new Ship(3, "Submarine");
fleet[3] = new Ship(3, "Something else");
fleet[4] = new Ship(2, "Destroyer");
I think I would define an owning Grid class, the holds all of the GridUnits. Then this Grid would also hold a List. A Ship would just have properties like size, orientation, BowCell. When adding a ship to the grid, the Grid could set the status of the units accordingly.
This way, you can have usefull methods on the ship level like IsSunk(), OccupiesUnit(), etc...
Why don't you create something like this
class Ship
{
public ShipUnits[] _SUParts;
public String _strType;
public Ship(String styType, int NbPart)
{
_SUParts = new ShipUnit[length];
_strType = strType;
}
}
that being said, I would not put all members public. I'de use Getter/Setter to change the values
I assumed by type you also mean the name of the ship (destroyer,etc.)
How many types of ships are there. Is that fixed or variable at runtime?
If it is fixed and not too many, you should probably just use separate arrays for each. If they are variable AND you have only one array for each type, you could use a generic dictionary (of enumShipUnitType, ShipUnit[]).
You can then iterate over the dictionary by getting the KeyValuePair from it like so.
For Each kvp As KeyValuePair(Of enumShipUnitType, ShipUnit[]) In m_dictShipUnits
For each oShipUnit as Shipunit in kvp.Value
'Do whatever
Next
Next
class Ship {
public Size Size { get; set; }
public Orientation Orientation { get; set; }
public Point Position { get; set; }
public Boolean Sunk { get; set; }
public String Name { get; set; }
[...]
}
Inherit from Ship and create sub classes like Battleship, Cruiser, etc for the different ships. Add a "IsHit(Point shot)" method that compares Size, Orientation, Position and the shot position (the Rectangle class has many nice functions for that).
class Grid {
private Size size = new Size(10, 10);
private List<Ship> ships = new List<Ship>();
private List<Point> shots;
[...]
}
Create two grids (one for each player), add a shoot method that calls IsHit for every Ship and then adds the shot to shots. After each move if every point of a ship is hit (is in shots) and set the ship to Sunk if all are hit.