Java карточная игра «Война» выходит за границы исключения - PullRequest
0 голосов
/ 08 ноября 2019

Я создаю Java-версию карточной игры «Война» с использованием списков массивов.

Это все файлы, в основном основанные на «Как программировать Java, ранние объекты» Пола Дейла https://github.com/eldar101/EldarRep/tree/master/Game_Of_War/src

Игра запрашивает имена двух игроков и разбивает колоду на две 26-карточные колоды. Я добавил сообщения JPanel, чтобы уведомить о размере колоды и о том, кто победит на каждом ходуОн проходит обороты нормально и достигает даже сотен оборотов, но по какой-то причине никогда не кончается и выдает:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 14 out of bounds for length 14
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
    at java.base/java.util.Objects.checkIndex(Objects.java:373)
    at java.base/java.util.ArrayList.get(ArrayList.java:425)
    at DeckOfCards.getCard(DeckOfCards.java:69)
    at Game.gamePlay(Game.java:51)
    at Game.<init>(Game.java:31)
    at main.main(main.java:5)

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

Это код самой игры, если вы хотите быстро взглянутьздесь:

import java.util.Scanner;
import javax.swing.JOptionPane;


public class Game {
    String p1, p2;
    int p1DeckSize = 0, p2DeckSize = 0;
    DeckOfCards deck, deckP1, deckP2;

    public Game() {

        Scanner input = new Scanner(System.in);
        deck = new DeckOfCards(); // crate a new deck
        deck.shuffle(); // Shuffle the deck
        deckP1 = new DeckOfCards();
        deckP1.clearDeck();
        deckP2 = new DeckOfCards();
        deckP2.clearDeck();
        for (int i = 0; i < 26; i++) {
            deckP1.addICard(i,deck.getCard(i));
        }
        for (int i = 0; i < 26; i++) {
            deckP2.addICard(i,deck.getCard(i+26));
        }
        deck.clearDeck();
        JOptionPane.showMessageDialog(null, "Welcome to a game of \"War\"!");
        this.p1 = JOptionPane.showInputDialog(null, "Please enter player 1's name:");
        this.p2 = JOptionPane.showInputDialog(null, "Please enter player 2's name:");
        JOptionPane.showMessageDialog(null, this.p1 + " is player 1 \n" + this.p2 + " is player 2");

        gamePlay();
    }

    public void gamePlay() {
        int turn = 1, i = 0;
        //int indexP1 = 0, indexP2 = 0;
        while (deckP1.deckSize() != 0 && deckP2.deckSize() != 0) {
            JOptionPane.showMessageDialog(null, "Turn number " + turn++);
            JOptionPane.showMessageDialog(null, p1 + " has " + deckP1.getCard(i).toString() + "\n" + p2 + " has " + deckP2.getCard(i).toString());
            if (deckP1.getCard(i).cardValue() > deckP2.getCard(i).cardValue()) {
                JOptionPane.showMessageDialog(null, p1 + " wins this turn!");
                turnWin(deckP1, deckP2, i);
                JOptionPane.showMessageDialog(null, p1 + " : " +deckP1.deckSize() +" " + p2+ " : " +deckP2.deckSize()  );
            } else if (deckP1.getCard(i).cardValue() < deckP2.getCard(i).cardValue()) {
                JOptionPane.showMessageDialog(null, p2 + " wins this turn!");
                turnWin(deckP2, deckP1, i);
                JOptionPane.showMessageDialog(null, p1 + " : " +deckP1.deckSize() +" " + p2+ " : " +deckP2.deckSize()  );
            } else {
                JOptionPane.showMessageDialog(null, "The cards are equal! time for war!");
                JOptionPane.showMessageDialog(null, p1 + " : " +deckP1.deckSize() +" " + p2+ " : " +deckP2.deckSize()  );
                JOptionPane.showMessageDialog(null, p1 + "'s third card is " + deckP1.getCard(i+3) + "\n" + p2  + "'s third card is " + deckP2.getCard(i+3));
                warStage(deckP1, deckP2, i);
                i++;
                JOptionPane.showMessageDialog(null, p1 + " : " +deckP1.deckSize() +" " + p2+ " : " +deckP2.deckSize()  );

            }
            if (deckP1.deckSize() == 0)
                JOptionPane.showMessageDialog(null, p1 + " Lost the game!" + p2 + " is the winner!");
            else if (deckP2.deckSize() == 0)
                JOptionPane.showMessageDialog(null, p2 + " Lost the game!" + p1 + " is the winner!");
        }
    }


    public void turnWin(DeckOfCards d1, DeckOfCards d2, int i) {
        Card temp1 = new Card(d1.getCard(i).face, d1.getCard(i).suit);
        Card temp2 = new Card(d2.getCard(i).face, d2.getCard(i).suit);
        d1.removeICard(i);
        d2.removeICard(i);
        d1.addCard(temp1);
        d1.addCard(temp2);
    }  //end method turnWin

    public void warStage(DeckOfCards d1, DeckOfCards d2, int i) {
        Card temp1 = new Card(d1.getCard(i + 3).face, d1.getCard(i + 3).suit);
        Card temp2 = new Card(d2.getCard(i + 3).face, d2.getCard(i + 3).suit);
        if (temp1.cardValue() > temp2.cardValue())
        {
            for (int j = 0; j < 3; j++){
                turnWin(d1, d2,i+1);}

        } else if (temp1.cardValue() < temp2.cardValue()) {
            for (int j = 0; j < 3; j++){
                turnWin(d2, d1, i+1);}
        }
        else
        {
            warStage(d1,d2,i+3);
        }
    }  //end method warStage
}

Спасибо за любую помощь.

Ответы [ 2 ]

1 голос
/ 08 ноября 2019

Глядя на обсуждаемую строку:

JOptionPane.showMessageDialog(null, p1 + "'s third card is " + deckP1.getCard(i+3) + "\n" + p2  + "'s third card is " + deckP2.getCard(i+3));

вы попадаете в точку в игре, где:

Игрок X: имеет все карты, кроме 3, Игрок Y: имеет3 карты

Оба игрока играют по 5:

  • Игрок X может положить 3 карты
  • Игрок Y может положить 2 карты

когда вы пытаетесь получить (x + 3), эта карта не существует, поэтому вы получаете исключение, которое видите. Без поиска в Google я понятия не имею, как это должно закончиться, поскольку я никогда не испытывал это на самом деле:

  • Стадия Войны происходит только с двумя картами?
  • Проигрывает ли игрок Y автоматическитак как они не могут заплатить анте?

Есть несколько вещей, на которые вам стоит обратить внимание:

1) Используйте перечисления для опций Face и Suit, это может бытьнемного безопаснее раздача карт, выполнив:

for all Suits
    for all Faces
        deck.add(new Card(suit,face));

2) Начните использовать список массивов, такой как стек или очередь. По сути, вы должны когда-либо делать

Deck.deal ()

, который всегда будет брать верхнюю карту (как бы вы ни смотрели сверху / снизу). В 99% карточных игр (о которых я могу думать) вы когда-либо сдавали карты только сверху, поэтому иметь возможность получить доступ к третьей карте вниз, не выбрасывая верхние 3 карты, не имеет смысла. Теперь некоторые игры типа RPG позволяют вам искать колоды и т. Д., Но это совсем другой набор правил.

3) Создайте

public class Player {
    private Deck active;
    private Deck discard;
}

, что означает, что вы можете заключать сделки () с вашего активногоколода и добавить в вашу колоду сброса. Например, у вас есть (что-то вроде):

p1Card = p1.deal();
p2Card = p2.deal();

if (p1Card > p2Card) 
   p2.getDiscard().addAll(p1Card, p2Card);

, это также означает, что вы можете проверить p1Card на null или DeckEmptyException и сделать что-то вроде:

p1.shuffleDiscard();

, что бы перемешатьи добавьте все карты от сброса к активным. Который я считаю правильным способом играть в войну, вместо того, чтобы просто добавлять выигранные карты в конец текущей колоды.

1 голос
/ 08 ноября 2019

Скорее всего, в вашем методе gameplay() ваш контроль переходит к методу warStage(), и там, если я не ошибаюсь, вы удаляете "карты" из "колоды", и этот DeckOfCards поддерживается каким-то спискоми вы просто удаляете запись из списка. И тогда вы увеличиваете переменную-счетчик i.

С другой стороны, размер колоды уменьшается, что является игровой логикой. Но когда элемент управления возвращается наверх, возможно, DeckOfCards имеет Card, но не в указанном вами индексе i.

Просто сначала выполните проверку размера отдельной колоды, а затем переходите к логике. Это означает, что в методе gameplay() последние два метода задаются в качестве первых двух условий соответственно, что делает первое условие третьим условием и делает его else if
Итак:
if deckP1.deckSize() check
else if deckP2.deckSize() check
else if deckP1.getCard(i).cardValue() > deckP2.getCard(i).cardValue()
и т. Д.

...