I am currently attempting to make a Trading Card Game and I have got a whole array of features working already, yet I am stuck now at the portion where one player can attacker another player (more strictly: the monster cards of another player on the field). The game is designed primarely to be played with two players in mind, though having it open for future extensions is never a bad idea.

This is the design I have so far, shown as a minimalistic example in pseudo-code:

class Game
    private final Player self
    private final Player opponent

class Player
    private final String name

The game loops over all players and lets them do their turn, which may involve attacking another player. That method has the following structure:

class AttackMonsterAction
    private final int monsterIndex
    private final int targetMonsterIndex
    private final Player targetPlayer

    public void performAction(final Player player)

If it is of any relevance, I am coding this in Java.

My concrete question is the following: How do I create my class design such that AttackMonsterAction called from a certain Player object, can reference "the other player"?

  • A nice and clean way for me would be to be able to access the owner of a monster from the monster's data. If you have some map where you use the monster id (or index) for key and the player that owns it, or even a monster object that has the owning player as a property, then you would not even pass the player in the action. Commented May 19, 2014 at 10:17
  • Why would you like to refer to "the other player"? Don't! Imagine, you want somewhat later to implement that the monster of a player can attack another monster of the same player. Refering to the other player is useless in this case. So the monster needs some kind of controller. It then tells to its controller "I got attacked and took 2000 damage points" or something like that. The controller then knows both players and knows what monster belongs to which player so it can handle all the stuff that has to be done next.
    – valenterry
    Commented May 19, 2014 at 15:43
  • @valenterry The concrete action does not depend on "the other player", it only needs two players and two monster indices as input and will do whatever you ask it to do. I do however, from within the GUI for example, need to determine whom is the opponent in regular play.
    – skiwi
    Commented May 19, 2014 at 15:44
  • I also see some drawbacks with the GameState solution from @GrahamA. It seems nice first, but it makes it for example harder to test, because an AttackMonsterAction does not have to know for example how many turns have been made - so you should not bother it with information from a GameState that it does not need or care of.
    – valenterry
    Commented May 19, 2014 at 15:45
  • @valenterry I see where the confusion came from on AttackMonsterAction, I updated it to reflect my current version where it does include the targetPlayer.
    – skiwi
    Commented May 19, 2014 at 15:46

1 Answer 1


A couple of options come to mind:

  • Pass a GameState object to performAction, the GameState represents the current environment including the other palyer(s) and game board. This would allow you to move performAction into an interface and use it for your other actions such as move and hide

  • Use a Mediator Object 2 to manage the interaction between the two players.

Regarding adding more players in the future; sounds like a big redesign so apply the XP principal of "You aren't gonna need it " and dont add it yet. Write tests to prove that the game works and then when you want to add more players use you tests to make sure that the two player game still works.

  • 1
    +1 for the GameState-object. I would also consider making the GameState-object immutable, which may sound counterintuitive at first but could lead to the simplest and most efficient design. If the performAction-method actually mutates the state instead of just returning a new object representing the state after the action, you'll soon need to make a copy of the state before each performAction-call for backtracking purposes. (Think about an undo feature or a backtracking AI or a complex action that could fail halfway through, leaving behind an undefined game state...)
    Commented May 19, 2014 at 13:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.