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.
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 have below class object structure with having three inner objects and i am trying to check that only one child object should have the data other wise throw an error and i can do this with if- else statements but looking to see any other way to implement this
public class GlazingOrGasMaterial
{
public GlazingComplexMaterial GlazingComplexMaterial { get; set; }
public GlazingSimpleMaterial GlazingSimpleMaterial { get; set; }
public GlazingGasMaterial GlazingGasMaterial { get; set; }
public GlazingOrGasMaterial(GlazingOrGasMaterial layer)
{
if (layer.GlazingComplexMaterial != null && layer.GlazingGasMaterial != null && layer.GlazingSimpleMaterial == null)
{
throw new ArgumentException("exception for more than one object having data");
}
// more if statements
}
}
and i am calling this constructor like as in below
foreach(var layer in input.Layers)
{
GlazingOrGasMaterial glazingOrGasMaterial = new GlazingOrGasMaterial(layer);
}
Could any one please let me know any way to do this escaping bunch of if-else statements, many thanks in advance
Actually, according OOP, other guys are right, you had better change your class strategy. But I don't know the whole task so I'm able to give an advice only.
I also provided another solution of your question according to your requirements:
public GlazingOrGasMaterial(GlazingOrGasMaterial layer)
{
BitArray materialBits = new BitArray(new bool[] { layer.GlazingComplexMaterial != null, layer.GlazingGasMaterial != null, layer.GlazingSimpleMaterial != null });
byte[] array = new byte[1]; // max number of states depends on the type: byte - 8, short - 16 etc.
materialBits.CopyTo (array, 0);
byte materialState = array[0];
if((materialState != 0) && ((materialState & (materialState - 1)) == 0)) //check if only 1 property has a data
throw new ArgumentException("exception for more than one object having data");
else
//do what you wish
//an example, using by switch you could recognize the exactly not null property
}
How about creating a collection from your objects and counting the ones which meet your expectation:
public GlazingOrGasMaterial(GlazingOrGasMaterial layer)
{
if (new object[] { layer.GlazingComplexMaterial, layer.GlazingSimpleMaterial, layer.GlazingGasMaterial }.Count(x => x != null) != 1)
{
throw new ArgumentException("Expected only one material");
}
...
}
I think you could also consider using a different data modeling approach to enforce this requirement - for example, you could make all of the materials inherit from abstract BaseMaterial and then have the "container" class (if you'd still need it) with only one BaseMaterial property instead of 3 separate ones.
I suggest you change the shape of your class to enforce the 1 material rule. If all the possible materials extend from a common material, then you can create this base class and only allow one instance.
public class GlazingOrGasMaterial
{
public Material _material { get; set; }
public GlazingOrGasMaterial(Material material)
{
_material = material;
}
}
public class Material
{
}
public class GlazingComplexMaterial : Material
{
}
public class GlazingSimpleMaterial : Material
{
}
public class GlazingGasMaterial : Material
{
}
You can then instantiate the class with one of the materials without having to worry that there are multiple. This avoids runtime exceptions!
void Main()
{
var material = new GlazingComplexMaterial();
new GlazingOrGasMaterial(material);
}
This also avoids the problem in the original design where a 2nd or even 3rd material can just be assigned, without going through the constructor validation logic.
I realise this is probably a very simple question and will be answered in no time. But wondering what to do. I have a class called Budget with an object named 'user01' I would basically like to be able to access that object across multiple classes, similar to the code below.
Main
static void Main(string[] args)
{
Budget user01 = new Budget(1000);
}
Budget Class
class Budget
{
private int _budget;
public Budget(int budget)
{
_budget = budget;
}
public int UserBudget
{
get { return _budget; }
set { _budget = value; }
}
}
Expense Class
class Expenses
{
// What I've been trying to do...
public int Something(user01.budget)
{
user01.budget - 100;
return user01.budget;
}
}
I'm not really sure where to go from here, and am hoping to a little help/explanation. Many thanks
This is invalid:
public int Something(user01.budget)
But you can supply an instance of a Budget object to that method:
public int Something(Budget budget)
{
budget.UserBudget -= 100;
return budget.UserBudget;
}
Then you can invoke that method from your consuming code:
Budget user01 = new Budget(1000);
Expenses myExpenses = new Expenses();
int updatedBudget = myExpenses.Something(user01);
The method doesn't "access the variable user01". However, when you call the method, you supply it with your user01 instance. Inside of the method, the supplied instance in this case is referenced by the local budget variable. Any time you call the method and give it any instance of a Budget, for that one time that instance will be referenced by that local variable.
Go ahead and step through this using your debugger and you should get a much clearer picture of what's going on when you call a method.
(Note that your naming here is a bit unintuitive, which is probably adding to the confusion. Is your object a "budget" or is it a "user"? Clearly defining and naming your types and variables goes a long way to making code easier to write.)
Its a pretty simple change to your Expenses class:
class Expenses
{
// What I've been trying to do...
public int Something(Budget userBudget)
{
userBudget.UserBudget -= 100;
return userBudget.UserBudget;
}
}
Which you then call like this from your main class:
static void Main(string[] args)
{
Budget user01 = new Budget(1000);
Expenses expenses = new Expenses();
var result = expenses.Something(user01);
}
Or, if you make your Something method static you can call it without an instance:
class Expenses
{
// What I've been trying to do...
public static int Something(Budget userBudget)
{
userBudget.UserBudget -= 100;
return userBudget.UserBudget;
}
}
Which you call like this:
static void Main(string[] args)
{
Budget user01 = new Budget(1000);
var result = Expenses.Something(user01);
}
Its important when designing methods to remember that a method takes in a general argument and its the caller that passes in something specific.
class bishop:unit {}
class knight:unit {}
class peasant:unit {}
void Battle(unit first, unit second, byte firstAmount, byte secondAmount)
{
System.Array sideA = System.Array.CreateInstance(first.GetType(),firstAmount);
for(int i=0; i< firstAmount; i++)
{
sideA[i] = ???
}
}
In my last question I had problems with creating dynamic arrays and here is my next step problem! :D
Passable types to this method bishop, knight and etc
Actually I don't understand how to initialize objects now. I can't type just sideA[i] = new first.GetType()(constructor parameters) and understand why, but I don't understand how to work around this
This is really, really bad design.
I assume, that your method Battle could be an instance method of a class Game, which you didn't provide to us.
Then I strongly recommend, that the Battle method should NOT create instances of objects it works with. It should only take them and do a battle action (compute lives, etc.).
So, create these objects elsewhere and then just post them to the method.
class Game
{
List<Bishop> bishops = new List<Bishop>() { new Bishop(..), ... };
List<Knight> knights = new List<Knight>() { new Knight(..), ... };
void Battle(List<Unit> first, List<Unit> second)
{
foreach(var f in first)
{
// get random unit from the second collection and attack him
f.Attack(GetRandomKnight(second));
}
}
public void StartBattle()
{
Battle(bishop, knights);
}
}
Also make sure that you use correct C# naming. A name of a class should start with a capital letter.
class Unit
{
public virtual void Attack(Unit enemy)
{
// default attack
Kick(enemy);
}
protected Kick(Unit enemy) { ... }
}
class Bishop : Unit { }
Ondrej has a good answer. Just to help you with arrays, you should never use reflection unless with a good reason. I see no reason why you should be doing it here. You can use the typical new keyword to instantiate an array.
void Battle(unit first, unit second, byte firstAmount, byte secondAmount)
{
var sideA = new unit[firstAmount];
for(int i=0; i< sideA.Length; i++)
{
sideA[i] = ???
}
}
If the instantiated array should really be of run time type of first, then you can rely on generics.
void Battle<T1, T2>(T1 first, T2 second, byte firstAmount, byte secondAmount)
where T1 : unit where T2 : unit
{
var sideA = new T1[firstAmount];
for(int i=0; i< sideA.Length; i++)
{
sideA[i] = ???
}
}
The totally dynamic way to settle things will be SetValue and GetValue:
void Battle(unit first, unit second, byte firstAmount, byte secondAmount)
{
var sideA = Array.CreateInstance(first.GetType(),firstAmount);
for(int i=0; i< firstAmount; i++)
{
sideA.SetValue(???, i);
sideA.GetValue(i); //to get the value back.
}
}
Basically you dont get indexer syntax for System.Array.
I'm a C# beginner and am struggling a little bit with how classes relate to one another.
I am trying to code up a very simple elevator simulation. I have a class for Elevator:
class Elevator
{
public int currentFloor;
public Elevator()
{
currentFloor = 0;
}
public void ascend()
{
currentFloor++;
}
public void descend()
{
currentFloor--;
}
}
Very simple. This works, I can instantiate a new elevator object and have it go up and down, etc...
Now, I want to create a building object, so I created a new class for Buildings. However, I am now stuck - how do I add variable amounts of elevator objects to my buildings? For example, I might want to instantiate a building with 3 elevators, or another with 5...
I started creating a solutiomn where the building class has a List of elevators I can dynamically add to, but that seems so obtuse. So what I am looking for is something like:
Building office = new Building();
office.elevator1 = new Elevator();
office.elevator2 = new Elevator();
which obviously doesn't work because I don't have elevator1 and elevator2 declared in the Building class. What is the best/cleanest way to accomplish what I am looking to do? Also, what is this called? I Googled a ton of terms - class belongs to another class, instantiating a class from another class, similar terms with object instead of class... I've also looked over some of the elevator simulator code out there, but couldn't find anything dynamic like I'm looking for...
Having a List<Elevator> is quite appropriate here; it describes the real-world model very well.
Perhaps it would be better if it were an Elevator[] (in the sense that perhaps it should not be possible to change the number of installed elevators after the building has been erected), but that's not absolute.
In any case, the collection of elevators should be exposed as a read-only property of appropriate type because it doesn't make sense to swap it with another one.
You can add member of type equal to List<Elevator> nd inject inside constructor
Sample
public class Building
{
private List<Elevator> yourList;
public Building(List<Elevator> value)
{
yourList = value;
}
}
Use case :
var list = new List<Elevator>();
list.Add
.....
var building = new Building(list);
Here's an alternative:
class Building
{
public List<Elevator> Elevators { get; set; }
public Building(params Elevator[] elevators)
{
Elevators = elevators.ToList();
}
}
The you can do:
var building = new Building(new Elevator(), new Elevator(), new Elevator());
And add more later:
building.Elevators.Add(new Elevator());
Depends. Say your building will only ever have one elevator. You'd want to do something like this:
public class Building
{
public Elevator Elevator { get; set; }
}
Then when you create the building like you did in your code above, you can do something like this:
office.Elevator = new Elevator();
You're new to C#, so you may not have really been exposed to Properties yet (more reading). Cliffs on Properties: they're creating a way for you to get and set data about your object. In this example, we're getting/setting the Elevator.
Now, if your building is going to have an unknown amount of elevators, you can't just write properties for Elevator1 to ElevatorInfinity. That's when you'll want to use a collection of some sort. As others have posted in here, you can do this like so:
public class Building
{
public IList<Elevator> Elevators { get; set; }
}
And to add an elevator to your building:
// Make sure you instantiate the list! For practice, you should run this code without instantiating the list, so you can see what happens.
office.Elevators = new List<Elevator>();
office.Elevators.Add(new Elevator());
More reading on IList
I think you can override indexer. Of course, you should backbone it with List. Lists are ok.
namespace Tests_CSharp_Indexer
{
class Elevator
{
}
class Building
{
public class ElevatorList
{
private List<Elevator> elevators = new List<Elevator>();
public Elevator this[int i]
{
get
{
return elevators[i];
}
set
{
if (i == elevators.Count)
{
elevators.Add(value);
}
else
{
elevators[i] = value;
}
}
}
public int Count {
get
{
return elevators.Count;
}
}
}
public readonly ElevatorList Elevators = new ElevatorList();
}
class Program
{
static void Main(string[] args)
{
Building building = new Building();
building.Elevators[0] = new Elevator();
building.Elevators[1] = new Elevator();
building.Elevators[2] = new Elevator();
Console.Out.WriteLine(building.Elevators.Count);
}
}
}