Reputation: 558
I'm working on a Monopoly based game with properties, money, cards, etc. I recently ran into a problem when working on the chance card aspect of the game...
I have an array of Strings that say things, ex,"Tax refund; collect $25" or "You lose money due to stocks; -$100". Each card does something different, not all of them just deal with money. My question: how can i store these cards to each hold a string with its description but also any action that is involved. For example, card1 has a String and an int value (-25), but on the other hand another card, card2 has a String, an int value(+10) and a property. Sorry if the question is really vague but I don't know how else to describe it.
Just to clarify:
A card could contain simply the description and a money value. While another card might contain a description, money value and move certain spaces.
Thanks to everyone who gave out awesome ideas so quickly!
Upvotes: 2
Views: 2818
Reputation: 1
Make a Card
class, with a string called text
or something, and a method called onAction()
or something. Then, make lots of other classes - one for each card - extending the Card
class. Give the string the text you want and in the method you can then put exactly what you want to happen. You can create a class called Deck
containing instances of all of these Card
s and an array/list, and a draw()
method or whatever you've done already. On drawing a Card
from the Deck
, get it to print that Card
's text and call its onAction()
method.
Hope this helps.
Upvotes: 0
Reputation: 10023
This is a solution that allows each card to have several actions.
The ActionType is an interface, as it only has several correct values.
All the fields are made final as once the cards have been created, they shouldn't be allowed to change.
The getActions() method returns a copy of the array as we don't want the game to be able to modify the actions of the card after creation.
enum ActionType {
MONEY, MOVE, ...
}
class Action {
private final String description;
private final ActionType type;
private final int value;
public Action(String desc, ActionType type, int value) {
this.description = desc;
this.type = type;
this.value = value;
}
public String getDescription() {
return description;
}
public ActionType getType() {
return type;
}
public int getValue() {
return value;
}
}
class Card {
private final Action[] actions; // If you want to be able to modify the list of actions after creation, use a non-final List<>, otherwise an array
public Card(Action... actions) {
this.actions = actions;
}
public Action[] getActions() {
Action[] copy = new Action[actions.length];
System.arraycopy(actions, 0, copy, 0, actions.length);
}
}
Upvotes: 1
Reputation: 5306
If your range of actions is very limited (say, 2 or 3 actions involving money, move squares, etc) then I might use the following class:
class Card {
// It would be a good practice to not make the following fields
// public and use getters/setters instead but I've made them this
// way just for illustration purposes
public String text;
public String action;
public int value;
Card(String text, String action, int value) {
this.text = text;
this.action = action;
this.value = value;
}
}
This way (as already pointed out by some other answers), you can use an array of Card
s instead of array of String
s. You can then have text in one field, the action in a separate field, and the value associated with that action in a third field. For example, you could have the following cards:
Card lose25 = new Card("You lose $25", "money", -25);
Card move5squares = new Card("Move 5 squares ahead!", "move", 5);
When you're 'processing' the cards, you can do so in the following manner:
...
if (card.action.equals("money") {
// Update user's money with card.value
} else if (card.action.equals("move") {
// Update user's position with card.value
} else if (card.action.equals("...") {
// and so on...
}
...
EDIT:
If the cards can hold more than one action, you can use a HashMap to store actions for that card:
class Card {
public String text;
public HashMap<String, Integer> actions;
Card(String text) {
this.text = text;
actions = new HashMap<String, Integer>();
}
addAction(String action, int value) {
actions.put(action, value);
}
}
A HashMap
is a collection that can store key-value pairs. So for a card that has 2 actions, you can use the above code as:
Card aCard = new Card("Lose $25 and move back 3 spaces!");
aCard.addAction("money", -25);
aCard.addAction("move", -3);
Now, when you're actually processing the cards, you need to check the HashMap
for all actions stored in this card. One way to iterate through the HashMap
is to do the following:
Card processCard = ...;
for (Map.Entry<String, Integer> entry : processCard.actions.entrySet()) {
// This loop will get each 'action' and 'value' that you added to
// the HashSet for this card and process it.
String action = entry.getKey();
int value = entry.getValue();
// Add the earlier 'card processing' code here...
if (action.equals("money") {
// Update user's money with value
} else if (action.equals("move") {
// Update user's position with value
} else if (action.equals("...") {
// and so on...
}
}
Upvotes: 5
Reputation: 285403
Create a class for Card, use the Command Pattern design pattern so each card can have a different type of action if need be. So it will hold a String field, text, an int field, value, and another field that is for an interface that represents your action.
The key field will be the "action" field that holds a reference to an interface type, say called CardAction:
interface CardAction {
execute();
}
Or you could use use a Runnable or a Future if you want to use a ready made interface. This way you can inject objects of this class with different actions for different types of cards. This will prevent you from having to create multiple different Card classes.
Upvotes: 4
Reputation: 66637
Have a Card class with description and value.
Card
{
String description;
int value;
Card(String desc, int value)
{
this.description = desc;
this.value = value;
}
getters..
setters...
}
Create objects like
Card c = new Card("You may loose 25$...", -25);
Note that, these cards with int value can accept values between -2,147,483,648 to 2,147,483,647. If you want some higher values, you can change int to long or something else.
Upvotes: 0
Reputation: 4104
Make a Card Class, it should contain the description (String) and a value (int) (+10,-25, 0 ect...). You then would have a array of Cards instead of array of strings.
Upvotes: 0