Newer
Older
Algolike / src / main / java / views / MainPanel.java
package views;

import controls.BotIntelligence;
import controls.StepScheduler;
import interfaces.IAttack;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import static java.lang.Integer.parseInt;
import static views.Constants.*;

public class MainPanel extends JPanel {
    private List<CardButton> myHandButtons;

    private List<CardButton> opponentHandButtons;

    private List<Integer> selectableMyHandKeys;
    private List<Integer> selectableOpponentHandKeys;
    Constants.Step currentStep;
    JPanel myHandButtonsPanel;
    JPanel myHandAttackerPanel;
    JPanel myPanel;
    JPanel opponentButtonsPanel;
    JPanel opponentAttackerPanel;
    JPanel opponentPanel;
    /**
     * アタックで使用するカードが既に決定しているか
     */
    boolean isDecidedAttacker;
    int guess;
    int attacker;
    int target;
    int indexForMyHands = 0;
    int indexForOpponent = 0;
    private JPanel deckButtonPanel;

    public MainPanel(StepScheduler stepScheduler) {
        super(new BorderLayout());
        myHandButtons = new ArrayList<>();
        opponentHandButtons = new ArrayList<>();
        selectableOpponentHandKeys = new ArrayList<>();
        currentStep = Step.SelectMyHands;

        deckButtonPanel = new JPanel();
        myHandButtonsPanel = new JPanel();
        opponentButtonsPanel = new JPanel();

        myHandAttackerPanel = new JPanel();
        myPanel = new JPanel();
        opponentAttackerPanel = new JPanel();
        opponentPanel = new JPanel();

        myPanel.add(myHandAttackerPanel);
        myPanel.add(myHandButtonsPanel);

        opponentPanel.add(opponentAttackerPanel);
        opponentPanel.add(opponentButtonsPanel);

        if (!stepScheduler.isDeckLess()) {        //デッキが存在する場合
            var cardButton = new JButton("deck");
            cardButton.setPreferredSize(new Dimension(CARD_HEIGHT, CARD_WIDTH));
            deckButtonPanel.add(cardButton);
        }
        repaintField(stepScheduler);
        /**
         * setButton末尾にあった処理をコンストラクタ内へ。
         *
         */
        add(deckButtonPanel, BorderLayout.WEST);
        //add(myHandButtonsPanel, BorderLayout.SOUTH);
        add(myPanel, BorderLayout.SOUTH);

        //add(opponentButtonsPanel, BorderLayout.NORTH);
        add(opponentPanel, BorderLayout.NORTH);
        opponentHandButtons.stream().filter(x -> x.getText().equals(CLOSED_SYMBOL)).forEach(x -> {
            x.setEnabled(true);
        });
        repaint();
    }

    void botBehave(IAttack iAttack) {
        iAttack.updateTurn();
        var bot = new BotIntelligence();

        JOptionPane.showMessageDialog(null, "Botのターンです。");
        var selectText = "";
        var atk = 0;
        if (!iAttack.isDeckLess()) { //デッキにカードが存在するとき
            paintDrawCard(iAttack);//デッキから引いたカードを描画する
            selectText = "Botはカードをドローしました。";
        } else {
            atk = bot.selectAttacker(iAttack);
            opponentHandButtons.get(atk).setEnabledSelection(true);
            selectText = "Botはアタックに使用するカードを選びました。";
        }
        JOptionPane.showMessageDialog(null, selectText);

        var targetText = "";
        var tar = bot.selectTarget(iAttack);
        myHandButtons.get(tar).setEnabledSelection(true);
        JOptionPane.showMessageDialog(null, "Botはこのカードを対象にしました。");


        var dec = bot.declareNumber(iAttack, tar);
        JOptionPane.showMessageDialog(null, "Botは\"" + dec + "\"を宣言しました。");

        iAttack.attack(dec, atk, tar);
        boolean isSucceed = iAttack.isSucceedLatestAttack();

        String resultMessage = "Botのアタックは ";
        resultMessage += isSucceed ? "成功しました。" : "失敗しました。";
        JOptionPane.showMessageDialog(null, resultMessage);

        myHandButtons.get(tar).setEnabledSelection(false);
        repaintField(iAttack);
        if (isGameOver(iAttack)) {
            finishGame(iAttack);
            return;
        }
        iAttack.updateTurn();
        playerBehave(iAttack);
    }

    void paintDrawCard(IAttack iAttack) {
        var deckTopCard = iAttack.getTopCard();

        if (!iAttack.isDeckLess()) {    //デッキが存在する場合にデッキトップのカードを表示する処理
            var cardButton = new CardButton(deckTopCard.getKey().toString());
            cardButton.setBounds(0, 100, CARD_WIDTH, CARD_HEIGHT);
            if (iAttack.isATurn()) {
                myHandAttackerPanel.add(cardButton);
                isDecidedAttacker = true;
            } else {
                cardButton.setText(CLOSED_SYMBOL);
                opponentAttackerPanel.add(cardButton);
            }
            if (iAttack.getDeckNumber() == 1) {
                deckButtonPanel.removeAll();
            }
        }

        validate();
        repaint();
    }

    void repaintField(IAttack iAttack) {

        var myHands = iAttack.getMyHands();
        var opponentHands = iAttack.getOpponentHands();

        /**
         * 初期化処理(する必要があるのかどうかは知らない)
         */
        isDecidedAttacker = false;
        myHandButtonsPanel.removeAll();//
        myHandButtons.clear();
        myHandAttackerPanel.removeAll();
        opponentAttackerPanel.removeAll();
        opponentButtonsPanel.removeAll();//
        opponentHandButtons.clear();

        /**
         * 自分の手札に関する処理
         */
        indexForMyHands = 0;
        for (var i : myHands) {
            var cardButton = new CardButton(i.getKey().toString());
            cardButton.setStatus(i.getValue() ? CardButton.Status.OPEN : CardButton.Status.MY_CLOSED);

            myHandButtons.add(cardButton);
            //myHandButtonsPanel.add(cardButton, BorderLayout.WEST);
            myHandButtonsPanel.add(cardButton);
            final var a = indexForMyHands;//actionPerformedの中に書くと、クリックされて初めて、回しきったindexForMyHandsを参照してしまうため、ここで一時変数に格納する
            cardButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (!iAttack.isDeckLess()) return;//デッキがあるときは何も反応しないように
                    for (var my : myHandButtons) my.setEnabledSelection(false);
                    cardButton.setEnabledSelection(true);
                    var option = JOptionPane.showConfirmDialog(null, "このカードを使ってアタックをしますか?", "confirmation", 2);


                    if (option == JOptionPane.YES_OPTION) {
                        attacker = a;
                        isDecidedAttacker = true;
                    } else {
                        cardButton.setEnabledSelection(false);
                    }
                }
            });
            indexForMyHands++;
        }
        //ここまでが自分のカードに関する処理

        /**
         *相手のカードに関する処理
         */
        indexForOpponent = 0;
        for (var i : opponentHands) {
            var cardButton = new CardButton(i.getValue() ? i.getKey().toString() : CLOSED_SYMBOL);
            cardButton.setStatus(i.getValue() ? CardButton.Status.OPEN : CardButton.Status.CLOSED);
            cardButton.setEnabled(!i.getValue());
            cardButton.addActionListener(new ActionListener() {
                final int index = indexForOpponent;

                public void actionPerformed(ActionEvent e) {
                    if (!iAttack.isDeckLess()) isDecidedAttacker = true;
                    if (!isDecidedAttacker) {
                        JOptionPane.showMessageDialog(null, "あなたの手札からアタックに使用するカードを選んでください. ", "Warn",
                                JOptionPane.WARNING_MESSAGE);
                        return;
                    }

                    cardButton.setEnabledSelection(true);

                    //相手のカードを選択したときに確認用ダイアログを出す
                    var option = JOptionPane.showConfirmDialog(null, "このカードを選びますか?", "confirmation", 2);
                    if (option == JOptionPane.YES_OPTION) {
                        target = opponentHands.size() - index;//画面上,相手の手札も自分の手札と同じように左から右へ並べられているため,それを補正するために反転させている
                        var t = index;
                        opponentHandButtons.stream().filter(x -> x.getText().equals(CLOSED_SYMBOL)).forEach(x -> {
                            x.setEnabled(false);
                        });
                        String[] optionsToChoose = new String[DECK_COUNT];
                        for (var i = 0; i < optionsToChoose.length; i++) optionsToChoose[i] = String.valueOf(i);
                        var getDeclaredNumber = (String) JOptionPane.showInputDialog(
                                null,
                                "このカードの数字を宣言してください。",
                                "Declare Number",
                                JOptionPane.QUESTION_MESSAGE,
                                null,
                                optionsToChoose,
                                optionsToChoose[0]);
                        if (getDeclaredNumber != null) {   //数字を宣言して、承認したとき
                            guess = Integer.parseInt(getDeclaredNumber);
                            var g = Integer.parseInt(getDeclaredNumber);
                            iAttack.attack(g, attacker, t);

                            boolean isSucceed = iAttack.isSucceedLatestAttack();

                            String resultMessage = "あなたのアタックは";
                            resultMessage += isSucceed ? "成功しました。" : "失敗しました。";
                            JOptionPane.showMessageDialog(null, resultMessage);
                        } else {
                            opponentHandButtons.stream().filter(x -> x.getText().equals(CLOSED_SYMBOL)).forEach(x -> {
                                x.setEnabled(true);
                            });
                            return;
                        }

                    } else {
                        cardButton.setEnabledSelection(false);
                        return;
                    }
                    for (var my : myHandButtons) my.setEnabledSelection(false);
                    cardButton.setEnabledSelection(false);
                    repaintField(iAttack);
                    if (isGameOver(iAttack)) {
                        finishGame(iAttack);
                        return;
                    }
                    botBehave(iAttack);
                }
            });
            opponentHandButtons.add(cardButton);
            opponentButtonsPanel.add(cardButton, 0);//見た目の順序が逆になるように,0番目に挿入
            indexForOpponent++;
        }
        //ここまでが相手のカードに関する処理
        validate();
        repaint();
    }

    public void playerBehave(IAttack iAttack) {
        isDecidedAttacker = false;
        JOptionPane.showMessageDialog(null, "あなたのターンです。");
        var selectText = "";
        var atk = 0;
        if (!iAttack.isDeckLess()) { //デッキにカードが存在するとき
            selectText = "あなたは数字\"" + iAttack.getTopCard().getKey() + "\"のカードをドローしました。";
        } else {
            selectText = "アタックに使用するカードを手札から選んでください。";
        }
        paintDrawCard(iAttack);

        JOptionPane.showMessageDialog(null, selectText);

        if (!iAttack.isDeckLess()) JOptionPane.showMessageDialog(null, "アタックする対象を相手の手札から選んでください。");

    }

    /**
     * ゲームが終了しているか
     *
     * @param iAttack
     */
    boolean isGameOver(IAttack iAttack) {

        if (iAttack.isALose()) {
            return true;
        } else if (iAttack.isBLose()) {
            return true;
        }

        return false;
    }

    void finishGame(IAttack iAttack) {
        var myHands = iAttack.getMyHands();
        var opponentHands = iAttack.getOpponentHands();

        /**
         * 初期化処理(する必要があるのかどうかは知らない)
         */
        isDecidedAttacker = false;
        myHandButtonsPanel.removeAll();//
        myHandButtons.clear();
        opponentButtonsPanel.removeAll();//
        opponentHandButtons.clear();
        /**
         * 自分の手札に関する処理
         */
        indexForMyHands = 0;
        for (var i : myHands) {
            var cardButton = new CardButton(i.getKey().toString());
            cardButton.setStatus(i.getValue() ? CardButton.Status.OPEN : CardButton.Status.MY_CLOSED);
            myHandButtons.add(cardButton);
            myHandButtonsPanel.add(cardButton, BorderLayout.WEST);

            final var a = indexForMyHands;//actionPerformedの中に書くと、クリックされて初めて、回しきったindexForMyHandsを参照してしまうため、ここで一時変数に格納する
            indexForMyHands++;
        }
        //ここまでが自分のカードに関する処理

        /**
         *相手のカードに関する処理
         */
        indexForOpponent = 0;
        for (var i : opponentHands) {
            var cardButton = new CardButton(i.getValue() ? i.getKey().toString() : CLOSED_SYMBOL);
            cardButton.setStatus(i.getValue() ? CardButton.Status.OPEN : CardButton.Status.CLOSED);
            cardButton.setEnabled(!i.getValue());
            opponentHandButtons.add(cardButton);
            opponentButtonsPanel.add(cardButton, 0);//見た目の順序が逆になるように,0番目に挿入
            indexForOpponent++;
        }
        //ここまでが相手のカードに関する処理
        validate();
        repaint();
        if (iAttack.isALose()) {
            JOptionPane.showMessageDialog(null, "Botが勝利しました。");
        } else if (iAttack.isBLose()) {
            JOptionPane.showMessageDialog(null, "あなたが勝利しました。");
        }

    }
}