I am trying to implement a card game(similar to bridge). There are bunch of classes which represent Suit,Player,Cart,Team,etc.
In each round each player throws 4 cards and once all 13 cards from each player’s hand are thrown, we can calculate points each team of two players collected.
I need to tell the Main form somehow to end (better term is to start a new round ) when all 52 cards are thrown.
I am trying to implement the following pseudo algorithm
While(not all cards played)
{
continue the game
}
Calculate each player’s score according to the collect hand
Not sure where to put this while loop. Certainly not in Form_Load.
Your question is somewhat general, so here is my primary reccommendation:
Don't put business logic in a view class. Your view should react via method calls/events to changes in underlying state. Unfortunately, this is much easier in a tech built around an MVVM/MVC pattern (like WPF).
That being said, I would create a "GameController" class that manages the game state and holds rules such as this. Every time a card is played it would run through a method like:
void CheckRoundEnd()
{
if (cardsPlayed == 52)
EndRound();
}
EndRound would raise an event that the form listened to, or invoke appropriate methods on the form to reset the view for the next round.
Related
I'm developing a role-playing game in C# (Unity) with a Lua scripting front-end for game logic and modding. I have a design question I've been thinking about and can't seem to find the answer. I'm implementing an Effect class, which provides a common interface to define and handle effects that affect champions or creatures, whether due to a spell, an enchanted item, or a condition (paralyzed, afraid...). The objective is to be as flexible as possible and decouple effects code from the actual champion components/classes.
I want the effect to have access to callbacks, so that it can alter what happens to the entity. If the character health changes for example, active effects can kick in and change that change before it's applied. Here are two examples in Lua, the API should be self-explanatory:
Ring of Health Loss Halving:
onHealthAdjustment = function(entity, val)
if val < 0 then val = math.floor(val / 2); end
return val;
end
Mana Shield spell:
onHealthAdjustment = function(entity, val)
if val < 0 then
championProperties = entity.championProperties;
if championProperties then
championProperties:adjustMana(val);
end
return 0;
else
return val;
end
end
That's fine, but how to handle execution order of callbacks?
Let's say the champion loses 10 health. If the ring gets processed first, it lowers that to 5, then the spell reduces health loss to 0 and removes 5 mana instead.
If the spell gets processed first, it reduces health loss to 0, removes 10 mana, and then the ring callback gets a 0 and does nothing.
I can add an effect priority variable, but there would always end up some with the same value. Process in last-applied first order, or process last-applied only leads to stupid exploits with for example picking and clicking back items in the inventory to make sure what order the effects are processed... I don't see a way to call callbacks in parallel instead of sequentially...
I'm either not seeing an obvious way to fix the current pattern, or I need to change to another design pattern. I've read about Strategy and Observer patterns but can't seem to find a clear answer. How are these cases usually handled?
Thanks!
there would always end up some with the same value
So? If you get a collision, fix it. The order in which the effects are applied is not arbitrary, it's part of your design
Presumably in your code you have a list of event handlers per event type which you iterate through when the event happens. Just make sure that list is in the right order (e.g. by controlling the order they are registered) and you're done.
Side note. In case you didn't know, this:
onHealthAdjustment = function(entity, val) end
Can be written like this:
function onHealthAdjustment(entity, val) end
I've got a Gameboard containing a lot of dices.
Every can be tilted to either direction (limited by the boundaries of the Gameboard and other dices in their way) by dragging the mouse on top of it in on of the four directions.
So the dices themself handle the input but before executing a tilt I have to check whether the move is allowed on the gameboard.
Therefore I'd give every dice a reference to the gameboard but is there a better way to get this two-way behaviour?
Instead of handling this logic inside of the dice objects with a reference to the Gameboard, I'd recommend looking at doing the opposite and instead handling this in an an abstracted system (creating a 3rd element that bridges these two components together and handles the required logic), checking whether each move is valid or not.
To do this you'd need to change the mouse input so that it is also handled in an abstracted system rather than on each Dice, so when you touch a Dice object this system is able to check which object was touched, before then running the code to check if the move is valid on that object. This would most likely involve you storing a List/Array/Dictionary of all the Dice objects, so that you're able to check and see if the touched object is contained within and therefore valid. You can then get any properties you need from the Dice object by using touchedObject.GetComonent<Dice>(); (or you can store all these properties separately from the actual MonoBehaviour and instead look them up).
With this method you can check against the Dice object and the gameboard to see if the next move is valid, without having each object being dependant on the other (which would cause circular dependencies). This also gives the added advantage of giving you more flexibility to change or remove this code going forwards.
This is one of many different approaches you could take, another would be to have your gameboard store a reference of each Dice object and have the Dice object fire an event when interact with (that the gameboard is listening for), so the gameboard code is then able run the check - though from experience I'd go with the former approach and look at decoupling as much as possible.
How can I make a game to restart when I lose? My game is structured in 3 parts: mainMenu,Game and the end (when you lose). So I divided the Update and draw method in 3 parts. Now I need the option to restart the game if I lose.
bool lost=false; //when it is "true" I lost
if(lost==true)
{
if(Keyboard.GetState().IsKeyDown(Keys.Enter))
{
// Restart game
}
}
you need to make sure you set lost = false when you restart
You'd have to show more for anyone to be able to give more specific help, so all I can say is that you need to somehow reset your game state in that event right there -- and this depends heavily on how you yourself built it. For example, a common scheme is to have an IScreen interface that all screens implement, and the Game class simply holds one of these. To switch from one to another (e.g. from a, say, "WorldScreen" to a "MainScreen"), you'd simply initialize the MainScreen and throw away the WorldScreen object.
I'm writing the simple card game "War" for homework and now that the game works, I'm trying to make it more modular and organized. Below is a section of Main() containing the bulk of the program. I should mention, the course is being taught in C#, but it is not a C# course. Rather, we're learning basic logic and OOP concepts so I may not be taking advantage of some C# features.
bool sameCard = true;
while (sameCard)
{
sameCard = false;
card1.setVal(random.Next(1,14)); // set card value
val1 = determineFace(card1.getVal()); // assign 'face' cards accordingly
suit = suitArr[random.Next(0,4)]; // choose suit string from array
card1.setSuit(suit); // set card suit
card2.setVal(random.Next(1,14)); // rinse, repeat for card2...
val2 = determineFace(card2.getVal());
suit = suitArr[random.Next(0,4)];
card2.setSuit(suit);
// check if same card is drawn twice:
catchDuplicate(ref card1, ref card2, ref sameCard);
}
Console.WriteLine ("Player: {0} of {1}", val1, card1.getSuit());
Console.WriteLine ("Computer: {0} of {1}", val2, card2.getSuit());
// compare card values, display winner:
determineWinner(card1, card2);
So here are my questions:
Can I use loops in Main() and still consider it modular?
Is the card-drawing process written well/contained properly?
Is it considered bad practice to print messages in a method (i.e.: determineWinner())?
I've only been programming for two semesters and I'd like to form good habits at this stage. Any input/advice would be much appreciated.
Edit:
catchDuplicate() is now a boolean method and the call looks like this:
sameCard = catchDuplicate(card1, card2);
thanks to #Douglas.
Can I use loops in Main() and still consider it modular?
Yes, you can. However, more often than not, Main in OOP-programs contains only a handful of method-calls that initiate the core functionality, which is then stored in other classes.
Is the card-drawing process written well/contained properly?
Partially. If I understand your code correctly (you only show Main), you undertake some actions that, when done in the wrong order or with the wrong values, may not end up well. Think of it this way: if you sell your class library (not the whole product, but only your classes), what would be the clearest way to use your library for an uninitiated user?
I.e., consider a class Deck that contains a deck of cards. On creation it creates all cards and shuffles it. Give it a method Shuffle to shuffle the deck when the user of your class needs to shuffle and add methods like DrawCard for handling dealing cards.
Further: you have methods that are not contained within a class of their own yet have functionality that would be better of in a class. I.e., determineFace is better suited to be a method on class Card (assuming card2 is of type Card).
Is it considered bad practice to print messages in a method (i.e.: determineWinner())?
Yes and no. If you only want messages to be visible during testing, use Debug.WriteLine. In a production build, these will be no-ops. However, when you write messages in a production version, make sure that this is clear from the name of the method. I.e., WriteWinnerToConsole or something.
It's more common to not do this because: what format would you print the information? What text should come with it? How do you handle localization? However, when you write a program, obviously it must contain methods that write stuff to the screen (or form, or web page). These are usually contained in specific classes for that purpose. Here, that could be the class CardGameX for instance.
General thoughts
Think about the principle "one method/function should have only one task and one task only and it should not have side effects (like calculating square and printing, then printing is the side effect).".
The principle for classes is, very high-level: a class contains methods that logically belong together and operate on the same set of properties/fields. An example of the opposite: Shuffle should not be a method in class Card. However, it would belong logically in the class Deck.
If the main problem of your homework is create a modular application, you must encapsulate all logic in specialized classes.
Each class must do only one job.
Function that play with the card must be in a card class.
Function that draw cards, should be another class.
I think it is the goal of your homework, good luck!
Take all advices on "best practices" with a grain of salt. Always think for yourself.
That said:
Can I use loops in Main() and still consider it modular?
The two concepts are independent. If your Main() only does high-level logic (i.e. calls other methods) then it does not matter if it does so in a loop, after all the algorithm requires a loop. (you wouldn't add a loop unnecessarily, no?)
As a rule of thumb, if possible/practical, make your program self-documenting. Make it "readable" so, if a new person (or even you, a few months from now) looks at it they can understand it at any level.
Is the card-drawing process written well/contained properly?
No. First of all, a card should never be selected twice. For a more "modular" approach I would have something like this:
while ( Deck.NumCards >= 2 )
{
Card card1 = Deck.GetACard();
Card card2 = Deck.GetACard();
PrintSomeStuffAboutACard( GetWinner( card1, card2 ) );
}
Is it considered bad practice to print messages in a method (ie: determineWinner())?
Is the purpose of determineWinner to print a message? If the answer is "No" then it is not a matter of "bad practice", you function is plain wrong.
That said, there is such a thing as a "debug" build and a "release" build. To aid you in debugging the application and figuring out what works and what doesn't it is a good idea to add logging messages.
Make sure they are relevant and that they are not executed in the "release" build.
Q: Can I use loops in Main() and still consider it modular?
A: Yes, you can use loops, that doesn't really have an impact on modularity.
Q: Is the card-drawing process written well/contained properly?
A: If you want to be more modular, turn DrawCard into a function/method. Maybe just write DrawCards instead of DrawCard, but then there's an optimization-versus-modularity question there.
Q: Is it considered bad practice to print messages in a method (ie: determineWinner())?
A: I wouldn't say printing messages in a method is bad practice, it just depends on context. Ideally, the game itself doesn't handle anything but game logic. The program can have some kind of game object and it can read state from the game object. This way, you could technically change the game from being text-based to being graphical. I mean, that's ideal for modularity, but it may not be practical given a deadline. You always have to decide when you have to sacrifice a best practice because there isn't enough time. Sadly, this is all too often a common occurrence.
Separate game logic from the presentation of it. With a simple game like this, it's an unnecessary dependency.
I have two classes, Human and Monster.
both have a Property called MoveBehavior
Human has HumanMoveBehavior, and Monster has MonsterMoveBehavior
I want the HumanMoveBehavior to move AWAY from Monsters, and MonsterMoveBehavior to move TOWARD Humans.
The problem I'm having is where should I put my code to move?
In the Human/Monster class?
Using this approach, I had a Move() Method, which takes a List of all entities in game, decides whether it's a Monster or Human using a method called GetListOfOpponents(List allsprites) and then runs GetNearestOpponent(List opponents);
But this looks really messy.
Should I have a SpriteController that decides where the Sprites move? I'm unsure where I need to put this code :(
Thanks!
You could think of a AIManager that just says:
foreach(GameObject go in m_myObjects) // m_myObjects is a list of all objects that require updating
{
go.Update(); // standard GameObject function
}
After that, each class should take care of its own piece of code. So updating works in the class itself.
So Human says:
// just a class which is a gameObject and also has moving behaviour
// do the same with monster
public class Human : GameObject, IMoveBehaviour
{
public override Update()
{
GoMove();
}
public void GoMove()
{
// human specific logic here
}
}
// This interface describes that some movement
// will happen with the implementing class
public interface IMoveBehaviour
{
void GoMove();
}
With using an interface, you can make the specific language part of the class and you don't have need to ALSO create some class that will handle that for you. Of course it is possible. But in real life, the human/monster is the one that is moving, not some object he is carrying.
UPDATE
Answer to the comment. Because there is an AIManager, or even a complete GameObjectManager would be nice to maintain all GameObjects, you could ask the AIManager for the placed where you could not go.
Because pathfinding is most of the time done by use of some navigation mesh or a specified grid, the GameObjectManager can return the specific Grid with all navigable points on it. You should for certain not define all positions in every monster. Because most of the time, the monster does not exactly know where everyone is (in real life). So knowing where not to go is indeed good, but knowing where everyone is, will give your AI too much advantage as well.
So think of returning a grid with the points where to go and where not to, instead of maintaining such things inside the monster/human. Always check where you should leave what, by thinking about what would be the thing in real life.
The way Valve handled this for entities in Half Life 2, is one of the better ways, I think. Instead of giving each AI its own separate Move methods and calling those, it simply called the Think() method and let the entity decide what it needed to do.
I'd go with what Marnix says and implement an AIManager that loops through each active AI in the game world, calling the Think() method of each. I would not recommended interfacing your Human class with an "IMoveBehavior" simply because it would be better to abstract that into a "WorldEntity" abstract class.
You might have invisible entities that control things like autosaves, triggers, lighting, etc, but some will have a position in the world. These are the ones who will have a vector identifying their position. Have the AI's Think() method call its own move() method, but keep it private. The only one who needs to think about moving is the AI itself.
If you want to encourage the AI to move outside of the Think) method, I would suggest some kind of imperative, such as a Goal-Oriented Action Planning (GOAP) system. Jeff Orkin wrote about this fantastic concept, and it was used in games such as F.E.A.R. and Fallout 3. It might be a bit overkill for your application, but I thought it was interesting.
http://web.media.mit.edu/~jorkin/goap.html