2

I am trying to design a simple Soccer game. To keep things simple, I am having a SoccerField to represent the field and a Player class to represent an individual.

A SoccerField will contain a list of players. A Player would belong to a SoccerField (Even though a player can exist by itself, during a game, a player will be part of a SoccerField). How can I represent this relationship? i.e. For moving a player, how can I would like to access the SoccerField boundaries as well as get other players in the SoccerField and validate if the cell is unoccupied.

// Say the Field is represented as a 2D Matrix
class SoccerField {
    int maxRow;
    int maxCol;
    List<Player> players;

    public SoccerField(int maxRow, int maxCol) {
        this.maxRow = maxRow;
        this.maxCol = maxCol;
        this.players = new ArrayList<>();
    }

    public initializePlayers(int xPos, int yPos) {
        Player player = new Player(xPos, yPos);
        this.players.add(player);
    }
}

class Player {
    int xPosition;
    int yPosition;

    // How to represent that a player belongs to a SoccerField?
    // Can I have a reference to the SoccerField in a player?
    // SoccerField field; ----> Is this an acceptable design?

    public Player(int xPosition, int yPosition) {
        this.xPosition = xPosition;
        this.yPosition = yPosition;
    }

    public move(int xPos, int yPos) {
        // Validate that xPos and yPos exists within the Soccer Field
        // If I have a reference to "SoccerField", I can validate the following
        // 1. Check if a player moves to a valid cell
        // 2. Check if a player does not occupy an already occupied cell
    }
}

class Solution {
    SoccerField soccerField = new SoccerField(5, 5);
    Player player1 = soccerField.initializePlayer(0, 0);
    Player player2 = soccerField.initializePlayer(1, 1);

    // Now that I have player objects, I want to move the players
    // Imagine a video game where I am taking control of a player and moving the player
    player1.move(0,1);
    player2.move(1,2);
}

Any suggestions on how can I better represent the above classes?

3 Answers 3

4

How to represent that a player belongs to a SoccerField?
Can I have a reference to the SoccerField in a player?
SoccerField field; ----> Is this an acceptable design?

Yes, you can have a reference to the (current) SoccerField that a player plays on within the Player class.

Any suggestions on how can I better represent the above classes?

That depends very much on the mechanics of the game you are creating.

If the game is intended to be similar to a first-person video game, where one game-player (either human or computer) always controls the same soccer-player throughout the game, then I don't see that much wrong with your current design.

If the game is intended to be played more like a game of chess, where one game-player moves multiple soccer-players around on the field (move the player at (1,1) to (2,1)), then it might make more sense that the SoccerField has the knowledge of the position of each Player and also the ability to move Players around (with the associated rules checks).

1
  • Thanks! I was intending to design like a game of chess where a single game player has the ability to move multiple soccer players on the field.
    – SyncMaster
    Commented Dec 8, 2021 at 7:45
2

Better Create a Game class. This way players exist outside of game also. You can have different kind of soccerfield (like in a PSP game)

class Game {
   final SoccerField field;
   final List<Players> players;
   Score teamA, teamB;

   Game(SoccerField, players) { initialize them here }

   movePlayer(player, x, y) { move it here }
}
1
  • +1 for an excellent suggestion. This models real life, and removes the need for the circular reference between players and soccer field that others are saying is ok.
    – kiwiron
    Commented Dec 20, 2021 at 6:47
0

An alternative design I like to use in similar cases, is to use views or projections.

What I mean by this, is to have the Player be an interface and have the SoccerField, which is already a place where you create the Player, create an ad-hoc / anonymous implementation by just projecting the part of the data it already has to implement the player's behavior. Like this:

public interface Player {
   void moveTo(int x, int y);
}

public final class SoccerField {
   // Some internal, possibly optimized data structure

   public Player initializePlayer(int x, int y) {
       // Mark in internal structure
       return (newX, newY) -> {
          // Check whether free, etc.
          // Move
       };
   }
}

This is great for cases where the "child" object is really just a part/projection of the parent and it has no real independent behavior. It is less/not suited for cases where the player has behavior on its own, or is polymorphic.

Just as an alternative. YMMV.

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.