【问题标题】:How can I change my class so that i can re-use it or change number of columns and rows? [closed]如何更改我的班级以便我可以重新使用它或更改列数和行数? [关闭]
【发布时间】:2020-04-22 18:25:40
【问题描述】:

所以,我正在开展一个项目,我希望能够将相同的棋盘用于不同的游戏,只需更改列数和行数。到目前为止,我有四个班级和两个枚举,但我的问题是如何制作类似通用板的东西来玩井字游戏并连接四个?我会在下面添加我的课程。

Board.java

package Board;

import java.awt.*;

import Cells.Cell;
import Cells.Properties;

/**
 * The Board class models the ROWS-by-COLS game-board.
 */
public class BoardTTT {
      // Named-constants for the game board
       public static final int ROWS = 3;  // ROWS by COLS cells
       public static final int COLS = 3;
       public static final String TITLE = "Tic Tac Toe";

       // Name-constants for the various dimensions used for graphics drawing
       public static final int CELL_SIZE = 100; // cell width and heigh (square)
       public static final int CANVAS_WIDTH = CELL_SIZE * COLS;  // the drawing canvas
       public static final int CANVAS_HEIGHT = CELL_SIZE * ROWS;
       public static final int GRID_WIDTH = 8;  // Grid-line's width
       public static final int GRID_WIDHT_HALF = GRID_WIDTH / 2; // Grid-line's half-width
       // Symbols (cross/nought) are displayed inside a cell, with padding from border
       public static final int CELL_PADDING = CELL_SIZE / 6;
       public static final int SYMBOL_SIZE = CELL_SIZE - CELL_PADDING * 2;
       public static final int SYMBOL_STROKE_WIDTH = 8; // pen's stroke width

   // package access
   private Cell[][] cells; // composes of 2D array of ROWS-by-COLS Cell instances

   /** Constructor to initialize the game board */
   public BoardTTT() {
      setCells(new Cell[ROWS][COLS]); // allocate the array
      for (int row = 0; row < ROWS; ++row) {
         for (int col = 0; col < COLS; ++col) {
            getCells()[row][col] = new Cell(row, col); // allocate element of array
         }
      }
   }

   /** Initialize (or re-initialize) the game board */
   public void init() {
      for (int row = 0; row < ROWS; ++row) {
         for (int col = 0; col < COLS; ++col) {
            getCells()[row][col].clear(); // clear the cell content
         }
      }
   }

   /** Return true if it is a draw (i.e., no more EMPTY cell) */
   public boolean isDraw() {
      for (int row = 0; row < ROWS; ++row) {
         for (int col = 0; col < COLS; ++col) {
            if (getCells()[row][col].content == Properties.EMPTY) {
               return false; // an empty Properties found, not a draw, exit
            }
         }
      }
      return true; // no empty cell, it's a draw
   }

   /** Return true if the player with "Properties" has won after placing at
       (PropertiesRow, PropertiesCol) */
   public boolean hasWon(Properties Properties, int PropertiesRow, int PropertiesCol) {
      return (getCells()[PropertiesRow][0].content == Properties   // 3-in-the-row
                 && getCells()[PropertiesRow][1].content == Properties
                 && getCells()[PropertiesRow][2].content == Properties
             || getCells()[0][PropertiesCol].content == Properties // 3-in-the-column
                 && getCells()[1][PropertiesCol].content == Properties
                 && getCells()[2][PropertiesCol].content == Properties
             || PropertiesRow == PropertiesCol              // 3-in-the-diagonal
                 && getCells()[0][0].content == Properties
                 && getCells()[1][1].content == Properties
                 && getCells()[2][2].content == Properties
             || PropertiesRow + PropertiesCol == 2          // 3-in-the-opposite-diagonal
                 && getCells()[0][2].content == Properties
                 && getCells()[1][1].content == Properties
                 && getCells()[2][0].content == Properties);
   }

   /** Paint itself on the graphics canvas, given the Graphics context */
   public void paint(Graphics g) {
      // Draw the grid-lines
      g.setColor(Color.GRAY);
      for (int row = 1; row < ROWS; ++row) {
         g.fillRoundRect(0, CELL_SIZE * row - GRID_WIDHT_HALF,
               CANVAS_WIDTH - 1, GRID_WIDTH,
               GRID_WIDTH, GRID_WIDTH);
      }
      for (int col = 1; col < COLS; ++col) {
         g.fillRoundRect(CELL_SIZE * col - GRID_WIDHT_HALF, 0,
               GRID_WIDTH, CANVAS_HEIGHT - 1,
               GRID_WIDTH, GRID_WIDTH);
      }

      // Draw all the cells
      for (int row = 0; row < ROWS; ++row) {
         for (int col = 0; col < COLS; ++col) {
            getCells()[row][col].paint(g);  // ask the cell to paint itself
         }
      }
   }

public Cell[][] getCells() {
    return cells;
}

public void setCells(Cell[][] cells) {
    this.cells = cells;
}
}

Cell.java

package Cells;
import java.awt.*;

import Board.BoardTTT;

/**
 * The Cell class models each individual cell of the game BoardTTT.
 */
public class Cell {
   // Package access
   public Properties content; // content of this cell (Properties.EMPTY, Properties.CROSS, or Properties.NOUGHT)
   int row, col; // row and column of this cell

   /** Constructor to initialize this cell with the specified row and col */
   public Cell(int row, int col) {
      this.row = row;
      this.col = col;
      clear(); // clear content
   }

   /** Clear this cell's content to EMPTY */
   public void clear() {
      setContent(Properties.EMPTY);
   }

   /** Paint itself on the graphics canvas, given the Graphics context */
   public void paint(Graphics g) {
      // Use Graphics2D which allows us to set the pen's stroke
      Graphics2D g2d = (Graphics2D)g;
      g2d.setStroke(new BasicStroke(BoardTTT.SYMBOL_STROKE_WIDTH,
            BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); // Graphics2D only
      // Draw the Properties if it is not empty
      int x1 = col * BoardTTT.CELL_SIZE + BoardTTT.CELL_PADDING;
      int y1 = row * BoardTTT.CELL_SIZE + BoardTTT.CELL_PADDING;
      if (getContent() == Properties.CROSS) {
         g2d.setColor(Color.RED);
         int x2 = (col + 1) * BoardTTT.CELL_SIZE - BoardTTT.CELL_PADDING;
         int y2 = (row + 1) * BoardTTT.CELL_SIZE - BoardTTT.CELL_PADDING;
         g2d.drawLine(x1, y1, x2, y2);
         g2d.drawLine(x2, y1, x1, y2);
      } else if (getContent() == Properties.NOUGHT) {
         g2d.setColor(Color.BLUE);
         g2d.drawOval(x1, y1, BoardTTT.SYMBOL_SIZE, BoardTTT.SYMBOL_SIZE);
      }
   }

public Properties getContent() {
    return content;
}

public void setContent(Properties content) {
    this.content = content;
}
}

超级游戏

package Game;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import Board.BoardTTT;
import Cells.Properties;

import Cells.Cell;
/**
 * Tic-Tac-Toe: Two-player Graphic version with better OO design.
 * The Board and Cell classes are separated in their own classes.
 */

public class SuperGame extends JPanel{

   public BoardTTT board;            // the game board
   public GameState currentState; // the current state of the game
   public Properties currentPlayer;     // the current player
   public JLabel statusBar;       // for displaying status message

   /** Constructor to setup the UI and game components */
   public SuperGame() {



      // Setup the status bar (JLabel) to display status message
      statusBar = new JLabel("         ");
      statusBar.setFont(new Font(Font.DIALOG_INPUT, Font.BOLD, 14));
      statusBar.setBorder(BorderFactory.createEmptyBorder(2, 5, 4, 5));
      statusBar.setOpaque(true);
      statusBar.setBackground(Color.LIGHT_GRAY);

      setLayout(new BorderLayout());
      add(statusBar, BorderLayout.PAGE_END); // same as SOUTH
      setPreferredSize(new Dimension(BoardTTT.CANVAS_WIDTH, BoardTTT.CANVAS_HEIGHT + 30));
            // account for statusBar in height
      board = new BoardTTT();   // allocate the game-board
      initGame();  // Initialize the game variables
   }


   /** Initialize the game-board contents and the current-state */
   public void initGame() {
      for (int row = 0; row < BoardTTT.ROWS; ++row) {
         for (int col = 0; col < BoardTTT.COLS; ++col) {
            board.getCells()[row][col].content = Properties.EMPTY; // all cells empty
         }
      }
      currentState = GameState.PLAYING;  // ready to play
      currentPlayer = Properties.CROSS;        // cross plays first


}

   /** Update the currentState after the player with "theProperties" has placed on (row, col) */
   public void updateGame(Properties theProperties, int row, int col) {
      if (board.hasWon(theProperties, row, col)) {  // check for win
         currentState = (theProperties == Properties.CROSS) ? GameState.CROSS_WON : GameState.NOUGHT_WON;
      } else if (board.isDraw()) {  // check for draw
         currentState = GameState.DRAW;
      }
      // Otherwise, no change to current state (PLAYING).
   }

   /** Custom painting codes on this JPanel */
   @Override
   public void paintComponent(Graphics g) {  // invoke via repaint()
      super.paintComponent(g);    // fill background
      setBackground(Color.WHITE); // set its background color

      board.paint(g);  // ask the game board to paint itself

      // Print status-bar message
      if (currentState == GameState.PLAYING) {
         statusBar.setForeground(Color.BLACK);
         if (currentPlayer == Properties.CROSS) {
            statusBar.setText("X's Turn");
         } else {
            statusBar.setText("O's Turn");
         }
      } else if (currentState == GameState.DRAW) {
         statusBar.setForeground(Color.RED);
         statusBar.setText("It's a Draw! Click to play again.");
      } else if (currentState == GameState.CROSS_WON) {
         statusBar.setForeground(Color.RED);
         statusBar.setText("'X' Won! Click to play again.");
      } else if (currentState == GameState.NOUGHT_WON) {
         statusBar.setForeground(Color.RED);
         statusBar.setText("'O' Won! Click to play again.");
      }
   }
}

MainTTT.java

package Game;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import Board.BoardTTT;
import Cells.Properties;
import Cells.Cell;
/**
 * Tic-Tac-Toe: Two-player Graphic version with better OO design.
 * The Board and Cell classes are separated in their own classes.
 */

public class MainTTT extends SuperGame{

   /** Constructor to setup the UI and game components */
   public MainTTT() {

      // This JPanel fires MouseEvent
      this.addMouseListener(new MouseAdapter() {
         @Override
         public void mouseClicked(MouseEvent e) {  // mouse-clicked handler
            int mouseX = e.getX();
            int mouseY = e.getY();
            // Get the row and column clicked
            int rowSelected = mouseY / BoardTTT.CELL_SIZE;
            int colSelected = mouseX / BoardTTT.CELL_SIZE;

            if (currentState == GameState.PLAYING) {
               if (rowSelected >= 0 && rowSelected < BoardTTT.ROWS
                     && colSelected >= 0 && colSelected < BoardTTT.COLS
                     && board.getCells()[rowSelected][colSelected].content == Properties.EMPTY) {
                  board.getCells()[rowSelected][colSelected].content = currentPlayer; // move
                  updateGame(currentPlayer, rowSelected, colSelected); // update currentState
                  // Switch player
                  currentPlayer = (currentPlayer == Properties.CROSS) ? Properties.NOUGHT : Properties.CROSS;
               }
            } else {        // game over
               initGame();  // restart the game
            }
            // Refresh the drawing canvas
            repaint();  // Call-back paintComponent().
         }
      });

   }



   /** The entry "main" method */
   public static void main(String[] args) {
      // Run GUI construction codes in Event-Dispatching thread for thread safety
      javax.swing.SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            JFrame frame = new JFrame(BoardTTT.TITLE);
            // Set the content-pane of the JFrame to an instance of main JPanel
            frame.setContentPane(new MainTTT());
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setLocationRelativeTo(null); // center the application window
            frame.setVisible(true);            // show it
         }
      });
   }
}

Properties.java

package Cells;

public enum Properties {
    EMPTY, CROSS, NOUGHT;

}

游戏状态

package Game;

public enum GameState {
    PLAYING, DRAW, CROSS_WON, NOUGHT_WON
}

【问题讨论】:

  • 如果您希望能够重用类并更改列数和行数,请不要将COLSROWS 指定为常量,而是将它们作为参数传递给构造函数。我真的很困惑为什么这不明显,特别是如果你足够先进,可以编写所有其他代码。

标签: java inheritance interface


【解决方案1】:

你需要继承之类的东西:

abstract class Board{
   private int rows;
   private int cols;

   public int getRows(){
     return this.rows;
   }

   public void setRows(int rows){
     this.rows = rows;
   }

   public int getCols(){
     return this.cols;
   }

   public void setCols(int cols){
     this.cols = cols;
   }

}


class TicTacToe extends Board{
  //implement different values if you want, use @Override for example or set value in the constructor
}

class ConnectFour extends Board{
 //implement different values if you want, use @Override for example or set value in the constructor
}

【讨论】:

    猜你喜欢
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多