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

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

import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
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();
        //setButtons(stepScheduler);
        if(!stepScheduler.isDeckLess()){        //デッキが存在する場合
            var top=stepScheduler.getTopCard();
            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(myHandButtonsPanel, BorderLayout.SOUTH);

        add(opponentButtonsPanel, BorderLayout.NORTH);
        setStep(Step.SelectOpponentHands);
        repaint();
    //    if(stepScheduler.isATurn())playerBehave(stepScheduler);
      //  else botBehave(stepScheduler);
    }

    void setButtons(IAttack iAttack) {

      //  myHandButtonsPanel.setLayout(new BorderLayout());
       // myHandButtonsPanel.setLayout(null);
        var deckTopCard=iAttack.getTopCard();
        var myHands = iAttack.getMyHands();
        var opponentHands = iAttack.getOpponentHands();
        isDecidedAttacker=false;

        if(!iAttack.isDeckLess()){    //デッキが存在する場合にデッキトップのカードを引く処理

            var cardButton =new CardButton(deckTopCard.getKey().toString());
            cardButton.setBounds(0,100,CARD_WIDTH,CARD_HEIGHT);
            myHandButtons.add(cardButton);
            myHandButtonsPanel.add(cardButton, BorderLayout.WEST);
            isDecidedAttacker=true;
        }else{  //デッキが存在しない場合、アタックに使用するカードを選択する処理

        }

        if(!iAttack.isDeckLess()){        //デッキが存在する場合

            var top=iAttack.getTopCard();
            var cardButton =new JButton("deck");
            cardButton.setPreferredSize(new Dimension(CARD_HEIGHT,CARD_WIDTH));
            deckButtonPanel.add(cardButton);
        }else {

        }

        indexForMyHands=0;
        //選択可能な自分のカードのキーを取得
        selectableMyHandKeys = myHands.stream().
                filter(x -> !x.getValue()).//その中から非公開のカードを抽出
                        map(x -> x.getKey()).toList();//カードのリストからキーのリストへ変換
        for (var i : myHands) {
            var cardButton = new CardButton(i.getKey().toString());
            cardButton.setStatus(i.getValue()? CardButton.Status.OPEN: CardButton.Status.MY_CLOSED);
         //   if (!selectableMyHandKeys.contains(i.getKey())) cardButton.setEnabled(false);
            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(currentStep!=Step.SelectMyHands)return;
                    cardButton.setEnabledSelection(true);
                    var option = JOptionPane.showConfirmDialog(null, "Attack with This Card?", "confirmation", 2);

                    cardButton.setEnabledSelection(false);
                    if (option == JOptionPane.YES_OPTION){
                        attacker=a;
                        isDecidedAttacker=true;
                    }
                }
            });
            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(false);
            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;
                    }
                    var baseColor= cardButton.getBackground();
                 //   cardButton.setBackground(SELECTED_COLOR);
                    cardButton.setEnabledSelection(true);
             //       cardButton.setBorder(new LineBorder(SELECTED_COLOR, 4, 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);

                            //次の画面に遷移する処理
                            update(iAttack);


                        }else{
                            setStep(Step.SelectOpponentHands);
                        }

                    }
                    cardButton.setEnabledSelection(false);
                    Timer timer = new Timer(1000, this);
                    timer.setDelay(6000);
                    botBehave(iAttack);
                }
            });
            opponentHandButtons.add(cardButton);
            opponentButtonsPanel.add(cardButton, 0);//見た目の順序が逆になるように,0番目に挿入
            indexForOpponent++;
        }


        add(deckButtonPanel,BorderLayout.WEST);

        //add(myHandButtonsPanel, BorderLayout.SOUTH);
        add(myHandButtonsPanel, BorderLayout.SOUTH);

        add(opponentButtonsPanel, BorderLayout.NORTH);
        setStep(Step.SelectOpponentHands);
       // update(stepScheduler);
        //試行錯誤用 ->やりたいことはできた
//        myHandButtonsPanel.removeAll();
//        for(var mh : myHandButtons){
//            myHandButtonsPanel.add(mh);
//        }
    }

    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);
            selectText = "Bot selected. ";
        }
        JOptionPane.showMessageDialog(null,selectText);

        var targetText = "";
        var tar = bot.selectTarget(iAttack);
        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);

        repaintField(iAttack);
        iAttack.shiftTurn();
        playerBehave(iAttack);
    }
    void update(IAttack iAttack){
        myHandButtonsPanel.removeAll();//
        myHandButtons.clear();
        //選択可能な自分のカードのキーを取得
        selectableMyHandKeys = iAttack.getMyHands().stream().
                filter(x -> !x.getValue()).//その中から非公開のカードを抽出
                        map(x -> x.getKey()).toList();//カードのリストからキーのリストへ変換
        for (var i : iAttack.getMyHands()) {
            var cardButton = new CardButton(i.getKey().toString());
            cardButton.setStatus(i.getValue()? CardButton.Status.OPEN: CardButton.Status.MY_CLOSED);
            //   if (!selectableMyHandKeys.contains(i.getKey())) cardButton.setEnabled(false);
            myHandButtons.add(cardButton);
            myHandButtonsPanel.add(cardButton, BorderLayout.WEST);
            final var a=indexForMyHands;
            cardButton.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {

                    //if(currentStep!=Step.SelectMyHands)return;
                    cardButton.setEnabledSelection(true);
                    var option = JOptionPane.showConfirmDialog(null, "Attack with This Card?", "confirmation", 2);
                    cardButton.setEnabledSelection(false);
                    if (option == JOptionPane.YES_OPTION){
                        attacker=a;
                        isDecidedAttacker=true;
                    }
                }
            });
        }

        opponentButtonsPanel.removeAll();//
        opponentHandButtons.clear();
        //選択可能な相手のカードのキーを取得
        selectableOpponentHandKeys = iAttack.getOpponentHands().stream().
                        filter(x -> !x.getValue()).//その中から非公開のカードを抽出
                        map(x -> x.getKey()).toList();//カードのリストからキーのリストへ変換
        indexForOpponent = 0;
        for (var i : iAttack.getOpponentHands()) {

            var isOpen=i.getValue();
           // var cardButton = new CardButton(isOpen?i.getKey().toString():CLOSED_SYMBOL);
            var cardButton = new CardButton(i.getKey().toString());
            cardButton.setStatus(isOpen? CardButton.Status.OPEN: CardButton.Status.CLOSED);
            //   if (!selectableMyHandKeys.contains(i.getKey())) cardButton.setEnabled(false);
            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;
                    }
                    var baseColor= cardButton.getBackground();
                    //   cardButton.setBackground(SELECTED_COLOR);
                    cardButton.setEnabledSelection(true);
                    //       cardButton.setBorder(new LineBorder(SELECTED_COLOR, 4, true));
                    //相手のカードを選択したときに確認用ダイアログを出す
                    var option = JOptionPane.showConfirmDialog(null, "Select This Card?", "confirmation", 2);
                    if (option == JOptionPane.YES_OPTION) {

                        target = iAttack.getOpponentHands().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);

                            //次の画面に遷移する処理
                            update(iAttack);


                        }else{
                            setStep(Step.SelectOpponentHands);
                        }

                    }
                    cardButton.setEnabledSelection(false);
                    Timer timer = new Timer(1000, this);
                    timer.setDelay(6000);
                    botBehave(iAttack);
                }
            });
            opponentHandButtons.add(cardButton);
            opponentButtonsPanel.add(cardButton, 0);//見た目の順序が逆になるように,0番目に挿入
            indexForOpponent++;
        }


//        for(int i=0,n=opponentHandButtons.size();i<n;i++){
//            var rev= n-i-1;
//            if(iAttack.getOpponentHands().get(rev).getValue()) {
//                opponentHandButtons.get(rev).setText(iAttack.getOpponentHands().get(rev).getKey().toString());
//                opponentHandButtons.get(rev).setStatus(CardButton.Status.OPEN);
//            }
//        }
//        iAttack.getOpponentHands().stream().forEach(x->{
//
//         var cardButton = new JButton(x.getValue() ? x.getKey().toString() :CLOSED_SYMBOL);
//         cardButton.setPreferredSize(new Dimension(CARD_WIDTH, CARD_HEIGHT));
//         cardButton.setEnabled(true);
//         opponentHandButtons.add(cardButton);
//         opponentButtonsPanel.add(cardButton, 0);//見た目の順序が逆になるように,0番目に挿入
//        });
        opponentHandButtons.stream().forEach(x -> {
            x.setEnabled(true);
        });


        isDecidedAttacker=false;
      //  add(opponentButtonsPanel);
      validate();
        repaint();
    }
    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;//デッキがあるときは何も反応しないように

                    cardButton.setEnabledSelection(true);
                    var option = JOptionPane.showConfirmDialog(null, "Attack with This Card?", "confirmation", 2);

                    cardButton.setEnabledSelection(false);
                    if (option == JOptionPane.YES_OPTION){
                        attacker=a;
                        isDecidedAttacker=true;
                    }
                }
            });
            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);

                            //次の画面に遷移する処理
                            //repaintField(iAttack);


                        }else{
                            setStep(Step.SelectOpponentHands);
                            return;
                        }

                    }else{
                        cardButton.setEnabledSelection(false);
                        return;
                    }
                    cardButton.setEnabledSelection(false);
                    repaintField(iAttack);

                    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.");

    }
}