Запрещение одному и тому же игроку быть обоими игроками в игре

Я делаю модель ООП, где игроки могут присоединяться к играм на игровой платформе. Один из критериев заключался в том, чтобы не позволять одному и тому же человеку быть обоими людьми, играющими в игру, и теперь я застрял в том, как расширить это, чтобы было любое количество максимальных игроков.

В классе игроков ..

public class GameExt2 {

    private final int minAge;   
    private final PlayerExt2[] players;
    private String gameName;
    private int gameId;
    private double fee;
    private double amountOwed;
    private double totalFeesOwed;
    private int numberOfPlayersPlaying;
    private String playerNames;
    private int oweLimit;
    private int maxNumberPlayers;



public GameExt2( String gameName, int gameId, int minAge, double fee, int oweLimit, int maxNumberPlayers){



    this.gameId=gameId;
    this.gameName=gameName;
    this.minAge=minAge;
    this.fee=fee;
    this.oweLimit=oweLimit;
    this.players=new PlayerExt2[maxNumberPlayers];


    public String matchId(PlayerExt2 player){
        return("Sorry " + player.getName()+ ", you cannot be both players");
}





    public String isTooYoung(PlayerExt2 player){
        return("Sorry " + player.getName()+ ", you are too young to play" +gameName);
}





    public String maxPlayersReached(PlayerExt2 player){
        return("Sorry " + player.getName()+ ", there are already "+maxNumberPlayers+ " playing");
}





    private void playerJoined(PlayerExt2 player){
        System.out.println(player.getName() + " has joined the game " + gameName);          
    }






   public void addPlayer(PlayerExt2 player) {
        int nextFreeSlot = getNextFreeSlot();
        if (nextFreeSlot > 0) {
            if (isEligible(player)) {
                if (!isAlreadyPlaying(player)) {
                    players[nextFreeSlot] = player;
                    playerJoined(player);
                player.addGameJoined();
                player.addFeeOwed(fee);
                player.setNameGamePlaying(gameName);            //necessary for printing details of the player

                }
                else {
                    matchId(player);
                                                        // Already playing
                }
            }
            else {
              isTooYoung(player);
                                                        //player inelligible to play
            }
        }
        else {
            maxPlayersReached(player);
                                                            // game already full
        }
    }





    private boolean isAlreadyPlaying(PlayerExt2 newPlayer) {
        for (PlayerExt2 player : players) {
            if (player.getId() == newPlayer.getId()) return true;
        }
        return false;
    }





    private int getNextFreeSlot() {
        for (int i = 0; i < players.length; i++) {
            if (players[i] == null) return i;
        }
        return -1;                                          // negative indicates there's no free slot
    }





    private boolean isEligible(PlayerExt2 player) {
        return player.getAge() > minAge;
    }

Player class...




    public String addFeeOwed(double fee){

        amountOwed=amountOwed+fee;
        return("For playing this game of "+nameGamePlaying+ ", "+playerName+"'s balance now stands at £"+amountOwed);
}



    public void addGameJoined(){
        gamesJoined++;
}

раздел основных ...

    GameExt2 snakesAndLadders=new GameExt2("SnakesAndLadders",4564345,8,3,10,4);




    PlayerExt2 marina= new PlayerExt2(123, "Marina", 15, 4,1999,0);
    marina.calculateAge();
 System.out.println(marina.printDetails());
    snakesAndLadders.addPlayer(marina);



    PlayerExt2 erin=new PlayerExt2(163,"Erin",3,6,2010,0);
    erin.calculateAge();
System.out.println(erin.printDetails());
    snakesAndLadders.addPlayer(erin);




    PlayerExt2 matthew=new PlayerExt2(312,"Matthew",27,5,2002,12);
    matthew.calculateAge();
System.out.println(matthew.printDetails());
    snakesAndLadders.addPlayer(matthew);

Если playerId уникален, то разве это не будет просто playerOne.playerId != playerTwo.playerId?

Tom 30.10.2018 10:47

Почему в конструкторе есть объявление метода? (Догадываюсь, что вы неправильно отформатировали)

adickinson 30.10.2018 10:49

@Andrew Полагаю, должно было быть два смежных метода: конструктор, затем joinGame. Просто форматировал то, что там было - бардак.

Michael 30.10.2018 10:52

Я сделал обоснованное предположение о том, как должен быть структурирован ваш код. Если бы вы научились правильному отступу, у вас не было бы этой проблемы.

Michael 30.10.2018 10:53

Да! Будет ли это условным выражением? (Извините, что вас так раздражает, я новичок в программировании)

Marina Calder 30.10.2018 10:53

а что, если тогда максимальное количество игроков не ограничивалось 2?

Marina Calder 30.10.2018 11:03
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
125
2

Ответы 2

Если вы думаете, что это должно быть концептуально структурировано, это не ограничения, которые игрок должен сам соблюдать. В реальной жизни игроку все равно, слишком ли он молод для игры. В турнире за это будет отвечать какой-нибудь администратор или, может быть, судья. Нам не обязательно моделировать это в точности, но дело в том, что это должно быть вне контроля игрока. Я бы поместил эту логику в класс Game, к которому добавляются Player.

Вы уже можете видеть, как это странно влияет на ваш код. В вашем плеере есть поле numberOfPlayers. Имеет ли это смысл? numberOfPlayers - собственность человека? У вас есть эта информация в вашем паспорте или водительских правах?

Вот примерная структура (не полный код)

class Game
{
    private final int minAge;
    private final Player[] players;

    public Game(int numberOfPlayers, int minAge) {
        //create array of the correct size, it will be filled with nulls
        this.players = new Player[numberOfPlayers];
        this.minAge = minAge;
    }

    void addPlayer(Player player) {
        int nextFreeSlot = getNextFreeSlot();
        if (nextFreeSlot > 0) {
            if (isEligible(player)) {
                if (!isAlreadyPlaying(player)) {
                    players[nextFreeSlot] = player;
                }
                else {
                    // Already playing
                }
            }
            else {
                // Ineligible
            }
        }
        else {
            // Full
        }
    }

    private boolean isAlreadyPlaying(Player newPlayer) {
        for (Player player : players) {
            if (player.getId() == newPlayer.getId()) return true;
        }
        return false;
    }

    private int getNextFreeSlot() {
        for (int i = 0; i < players.length; i++) {
            if (players[i] == null) return i;
        }
        return -1; // negative indicates there's no free slot
    }

    private boolean isEligible(Player player) {
        return player.getAge() > minAge;
    }
}

Ого, я не могу вас отблагодарить! в этом гораздо больше смысла, мой образ мышления был неправильным! Я очень ценю, что вы уделили мне время, чтобы помочь мне вот так!

Marina Calder 30.10.2018 11:10

Даже когда у вас всего два игрока, я бы все равно использовал коллекцию, чтобы «собрать» всех игроков. Это позволяет избежать использования if (playerOne == null), и его гораздо легче адаптировать, допустив большее количество плееров. Поскольку мы проверяем, что ни один идентификатор не дублируется, мы даже можем использовать Set, если игроков не нужно сортировать (например, когда они присоединились).

Tom 30.10.2018 11:11

@Tom Я не уверен, что согласен. Очевидно, что если требуются проигрыватели n, то коллекция - единственный способ решить эту проблему, но если это всегда два игрока, то я подозреваю, что другие методы в игре будет легче читать, если есть просто два поля. Трудно узнать, не зная, что это за игра, но это мое подозрение. Я бы, вероятно, пошел еще дальше и имел бы GameSignUp или что-то в этом роде (по сути, GameFactory), которое применяет эти ограничения, тогда сама игра может иметь 2 ненулевых поля в момент создания экземпляра.

Michael 30.10.2018 11:15

Можно ли с помощью этого метода распечатать сообщение в разделе «К игре присоединился новый игрок»?

Marina Calder 30.10.2018 11:50

Я очень-очень благодарен за все это! Я предполагаю, что если бы количество игроков не было ограничено двумя для каждой игры (то есть в некоторых играх было 4), то это было бы намного сложнее?

Marina Calder 30.10.2018 14:30

@MarinaCalder Не много, но, может быть, немного. Либо используйте массив, либо список для игроков. Если вам сложно изменить этот аспект, просто опубликуйте еще один вопрос, демонстрирующий вашу попытку. Не стесняйтесь вызвать мне здесь, если вы хотите, чтобы я посмотрел на это

Michael 30.10.2018 14:39

Я думаю, что на данный момент я достиг максимального количества вопросов. Ненавижу спрашивать, но опубликовать пример - много проблем?

Marina Calder 30.10.2018 15:02

Я чувствую, что многому у тебя научился! Большое вам спасибо (извините, если я звучу очень однообразно!)

Marina Calder 30.10.2018 15:36

@MarinaCalder Нет проблем. Рад помочь

Michael 30.10.2018 15:37

@Michael, извини, что снова тебя подслушал. Я отредактировал свой комментарий (вместо того, чтобы создавать новый вопрос, потому что не могу) с помощью моего нового кода, но вывод выходит с неточными числами при печати, если вообще печатает, сделал ли я что-то явно не так?

Marina Calder 30.10.2018 21:26

@Michael, у меня недостаточно репутации, чтобы добавить это в чат

Marina Calder 30.10.2018 23:38

Несколько примечаний:

  • joinGame () не должен входить в класс Player. Размещение этого метода не является расширяемым, однако, судя по тому факту, что в нем упоминается параметр nameGamePlaying, на который нет ссылки в Player, этот метод уже находится в Game.class или в другом вашем эквиваленте.
  • Если вы хотите сравнить, предназначены ли два экземпляра для представления одного и того же объекта, переопределите метод equals, поскольку многие методы в Java используют его для сравнения, поэтому это избавит вас от множества хлопот. Метод equals должен сравнивать, являются ли два экземпляра эквивалентными логически, поэтому в этом случае нам просто нужно сравнить playerId, однако другим классам могут потребоваться другие поля сравнения.
  • Не жестко кодируйте константы, такие как максимальное количество игроков. Ваш пример является свидетельством этого, потому что вы на самом деле хотите максимум 2 игроков, но закодировали значение 3. Когда вы поймете эту ошибку или если вы просто захотите увеличить максимальное количество игроков, вам придется отслеживать каждого возникновение 3 и замените его. Вместо этого объявите константу MAX_PLAYERS на уровне класса и при необходимости укажите на нее ссылку.
  • Вам нужно будет объявить геттеры в Person.class, чтобы нижеследующее работало.
  • Вложите операторы if, чтобы исключить повторение. Нет необходимости постоянно проверять максимальное количество игроков, как вы это делаете изначально, если вы вложите свою последующую логику в оператор if, проверяющий максимальное количество игроков.

Код ниже, любые вопросы, пожалуйста, задавайте.


//In Game.class or equivalent
private final int MAX_PLAYERS = 2;
private List<Player> playerList; //Should be initialised with the main Game(?) class.
public String joinGame(Person player){
    if (playerList.size() < MAX_PLAYERS){
        if (!playerList.contains(player) && player.getPlayerAge() >= minAge){
            playerList.add(player)
            return (player.getPlayerName() + " has joined the game " + nameGamePlaying + ".");
        }else{
            return ("Sorry, " + player.getPlayerName()+ " is too young to play or is already playing " + nameGamePlaying);
        }
    } else {
        return ("Sorry, "+ player.getPlayerName()+ " cannot play " + nameGamePlaying + " as there are already two players.");
    }
}

//In Person.class
@Override
public boolean equals(Object obj){
    if (this == obj){
        return true;
    }
    if (obj == null){
        return false;
    }
    if (getClass() != obj.getClass()){
        return false;
    }
    Person toCompare = (Person) obj;

    if (this.playerId != toCompare.getPlayerId()){
        return false;
    }

    //Optional, depending on your construct.
    if (playerName == null){
        if (toCompare.getPlayerName != null){
            return false;
        }
    }else{
        if (!playerName.equals(toCompare.getPlayerName(){
            return false;
        }
    }

    //... More logical equality checks

    return true;
}

Спасибо вам большое за это! Я сделал менее сложную версию, как отредактировано выше, но она дает мне странные выходные числа и сообщения. Что-то не так с тем, что я написал, из того, что вы видите? @Эндрю

Marina Calder 30.10.2018 22:49

Чтобы рассказать вам больше, потребуется больше информации, чем просто «странные выходные числа и сообщения».

adickinson 31.10.2018 10:33

ну, например, он не позволит игрокам присоединиться к игре с максимум 4 игроками с выводом «игра заполнена», когда еще никто не играет

Marina Calder 31.10.2018 10:50

Во-первых, у вашего массива player есть модификатор final. Посмотрите, что делает final, и посмотрите, как отлаживать свои программы, чтобы определить, что работает, а что нет.

adickinson 31.10.2018 11:00

Я изменил его на общедоступный, но по-прежнему не позволяю игрокам присоединиться

Marina Calder 31.10.2018 11:07

Нет, "финал". Не модификатор доступа, ключевое слово final означает, что после начального назначения объект больше не может быть изменен. Вы инициализируете массив, и, поскольку он имеет модификатор final, вы больше не можете изменять его содержимое. Если вы хотите добавить или удалить игроков в массив, он не может быть окончательным.

adickinson 31.10.2018 11:15

да извините, мой мозг вроде как в панике, вот что я имел в виду, "финал" удален

Marina Calder 31.10.2018 11:16

Что ж, тогда посмотрите, как отлаживать свой код, это даст вам лучшее понимание того, что происходит не так, а также позволит вам изучить, что различные операции делают с состоянием ваших объектов, чтобы вы быстрее научились. Какую среду IDE вы используете?

adickinson 31.10.2018 11:19

Нет, но отладчик позволяет вам устанавливать точки останова в разных точках, которые приостанавливают выполнение программы при достижении, поэтому вы можете проверить, соответствуют ли состояния переменных ожидаемым. plugins.jedit.org/plugins/?Debugger

adickinson 31.10.2018 11:24

Боюсь, эта ссылка устарела, знаете, что не так с кодом?

Marina Calder 31.10.2018 11:27

Ой, плохо по устаревшей части, но все же. Я не знаю, что не так с вашим кодом, но это ваш код, и никто здесь не собирается делать всю работу за вас. Найдите способ отладить свой код.

adickinson 31.10.2018 11:29

хорошо, в любом случае спасибо, есть какие-нибудь подсказки, как не позволить игроку присоединиться, если он уже находится в игре?

Marina Calder 31.10.2018 11:45

Я уже ответил на это, прочитал оригинальный комментарий о переопределении равных.

adickinson 31.10.2018 11:59

Другие вопросы по теме