2016-06-22 2 views
1

私は現在、ゲームの実装を開発しようとしています。ほぼすべての問題のソリューションを見つけることができましたが、私は "パターン"に苦しんでいます。私が試したほとんどすべては、 "まばたき"のような正しいパターンを提供しません。私は、GUI /スイングが遅延のために間違ったパターンの理由かもしれないと思っていますが、私はそのことやそれを修正する方法についてもわかりません。スイング関連ではない構造の生命問題のゲーム

スタティックパターンと現在のコードのスクリーンショットを添付します。アドバイスをいただければ幸いです。実装された戦略インタフェースは、いくつかの整数(3 = MAX、2 = MIN)しか提供しません。インターフェイスを使って作業する

GameOfLife Patterns

GameOfLifeFrame

public class GameOfLifeFrame extends JFrame implements ActionListener{ 
    private GameOfLifeBoard gameBoard; 
    private GameOfLifeInterface gameInterface; 
    private JPanel btnPanel; 
    private JPanel jPanel; 
    private JMenuBar jMenuBar; 
    private JMenu jMenu; 
    private JButton btnStart; 
    private JButton btnStop; 

private JMenuItem jMenuItemStart; 
private JMenuItem jMenuItemStop; 
private JMenuItem jMenuItemReset; 
private JMenuItem jMenuItemExit; 
* Constructor 
*/ 
public GameOfLifeFrame(){ 
    initComponents(); 
} 

private void initComponents(){ 
    gameBoard = new GameOfLifeBoard(); 
    gameInterface = new GameOfLifeInterface(gameBoard); 
    add(gameInterface); 

    btnPanel = new JPanel(); 
    jPanel = new JPanel(); 
    setJMenu(); 

    setButtons(); 

    setTitle("Game of Life"); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setLocationByPlatform(true); 

    Dimension minDim = new Dimension(500,500); 
    Dimension prefDim = new Dimension(500,500); 
    setMinimumSize(minDim); 
    setPreferredSize(prefDim); 

    add(jMenuBar, BorderLayout.PAGE_START); 
    add(jPanel, BorderLayout.NORTH); 
    add(btnPanel, BorderLayout.SOUTH); 

    pack(); 
    setVisible(true); 
} 

/** 
* private void setJMenu 
* Creates JMenu for GameOfLife Frame 
*/ 
private void setJMenu(){ 
    jMenuBar = new JMenuBar(); 
    jMenu = new JMenu("Menü"); 
    jMenuItemStart = new JMenuItem("Start"); 
    jMenuItemStop = new JMenuItem("Stop"); 
    jMenuItemReset = new JMenuItem("Zurücksetzen"); 
    jMenuItemExit = new JMenuItem("Verlassen"); 

    //Menu ActionListener 
    jMenuItemStart.addActionListener(this); 
    jMenuItemStop.addActionListener(this); 
    jMenuItemReset.addActionListener(this); 
    jMenuItemExit.addActionListener(this); 

    //Adding MenuItem to Menu & Menu to MenuBar 
    jMenu.add(jMenuItemStart); 
    jMenu.add(jMenuItemStop); 
    jMenu.add(jMenuItemReset); 
    jMenu.add(jMenuItemExit); 
    jMenuBar.add(jMenu); 
} 

/** 
* actionPerformed 
* get Action on GUI. Reaction depends on Buttons. 
* 
* @param e ActionEvent 
*/ 
@Override 
public void actionPerformed(ActionEvent e){ 
    if(e.getSource() == jMenuItemStart){ 
     gameInterface.setActivity(true); 
     if(btnStart.getText() == "Resume"){ 
      btnStart.setText("Start"); 
     } 
    } 
    else if(e.getSource() == jMenuItemStop){ 
     gameInterface.setActivity(false); 
     if(btnStart.getText() == "Start"){ 
      btnStart.setText("Resume"); 
     } 
    } 
    else if(e.getSource() == jMenuItemReset){ 
     gameBoard.setGameBoard(gameBoard.clearGameBoard()); 
     if(!(btnStart.getText() == "Start")){ 
      btnStart.setText("Start"); 
     } 
     gameBoard.randomize(); 
    } 
    else if(e.getSource() == jMenuItemExit){ 
     System.exit(0); 
    } 
    else if(e.getSource() == btnStart){ 
     gameInterface.setActivity(true); 
     if(btnStart.getText() == "Resume"){ 
      btnStart.setText("Start"); 
     } 
    } 
    else if(e.getSource() == btnStop){ 
     gameInterface.setActivity(false); 
     btnStart.setText("Resume"); 
    } 
} 

/** 
* setButtons 
* sets Buttons Start and Stop and adds them to the Panel & ActionListener 
*/ 
private void setButtons(){ 
    btnStart = new JButton("Start"); 
    btnStop = new JButton("Stop"); 
    btnPanel.add(btnStart); 
    btnPanel.add(btnStop); 
    btnStart.addActionListener(this); 
    btnStop.addActionListener(this); 
} 

/** 
* Main Method, creates an instance of GameOfLifeFrame(GameOfLifeBoard) 
* @param args Main Method 
*/ 
public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      new GameOfLifeFrame(); 
     } 
    }); 
} 

}

GameOfLifeBoard

public class GameOfLifeBoard implements Strategy { 
    private boolean[][] gameBoard; 

public GameOfLifeBoard() { 
    this.gameBoard = new boolean[ROW][COL]; 
    for (int i = 0; i < gameBoard.length; i++) { 
     for (int j = 0; j < gameBoard[i].length; j++) { 
      gameBoard[i][j] = false; 
     } 
    } 
} 

/** 
* getGameBoard 
* @return gameBoard 
*/ 
boolean[][] getGameBoard(){ 
    return gameBoard; 
} 

/** 
* setGameBoard 
* @param boolArray two-dimensional Array 
*/ 
void setGameBoard(boolean[][] boolArray){ 
    for (int i = 0; i < boolArray.length; i++){ 
     for (int j = 0; j < boolArray[i].length; j++){ 
      gameBoard[i][j] = boolArray[i][j]; 
     } 
    } 
} 

/** 
* clearGameBoard clears the current gameBoard by setting all boolean to false 
* @return clGameBoard returns a blank gameBoard 
*/ 
boolean[][] clearGameBoard(){ 

    for (int i = 0; i < gameBoard.length; i++) { 
     for (int j = 0; j < gameBoard[i].length; j++) { 
      gameBoard[i][j] = false; 
     } 
    } 
    return gameBoard; 
} 

/** 
* nextGeneration calculates the new Generation (gameBoard) 
* using the static variables 3 and 2 (MAX and MIN) from Strategy (interface) 
* by applying the rules from Strategy 
* 
* nextGeneration uses a temporary 2D boolean Array to replace the old Generation with the new Generation 
* by looping through the current gameBoard and replacing each cell with the new status of the cell 
* in the new generation 
*/ 
void nextGeneration(){ 
    boolean[][] newGen = new boolean[ROW][COL];; 

    for (int i = 0; i < gameBoard.length; i++) { 
     for (int j = 0; j < gameBoard[i].length; j++) { 

      newGen[i][j] = gameBoard[i][j]; 

      switch (getAliveNeighbourCells(i,j)){ 
       case MAX: 
        if(getCellState(i,j)){ 
         newGen[i][j] = true; 
        } 
        else if(!getCellState(i,j)){ 
         newGen[i][j] = true; 
        } 
        break; 
       case MIN: 
        if(getCellState(i,j)){ 
         newGen[i][j] = true; 
        } 
        else if(!getCellState(i,j)){ 
         newGen[i][j] = false; 
        } 
        break; 
       default: 
        newGen[i][j] = false; 
        break; 
      } 
     } 
    } 
    for (int i = 0; i < gameBoard.length; i++) { 
     for (int j = 0; j < gameBoard[i].length; j++) { 
      gameBoard[i][j] = newGen[i][j]; 
     } 
    } 

} 

/** 
* randomize randomizes each cell on the gameBoard by setting it to true or false (25% true) 
*/ 
void randomize(){ 
    for(int i = 0; i < gameBoard.length; i++){ 
     for(int j = 0; j < gameBoard[i].length; j++){ 
      double d = Math.random(); 
      if(d <= 0.25){ 
       gameBoard[i][j] = true; 
      } 
      else{ 
       gameBoard[i][j] = false; 
      } 
     } 
    } 
} 

/** 
* getNeighbourCells, counts the surrounding cells next to the current cell 
* @param x delivers position of current cell 
* @param y delivers position of current cell 
* @return counter-1, because the loops count the current cell itself 
*/ 

private int getAliveNeighbourCells(int x, int y) { 
    int counter = 0; 
    for (int i = x-1; i <= x + 1; i++) { 
     for (int j = y-1; j <= y + 1; j++) { 
      if(i >= 0 && i < gameBoard.length-1 && j >= 0 && j < gameBoard[i].length-1){ 
       if(gameBoard[i][j]){ 
        counter++; 
       } 
      } 
     } 
    } 
    return counter; 
} 

/** 
* getCellState returns CellState of a specific cell on the gameBoard 
* @param i delivers position of current cell 
* @param j delivers position of current cell 
* @return gameBoard[i][j] returns current CellState on gameBoard at position [i][j] 
*/ 
@Override 
public boolean getCellState(int i, int j) { 
    return gameBoard[i][j]; 
} 

GameOfLifeInterface

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 


public class GameOfLifeInterface extends JPanel implements ActionListener{ 
private Timer time = new Timer(150, this); 
private GameOfLifeBoard gameBoard; 
private boolean isActive; 

/** 
* GameOfLifeInterface randomizes the gameBoard 
* @param gameBoard gets randomized by GameOfLifeBoard.randomize 
*/ 
public GameOfLifeInterface(GameOfLifeBoard gameBoard){ 
    this.gameBoard = gameBoard; 
    gameBoard.randomize(); 
} 

/** 
* paintComponent draws the current Generation (Dead Cell will be painted in white, Alive Cell in Black) 
* and restarts or stops the Timer time 
* @param graph Graphics 
*/ 

public void paintComponent(Graphics graph){ 
    super.paintComponent(graph); 
    int iBox = 2; 
    for (int i = 0; i < gameBoard.getGameBoard().length; i++) { 
     for (int j = 0; j < gameBoard.getGameBoard()[i].length; j++) { 
      graph.setColor(!gameBoard.getGameBoard()[i][j]? Color.WHITE : Color.BLACK); 
      graph.fillRect(i * iBox, j * iBox, iBox, iBox); 
     } 
    } 
    if(isActive){ 
     time.restart(); 
    } 
    else{ 
     time.stop(); 
     repaint(); 
    } 
} 

/** 
* setActivity sets private boolean: true or false 
* @param activity boolean stores decision of User (Buttons: Stop/Start) 
*/ 
public void setActivity(boolean activity){ 
    isActive = activity; 
} 

/** 
* actionPerformed if Timer time has past, the current Generation will be replaced with the new Generation 
* GameBoard gets repainted to show the new Generation 
* @param e ActionEvent 
*/ 
@Override 
public void actionPerformed(ActionEvent e) { 
    if(e.getSource().equals(time)){ 
     gameBoard.nextGeneration(); 
     repaint(); 
    } 
} 

インタフェース戦略

public interface Strategy { 
int ROW = 500; 
int COL = 500; 
int MIN = 2; 
int MAX = 3; 

boolean getCellState(int i, int j); 

}

答えて

2

あなたgetAliveNeighborCells方法が間違っています。中央のセルの値を数えます。中央のセルの値は、周囲のセルの数だけカウントする必要があります。それだけでこれらの細胞をカウントしなければならないとき

XXX 
XXX 
XXX 

だからあなたのコードは次のパターンをチェックします

XXX 
X X 
XXX 

を最も簡単な解決策は自分ifの文に条件(i != x || j != y)を追加することで、このように:

if(gameBoard[i][j] && (i != x || j != y)){ //... 

あなたのコードには他のバグがあるかもしれませんが、重要な部分がたくさん残っているので、コンパイルしてテストすることはできません。ここで

が改善/修正あなたのコードにいくつかの提案です:

代わりの通常の構成要素のようなあなたのJMenuBarを追加するには、その目的のために、明示的であるsetJMenuBar方法を、使用する必要があります。

これは文体的な決定ですが、私はあなたのsetJMenuメソッドをgetJMenuBarメソッドに変更しました。これは新しいJMenuBarを返し、呼び出し元にそれをフィールドに割り当てさせます。これに関係して、初期化後に変更すべきでないフィールドを作成することもお勧めします。final

actionPerformedの方法では、String==と比較します。これはbad ideaです。この状況では技術的には機能しますが、いつかはあなたのために予期せず失敗することはほとんどありません。代わりにStringequalsと比較する必要があります。

GameOfLifeBoardには、getGameBoardメソッドを削除し、アクセサーメソッドに置き換えて必要な情報を取得することをお勧めします。私がお勧めする方法はbool getBoardItem(int row, int col)(これは既にgetCellStateで覆われています)、int getBoardRows()int getBoardColumns(int row)です。それらは同じ情報を得ることができますが、発信者がボードを変更することはできません。

nextGenerationには、newGenの各フィールドを手動でgameBoardにコピーします。それはうまくいきますが、参照を更新するほうが速いのはgameBoard = newBoardです。

ROWCOLStrategyに定義すると、不必要に1つのサイズにロックされているようです。メソッド宣言をint getRowSize()int getColSize()に置き換え、実装が必要な値を返すようにすることができます。これにより、さまざまな実装で必要なサイズを使用できるようになります。

これは、可能な改善として私に際立つものです。

+0

不足している部分を編集して追加しようとしています。ご協力いただきありがとうございます! –

+0

あなたのソリューションを実装し、それが機能しています。ありがとう! 私のコードのさらなるバグや、より良いコードを生成するためのアドバイスを教えてもらえますか? –

+0

@ S.Neum私は、私が変えるべきことのいくつかの提案を加えました。 – resueman