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 opponentButtonsPanel;
    /**
     * アタックで使用するカードが既に決定しているか
     */
    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();
        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(opponentButtonsPanel, BorderLayout.NORTH);
        setStep(Step.SelectOpponentHands);
        repaint();
    }

    void setStep(Step step) {
        currentStep = step;
        switch (step) {
            case SelectMyHands:
                break;
            case SelectOpponentHands:
                opponentHandButtons.stream().filter(x -> x.getText().equals(CLOSED_SYMBOL)).forEach(x -> {
                    x.setEnabled(true);
                });
                break;

            case Declare:
                opponentHandButtons.stream().filter(x -> x.getText().equals(CLOSED_SYMBOL)).forEach(x -> {
                    x.setEnabled(false);
                });
                break;
            case Confirm:

                break;
        }
    }
    void botBehave(IAttack iAttack){
        iAttack.shiftTurn();
        var bot = new BotIntelligence();

        JOptionPane.showMessageDialog(null,"Bot`s Turn.");
        var selectText = "";
        var atk =0;
        if(!iAttack.isDeckLess()){ //デッキにカードが存在するとき
            paintDrawCard(iAttack);//デッキから引いたカードを描画する
            selectText = "Bot drew.";
        }else{
            atk= bot.selectAttacker(iAttack);
            opponentHandButtons.get(atk).setEnabledSelection(true);
            selectText = "Bot selected. ";
        }
        JOptionPane.showMessageDialog(null,selectText);

        var targetText = "";
        var tar = bot.selectTarget(iAttack);
        myHandButtons.get(tar).setEnabledSelection(true);
        JOptionPane.showMessageDialog(null,"Bot targeted this.");


        var dec =  bot.declareNumber(iAttack, tar);
        JOptionPane.showMessageDialog(null,"Bot declared "+ dec +".");

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

        String resultMessage="Bot`s Attack Was ";
        resultMessage+=isSucceed?"Succeed.":"Failed.";
        JOptionPane.showMessageDialog(null,resultMessage);

        myHandButtons.get(tar).setEnabledSelection(false);
        repaintField(iAttack);
        if(isGameOver(iAttack)){
            finishGame(iAttack);
            return;
        }
        iAttack.shiftTurn();
        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()){
                myHandButtons.add(cardButton);
                myHandButtonsPanel.add(cardButton, BorderLayout.WEST);
                isDecidedAttacker=true;
            }else {
                cardButton.setText(CLOSED_SYMBOL);
                opponentHandButtons.add(cardButton);
                opponentButtonsPanel.add(cardButton, BorderLayout.WEST);
            }
            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();
        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を参照してしまうため、ここで一時変数に格納する
            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, "Attack with This Card?", "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, "Select Attacker from Your Hands. ", "Warn",
                                JOptionPane.WARNING_MESSAGE);
                        return;
                    }

                    cardButton.setEnabledSelection(true);

                    //相手のカードを選択したときに確認用ダイアログを出す
                    var option = JOptionPane.showConfirmDialog(null, "Select This Card?", "confirmation", 2);
                    if (option == JOptionPane.YES_OPTION) {
                        target = opponentHands.size()-index;//画面上,相手の手札も自分の手札と同じように左から右へ並べられているため,それを補正するために反転させている
                        var t = index;
                        setStep(Step.Declare);
                        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,
                                "What number is this card?",
                                "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);
                            setStep(Step.Confirm);

                            boolean isSucceed=iAttack.isSucceedLatestAttack();

                            String resultMessage="Your Attack Was ";
                            resultMessage+=isSucceed?"Succeed.":"Failed.";
                            JOptionPane.showMessageDialog(null,resultMessage);
                        }else{
                            setStep(Step.SelectOpponentHands);
                            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,"Your Turn.");
        var selectText = "";
        var atk =0;
        if(!iAttack.isDeckLess()){ //デッキにカードが存在するとき
            selectText = "You drew \""+ iAttack.getTopCard().getKey()+"\".";
        }else{
            selectText = "Select Card used in Your Attack from Your Hands.";
        }
        paintDrawCard(iAttack);

        JOptionPane.showMessageDialog(null,selectText);

        if(!iAttack.isDeckLess())JOptionPane.showMessageDialog(null,"Select Card from Opponent`s Hands.");

    }

    /**
     * ゲームが終了しているか
     * @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 Win.");
        }else if(iAttack.isBLose()){
            JOptionPane.showMessageDialog(null,"You Win.");
        }

    }
}