I am becoming a bit more confident with my programming skills, so I've decided to restart a card game I'd previously began. The point of this program is now that I have a decent grasp of program flow, variables, conditions and so on, I want to deepen my understanding of OOP
So I need some advise on object oriented design
My card game will have 5 classes:
Main
Card
Deck (has-a Card ArrayList)
Player (has-a Card ArrayList of Card objects received from a Deck object)
Dealer
I am wondering if it would be proper OOP to make the Dealer class an interface. All players should be able to play the role of dealer, but needless to say, there is only one dealer per round of cards. Is it ok to make the Player class implement the methods a dealer can perform (such as dealGame()) even when 7 out of 8 Player objects in any given round won't be making use of their implemented methods, and furthermore, are NOT TO BE CONSIDERED A DEALER at the time? Or would it be better to make the dealGame() method belong to the Deck class and call the deck to deal a game? Sorry if this is a dumb question, but I'm a bit sketchy on the principles of OOP and want some advise to learn to do it right the first time.
I also thought of making Dealer extend Player but I think that would be wrong because I need players to assume a role of Dealer on the fly, rather than be declared as a Dealer object in an unchangeable fashion. In this case - if Dealer extends Player - I think I would need to declare all players of the game as Dealers.
So basically I'm asking:
If you were making a card game with these 5 classes, would you make the Dealer class an interface and the rest regular classes, and why or why not?
Am I generally on the right track with OOP or am I completely lost?
You have good approach, however still some work to do :). All the classes are fine, but Delaer is NOT.
First - if player is dealer one round and second someone other is dealer, I dont see a point of extended class or an interface.
In fact, for beginning, I would not make any player a dealer, it makes things complicated.
The easiest and best way how to deal with this, is create 5.Game. Game has Deck and all the players and it is working similar as dealer. It waits for players to response, it shows cards when it should etc.
If you really want make players as dealers it will be more complicated :). Well you need the Game class as well, because the Game has to decide who starts as dealer and it should took away or give players the dealers rights (well I dont see the point of it, but if you want... :) ).
And how to do that? The Game has Player dealer variable. If should have something like registerDealer(Player player) method. Then you need some kind of interface to communicate between Game and Player.
If you want for Player to have ALL THE RESPONSIBILITY for Game, you can use Visitor pattern. (it allows dealer to "sneak" inside game instance and do whatever public methods can do).
Otherwise, you can just let the Game to ask dealer what to do and wait for players input. It should be done by calling method like dealer.askWhatToDo() and using returning value for action. It allows validating input... However if I am right, the valid input in poker is always only one, so I dont see any difference, if Game itself decides what to do...
The only reason I see is if dealer can shuffle the cards or raise the base or stuff like that, then it can be done... Or if you want simulate poker game with poker-players and dealers can do non-valid things like in real life :).
It really depends a lot on how the program works, what you expect each class to be able to do, and how the life cycle of each object works (e.g can a player become a dealer in later rounds).
My first impression from what you wrote is that you need a base class "person" from which "player" and "dealer" inherit, but that's just a guess working off limited information.
Dealer isn't really a special type of Player. It's just one instance of Player at a time that has special responsibilities. I think you're on the right track but you may want to create a class for the particular Game you're playing.
Let's say you're writing a poker game. The Dealer in that case can occasionally influence the order of play (depending on the style). But if you're playing War, the dealer is just someone who hands out the cards and you really don't care. In that case the concept of "who's the dealer" and "how should the dealer deal the game" are responsibilities of the game itself, not the player.
Related
Firstly, this is for university so I cannot be given an answer, rather have it explained why my code does not work and be pointed in the right direction in regards to a solution. This must be considered learning and no more than that. I have also had to change the method names etc.
So I have a player who plays multiple sports; he may be both a BaseballPlayer and/or FootballPlayer, which are subclasses of Player.
BaseballSquad and FootballSquad are the actual teams and are subclasses of TeamList. TeamList has an arrayList protected ArrayList<Player> team which stores a team's players. Players are added to the ArrayList via the TeamList method:
public void addPlayer(Player player)
{
team.add(player);
}
Each player class (either Baseball or Football) has its own points tally method, differing only in points and goals. For the purpose of the assignment, the player and his tally is accessed via a toString() method. These are printed via TeamList by using an Iterator of type Player.
Adding a player to multiple sports works; printing a list of a team's players works.
What does NOT work is printing the correct score tally. For example, if I have a Baseball team and I add a Football player to that team, then what is printed is the player's goal tally, not his Baseball points.
As far as I understand it during runtime the class type remains unchanged but what I need it to be able to, in a sense, change a player's class as I want a Football player to be recognised as a Baseball player if that's the sport he plays.
I feel that I have made a silly mistake somewhere as the rest of the code works. Either that or I have fluked it so far. Any help at all is appreciated and I apologise that I cannot show the whole code!
Unfortunately what you try to accomplish is undoable in Java. Player's object has only one real class, you could of course cast it up or down on the polymorphic hierarchy but casting a FootballPlayer to BaseballPlayer will result with an error. The reason you can add a football player to the collection along with baseball players is that collections in Java are covariant (explained here).
The closest resolution I could suggest is to experiment with more complex class hierarchies as Java allows us to implement more than one interface at a time (in opposite the limit of extending only one class).
Hope I was helpful in a way that will allow you to complete the task on your own.
What does NOT work is printing the correct score tally. For example, if I have a Baseball team and I add a Football player to that team, then what is printed is the player's goal tally, not his Baseball points.
Okay, that doesn't make any sense, why would a Football player be associated with Baseball? How would the program differentiate what Score it should be getting from the Player in this case and would it make any sense to do so?
If it doesn't make sense in the real world, it's unlikely to make sense in the virtual world either
As far as I understand it during runtime the class type remains unchanged but what I need it to be able to, in a sense, change a player's class as I want a Football player to be recognised as a Baseball player if that's the sport he plays.
I would guess your assumption is right, in that FootballPlayer doesn't magically change to a BaseballPlayer. Baseball should not allow you to add any other type of Player other then BaseballPlayers. The only way a FootballPlayer could play Baseball is if they were also a BaseballPlayer.
Now, in Java you can achieve this through the user of interfaces, so a player could play multiple sports, the problem you need to overcome, is how to get the Player's score for a specific Sport - where should this information actually be maintained? Does it belong to the Sport or the Player?
Let's take a step back and try and see the bigger picture. From your description you have...
A Player, who may play zero or more Sports
A Sport, which may have zero or more Players (but probably won't have the same Player more then once). A Sport is a container for a specific type of Player (ie Baseball is a container of BaseballPlayers)
A Score, which is associated to a Player AND a Sport. How you manage this is up to you, I'm going to suggest associating the Score with the Player directly.
So, the basic concept is:
A Sport may contain zero or more (specific) Players, but may only contain a single instance of any given Player (Fred can't play Baseball twice)
A Player can play multiple Sports (which can be achieved through the use of interfaces), so Fred can play Baseball and Football
A Score is associated with a Player for a given Sport
Since the baseline requirement seems to be that the Sport needs to be able to list the Player's scores and (I'm assuming) it would be possible to list the Player's scores for all the Sports they play, it make sense to me to allow Player to manage the Score.
So, you might imagine a Player "might" look something like this...
public interface Player {
// Bunch of other functionality...
public List<Sport> getSports();
public Map<Sport, Score> getScores();
public Score getScore(Sport sport);
}
This means that when you want to list the Scores for all the Players for a given Sport, Sport would loop through it's List of Players and get the Score for itself, maybe something like this...
for (Player player : players) {
Score score = player.getScore(this);
}
But if you want to know all the Scores/Sports for a given Player, you could get that information directly from the Player themselves.
This is just a broad idea/concept which attempts to decouple some of the code and provide a broad baseline from which you can develop more complex relationships/data
Polymorphism doesn't change the base type of the object. It simply allows the object to act/behave like a different type of object (confused yet). That is, you could have a Player behave like a BaseballPlayer AND a FootballPlayer.
Context is defined from the codes point of view, if it expects a BaseballPlayer, it will only see a BaseballPlayer.
A interface simply defines a contract that a object guarantees to provide, so if it implements BaseballPlayer, it guarantees to implement all the functionality expected of the BaseballPlayer interface, equally can be said for FootballPlayer.
If the two classes have overlapping functionality (ie getScore), then you need to be able to manage it so that the getScore method knows the context in which it is been called (which is why I pass the Sport to it), otherwise your implementation has no hope of knowing what it should pass back - it lacks context
My friend and I are working on a game. Right now the game is very simple but we want to understand how we would go about implementing the Single Responsibility Principle between three objects. We have player, enemy, and bullet classes.
The player and enemy both need to be able attack and move, while the
bullet only needs to be able to move.
They all need to be able to collide with one another.
The player moves and attacks based on user input
The enemy moves and attacks based on predetermined attack patterns.
We're really really struggling with the class structure and how to organize the code - we were debating using objects that just hold state and then big controller classes that each do one thing (manage collisions, manage attacking, etc.). Could someone please provide a suggested architecture that follows SRP?
Thank you!
So basically my question is the same as this one:
Card game with huge amount of cards and complex actions
But I don't "speak or understand a word" of C++.
It's my very first big java project and I want to implement a Trading Card Game component.
My problem is: I plan on using 100+ different cards, with different actions. There'll be 4 main types. Within those types, the card's actions are similar but still different.
I thought about making an extra class like
public class CardActionDatabase {
public void card1Action(){}
public void card2Action(){}
....
}
But the problem is, I can't invoke/call them within the actual code like
(playedcard.getName())Action()
since that's impossible in a compiled language.
So basically I'd have to "if" the recent played card with all existing ones, which would be inefficient.
How can I accomplish this?
I've been messing around with card games myself, and there are a few options here. A simple way to do it (though perhaps not the most efficient) is thusly:
First, create an abstract class Card that contains common variables and methods, such as String name and public void onPlay(). Then you might make another abstract subclass for each of your four types.
Then, create subclasses of Card for each unique card in your game. These subclasses define onPlay() in their own way. Then in your player turn logic, when a player chooses a card, that card's onPlay method is called. You can even add stuff like onDiscard, onDestroy, or onTurnStart.
You might also consider creating controller classes between the "Cards" and the "Field/Play Area". For example, you might have a HandController class that has public methods DiscardRandom(), Discard(int index) and Draw() which the Cards can use to manipulate the gameplay as they should.
It can become troublesome and complex to manage the chain of calls needed to perform actions appropriately, but strong documentation goes a long way.
I am having a bit of issues with design. Maybe I am thinking about this all wrong, but it seems that what I am designing only works well in a procedural manner.
The Game
I am working on a game, this game has about 10-20 players inside of it, and consists of 3 rounds. When players start up the game, the server loads their data from a database, stores it in a java class, and sends data that is requested to the client. Lets call this Player.java. This class is persistent in between the rounds of the game.
Every player in the game also has a role. This role changes in-between each round and I need this role to be linked with Player.java in some way. Right now I have 3 roles: Hunter, Seeker, and Spectator. Each role has the same basic things: onDeath(), onRespawn(), onKill(KillEvent event). I also need to be able to easily check what role a player is. (For example linking the roles with a enum).
The Problem
The problem I am running into now is how do I implement this in a OOP way? Originally, I had each role as a class that implements Role.java, and every time a role is created, it takes a Player in the constructor. This is all fine and dandy until I start changing people's roles in the middle of the rounds and after the end of each round. It seems like bad practice to me if I am consistently setting the players role to a new object.
Summary
To sum this up (since I am terrible at describing things), it seems like all of this would work perfectly in a procedural manner, but I can't figure out for the life of me a good way to implement this concept using OOP. The way I have it implemented now, each Player has a enum stating what role they are, and to change that role I simply change the enum in Player. With that being said though, once I get to the game logic, I end up with a TON of nested if statements, something that I feel could be greatly reduced with some polymorphism.
So to end with a question, what would be a good plan of attack to implement this (or a slightly modified version of this system) in a object oriented way without having to consistently create new objects that take in data from old objects? (I don't have a ton of experience with OOP, but to me this just seems like a bad idea)
I think I would go for this solution:
Make Player an Interface
Create a Proxy-Class for it (a class that has only one property, which is of type Player, and redirects all methods to this object). Lets call it ConcretePlayer
Add a setRole method, taking a Role to ConcretePlayer.
Make Role implement Player
Create Subclasses of Role like you did, each takes a ConcretePlayer in their constructor.
Store the stats that are shared among all Roles in the ConcretePlayer
Externally use Player or ConcretePlayer to access everything.
It's not fleshed out perfectly, but I think you get the idea. You may find that Role and Player shouldn't share the same interface, or that you want to create an own interface for the callbacks, but that depends on the rest of your code and usecases.
I want to create a class lets say called enemy 1, enemy 2, and enemy 3.
Enemy 1: Very easy to kill, but many.
Enemy 2: Harder to kill, but less of them.
Enemy 3: Boss, super hard to kill, only one.
Lets say that many is going to be 1,000. Less of them will be 100. Boss is of course one.
So it would be stupid to make 1,101 different instances for a game of just enemy. It would require to much code.
Now my fighter, which is sick, can fire a lot of missiles. Lets say 2,000 a minute for the sake of fun.
I need to check for collisions between the enemy and all the missiles. I plan only using 4 different instances. Which would be enemy1, enemy2, enemy3, and a missile.
Any ideas on how to go about this? Obviously I would need threads, but I am not sure how to check for collisions in this instance.
If you've got 1101 enemies wandering around the place then each of them will have their location, their damage, their ammo stock and so on, so you will need 1101 instances. You only need four classes. Then you create a whole array of instances of each class.
You also need an instance for every missile.
Collisions? Well, are you planning on using some 3d graphics gaming library for this? It'll probably handle collision detection. Or are your enemies all spheres? You need geometry...
So it would be stupid to make 1,101 different instances for a game of just enemy. It would require to much code.
Not at all. You may be confusing class with instance because you will in fact have to create 1,101 instances of these objects, but will only need code for 3 Enemy classes (or 1 class perhaps if you can make how hard it is to kill a property of the class). Likely you will have a collection, such as an ArrayList of Enemy.
The other answer handles collisions, but likely you will do this part in your model, not in your view code.