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.
Related
In Haskell you can create a new datatype for example as follows:
Player = Player1 | Player2
And further in your code you can check whether it's Player1 or Player2 by just typing Player1 and not some strange with like "Player1" that it has to be a String or check with an integer.
Is something similar possible in C#?
I can only think of:
class Player
{
public int CurrentPlayer { get; private set; }
public Player(int plyr)
{
CurrentPlayer = plyr;
}
}
But now I can't check with just thisplayer = Player1 (if thisplayer is a Player).
Eventually this sort of means: How can you create your own object that can only have an already defined finite amount of values, for example like Bools?
Use Enums:
using System;
public class Program
{
private enum Player { PlayerOne, PlayerTwo }
public static void Main()
{
Player player = Player.PlayerTwo; // Change me between Player.PlayerOne and Player.PlayerTwo to see the output change.
switch(player)
{
case Player.PlayerOne:
//this will get executed
Console.WriteLine("Player is Player One!");
//do stuff
break;
case Player.PlayerTwo:
//this will not get executed
Console.WriteLine("Player is Player Two!");
//do stuff
break;
default:
//this will not get executed
break;
}
}
}
Output:
Player is Player Two!
See for yourself on .NET Fiddle
Enums are a way to create a somewhat-strongly-typed set of aliases for integers. However, you can always cast an integer (of whatever type you specified for your enum, by default int) to the enum type, so you have to trust the code to not do that (which might be acceptable for an internal enum type). Additionally, you can't add any additional information to the enum value itself; any time you interpret the value, you have to use a switch or similar construct.
If you want to actually have a class with properties and such, but want to restrict the number of instances of that class, you can extend the singleton pattern like this:
sealed class Player
{
// Properties that a Player object has, an improvement over using an enum
// which don't allow you to specify properties.
public int Number { get; }
public bool IsHost { get; }
// This constructor is private, so only the code inside the Player class may create a Player object
// (notwithstanding reflection, etc., which are outside the rules of static typing).
private Player(int number, bool isHost)
{
Number = number;
IsHost = isHost;
}
// Static properties provide singleton instances of Player for each player number.
public static Player One { get; } = new Player(1, true);
public static Player Two { get; } = new Player(2, false);
public static Player Three { get; } = new Player(3, false);
public static Player Four { get; } = new Player(4, false);
}
And then use it like this:
void Main()
{
SomethingThatTakesPlayer(Player.Three);
}
void SomethingThatTakesPlayer(Player p)
{
Console.WriteLine($"Player #{p.Number} is the host? {p.IsHost}");
}
Given multiple instances of the same class that have different properties of a common emum, how can I create a dictionary with the keys of the given enum that will only allow a class that contains the enum value matching that key? For example, given the following code:
public enum Slot {Head, Torso, Legs}
public class Armor
{
Slot slot;
}
How could I create a dictionary that given a key of Slot.Torso will only allow a value that is an Armor class with a slot property of Slot.Torso.
If not a dictionary, is there any other way to express this in C#?
Thanks
I'm assuming you're looking for compile time safety. Therefore, I suggest using generics to solve this problem.
Define a base class for your Slot types and implementations thereof:
public abstract class Slot { }
public sealed class Head : Slot { }
public sealed class Torso : Slot { }
public sealed class Legs : Slot { }
Your Armor implementation could then look something like this:
public abstract class Armor { }
public sealed class Armor<TSlot> : Armor
where TSlot : Slot, new()
{
public TSlot Slot { get; }
public Armor() => Slot = new TSlot();
}
The relevant bit is that you only allow for generic instances being created with a specific type of slot. The new() constraint was only added to keep my sample code short.
Now you're ready to create your restrictive and compile time safe implementation of a dictionary for Armor instances using any Slot as key:
public sealed class SafeDictionary
{
private readonly Dictionary<Slot, Armor> _dictionary = new Dictionary<Slot, Armor>();
public Armor this[Slot slot] => _dictionary[slot];
public void Add<TSlot>(TSlot slot, Armor<TSlot> armor)
where TSlot : Slot, new()
{
_dictionary.Add(slot, armor);
}
}
Usage is free with regard to what key value pairs you add:
var head = new Armor<Head>();
var torso = new Armor<Torso>();
var torsoKey = new Torso();
var dictionary = new SafeDictionary();
dictionary.Add(head.Slot, head);
dictionary.Add(torsoKey, torso);
Console.WriteLine(torso == dictionary[torsoKey]);
// Do not compile:
// dictionary.Add(torsoKey, head);
// dictionary.Add<Torso>(torsoKey, head);
This allows you to use any number of keys (Slots) with any number of values (Armors). As your requirement it is not possible to add an Armor instance with a Head slot using a Torso key. (And any other incompatible combination).
The price you pay is the need of one marker interface (Slot, here as abstract class) and in this example an empty implementation of Armor. If you'd like to regain the Slot property on Armor it can be done by adding an interface IArmor. There would also be options to restrict the Head, Torso and Legs instances to singletons to come closer to your example of using enums, but that's out of scope here.
I hope the above solution gives you enough material to solve your problem and develop the solution that best fits your needs.
Possible solution:
public enum Slot { Head, Torso, Legs }
public interface IArmor
{
Slot SlotType { get; }
}
public class Torso : IArmor
{
public Slot SlotType { get => Slot.Torso; }
}
public class Slots
{
private Dictionary<Slot, IArmor> _slots { get; set; } = new Dictionary<Slot, IArmor>();
public void Add(Slot slot, IArmor slotClass)
{
if (slot == slotClass.SlotType)
{
_slots.Add(slot, slotClass);
}
else
{
throw new Exception("Invalid type.");
}
}
}
And instance like:
var slots = new Slots();
slots.Add(Slot.Torso, new Torso());
Create an enum with the class names you want to whitelist. Then use reflection to create an instance of those and compare their type with the type of the property. Your property can be of type object and then you may either cast it to the type of class being tested, or check it's current type.
Something along those lines:
public enum WhitelistedTypes
{
Head = 1,
Torso = 2,
Legs = 3,
}
var armorInstance = new Armor();
var asm = typeof(Armor).Assembly;
foreach (var item in Enum.GetValues(typeof(WhitelistedTypes)))
{
var typeName = ((WhitelistedTypes)item).ToString();
var objectType = typeof(Armor).Assembly.CreateInstance("SlotNamespace." + typeName).GetType();
if(armorInstance.Slot.GetType() == objectType)
{
//Do something
}
}
In writing an insurance premium calculator the basic scheme is as follows: Points are assigned to a predetermined number of attributes, such as car-value, num-incidents-in-past, years-experience-driving etc. Hene, if car worth is $3800, that lies within the 3001 to 4000 range which warrants 30 points in the premium calculation. If num-incidents-in-past is 3 or below, that warrants ZERO points. If 4-5 num-inc then points warranted is 5. If years-exp is between 1-5, that warrants 12 points. The idea is an arbitrary value is being assigned to a range of values for any given number of attributes. The premium calculations is simply tallying up the points warranted for each attribute category and multiplying by some factor i.e 2.5. I am trying to use B. LISKOV'S power of abstractions AND the SRP to neatly assign responsiblities to design a calculator that is extensible and well designed.
Based on the answer provided by drharris here Is there a C# type for representing an integer Range?
How do I access the value out of the following Dictionary whose key is a generic type Range as defined by drharris?
//************************ABSTRACTIONS************************
public abstract class AbsPerson
{
public virtual AbsPolicy APolicy { get; set; }
public virtual string ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public virtual string Address { get; set; }
}
public abstract class AbsPolicy
{
public virtual string PersonID { get; set; } //FK
public virtual int PropValue { get; set; }
public virtual int InsGroup { get; set; }
}
public abstract class AbsValueCategoryCalculator: IEvaluatePolicy
{
//DATA
public abstract void InitRange();
//REFERENCE drharris poster GENERIC TYPE SIGNATURE - public class Range<T> where T : IComparable<T>
public abstract Dictionary<Range<int>, int> ValueRange {get; set;}
public abstract int Tally { get; set; }
//BEHAVIOUR
public virtual void EvaluatePolicyDetails(AbsPerson person)
{
}
}
public interface IEvaluatePolicy
{
void EvaluatePolicyDetails(AbsPerson person);
}
//*************************CONCRETIONS**************************
public class CarValueCategoryCalculator : AbsValueCategoryCalculator
{
public CarValueCategoryCalculator()
{//ctor
InitRange();
}
public override void InitRange()
{
this.ValueRange = new Dictionary<Range<int>, int>();
this.ValueRange.Add(new Range<int>() { Minimum = 1000, Maximum = 2000 }, 10);
this.ValueRange.Add(new Range<int>() { Minimum = 2001, Maximum = 3000 }, 20);
this.ValueRange.Add(new Range<int>() { Minimum = 3001, Maximum = 4000 }, 30);
this.ValueRange.Add(new Range<int>() { Minimum = 4001, Maximum = 5000 }, 40);
this.ValueRange.Add(new Range<int>() { Minimum = 5001, Maximum = 6000 }, 50);
this.ValueRange.Add(new Range<int>() { Minimum = 6001, Maximum = 7000 }, 60);
}
public override Dictionary<Range<int>, int> ValueRange
{
get; set;
}
public override void EvaluatePolicyDetails(AbsPerson person)
{
//I am trying to tally the value given wether the cars worth lies within the range
if (this.ValueRange.ContainsKey(new Range<int>() { Maximum = person.APolicy.PropValue, Minimum = person.APolicy.PropValue }))
{
this.Tally =
}
Console.WriteLine("good");
}
public override int Tally
{
get;set;
}
}//end class
(As noted in comments, Sam's answer points out that a dictionary isn't really what's wanted here - that only finds equal keys, whereas the OP is trying to find a range key that contains a single value. Hash tables just aren't geared up for that.)
You need to either override GetHashCode and Equals in Range<T> (which would be sensible - ideally implementing IEquatable<Range<T>> at the same time) or create a separate type which implements IEqualityComparer<Range<T>> and then pass that to the dictionary constructor.
I would probably do it on the range type, like this:
public sealed class Range<T> : IEquatable<Range<T>>
where T : IComparable<T>, IEquatable<T>
{
...
public override int GetHashCode()
{
int hash = 23;
hash = hash * 31 + EqualityComparer.Default<T>.GetHashCode(Minimum);
hash = hash * 31 + EqualityComparer.Default<T>.GetHashCode(Maximum);
return hash;
}
public override bool Equals(object other)
{
return Equals(other as Range<T>);
}
public bool Equals(Range<T> other)
{
if (ReferenceEquals(other, this))
{
return true;
}
if (ReferenceEquals(other, null))
{
return false;
}
return EqualityComparer<T>.Default.Equals(Minimum, other.Minimum) &&
EqualityComparer<T>.Default.Equals(Maximum, other.Maximum);
}
}
Note that currently the Range<T> type is mutable, however - that's generally a bad idea for dictionary keys. It would be a good idea to make it at least "shallow-immutable" - there's not a lot you can do if the
You'll either need to override Equals and GetHashCode on Range such that the items are compared based on the values you're interested in (min and max) rather than the default behavior (which is based on the object's reference).
If you cannot mutate the type (or don't want to) then you can create a type that implements IEqualityComparer<Range<T>>, implements the appropriate equals and hash generation methods, and then create an instance of that comparer that you pass to the dictionary.
I'm trying to read between the lines here, and I think that you are asking the wrong question.
This bit of code catches my eye (you may want to make it clearer so that others understand your need better):
public override void EvaluatePolicyDetails(AbsPerson person)
{
//I am trying to tally the value given wether the cars worth lies within the range
if (this.ValueRange.ContainsKey(new Range<int>() { Maximum = person.APolicy.PropValue, Minimum = person.APolicy.PropValue }))
{
this.Tally =
}
Console.WriteLine("good");
}
I think that what you are actually trying to do here is fetch the associated int value when person.APolicy.PropValue is within a Range.
What you are currently doing is wrong, and will not work, even if you add the proper Equals and GetHashCode overrides. Dictionaries only do exact matches. You are trying to do range matching.
Instead, I suggest you drop the dictionary in favor of a List of a new type composed of a Range and whatever that int value is. Then I would sort the list based on the Range's Minimum value. Then, you could optionally do a binary search in the list to quickly find candidate Range objects, and then use the Range.ContainsValue function to verify if person.APolicy.PropValue is within the range. Or, in this case, given that you only have a handful of Ranges, you can just iterate over the whole list and break out of the loop as soon as you find a Range that contains your value.
This is definitely a bit more work for you, but I think that this will get you what you are really looking for.
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.
I'm trying to build a console app that is a blackjack game. BlackJackTable : TableGame and has 6 BettingSpots. I'm thinking I want to have an array that contains the BettingSpots. But I am getting errors trying to populate the BettingSpot[]. Any advice on how to better proceed with the design would be much appreciated.
public abstract class TableGame
{
// Can have 5-7 bettings spots. Has a dealer, players, Rules
public abstract void Rules();
public abstract BettingSpot[] bettingSpotArray;
public Dealer dealer = new Dealer();
}
public class BlackJackTable : TableGame
{
// A blackjack tablegame "has a" 6 BettingSpots available that a Player chooses to occupy. Have the Game ask the player which bettingspots they'd
// like to place a bet on. Bet amount must be the same for each. Use a try catch block to make sure TotalChips >= all bets.
public BlackJackTable(int tableNumber)
{
_tableNumber = tableNumber;
}
public override void BlackJackRules()
{ }
BettingSpot spot1 = new BettingSpot(1);
BettingSpot spot2 = new BettingSpot(2);
BettingSpot spot3 = new BettingSpot(3);
BettingSpot spot4 = new BettingSpot(4);
BettingSpot spot5 = new BettingSpot(5);
BettingSpot spot6 = new BettingSpot(6);
public override BettingSpot[] bettingSpotArray = new BettingSpot[5];
for (int i = 0; i < bettingSpotArray.Length; i++)
{
bettingSpotArray[i] = new BettingSpot[i+1];
}
public void QueryPlayerForBettingSpots(BettingSpot[] bettingSpotArray)
{
int[] BettingSpotsAvailable = new BettingSpot[5];
for (int idx = 0; idx < 5; idx++)
if (bettingSpotArray[idx] == 0)
BettingSpotsAvailable[idx]
Console.WriteLine("Place up to 3 bets on the following available BettingSpots: {0}", bettingSpotArray.Where<BettingSpot.
}
}
public class BettingSpot
{
protected decimal bet = 0;
public int _bettingSpotNumber;
// How many spots are on the Blackjack table will determine how many seats there will be. There are six betting spots allowed,
// so six bettingspots are created. THere are just 6 BettingSpots available and a player can
// occupy up to 3 BettingSpots at a time. A bettingspot "has a" bet. If no bet, put '0' in BettingSpotArray
public BettingSpot(int number)
{
_bettingSpotNumber = number;
}
public Player player
public decimal Bet
{
get
{
return bet;
}
set
{
bet = value;
}
}
A few things I noticed in your code.
First, I believe you're having trouble trying to populate bettingSpotArray[] because you're trying to do it inside the body of the class. You need to do it inside the body of a method or property - I'd suggest the constructor or the Rules() method.
Secondly, since you're not defining any code in the abstract class, you might find it easier to make the abstract class an interface and have your game classes implement the interface - that way the class will know what it has to implement, but you don't have to override everything. If you had some sort of default logic you wanted for a majority of the game classes, then I'd agree with using an abstract class that had that base logic, and the "special" classes would override it as needed. But that's just my take on it; you may have your own valid reasons for using an abstract class that are not readily apparent in your question.
I'm not sure the code you have posted will actually compile, but I'll give some code samples that should help you get to where you're trying to go.
public class BlackJackTable : TableGame
{
// If other classes need access to this I'd set it up as public
// property, not a public field. If not, I'd set the field to
// private
public override BettingSpot[] bettingSpotArray = new BettingSpot[5];
public BlackJackTable(int tableNumber)
{
// I don't see a _tableNumber field in your abstract class or your
// inheriting class - if you don't have that field you'll get an error
// in the compiler
_tableNumber = tableNumber;
}
// Your posted code had public override void BlackJackRules, but there is
// no BlackJackRules() method to override
public override void Rules()
{
// These are superfulous since you'll be using an array
// for the betting spots
//BettingSpot spot1 = new BettingSpot(1);
//BettingSpot spot2 = new BettingSpot(2);
//BettingSpot spot3 = new BettingSpot(3);
//BettingSpot spot4 = new BettingSpot(4);
//BettingSpot spot5 = new BettingSpot(5);
//BettingSpot spot6 = new BettingSpot(6);
// Now you can initialize your array
for (int i = 0; i < bettingSpotArray.Length; i++)
{
bettingSpotArray[i] = new BettingSpot[i+1];
}
}
}
Your QueryPlayerForBettingSpots doesn't make a lot of sense either, as it prompts for input from the user, but doesn't accept any input. Perhaps you haven't finished that method?
I think your overall approach is the correct approach, but your implementation has some issues (which I've noted above). Hopefully this will be of some help to you in moving forward in your project.