diff --git a/src/main/java/controls/PhaseController.java b/src/main/java/controls/PhaseController.java new file mode 100644 index 0000000..929c670 --- /dev/null +++ b/src/main/java/controls/PhaseController.java @@ -0,0 +1,44 @@ +package controls; + +import interfaces.ICardButtonEnabler; + +public class PhaseController extends Thread{ + ICardButtonEnabler iCardButtonEnabler; + Phase currentPhase; + int guess; + int attacker; + int target; + public PhaseController(ICardButtonEnabler iCardButtonEnabler){ + this.iCardButtonEnabler=iCardButtonEnabler; + currentPhase=Phase.Selection; + } + + public void setSelection(int attacker){ + this.attacker = attacker; + iCardButtonEnabler.setEnableSelection(attacker); + } + public void setTarget(int target){ + this.target = target; + iCardButtonEnabler.setEnableTarget(target); + } + @Override + public void run(){ + switch (currentPhase){ + case Selection: + case Target: + case Declaration: + } + + } + public void playerAttack(){ + + } + public void botAttack(){ + + } + enum Phase{ + Selection, + Target, + Declaration + } +} diff --git a/src/main/java/interfaces/ICardButtonEnabler.java b/src/main/java/interfaces/ICardButtonEnabler.java new file mode 100644 index 0000000..7ad2fa4 --- /dev/null +++ b/src/main/java/interfaces/ICardButtonEnabler.java @@ -0,0 +1,6 @@ +package interfaces; + +public interface ICardButtonEnabler { + void setEnableSelection(int selection); + void setEnableTarget(int target); +} diff --git a/src/main/java/views/HandButtons.java b/src/main/java/views/HandButtons.java new file mode 100644 index 0000000..d0b86a5 --- /dev/null +++ b/src/main/java/views/HandButtons.java @@ -0,0 +1,28 @@ +package views; + +import java.awt.event.ActionListener; +import java.util.ArrayList; + +/** + * 手札の情報をボタンで扱うためのクラス + */ +class HandButtons extends ArrayList { + public void addListeners(ActionListener al){ + for (var hb : this){ + hb.addActionListener(al); + } + } + public void setEnableButtons(boolean enableButtons){ + for (var hb : this){ + hb.setEnabled(enableButtons); + } + } + public void removeButtonListeners(){ + for(var my:this) { + for( ActionListener al : my.getActionListeners() ) { + my.removeActionListener( al ); + } + } + } + +} \ No newline at end of file diff --git a/src/main/java/views/MainFrame.java b/src/main/java/views/MainFrame.java index ddc4797..5e66a31 100644 --- a/src/main/java/views/MainFrame.java +++ b/src/main/java/views/MainFrame.java @@ -19,6 +19,7 @@ mainPanel.setVisible(true); this.add(mainPanel, BorderLayout.CENTER); this.pack(); + this.addWindowListener(new WindowListener() { @Override public void windowOpened(WindowEvent e) { diff --git a/src/main/java/views/MainPanel.java b/src/main/java/views/MainPanel.java index 5901ecb..ae78392 100644 --- a/src/main/java/views/MainPanel.java +++ b/src/main/java/views/MainPanel.java @@ -1,7 +1,7 @@ package views; import controls.*; -import interfaces.IAttack; +import interfaces.ICardButtonEnabler; import resources.Algo; import javax.swing.*; @@ -14,10 +14,10 @@ import static java.lang.Integer.parseInt; import static views.Constants.*; -public class MainPanel extends JPanel { - private List myHandButtons; +public class MainPanel extends JPanel implements ICardButtonEnabler { + private HandButtons myHandButtons; - private List opponentHandButtons; + private HandButtons opponentHandButtons; private List selectableMyHandKeys; private List selectableOpponentHandKeys; @@ -41,11 +41,12 @@ int indexForMyHands = 0; int indexForOpponent = 0; private JPanel deckButtonPanel; + PhaseController phaseController; public MainPanel(Algo algo) { super(new BorderLayout()); - myHandButtons = new ArrayList<>(); - opponentHandButtons = new ArrayList<>(); + myHandButtons = new HandButtons(); + opponentHandButtons = new HandButtons(); selectableOpponentHandKeys = new ArrayList<>(); currentStep = Step.SelectMyHands; @@ -91,6 +92,337 @@ repaint(); } + + + 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(); + + 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; + + var phaseController = new PhaseController(this); + + 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(); @@ -135,176 +467,6 @@ 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, "アタックする対象を相手の手札から選んでください。"); - - } - /** * ゲームが終了しているか * @@ -369,4 +531,40 @@ } } + + @Override + public void setEnableSelection(int attacker) { + + + } + + @Override + public void setEnableTarget(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) { //数字を宣言して、承認したとき + guess = parseInt(getDeclaredNumber); + var g = parseInt(getDeclaredNumber); + abstractGameState.attack(g, attacker, target); + + 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; + } + } }