Я делаю модель ООП, где игроки могут присоединяться к играм на игровой платформе. Один из критериев заключался в том, чтобы не позволять одному и тому же человеку быть обоими людьми, играющими в игру, и теперь я застрял в том, как расширить это, чтобы было любое количество максимальных игроков.
В классе игроков ..
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);
Почему в конструкторе есть объявление метода? (Догадываюсь, что вы неправильно отформатировали)
@Andrew Полагаю, должно было быть два смежных метода: конструктор, затем joinGame
. Просто форматировал то, что там было - бардак.
Я сделал обоснованное предположение о том, как должен быть структурирован ваш код. Если бы вы научились правильному отступу, у вас не было бы этой проблемы.
Да! Будет ли это условным выражением? (Извините, что вас так раздражает, я новичок в программировании)
а что, если тогда максимальное количество игроков не ограничивалось 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;
}
}
Ого, я не могу вас отблагодарить! в этом гораздо больше смысла, мой образ мышления был неправильным! Я очень ценю, что вы уделили мне время, чтобы помочь мне вот так!
Даже когда у вас всего два игрока, я бы все равно использовал коллекцию, чтобы «собрать» всех игроков. Это позволяет избежать использования if (playerOne == null)
, и его гораздо легче адаптировать, допустив большее количество плееров. Поскольку мы проверяем, что ни один идентификатор не дублируется, мы даже можем использовать Set, если игроков не нужно сортировать (например, когда они присоединились).
@Tom Я не уверен, что согласен. Очевидно, что если требуются проигрыватели n
, то коллекция - единственный способ решить эту проблему, но если это всегда два игрока, то я подозреваю, что другие методы в игре будет легче читать, если есть просто два поля. Трудно узнать, не зная, что это за игра, но это мое подозрение. Я бы, вероятно, пошел еще дальше и имел бы GameSignUp
или что-то в этом роде (по сути, GameFactory
), которое применяет эти ограничения, тогда сама игра может иметь 2 ненулевых поля в момент создания экземпляра.
Можно ли с помощью этого метода распечатать сообщение в разделе «К игре присоединился новый игрок»?
Я очень-очень благодарен за все это! Я предполагаю, что если бы количество игроков не было ограничено двумя для каждой игры (то есть в некоторых играх было 4), то это было бы намного сложнее?
@MarinaCalder Не много, но, может быть, немного. Либо используйте массив, либо список для игроков. Если вам сложно изменить этот аспект, просто опубликуйте еще один вопрос, демонстрирующий вашу попытку. Не стесняйтесь вызвать мне здесь, если вы хотите, чтобы я посмотрел на это
Я думаю, что на данный момент я достиг максимального количества вопросов. Ненавижу спрашивать, но опубликовать пример - много проблем?
Я чувствую, что многому у тебя научился! Большое вам спасибо (извините, если я звучу очень однообразно!)
@MarinaCalder Нет проблем. Рад помочь
@Michael, извини, что снова тебя подслушал. Я отредактировал свой комментарий (вместо того, чтобы создавать новый вопрос, потому что не могу) с помощью моего нового кода, но вывод выходит с неточными числами при печати, если вообще печатает, сделал ли я что-то явно не так?
@Michael, у меня недостаточно репутации, чтобы добавить это в чат
Несколько примечаний:
Код ниже, любые вопросы, пожалуйста, задавайте.
//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;
}
Спасибо вам большое за это! Я сделал менее сложную версию, как отредактировано выше, но она дает мне странные выходные числа и сообщения. Что-то не так с тем, что я написал, из того, что вы видите? @Эндрю
Чтобы рассказать вам больше, потребуется больше информации, чем просто «странные выходные числа и сообщения».
ну, например, он не позволит игрокам присоединиться к игре с максимум 4 игроками с выводом «игра заполнена», когда еще никто не играет
Во-первых, у вашего массива player есть модификатор final. Посмотрите, что делает final, и посмотрите, как отлаживать свои программы, чтобы определить, что работает, а что нет.
Я изменил его на общедоступный, но по-прежнему не позволяю игрокам присоединиться
Нет, "финал". Не модификатор доступа, ключевое слово final означает, что после начального назначения объект больше не может быть изменен. Вы инициализируете массив, и, поскольку он имеет модификатор final, вы больше не можете изменять его содержимое. Если вы хотите добавить или удалить игроков в массив, он не может быть окончательным.
да извините, мой мозг вроде как в панике, вот что я имел в виду, "финал" удален
Что ж, тогда посмотрите, как отлаживать свой код, это даст вам лучшее понимание того, что происходит не так, а также позволит вам изучить, что различные операции делают с состоянием ваших объектов, чтобы вы быстрее научились. Какую среду IDE вы используете?
Нет, но отладчик позволяет вам устанавливать точки останова в разных точках, которые приостанавливают выполнение программы при достижении, поэтому вы можете проверить, соответствуют ли состояния переменных ожидаемым. plugins.jedit.org/plugins/?Debugger
Боюсь, эта ссылка устарела, знаете, что не так с кодом?
Ой, плохо по устаревшей части, но все же. Я не знаю, что не так с вашим кодом, но это ваш код, и никто здесь не собирается делать всю работу за вас. Найдите способ отладить свой код.
хорошо, в любом случае спасибо, есть какие-нибудь подсказки, как не позволить игроку присоединиться, если он уже находится в игре?
Я уже ответил на это, прочитал оригинальный комментарий о переопределении равных.
Если
playerId
уникален, то разве это не будет простоplayerOne.playerId != playerTwo.playerId
?