diff --git a/src/main/java/controls/AbstractGameState.java b/src/main/java/controls/AbstractGameState.java new file mode 100644 index 0000000..0de21e9 --- /dev/null +++ b/src/main/java/controls/AbstractGameState.java @@ -0,0 +1,55 @@ +package controls; + +import resources.Algo; + +import java.util.List; +import java.util.Map; + +public abstract class AbstractGameState { + Algo algo; + static boolean isATurn; + boolean isSucceedLatestAttack; + public AbstractGameState(Algo algo){ + this.algo = algo; + isATurn=algo.isATurn(); + } + public void setTurn(){} + public abstract void attack(int guess, int attacker, int target); + public List> getMyHands() { + return algo.getHandsA(); + } + + public List> getOpponentHands() { + return algo.getHandsB(); + } + + public Map.Entry getTopCard() { + if (isDeckLess()) return null; + return algo.getDeck().get(0); + } + public void updateTurn() { + algo.updateTurn(); + isATurn= algo.isATurn(); + } + public boolean isATurn() { + return isATurn; + } + public boolean isDeckLess() { + return algo.getDeck().size() == 0; + } + public boolean isSucceedLatestAttack() { + return isSucceedLatestAttack; + } + + public int getDeckNumber() { + return algo.getDeck().size(); + } + + public boolean isALose() { + return algo.getLoseA(); + } + + public boolean isBLose() { + return algo.getLoseB(); + } +} diff --git a/src/main/java/controls/BotIntelligence.java b/src/main/java/controls/BotIntelligence.java index d2d1588..dd0d493 100644 --- a/src/main/java/controls/BotIntelligence.java +++ b/src/main/java/controls/BotIntelligence.java @@ -9,21 +9,21 @@ import static views.Constants.DECK_COUNT; public class BotIntelligence implements IBotBehavior { - - public BotIntelligence() { - + TurnBot turnBot; + public BotIntelligence(TurnBot turnBot) { + this.turnBot = turnBot; } /** * 未確定の数字を列挙する */ - List calculateCandidate(IAttack iAttack) { + List calculateCandidate() { //候補の初期化 var candidates = new ArrayList(); for (int i = 0; i < DECK_COUNT; i++) candidates.add(i); - candidates.removeAll(iAttack.getOpponentHands().stream().map(x -> x.getKey()).collect(Collectors.toList())); - candidates.removeAll(iAttack.getMyHands().stream().filter(x -> x.getValue()).map(x -> x.getKey()).collect(Collectors.toList())); + candidates.removeAll(turnBot.getOpponentHands().stream().map(x -> x.getKey()).collect(Collectors.toList())); + candidates.removeAll(turnBot.getMyHands().stream().filter(x -> x.getValue()).map(x -> x.getKey()).collect(Collectors.toList())); return candidates; } @@ -31,16 +31,15 @@ /** * 相手の手札に対して、候補となる数字を割り当てる * - * @param iAttack * @return 候補のリスト */ - List assignCandidateNumberEachHand(IAttack iAttack) { - var myHands = iAttack.getMyHands(); + List assignCandidateNumberEachHand() { + var myHands = turnBot.getMyHands(); var result = new ArrayList(); for (var card : myHands) {//ユーザーの手札を左から見ていく var index = myHands.indexOf(card);//左からindex番目に - var candidateList = calculateCandidate(iAttack);//確認するカード + var candidateList = calculateCandidate();//確認するカード if (card.getValue()) { @@ -82,8 +81,8 @@ //公開されていないカードのインデックスを選ぶ(カードにかかれている番号ではない) @Override - public int selectAttacker(IAttack iAttack) { - var botHands = iAttack.getOpponentHands(); + public int selectAttacker() { + var botHands = turnBot.getOpponentHands(); for (var i : botHands) {//小さいものから選択 if (!i.getValue()) return botHands.indexOf(i); @@ -92,8 +91,8 @@ } @Override - public int selectTarget(IAttack iAttack) { - var candidate = assignCandidateNumberEachHand(iAttack); + public int selectTarget() { + var candidate = assignCandidateNumberEachHand(); int result = 0; int min = DECK_COUNT; for (var i : candidate) { @@ -106,8 +105,8 @@ } @Override - public int declareNumber(IAttack iAttack, int target) { - var array = assignCandidateNumberEachHand(iAttack).get(target); + public int declareNumber(int target) { + var array = assignCandidateNumberEachHand().get(target); return array[new Random().nextInt(array.length)]; } diff --git a/src/main/java/controls/TurnBot.java b/src/main/java/controls/TurnBot.java new file mode 100644 index 0000000..ba6d508 --- /dev/null +++ b/src/main/java/controls/TurnBot.java @@ -0,0 +1,20 @@ +package controls; + +import resources.Algo; + +public class TurnBot extends AbstractGameState{ + public TurnBot(Algo algo) { + super(algo); + } + + @Override + public void attack(int guess, int attacker, int target) { + if (isDeckLess()) { + algo.inputSelectB(guess, attacker, target); + isSucceedLatestAttack = algo.getSucceedSelectB().getKey(); + } else { + algo.inputDrawB(guess, target); + isSucceedLatestAttack = algo.getSucceedDrawB().getKey(); + } + } +} diff --git a/src/main/java/controls/TurnPlayer.java b/src/main/java/controls/TurnPlayer.java new file mode 100644 index 0000000..a7d6bff --- /dev/null +++ b/src/main/java/controls/TurnPlayer.java @@ -0,0 +1,20 @@ +package controls; + +import resources.Algo; + +public class TurnPlayer extends AbstractGameState{ + public TurnPlayer(Algo algo) { + super(algo); + } + + @Override + public void attack(int guess, int attacker, int target) { + if (isDeckLess()) { + algo.inputSelectA(guess, attacker, target); + isSucceedLatestAttack = algo.getSucceedSelectA().getKey(); + } else { + algo.inputDrawA(guess, target); + isSucceedLatestAttack = algo.getSucceedDrawA().getKey(); + } + } +} diff --git a/src/main/java/interfaces/IBotBehavior.java b/src/main/java/interfaces/IBotBehavior.java index d5e2afa..f4e096a 100644 --- a/src/main/java/interfaces/IBotBehavior.java +++ b/src/main/java/interfaces/IBotBehavior.java @@ -1,9 +1,9 @@ package interfaces; public interface IBotBehavior { - int selectAttacker(IAttack iAttack); + int selectAttacker(); - int selectTarget(IAttack iAttack); + int selectTarget(); - int declareNumber(IAttack iAttack, int target); + int declareNumber(int target); } diff --git a/src/main/java/resources/Algo.java b/src/main/java/resources/Algo.java index 4b7c627..85919fc 100644 --- a/src/main/java/resources/Algo.java +++ b/src/main/java/resources/Algo.java @@ -15,7 +15,7 @@ private SucceedSelectA succeedSelectA; private SucceedSelectB succeedSelectB; int turnCount = 0; - + boolean isATurn; public Algo() { ///モデル生成分 loseB = new LoseB(); @@ -28,6 +28,7 @@ succeedSelectA = new SucceedSelectA(handsB, handsA); succeedSelectB = new SucceedSelectB(handsA, handsB); //追加分 + isATurn = true; deck.reset(DECK_COUNT); for (int i = 0; i < 2; i++) { handsA.getValue().add(deck.head()); @@ -92,4 +93,10 @@ public Map.Entry getSucceedDrawA() { return succeedDrawA.getValue(); } + + //追加分 + public boolean isATurn() { + return isATurn; + } + public void updateTurn(){isATurn= isATurn? false : true;} } \ No newline at end of file diff --git a/src/main/java/views/MainFrame.java b/src/main/java/views/MainFrame.java index d1f9c47..4b24ea1 100644 --- a/src/main/java/views/MainFrame.java +++ b/src/main/java/views/MainFrame.java @@ -1,6 +1,7 @@ package views; import controls.StepScheduler; +import resources.Algo; import javax.swing.*; import java.awt.*; @@ -13,7 +14,7 @@ public MainFrame() { super("Algolike"); stepScheduler = new StepScheduler(); - var mainPanel = new MainPanel(stepScheduler); + var mainPanel = new MainPanel(stepScheduler, new Algo()); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainPanel.setVisible(true); @@ -22,7 +23,7 @@ this.addWindowListener(new WindowListener() { @Override public void windowOpened(WindowEvent e) { - mainPanel.playerBehave(stepScheduler); + mainPanel.playerBehave(); } @Override diff --git a/src/main/java/views/MainPanel.java b/src/main/java/views/MainPanel.java index c075c5a..9da7a1b 100644 --- a/src/main/java/views/MainPanel.java +++ b/src/main/java/views/MainPanel.java @@ -2,7 +2,10 @@ import controls.BotIntelligence; import controls.StepScheduler; +import controls.TurnBot; +import controls.TurnPlayer; import interfaces.IAttack; +import resources.Algo; import javax.swing.*; import java.awt.*; @@ -28,6 +31,9 @@ JPanel opponentButtonsPanel; JPanel opponentAttackerPanel; JPanel opponentPanel; + + TurnPlayer turnPlayer; + TurnBot turnBot; /** * アタックで使用するカードが既に決定しているか */ @@ -39,7 +45,7 @@ int indexForOpponent = 0; private JPanel deckButtonPanel; - public MainPanel(StepScheduler stepScheduler) { + public MainPanel(StepScheduler stepScheduler, Algo algo) { super(new BorderLayout()); myHandButtons = new ArrayList<>(); opponentHandButtons = new ArrayList<>(); @@ -61,12 +67,16 @@ opponentPanel.add(opponentAttackerPanel); opponentPanel.add(opponentButtonsPanel); - if (!stepScheduler.isDeckLess()) { //デッキが存在する場合 + turnPlayer = new TurnPlayer(algo); + turnBot = new TurnBot(algo); + + if (!turnPlayer.isDeckLess()) { //デッキが存在する場合 var cardButton = new JButton("deck"); cardButton.setPreferredSize(new Dimension(CARD_HEIGHT, CARD_WIDTH)); deckButtonPanel.add(cardButton); } - repaintField(stepScheduler); + + repaintField(); /** * setButton末尾にあった処理をコンストラクタ内へ。 * @@ -83,63 +93,63 @@ repaint(); } - void botBehave(IAttack iAttack) { - iAttack.updateTurn(); - var bot = new BotIntelligence(); + void botBehave() { + turnBot.updateTurn(); + var bot = new BotIntelligence(turnBot); JOptionPane.showMessageDialog(null, "Botのターンです。"); var selectText = ""; var atk = 0; - if (!iAttack.isDeckLess()) { //デッキにカードが存在するとき - paintDrawCard(iAttack);//デッキから引いたカードを描画する + if (!turnBot.isDeckLess()) { //デッキにカードが存在するとき + paintDrawCard();//デッキから引いたカードを描画する selectText = "Botはカードをドローしました。"; } else { - atk = bot.selectAttacker(iAttack); + atk = bot.selectAttacker(); opponentHandButtons.get(atk).setEnabledSelection(true); selectText = "Botはアタックに使用するカードを選びました。"; } JOptionPane.showMessageDialog(null, selectText); var targetText = ""; - var tar = bot.selectTarget(iAttack); + var tar = bot.selectTarget(); myHandButtons.get(tar).setEnabledSelection(true); JOptionPane.showMessageDialog(null, "Botはこのカードを対象にしました。"); - var dec = bot.declareNumber(iAttack, tar); + var dec = bot.declareNumber(tar); JOptionPane.showMessageDialog(null, "Botは\"" + dec + "\"を宣言しました。"); - iAttack.attack(dec, atk, tar); - boolean isSucceed = iAttack.isSucceedLatestAttack(); + turnBot.attack(dec, atk, tar); + boolean isSucceed = turnBot.isSucceedLatestAttack(); String resultMessage = "Botのアタックは "; resultMessage += isSucceed ? "成功しました。" : "失敗しました。"; JOptionPane.showMessageDialog(null, resultMessage); myHandButtons.get(tar).setEnabledSelection(false); - repaintField(iAttack); - if (isGameOver(iAttack)) { - finishGame(iAttack); + repaintField(); + if (isGameOver()) { + finishGame(); return; } - iAttack.updateTurn(); - playerBehave(iAttack); + turnPlayer.updateTurn(); + playerBehave(); } - void paintDrawCard(IAttack iAttack) { - var deckTopCard = iAttack.getTopCard(); + void paintDrawCard() { + var deckTopCard = turnPlayer.getTopCard(); - if (!iAttack.isDeckLess()) { //デッキが存在する場合にデッキトップのカードを表示する処理 + if (!turnPlayer.isDeckLess()) { //デッキが存在する場合にデッキトップのカードを表示する処理 var cardButton = new CardButton(deckTopCard.getKey().toString()); cardButton.setBounds(0, 100, CARD_WIDTH, CARD_HEIGHT); - if (iAttack.isATurn()) { + if (turnPlayer.isATurn()) { myHandAttackerPanel.add(cardButton); isDecidedAttacker = true; } else { cardButton.setText(CLOSED_SYMBOL); opponentAttackerPanel.add(cardButton); } - if (iAttack.getDeckNumber() == 1) { + if (turnPlayer.getDeckNumber() == 1) { deckButtonPanel.removeAll(); } } @@ -148,10 +158,10 @@ repaint(); } - void repaintField(IAttack iAttack) { + void repaintField() { - var myHands = iAttack.getMyHands(); - var opponentHands = iAttack.getOpponentHands(); + var myHands = turnPlayer.getMyHands(); + var opponentHands = turnBot.getOpponentHands(); /** * 初期化処理(する必要があるのかどうかは知らない) @@ -179,7 +189,7 @@ cardButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (!iAttack.isDeckLess()) return;//デッキがあるときは何も反応しないように + if (!turnPlayer.isDeckLess()) return;//デッキがあるときは何も反応しないように for (var my : myHandButtons) my.setEnabledSelection(false); cardButton.setEnabledSelection(true); var option = JOptionPane.showConfirmDialog(null, "このカードを使ってアタックをしますか?", "confirmation", 2); @@ -209,7 +219,7 @@ final int index = indexForOpponent; public void actionPerformed(ActionEvent e) { - if (!iAttack.isDeckLess()) isDecidedAttacker = true; + if (!turnBot.isDeckLess()) isDecidedAttacker = true; if (!isDecidedAttacker) { JOptionPane.showMessageDialog(null, "あなたの手札からアタックに使用するカードを選んでください. ", "Warn", JOptionPane.WARNING_MESSAGE); @@ -239,9 +249,9 @@ if (getDeclaredNumber != null) { //数字を宣言して、承認したとき guess = Integer.parseInt(getDeclaredNumber); var g = Integer.parseInt(getDeclaredNumber); - iAttack.attack(g, attacker, t); + turnPlayer.attack(g, attacker, t); - boolean isSucceed = iAttack.isSucceedLatestAttack(); + boolean isSucceed = turnPlayer.isSucceedLatestAttack(); String resultMessage = "あなたのアタックは"; resultMessage += isSucceed ? "成功しました。" : "失敗しました。"; @@ -259,12 +269,12 @@ } for (var my : myHandButtons) my.setEnabledSelection(false); cardButton.setEnabledSelection(false); - repaintField(iAttack); - if (isGameOver(iAttack)) { - finishGame(iAttack); + repaintField(); + if (isGameOver()) { + finishGame(); return; } - botBehave(iAttack); + botBehave(); } }); opponentHandButtons.add(cardButton); @@ -276,43 +286,42 @@ repaint(); } - public void playerBehave(IAttack iAttack) { + public void playerBehave() { isDecidedAttacker = false; JOptionPane.showMessageDialog(null, "あなたのターンです。"); var selectText = ""; var atk = 0; - if (!iAttack.isDeckLess()) { //デッキにカードが存在するとき - selectText = "あなたは数字\"" + iAttack.getTopCard().getKey() + "\"のカードをドローしました。"; + if (!turnPlayer.isDeckLess()) { //デッキにカードが存在するとき + selectText = "あなたは数字\"" + turnPlayer.getTopCard().getKey() + "\"のカードをドローしました。"; } else { selectText = "アタックに使用するカードを手札から選んでください。"; } - paintDrawCard(iAttack); + paintDrawCard(); JOptionPane.showMessageDialog(null, selectText); - if (!iAttack.isDeckLess()) JOptionPane.showMessageDialog(null, "アタックする対象を相手の手札から選んでください。"); + if (!turnPlayer.isDeckLess()) JOptionPane.showMessageDialog(null, "アタックする対象を相手の手札から選んでください。"); } /** * ゲームが終了しているか * - * @param iAttack - */ - boolean isGameOver(IAttack iAttack) { + * */ + boolean isGameOver() { - if (iAttack.isALose()) { + if (turnPlayer.isALose()) { return true; - } else if (iAttack.isBLose()) { + } else if (turnPlayer.isBLose()) { return true; } return false; } - void finishGame(IAttack iAttack) { - var myHands = iAttack.getMyHands(); - var opponentHands = iAttack.getOpponentHands(); + void finishGame() { + var myHands = turnPlayer.getMyHands(); + var opponentHands = turnBot.getOpponentHands(); /** * 初期化処理(する必要があるのかどうかは知らない) @@ -352,9 +361,9 @@ //ここまでが相手のカードに関する処理 validate(); repaint(); - if (iAttack.isALose()) { + if (turnPlayer.isALose()) { JOptionPane.showMessageDialog(null, "Botが勝利しました。"); - } else if (iAttack.isBLose()) { + } else if (turnBot.isBLose()) { JOptionPane.showMessageDialog(null, "あなたが勝利しました。"); } diff --git a/src/test/java/controls/BotIntelligenceTest.java b/src/test/java/controls/BotIntelligenceTest.java index 44e99ba..aa18c35 100644 --- a/src/test/java/controls/BotIntelligenceTest.java +++ b/src/test/java/controls/BotIntelligenceTest.java @@ -11,10 +11,11 @@ @Test void 正しく未確定数字を計算ができる() { StepScheduler stepScheduler=new StepScheduler(); - BotIntelligence botIntelligence=new BotIntelligence(); + var algo = stepScheduler.algo; + BotIntelligence botIntelligence=new BotIntelligence(new TurnBot(algo)); stepScheduler.isATurn = false; - var candidate=botIntelligence.calculateCandidate(stepScheduler); + var candidate=botIntelligence.calculateCandidate(); printAlgoState(algo); var s= "["; for (var i : candidate)s+=i+" "; @@ -24,9 +25,9 @@ @Test void 各手札のカードに対して候補を算出できる(){ StepScheduler stepScheduler=new StepScheduler(); - BotIntelligence botIntelligence=new BotIntelligence(); - var algo = stepScheduler.algo; + var algo = stepScheduler.algo; + BotIntelligence botIntelligence=new BotIntelligence(new TurnBot(algo)); var iniHandsANum = algo.getHandsA().size(); var initDeckNum=algo.getDeck().size(); //正解のカードを選択させるための変数 @@ -38,6 +39,6 @@ stepScheduler.isATurn = false; printAlgoState(algo); - botIntelligence.assignCandidateNumberEachHand(stepScheduler); + botIntelligence.assignCandidateNumberEachHand(); } } \ No newline at end of file