package views; import controls.*; import interfaces.IGameView; import resources.Algo; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import static java.lang.Integer.parseInt; import static views.Constants.*; public class MainPanel extends JPanel implements IGameView { 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; PhaseController phaseController; private HandButtons myHandButtons; private HandButtons opponentHandButtons; private JPanel deckButtonPanel; public MainPanel(Algo algo) { super(new BorderLayout()); myHandButtons = new HandButtons(); opponentHandButtons = new HandButtons(); currentStep = Step.SelectMyHands; deckButtonPanel = new JPanel(); myHandButtonsPanel = new JPanel(); opponentButtonsPanel = new JPanel(); myHandAttackerPanel = new JPanel(); myPanel = new JPanel(); opponentAttackerPanel = new JPanel(); opponentPanel = new JPanel(); phaseController = new PhaseController(algo); 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); }else{ } //repaintField(); add(deckButtonPanel, BorderLayout.WEST); add(myPanel, BorderLayout.SOUTH); add(opponentPanel, BorderLayout.NORTH); opponentHandButtons.stream().filter(x -> x.getText().equals(CLOSED_SYMBOL)).forEach(x -> { x.setEnabled(true); }); updateOpponentHandButtons(); repaint(); } public void bindPhaseController(PhaseController phaseController){ this.phaseController = phaseController; } void updateMyHandButtons() { /** * 自分の手札のボタンにリスナーを追加する処理 */ myHandButtons.removeButtonListeners(); myHandButtons.setEnableButtons(true); myHandButtons.addListeners(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { var sourceButton = ((CardButton) e.getSource()); for (var my : MainPanel.this.myHandButtons) my.setEnabledSelection(false); sourceButton.setEnabledSelection(true); var option = JOptionPane.showConfirmDialog(null, "このカードを使ってアタックをしますか?", "confirmation", 2); if (option == JOptionPane.YES_OPTION) { attacker = myHandButtons.indexOf(sourceButton); isDecidedAttacker = true; phaseController.setSelection(attacker); } else { sourceButton.setEnabledSelection(false); } } }); } void updateOpponentHandButtons() { /** * 相手の手札を選択する処理をリスナーに追加する */ opponentHandButtons.removeButtonListeners(); opponentHandButtons.addListeners(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if(!phaseController.isDecidedAttacker()){ JOptionPane.showMessageDialog(null, "あなたの手札からアタックに使用するカードを選んでください. ", "Warn", JOptionPane.WARNING_MESSAGE); return; } var sourceButton = ((CardButton) e.getSource()); var index = opponentHandButtons.indexOf(sourceButton); sourceButton.setEnabledSelection(true); //相手のカードを選択したときに確認用ダイアログを出す var option = JOptionPane.showConfirmDialog(null, "このカードを選びますか?", "confirmation", 2); if (option == JOptionPane.YES_OPTION) { phaseController.setTarget(index); } else { sourceButton.setEnabledSelection(false); } } }); } void paintDrawCard(AbstractGameState abstractGameState) { 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(); } }else{ updateMyHandButtons(); } 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(); 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); } //ここまでが自分のカードに関する処理 /** *相手のカードに関する処理 */ 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 = !abstractGameState.isDeckLess() ? "あなたは数字\"" + abstractGameState.getTopCard().getKey() + "\"のカードをドローしました。" : "アタックに使用するカードを手札から選んでください。"; /** * デッキにカードが存在しないとき、 * 自分の手札を選択してから、相手のカードを選ぶようにする */ if (abstractGameState.isDeckLess()) { /** * 自分の手札のボタンにリスナーを追加する処理 */ myHandButtons.removeButtonListeners(); myHandButtons.setEnableButtons(true); myHandButtons.addListeners(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { var sourceButton = ((CardButton) e.getSource()); for (var my : MainPanel.this.myHandButtons) my.setEnabledSelection(false); sourceButton.setEnabledSelection(true); var option = JOptionPane.showConfirmDialog(null, "このカードを使ってアタックをしますか?", "confirmation", 2); if (option == JOptionPane.YES_OPTION) { attacker = myHandButtons.indexOf(sourceButton); isDecidedAttacker = true; phaseController.setSelection(attacker); } else { sourceButton.setEnabledSelection(false); } } }); // indexForMyHands = 0; // for (var i : myHandButtons) { // final var a = indexForMyHands; // i.addActionListener(new ActionListener() { // @Override // public void actionPerformed(ActionEvent e) { // // for (var my : MainPanel.this.myHandButtons) my.setEnabledSelection(false); // i.setEnabledSelection(true); // var option = JOptionPane.showConfirmDialog(null, "このカードを使ってアタックをしますか?", "confirmation", 2); // // if (option == JOptionPane.YES_OPTION) { // attacker = a; // isDecidedAttacker = true; // } else { // i.setEnabledSelection(false); // } // } // }); // indexForMyHands++; // } /** *相手の手札のボタンにリスナーを追加する処理 */ myHandButtons.removeButtonListeners(); opponentHandButtons.addListeners(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (!isDecidedAttacker) { JOptionPane.showMessageDialog(null, "あなたの手札からアタックに使用するカードを選んでください. ", "Warn", JOptionPane.WARNING_MESSAGE); } } }); } //paintDrawCard(); JOptionPane.showMessageDialog(null, selectText); if (!abstractGameState.isDeckLess()) { JOptionPane.showMessageDialog(null, "アタックする対象を相手の手札から選んでください。"); } /** * 相手の手札を選択する処理をリスナーに追加する */ opponentHandButtons.removeButtonListeners(); opponentHandButtons.addListeners(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { var sourceButton = ((CardButton) e.getSource()); var index = opponentHandButtons.indexOf(sourceButton); sourceButton.setEnabledSelection(true); //相手のカードを選択したときに確認用ダイアログを出す var option = JOptionPane.showConfirmDialog(null, "このカードを選びますか?", "confirmation", 2); if (option == JOptionPane.YES_OPTION) { phaseController.setTarget(index); } else { sourceButton.setEnabledSelection(false); } } }); /** * 選んだカードに対して、数字を宣言するリスナーを追加する */ indexForOpponent = 0; opponentHandButtons.removeButtonListeners(); opponentHandButtons.addListeners(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { var sourceButton = (CardButton) e.getSource(); var index = opponentHandButtons.indexOf(e.getSource()); sourceButton.setEnabledSelection(true); //相手のカードを選択したときに確認用ダイアログを出す var option = JOptionPane.showConfirmDialog(null, "このカードを選びますか?", "confirmation", 2); if (option == JOptionPane.YES_OPTION) { target = opponentHandButtons.size() - index;//画面上,相手の手札も自分の手札と同じように左から右へ並べられているため,それを補正するために反転させている var t = index; opponentHandButtons.stream().filter(x -> x.getText().equals(CLOSED_SYMBOL)).forEach(x -> { x.setEnabled(false); }); phaseController.setTarget(t); } else { sourceButton.setEnabledSelection(false); return; } for (var my : myHandButtons) my.setEnabledSelection(false); sourceButton.setEnabledSelection(false); repaintField(); if (isGameOver()) { finishGame(); return; } botBehave(); } }); // for (var i : opponentHandButtons) { // i.addActionListener(new ActionListener() { // // public void actionPerformed(ActionEvent e) { // var sourceButton = (CardButton)e.getSource(); // var index = opponentHandButtons.indexOf(e.getSource()); // // i.setEnabledSelection(true); // // //相手のカードを選択したときに確認用ダイアログを出す // var option = JOptionPane.showConfirmDialog(null, "このカードを選びますか?", "confirmation", 2); // if (option == JOptionPane.YES_OPTION) { // target = opponentHandButtons.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 = parseInt(getDeclaredNumber); // var g = 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 { // i.setEnabledSelection(false); // return; // } // for (var my : myHandButtons) my.setEnabledSelection(false); // i.setEnabledSelection(false); // repaintField(); // if (isGameOver()) { // finishGame(); // return; // } // botBehave(); // } // }); // indexForOpponent++; // } // abstractGameState.attack(guess, attacker, target); phaseController.setSelection(0); } 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 + "\"を宣言しました。"); boolean isSucceed = abstractGameState.isSucceedLatestAttack(); String resultMessage = "Botのアタックは "; resultMessage += isSucceed ? "成功しました。" : "失敗しました。"; JOptionPane.showMessageDialog(null, resultMessage); myHandButtons.get(tar).setEnabledSelection(false); if (isGameOver()) { finishGame(); return; } abstractGameState.updateTurn(); } /** * ゲームが終了しているか */ 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, "あなたが勝利しました。"); } } @Override public void onStartPlayerTurn(AbstractGameState abstractGameState) { JOptionPane.showMessageDialog(null, "あなたのターンです。"); var selectText = !abstractGameState.isDeckLess() ? "あなたは数字\"" + abstractGameState.getTopCard().getKey() + "\"のカードをドローしました。" : "アタックに使用するカードを手札から選んでください。"; paintDrawCard(abstractGameState); if (!abstractGameState.isDeckLess()) { selectText ="あなたは数字\"" + abstractGameState.getTopCard().getKey() + "\"のカードをドローしました。"; phaseController.setSelection(0); }else { selectText = "アタックに使用するカードを手札から選んでください。"; } JOptionPane.showMessageDialog(null, selectText); } @Override public void onDecidedSelection(int attacker) { } @Override public void onDecidedTarget(int target) { 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) { //数字を宣言して、承認したとき var g = parseInt(getDeclaredNumber); phaseController.setDeclaration(g); } else { opponentHandButtons.get(target).setEnabledSelection(false); } } @Override public void onFinishedPlayerAttack(int guess, boolean isSucceed) { String resultMessage = "あなたのアタックは"; resultMessage += isSucceed ? "成功しました。" : "失敗しました。"; resultMessage += "(宣言した値:" + guess + ")"; JOptionPane.showMessageDialog(null, resultMessage); } @Override public void onStartBotAttack(TurnBot turnBot) { var bot = new BotIntelligence(turnBot); JOptionPane.showMessageDialog(null, "Botのターンです。"); var selectText = ""; var atk = 0; if (!turnBot.isDeckLess()) { //デッキにカードが存在するとき paintDrawCard(turnBot);//デッキから引いたカードを描画する 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 + "\"を宣言しました。"); phaseController.botAttack(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(); } @Override public void onFinishedBotAttack(int guess, boolean isSucceed) { String resultMessage = "Botのアタックは"; resultMessage += isSucceed ? "成功しました。" : "失敗しました。"; resultMessage += "(宣言した値:" + guess + ")"; JOptionPane.showMessageDialog(null, resultMessage); } @Override public void repaintBoard(AbstractGameState abstractGameState) { var myHands = abstractGameState.getMyHands(); var opponentHands = abstractGameState.getOpponentHands(); /** * 初期化処理(する必要があるのかどうかは知らない) */ isDecidedAttacker = false; myHandButtonsPanel.removeAll();// myHandButtons.clear(); myHandAttackerPanel.removeAll(); opponentAttackerPanel.removeAll(); opponentButtonsPanel.removeAll();// opponentHandButtons.clear(); 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); } //ここまでが自分のカードに関する処理 /** *相手のカードに関する処理 */ 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番目に挿入 } //updateMyHandButtons(); updateOpponentHandButtons(); //ここまでが相手のカードに関する処理 validate(); repaint(); } @Override public void onFinishedGame(AbstractGameState abstractGameState, boolean isLoseA) { this.repaintBoard(abstractGameState); if (isLoseA) { JOptionPane.showMessageDialog(null, "Botが勝利しました。"); } else { JOptionPane.showMessageDialog(null, "あなたが勝利しました。"); } } }