1

したがって、actionListeners がアタッチされた JButton を使用するプログラムがありますが、プログラムがアクションの実行を待機する必要がある特定のポイントに達すると、待機をスキップして続行します。IOException がスローされていないことが原因なのか疑問に思っていますが、スローすると大量のエラーが返され、大きな混乱が生じます。

はい、私はコマンドラインとスイングを混在させていることを知っています。それは、コマンド ラインとして開始したためです。現在は、swing を作成しています。

誰でもこれを修正する簡単な方法を指摘できますか?

これが私のコードです:

public static void choiceRerollDice() {
            if (!canRerollDiceOne && !canRerollDiceTwo && !canRerollDiceThree && !canRerollDiceFour && !canRerollDiceFive) {
            System.out.println("Sorry, but you may not reroll any more dice...");
            displayDiceValues();
            System.exit(0);
        }
        else {
    System.out.println("Would you like to reroll any (more) dice? (yes/no)");
            area = "choiceReroll";
            }
}

public static void rerollChoice(String choiceReroll) {
    switch (choiceReroll) {
                case "yes":
                    rerollDice();
                    break;
                case "no":
                    //endTurn();
                    displayDiceValues();
                    f.validate();
                    f.repaint();
                    //calculatePlayer1Score();
                    //System.out.println("Thank you for playing!");
                    //System.out.println("Goodbye!");
                    System.exit(0);
                    break;
                default:
                    invalidInput();
    }
}

public static void rerollDice() {
    Scanner is = new Scanner(System.in);
    System.out.println("Which dice would you like to reroll? (Click the box under the dice!)");        
    rollSel = is.next();
    switch (rollSel) {
        case "roll":
        if (willRerollDiceOne) {
            if (canRerollDiceOne) {
                diceOne = 0;
                rollDiceOne();
                canRerollDiceOne = false;
                box1.setEnabled(false);
            }
            else {
                System.out.println("error");
            }
        }

        else {
        }
        if (willRerollDiceTwo) {
            if (canRerollDiceTwo) {
            diceTwo = 0;
            rollDiceTwo();
            canRerollDiceTwo = false;
            box2.setEnabled(false);
            }
            else {
                System.out.println("error");
            }
        }
        else {
        }
        if (willRerollDiceThree) {
            if (canRerollDiceThree) {
            diceThree = 0;
            rollDiceThree();
            canRerollDiceThree = false;
            box3.setEnabled(false);
            }
        }
        else {
        }
        if (willRerollDiceFour) {
            if (canRerollDiceFour) {
            diceFour = 0;
            rollDiceFour();
            canRerollDiceFour = false;
            box4.setEnabled(false);
            }
        }
        else {
        }
        if (willRerollDiceFive) {
            if (canRerollDiceFive) {
            diceFive = 0;
            rollDiceFive();
            canRerollDiceFive = false;
            box5.setEnabled(false);
            }
        }
        else {
        }
        box1.setSelected(false);
        box2.setSelected(false);
        box3.setSelected(false);
        box4.setSelected(false);
        box5.setSelected(false);
        f.validate();
        f.repaint();
            break;
        default:
            System.out.println("Error...");
            break;
    }
    choiceRerollDice();
}

JButton は次のとおりです。

public static JButton textYes = new JButton("Yes");
public static JButton textNo = new JButton("No");

actionListeners の場合:

      textYes.addActionListener(this);
      textNo.addActionListener(this);

そしてactionPerformed():

        if ("choiceReroll".equals(area)) {
            if(e.getSource() == textYes){
                rerollChoice("yes");
            }
            if(e.getSource() == textNo){
                rerollChoice("no");
            }
        }

ただし、入力を待つために停止する代わりに:

        else {
    System.out.println("Would you like to reroll any (more) dice? (yes/no)");
            area = "choiceReroll";
            }

それはただ続くrerollDice()

何か案は?

4

1 に答える 1

4

一般的な提案:

  • Scanner のほとんどの使用 (良いことです!) とブロッキング ループを取り除いたのでwhile (true)、現時点ではバックグラウンド スレッドを使用する必要はありません。私はそれを取り除き、必要な場合にのみ使用します。
  • あなたのクラスは巨大で扱いにくいため、含まれているロジックに従うのは非常に困難です。これは、コードをリファクタリングし、それぞれが独自の責任を持つ構成クラスに分割する理由の 1 つです。
  • これを行うことにより、非静的フィールドとメソッドを使用することを余儀なくされ、静的の使用のほとんどを排除することになります。これは非常に良いことです。
  • 同様に、配列と ArrayList などのリストを使用すると、冗長なコードを排除して、デバッグと変更をより簡単に行うことができます。

具体的な提案:

  • プログラム ロジックは、指示されたことだけを実行します。コードに println ステートメントを追加して、私が何を意味するかを確認してください。これを行う場合:

actionPerformed の内部:

        if ("choiceReroll".equals(area)) {
           System.out.println("choiceReroll equals area");
           if (e.getSource() == textYes) {
              System.out.println("source is textYes");
              rerollChoice("yes");
           }
           if (e.getSource() == textNo) {
              rerollChoice("no");
           }
        }

textYes ボタンが押されると rerollChoice("yes") が呼び出されることがわかります。

私が何を意味するかを見るために、コードに println を振りかけ続けてください。より具体的なレコメンドが近日公開される可能性があります。または、デバッガーの使い方を学んでから使用してください。


編集

たとえば、これは私の言いたいことの一部を示す、やや長すぎるサンプル プログラムです。いくつかのクラスと列挙型で構成されていることに注意してください。後者はオブジェクトの「状態」値を保持します。

わかりましたが、まじめな話、これまでのところ、これは私が書いたサイコロ ゲーム プログラムの中で最高のものです。ハ!

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.swing.*;
import javax.swing.border.Border;

/**
 * DiceGame.java
 * previously called Greed2.java
 * http://stackoverflow.com/questions/17264671/why-is-my-swing-program-still-advancing
 * @author Pete
 * 6/24/2013
 */
public class DiceGame {

   private static void createAndShowGui() {
      DicePanel mainPanel = new DicePanel();

      JFrame frame = new JFrame("Dice Game");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

@SuppressWarnings("serial")
class DicePanel extends JPanel {
   private static final String FIRST_ROLL_STATUS_TEXT = "Please select die to re-roll and press Second Roll";
   private static final String RESET_STATUS_TEXT = "Please press the First Roll Button";
   private static final String SECOND_ROLL_STATUS_TEXT = "Please press the Reset Button";
   private Die[] dieArray = new Die[5];
   private GameState gameState = GameState.FIRST_ROLL;
   private JButton rollButton = new JButton();
   private JButton exitButton = new JButton();
   private JTextArea messageArea = new JTextArea(20, 60);
   private Map<GameState, Action> rollActionMap = new HashMap<>();
   private JLabel statusLabel = new JLabel("  ");

   public DicePanel() {
      rollActionMap.put(GameState.FIRST_ROLL, new RollAction(this, GameState.FIRST_ROLL));
      rollActionMap.put(GameState.SECOND_ROLL, new RollAction(this, GameState.SECOND_ROLL));
      rollActionMap.put(GameState.RESET, new RollAction(this, GameState.RESET));

      exitButton.setAction(new ExitAction());

      setLayout(new BorderLayout());
      int gap = 3;
      setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
      add(statusLabel, BorderLayout.NORTH);
      add(new JScrollPane(messageArea), BorderLayout.CENTER);
      add(createSouthPanel(), BorderLayout.SOUTH);

      setGameState(GameState.RESET);
      setGameState(GameState.FIRST_ROLL);
   }

   private JPanel createSouthPanel() {
      int gap = 20;
      JPanel diePanel = new JPanel(new GridLayout(1, 0, gap, gap));
      for (int i = 0; i < dieArray.length; i++) {
         dieArray[i] = new Die();
         diePanel.add(dieArray[i].getDieLabel());
      }

      JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 10, 10));
      buttonPanel.add(rollButton);
      buttonPanel.add(exitButton);
      JPanel southPanel = new JPanel(new BorderLayout());
      southPanel.add(diePanel, BorderLayout.CENTER);
      southPanel.add(buttonPanel, BorderLayout.SOUTH);
      return southPanel;
   }

   public GameState getGameState() {
      return gameState;
   }

   public void rollAll() {
      for (Die die : dieArray) {
         die.roll();
         die.setSelectable(true);
      }
   }

   public void rollSelected() {
      for (Die die : dieArray) {
         if (die.isSelected()) {
            die.roll();
         }
         die.setSelected(false);
         die.setSelectable(false);
      }
   }

   public void setGameState(GameState gameState) {
      GameState currentState = this.gameState;
      this.gameState = gameState;
      rollButton.setAction(rollActionMap.get(gameState));

      if (currentState == GameState.RESET) {
         reset();
      } else if (currentState == GameState.FIRST_ROLL) {
         firstRoll();
      } else if (currentState == GameState.SECOND_ROLL) {
         secondRoll();
      }
   }

   private void firstRoll() {
      rollAll();
      statusLabel.setText(FIRST_ROLL_STATUS_TEXT);
   }

   private void secondRoll() {
      rollSelected();

      // TODO: calculate score and display

      statusLabel.setText(SECOND_ROLL_STATUS_TEXT);
   }

   public void reset() {
      for (Die die : dieArray) {
         die.reset();
      }
      statusLabel.setText(RESET_STATUS_TEXT);
   }
}

@SuppressWarnings("serial")
class RollAction extends AbstractAction {
   private DicePanel dicePanel;

   public RollAction(DicePanel dicePanel, GameState gameState) {
      super(gameState.getText());
      this.dicePanel = dicePanel;
      putValue(MNEMONIC_KEY, gameState.getMnemonic());
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      dicePanel.setGameState(dicePanel.getGameState().next());
   }
}

@SuppressWarnings("serial")
class ExitAction extends AbstractAction {
   private static final String EXIT = "Exit";

   public ExitAction() {
      super(EXIT);
      putValue(MNEMONIC_KEY, KeyEvent.VK_X);
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      Window win = SwingUtilities.getWindowAncestor(((Component)e.getSource()));
      win.dispose();
   }
}

enum GameState {
   FIRST_ROLL("First Roll", KeyEvent.VK_F), SECOND_ROLL("Second Roll", KeyEvent.VK_S), 
   RESET("Reset", KeyEvent.VK_R);

   private String text;
   private int mnemonic;

   private GameState(String text, int mnemonic) {
      this.text = text;
      this.mnemonic = mnemonic;
   }

   public int getMnemonic() {
      return mnemonic;
   }

   public String getText() {
      return text;
   }

   public GameState next() {
      int ordinal = ordinal();
      ordinal++;
      ordinal %= values().length;
      return values()[ordinal];
   }
}

class Die {
   private static final int BORDER_GAP = 3;
   private static final Border SELECTED_BORDER = 
         BorderFactory.createLineBorder(Color.red, BORDER_GAP);
   private static final Border UNSELECTED_BORDER = 
         BorderFactory.createEmptyBorder(BORDER_GAP, BORDER_GAP, BORDER_GAP, BORDER_GAP);

   private JLabel dieLabel = new JLabel();
   private Random random = new Random();
   private DieValue dieValue = DieValue.BLANK;
   private boolean selectable = false;
   private boolean selected = false;

   public Die() {
      reset();
      dieLabel.addMouseListener(new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent evt) {
            if (selectable) {
               setSelected(!selected);
            }
         }
      });
   }

   public Component getDieLabel() {
      return dieLabel;
   }

   public void setSelected(boolean selected) {
      this.selected = selected;
      Border border = selected ? SELECTED_BORDER : UNSELECTED_BORDER;
      dieLabel.setBorder(border);
   }

   public void roll() {
      int value = random.nextInt(6) + 1;
      dieValue = DieValue.getDieValue(value);
      dieLabel.setIcon(dieValue.getIcon());
   }

   public void reset() {
      dieValue = DieValue.BLANK;
      setSelected(false);
      setSelectable(false);
      dieLabel.setIcon(dieValue.getIcon());
   }

   public DieValue getValue() {
      return dieValue;
   }

   public boolean isSelected() {
      return selected;
   }

   public boolean isSelectable() {
      return selectable;
   }

   public void setSelectable(boolean selectable) {
      this.selectable = selectable;
   }
}

enum DieValue {
   BLANK(0, ""), 
   ONE(1, "One"), TWO(2, "Two"), THREE(3, "Three"), 
   FOUR(4, "Four"), FIVE(5, "Five"), SIX(6, "Six");

   private static final int OUT_FRAME = 110;
   private static final int ARC = 16;
   private static final float STROKE_WIDTH = 4f;
   private static final int SML_GAP = 2;
   private static final int OVAL_RADIUS = 24;
   private Icon icon;
   private String name;
   private int value;

   private DieValue(int value, String name) {
      this.value = value;
      this.name = name;
      this.icon = createIcon(value);
   }

   private Icon createIcon(int value) {
      BufferedImage img = new BufferedImage(OUT_FRAME, OUT_FRAME, 
            BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = img.createGraphics();
      Stroke stroke = new BasicStroke(STROKE_WIDTH);
      g2.setColor(Color.white);
      g2.fillRoundRect(0, 0, OUT_FRAME, OUT_FRAME, ARC, ARC);
      g2.setColor(Color.black);
      g2.setStroke(stroke);
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g2.drawRoundRect(SML_GAP, SML_GAP, OUT_FRAME - SML_GAP * 2, 
            OUT_FRAME - SML_GAP * 2, ARC, ARC);


      g2.setColor(Color.black);
      switch (value) {
      case 1:
         fillOval(g2, 1, 1);
         break;
      case 2:
         fillOval(g2, 0, 0);
         fillOval(g2, 2, 2);
         break;
      case 3:
         fillOval(g2, 0, 0);
         fillOval(g2, 1, 1);
         fillOval(g2, 2, 2);
         break;
      case 4:
         fillOval(g2, 0, 0);
         fillOval(g2, 0, 2);
         fillOval(g2, 2, 0);
         fillOval(g2, 2, 2);
         break;
      case 5:
         fillOval(g2, 0, 0);
         fillOval(g2, 0, 2);
         fillOval(g2, 1, 1);
         fillOval(g2, 2, 0);
         fillOval(g2, 2, 2);
         break;
      case 6:
         fillOval(g2, 0, 0);
         fillOval(g2, 0, 1);
         fillOval(g2, 0, 2);
         fillOval(g2, 2, 0);
         fillOval(g2, 2, 1);
         fillOval(g2, 2, 2);
         break;

      default:
         break;
      }

      g2.dispose();
      return new ImageIcon(img);
   }

   private void fillOval(Graphics2D g2, int row, int col) {
      double rectWidth = OUT_FRAME - 4 * STROKE_WIDTH;
      int x = (int) (2 * STROKE_WIDTH - OVAL_RADIUS / 2 + (col + 0.5) * rectWidth / 3);
      int y = (int) (2 * STROKE_WIDTH - OVAL_RADIUS / 2 + (row + 0.5) * rectWidth / 3);

      g2.fillOval(x, y, OVAL_RADIUS, OVAL_RADIUS);
   }

   public static DieValue getDieValue(int value) {
      for (DieValue dieImage : DieValue.values()) {
         if (dieImage.getValue() == value) {
            return dieImage;
         }
      }
      return null;
   }

   public Icon getIcon() {
      return icon;
   }

   public String getName() {
      return name;
   }

   public int getValue() {
      return value;
   }

}

これは次のように表示されます。

最初のロール: 最初のロール

2 番目のロール: セカンドロール

リセット: リセット

于 2013-06-23T20:40:32.937 に答える