package views; import controls.*; import interfaces.IAttack; import resources.Algo; 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; AbstractGameState abstractGameState; TurnPlayer turnPlayer; TurnBot turnBot; /** * アタックで使用するカードが既に決定しているか */ boolean isDecidedAttacker; int guess; int attacker; int target; int indexForMyHands = 0; int indexForOpponent = 0; private JPanel deckButtonPanel; public MainPanel(Algo algo) { 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); turnPlayer = new TurnPlayer(algo); turnBot = new TurnBot(algo); abstractGameState= turnPlayer; if (!abstractGameState.isDeckLess()) { //デッキが存在する場合 var cardButton = new JButton("deck"); cardButton.setPreferredSize(new Dimension(CARD_HEIGHT, CARD_WIDTH)); deckButtonPanel.add(cardButton); } repaintField(); /** * 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() { abstractGameState = turnBot; abstractGameState.updateTurn(); var bot = new BotIntelligence(turnBot); JOptionPane.showMessageDialog(null, "Botのターンです。"); var selectText = ""; var atk = 0; if (!abstractGameState.isDeckLess()) { //デッキにカードが存在するとき paintDrawCard();//デッキから引いたカードを描画する selectText = "Botはカードをドローしました。"; } else { atk = bot.selectAttacker(); opponentHandButtons.get(atk).setEnabledSelection(true); selectText = "Botはアタックに使用するカードを選びました。"; } JOptionPane.showMessageDialog(null, selectText); var targetText = ""; var tar = bot.selectTarget(); myHandButtons.get(tar).setEnabledSelection(true); JOptionPane.showMessageDialog(null, "Botはこのカードを対象にしました。"); var dec = bot.declareNumber(tar); JOptionPane.showMessageDialog(null, "Botは\"" + dec + "\"を宣言しました。"); abstractGameState.attack(dec, atk, tar); boolean isSucceed = abstractGameState.isSucceedLatestAttack(); String resultMessage = "Botのアタックは "; resultMessage += isSucceed ? "成功しました。" : "失敗しました。"; JOptionPane.showMessageDialog(null, resultMessage); myHandButtons.get(tar).setEnabledSelection(false); repaintField(); if (isGameOver()) { finishGame(); return; } abstractGameState.updateTurn(); playerBehave(); } void paintDrawCard() { var deckTopCard = abstractGameState.getTopCard(); if (!abstractGameState.isDeckLess()) { //デッキが存在する場合にデッキトップのカードを表示する処理 var cardButton = new CardButton(deckTopCard.getKey().toString()); cardButton.setBounds(0, 100, CARD_WIDTH, CARD_HEIGHT); if (abstractGameState.isATurn()) { myHandAttackerPanel.add(cardButton); isDecidedAttacker = true; } else { cardButton.setText(CLOSED_SYMBOL); opponentAttackerPanel.add(cardButton); } if (abstractGameState.getDeckNumber() == 1) { deckButtonPanel.removeAll(); } } validate(); repaint(); } void repaintField() { var myHands = abstractGameState.getMyHands(); var opponentHands = abstractGameState.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 (!abstractGameState.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 (!abstractGameState.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); abstractGameState.attack(g, attacker, t); boolean isSucceed = abstractGameState.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(); if (isGameOver()) { finishGame(); return; } botBehave(); } }); opponentHandButtons.add(cardButton); opponentButtonsPanel.add(cardButton, 0);//見た目の順序が逆になるように,0番目に挿入 indexForOpponent++; } //ここまでが相手のカードに関する処理 validate(); repaint(); } public void playerBehave() { abstractGameState = turnPlayer; isDecidedAttacker = false; JOptionPane.showMessageDialog(null, "あなたのターンです。"); var selectText = ""; var atk = 0; if (!abstractGameState.isDeckLess()) { //デッキにカードが存在するとき selectText = "あなたは数字\"" + abstractGameState.getTopCard().getKey() + "\"のカードをドローしました。"; } else { selectText = "アタックに使用するカードを手札から選んでください。"; } paintDrawCard(); JOptionPane.showMessageDialog(null, selectText); if (!abstractGameState.isDeckLess()) JOptionPane.showMessageDialog(null, "アタックする対象を相手の手札から選んでください。"); } /** * ゲームが終了しているか * * */ boolean isGameOver() { if (abstractGameState.isALose()) { return true; } else if (abstractGameState.isBLose()) { return true; } return false; } void finishGame() { var myHands = abstractGameState.getMyHands(); var opponentHands = abstractGameState.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 (abstractGameState.isALose()) { JOptionPane.showMessageDialog(null, "Botが勝利しました。"); } else if (abstractGameState.isBLose()) { JOptionPane.showMessageDialog(null, "あなたが勝利しました。"); } } }