实施MVC模型 [英] Implementing the MVC model
问题描述
每当我在SO上需要帮助时,都会要求我发布遵循MVC模型的代码.所以上网了,读了一些关于模型的主题,但是仍然不能正确理解这个概念.以下面的代码为例,我正在尝试使其适应MVC模型.有谁知道如何实现这一目标?
Whenever I need help here on SO, I'm asked to post code which follows the MVC model. So went online, read some subject regarding the model but still can't yet understand properly this concept. With the below code for example, I'm trying to adapt it to the MVC model. Does anyone have an idea how to achieve this?
下面的代码绘制2D阵列网格,在单元格内部绘制椭圆形,搜索单元格的邻居,找到通过单元格的路径,然后绘制路径中所有单元格经过的线.
The codes below draw a 2D array grid, paint oval inside cells, search for cells' neighbors, find a path through cells then draw lines passing by all cell within the path.
它包括测试用例,以帮助您更好地了解其工作原理.
It includes test cases to help you better understand how it works.
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Stack;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public final class Pha extends JFrame {
//a collection of cells in the path.
//each cell represented by [row,col]
private Stack<int[]> path;
// legth
//a path shorter than min can not surround any cell
private static final int MIN_PATH_LENGTH = 4;
//a collection of cells that has been tested
private ArrayList<int[]> checked;
//represents the cell where the search starts from
int[] origin;
//represents the token of the origin
Token originToken;
private static int ROWS = 15;
private static int COLS = ROWS;
private static int cellSize = 15;
private static int canvasWidth = (cellSize * COLS) + (ROWS *4) ;
private static int canvasHeight = cellSize * ROWS ;
private static int gridWidth = 1;
private static int halfGridWidth = gridWidth / 2;
private static int cellPadding = cellSize / 5;
private static int symbolSize = cellSize - (cellPadding * 2);
private static int symbolStrokeWidth = 3;
private enum Token{
VIDE, CERCLE_ROUGE, CERCLE_BLEU
}
private Token[][] board;
private final DrawCanvas canvas;
private GameState actualState;
public enum GameState{
JOUE, NUL, CERCLE_ROUGE_GAGNE, CERCLE_BLEU_GAGNE
}
private Token actualPlayer;
//used to set different test data
private static int testNumber = 0;
public Pha(){
canvas = new DrawCanvas();
canvas.setPreferredSize(new Dimension(canvasWidth, canvasHeight));
canvas.addMouseListener(new MouseAdapter(){
@Override
public void mouseClicked(MouseEvent e){
int x = e.getX();
int y = e.getY();
int selectedRow = y / cellSize;
int selectedCol = x / cellSize;
if(actualState == GameState.JOUE){
if(selectedRow >= 0 && selectedRow < ROWS && selectedCol >= 0
&& selectedCol < COLS && board[selectedRow][selectedCol] == Token.VIDE){
board[selectedRow][selectedCol] = actualPlayer;
updateGame(actualPlayer, selectedRow, selectedCol);
actualPlayer = (actualPlayer == Token.CERCLE_BLEU) ? Token.CERCLE_ROUGE : Token.CERCLE_BLEU;
findPath(new int[]{selectedRow, selectedCol});
}
}else{
initGame();
}
repaint();
}
});
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
cp.add(canvas, BorderLayout.EAST);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setTitle("Pha par esQmo");
setVisible(true);
board = new Token[ROWS][COLS];
initGame();
//fill some data for testing
int[] origin = loadtestData(board);
//int[] origin = new int[] {this.getX(),this.getY()};
findPath(origin);
}
private void initGame(){
for(int ligne = 0; ligne < ROWS; ++ligne){
for(int colonne = 0; colonne < COLS; ++colonne){
board[ligne][colonne] = Token.VIDE;
}
}
actualState = GameState.JOUE;
actualPlayer = Token.CERCLE_ROUGE;
}
public void updateGame(Token theSeed, int ligneSelectionnee, int colonneSelectionnee) {
/* if (aGagne(theSeed, ligneSelectionnee, colonneSelectionnee)) { // check for win
actualState= (theSeed == Token.CERCLE_ROUGE) ? GameState.CERCLE_ROUGE_GAGNE : GameState.CERCLE_BLEU_GAGNE;
} else if (estNul()) { // check for draw
actualState = GameState.CERCLE_BLEU_GAGNE;
}*/
// Otherwise, no change to current state (still GameState.PLAYING).
}
//search for a path
private void findPath(int[] origin) {
//initialize path and checked
path = new Stack<>();
this.origin = origin;
int row = origin[0], col = origin[1];
//represents the token of the origin
originToken = board[row][col];
//initialize list of checked items
checked = new CellsList();
boolean found = findPath(row, col);
if(found) {
printPath();
} else {
System.out.println("No path found");
}
}
//recursive method to find path. a cell is represented by its row, col
//returns true when path was found
private boolean findPath(int row, int col) {
//check if cell has the same token as origin
if(board[row][col] != originToken) {
return false;
}
int[] cell = new int[] {row, col};
//check if this cell was tested before to avoid checking again
if(checked.contains(cell)) {
return false;
}
//get cells neighbors
CellsList neighbors = getNeighbors(row, col);
//check if solution found. If path size > min and cell
//neighbors contain the origin, it means that path was found
if((path.size() > MIN_PATH_LENGTH) && neighbors.contains(origin) ) {
path.add(cell);
return true;
}
//add cell to checked
checked.add(cell);
//add cell to path
path.add(cell);
//if path was not found check cell neighbors
for(int[] neighbor : neighbors ) {
boolean found = findPath(neighbor[0],neighbor[1]);
if(found) {
return true;
}
}
//path not found
path.pop(); //remove last element from stack
return false;
}
//return a list of all neighbors of cell row, col
private CellsList getNeighbors(int row, int col) {
CellsList neighbors = new CellsList();
for (int colNum = col - 1 ; colNum <= (col + 1) ; colNum +=1 ) {
for (int rowNum = row - 1 ; rowNum <= (row + 1) ; rowNum +=1 ) {
if(!((colNum == col) && (rowNum == row))) {
if(withinGrid (rowNum, colNum ) ) {
neighbors.add(new int[] {rowNum, colNum});
}
}
}
}
return neighbors;
}
private boolean withinGrid(int colNum, int rowNum) {
if((colNum < 0) || (rowNum <0) ) {
return false;
}
if((colNum >= COLS) || (rowNum >= ROWS)) {
return false;
}
return true;
}
private void printPath() {
System.out.print("Path : " );
for(int[] cell : path) {
System.out.print(Arrays.toString(cell));
}
System.out.println("");
}
class DrawCanvas extends JPanel{
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
setBackground(Color.WHITE);
g.setColor(Color.BLACK);
for(int ligne = 1; ligne < ROWS; ++ligne){
g.fillRoundRect(0, (cellSize * ligne) - halfGridWidth, canvasWidth - 1,
gridWidth, gridWidth, gridWidth);
}
for(int colonne = 1; colonne < COLS; ++colonne){
g.fillRoundRect((cellSize * colonne) - halfGridWidth, 0
, gridWidth, canvasHeight - 1,
gridWidth, gridWidth);
}
Graphics2D g2d = (Graphics2D)g;
g2d.setStroke(new BasicStroke(symbolStrokeWidth,
BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
for(int ligne = 0; ligne < ROWS; ++ligne){
for(int colonne = 0; colonne < COLS; ++colonne){
int x1 = (colonne * cellSize) + cellPadding;
int y1 = (ligne * cellSize) + cellPadding;
if(board[ligne][colonne] == Token.CERCLE_ROUGE){
g2d.setColor(Color.RED);
g2d.drawOval(x1, y1, symbolSize, symbolSize);
g2d.fillOval(x1, y1, symbolSize, symbolSize);
} else
if(board[ligne][colonne] == Token.CERCLE_BLEU){
int x2 = (colonne * cellSize) + cellPadding;
g2d.setColor(Color.BLUE);
g2d.drawOval(x1, y1, symbolSize, symbolSize);
g2d.fillOval(x2, y1, symbolSize, symbolSize);
}
}
}
//draw lines
/* Stack<int[]> drawingPath = new Stack<>();
drawingPath.addAll(path);
drawingPath.add(drawingPath.get(0));
Point startPoint = null;
for (int[] cell : path){
Point endPoint = new Point((cell[1] * cellSize) + cellSize / 2, (cell[0] * cellSize) + cellSize / 2);
if (startPoint != null) {
//Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(new BasicStroke(symbolStrokeWidth,
BasicStroke.CAP_SQUARE, BasicStroke.CAP_BUTT));
g2d.draw(new Line2D.Double(startPoint, endPoint));
}
startPoint = endPoint;
}
*/
Stack<int[]> drawingPath = new Stack<>();
drawingPath.addAll(path);
drawingPath.add(drawingPath.get(0));
Point startPoint = null;
for (int[] cell : drawingPath) {
System.out.println(cell[1] + "," + cell[0]);
Point endPoint = new Point((cell[1] * cellSize) + cellSize / 2, (cell[0] * cellSize) + cellSize / 2);
if (startPoint != null) {
g2d.draw(new Line2D.Double(startPoint, endPoint));
}
startPoint = endPoint;
}
}
}
public static void main(String[] args){
//set test number. Change values between 0-2 to run different tests
testNumber = 2;
SwingUtilities.invokeLater(() -> {
// new Pha();
Pha pha = new Pha();
});
}
//method used for testing only: load test data
private static int[] loadtestData(Token[][] board) {
switch (testNumber) {
case 1:
board[6][6] = Token.CERCLE_ROUGE; //origin and target
board[6][7] = Token.CERCLE_ROUGE;
board[6][8] = Token.CERCLE_BLEU;
board[9][9] = Token.CERCLE_BLEU;
board[7][6] = Token.CERCLE_ROUGE;
board[7][7] = Token.CERCLE_BLEU;
board[7][8] = Token.CERCLE_BLEU;
board[8][6] = Token.CERCLE_ROUGE;
board[8][7] = Token.CERCLE_ROUGE;
board[8][8] = Token.CERCLE_ROUGE;
board[5][7] = Token.CERCLE_ROUGE;
board[5][8] = Token.CERCLE_ROUGE;
board[5][9] = Token.CERCLE_ROUGE;
board[6][9] = Token.CERCLE_ROUGE;
board[7][9] = Token.CERCLE_ROUGE;
return new int[] {6,6};
case 2:
//line 3
board[3][6] = Token.CERCLE_ROUGE;
//line 4
board[4][4] = Token.CERCLE_BLEU; //origin
board[4][5] = Token.CERCLE_BLEU;
board[4][6] = Token.CERCLE_BLEU;
board[4][8] = Token.CERCLE_BLEU;
//line5
board[5][3] = Token.CERCLE_BLEU;
board[5][5] = Token.CERCLE_ROUGE;
board[5][7] = Token.CERCLE_BLEU;
board[5][8] = Token.CERCLE_ROUGE;
board[5][9] = Token.CERCLE_BLEU;
//line 6
board[6][2] = Token.CERCLE_BLEU;
board[6][3] = Token.CERCLE_ROUGE;
board[6][4] = Token.CERCLE_ROUGE;
board[6][5] = Token.CERCLE_ROUGE;
board[6][6] = Token.CERCLE_ROUGE;
board[6][7] = Token.CERCLE_ROUGE;
board[6][8] = Token.CERCLE_ROUGE;
board[6][9] = Token.CERCLE_BLEU;
//line 7
board[7][3] = Token.CERCLE_BLEU;
board[7][4] = Token.CERCLE_BLEU;
board[7][5] = Token.CERCLE_BLEU;
board[7][6] = Token.CERCLE_BLEU;
board[7][7] = Token.CERCLE_ROUGE;
board[7][8] = Token.CERCLE_BLEU;
//line 8
board[8][3] = Token.CERCLE_ROUGE;
board[8][7] = Token.CERCLE_BLEU;
board[8][8] = Token.CERCLE_ROUGE;
board[8][9] = Token.CERCLE_BLEU;
//line 9
board[9][7] = Token.CERCLE_ROUGE;
board[9][8] = Token.CERCLE_BLEU;
board[9][9] = Token.CERCLE_ROUGE;
//line 10
board[10][8] = Token.CERCLE_ROUGE;
board[10][9] = Token.CERCLE_ROUGE;
return new int[] {4,4};
case 0: default:
board[6][6] = Token.CERCLE_ROUGE;
board[6][7] = Token.CERCLE_ROUGE; //origin and target
board[6][8] = Token.CERCLE_BLEU;
board[7][6] = Token.CERCLE_ROUGE;
board[7][7] = Token.CERCLE_BLEU;
board[7][8] = Token.CERCLE_ROUGE;
board[8][6] = Token.CERCLE_ROUGE;
board[8][7] = Token.CERCLE_ROUGE;
board[8][8] = Token.CERCLE_ROUGE;
board[5][7] = Token.CERCLE_ROUGE;
board[5][8] = Token.CERCLE_ROUGE;
board[5][9] = Token.CERCLE_ROUGE;
board[6][9] = Token.CERCLE_ROUGE;
board[7][9] = Token.CERCLE_ROUGE;
return new int[] {6,7};
}
}
}
class CellsList extends ArrayList<int[]>{
@Override //override to check by the value of int[]
public boolean contains(Object o) {
for (int[] a : this) {
if(Arrays.equals(a, (int[]) o)) {
return true;
}
}
return false;
}
}
推荐答案
My answer is based on the MCV model suggested by Hovercraft Full Of Eels in this post.
I made an effort to simplify it a little, added some comments, and adapted it to your code.
I also added path finding calculation.
The code contains 7 classes. I had each class in a separate file, all live in the same folder :
主类
import javax.swing.SwingUtilities;
public class MvcPha {
public static void main(String[] args) {
// run all on the Swing event thread
SwingUtilities.invokeLater(() -> {
Model model = new Model();
View view = new View();
new Control(model, view);
});
}
}
控件类
import java.beans.IndexedPropertyChangeEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.SwingUtilities;
public class Control {
private Model model;
private View view;
private Token lastToken;
public Control(Model model, View view) {
this.model = model;
this.view = view;
lastToken = Token.CERCLE_BLEU;
view.createGrid(model.getRows(), model.getCols());
view.addPropertyChangeListener(new ViewListener());
model.addPropertyChangeListener(Model.TOKEN, new ModelListener());
view.start();
}
//a listener added to view panel to listen to property changes events
//fired by the mouse listener of each cell
private class ViewListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(View.CELL_SELECTION)) {
int row = view.getSelectedRow();
int col = view.getSelectedCol();
Token token = model.getToken(row, col);
if (token == Token.VIDE) {
lastToken = (lastToken == Token.CERCLE_BLEU) ?
Token.CERCLE_ROUGE : Token.CERCLE_BLEU;
token = lastToken;
}
model.setToken(token, row, col);
}
}
}
//listener added to model to listen to token changes. used to updated view
//when token changes
private class ModelListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
IndexedPropertyChangeEvent iEvt = (IndexedPropertyChangeEvent)evt;
int index = iEvt.getIndex();
int row = index / Model.COLS;
int col = index % Model.COLS;
Token token = (Token) evt.getNewValue();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
view.setCell(token, row, col);
view.setPath(model.getPath());
view.refresh();
}
});
}
}
}
模型类
import java.beans.PropertyChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;
public class Model {
public static final int ROWS = 20;
public static final int COLS = ROWS;
public static final String TOKEN = "token";
private Token[][] grid = new Token[ROWS][COLS];
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
//a stack representing cells in the path
private Path path;
public Model() {
//set entire grid to Token.VIDE
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
grid[r][c] = Token.VIDE;
}
}
}
Token getToken(int row, int col) {
return grid[row][col];
}
void setToken(Token token, int row, int col) {
Token oldValue = grid[row][col];
Token newValue = token;
grid[row][col] = token;
int index = (row * grid[row].length) + col;
pcSupport.fireIndexedPropertyChange(TOKEN, index, oldValue, newValue);
findPath(new int[] {row, col});
}
void addPropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(name, listener);
}
int getRows() {
return ROWS;
}
int getCols() {
return COLS;
}
//search for a path
private void findPath(int[] origin) {
//initialize path and checked
path = new Path(grid);
path.findPath(origin);
}
CellsList getPath() {
return (path == null ) ? null : path.getPath();
}
}
查看课程
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeListener;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class View {
private static final int ICON_W = 18;
public static final String CELL_SELECTION = "cell selection";
private int rows;
private JPanel mainPanel;
private JLabel[][] grid;
private Map<Token, Icon> iconMap = new EnumMap<>(Token.class);
private int selectedRow;
private int selectedCol;
//a collection of cells representing a path
private CellsList path;
View() {
iconMap.put(Token.VIDE, createIcon(new Color(0, 0, 0, 0)));
iconMap.put(Token.CERCLE_BLEU, createIcon(Color.BLUE));
iconMap.put(Token.CERCLE_ROUGE, createIcon(Color.RED));
mainPanel = new JPanel();
}
private Icon createIcon(Color color) {
BufferedImage img = new BufferedImage(ICON_W, ICON_W, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(color);
g2.fillOval(1, 1, ICON_W - 2, ICON_W - 2);
g2.dispose();
return new ImageIcon(img);
}
void createGrid(int rows, int cols) {
MyMouseListener listener = new MyMouseListener();
setRows(rows);
mainPanel.setLayout(new GridLayout(rows, cols, 1, 1));
mainPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
mainPanel.setBackground(Color.BLACK);
grid = new JLabel[rows][cols];
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
grid[r][c] = new JLabel(iconMap.get(Token.VIDE));
grid[r][c].addMouseListener(listener);
grid[r][c].setOpaque(true);
grid[r][c].setBackground(Color.WHITE);
mainPanel.add(grid[r][c]);
}
}
}
int getSelectedRow() {
return selectedRow;
}
int getSelectedCol() {
return selectedCol;
}
void setCell(Token token, int row, int col) {
grid[row][col].setIcon(iconMap.get(token));
}
int getRows() {
return rows;
}
void setRows(int rows) {
this.rows = rows;
}
//added to each cell to listen to mouse clicks
//fires property change with cell index
private class MyMouseListener extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
JLabel selection = (JLabel) e.getSource();
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
if (selection == grid[r][c]) {
selectedRow = r;
selectedCol = c;
int index = (r * grid[r].length) + c;
mainPanel.firePropertyChange(CELL_SELECTION, -1, index);
}
}
}
}
}
void start() {
JFrame frame = new JFrame("MVC Pha");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
//add listener to listen to property changes fired by MyMouseListener
void addPropertyChangeListener(PropertyChangeListener viewListener) {
mainPanel.addPropertyChangeListener(viewListener);
}
void setPath(CellsList path) {
this.path = path;
if(path != null) {
drawPath();
}
}
//highlight path by changing background color.
//It can be changed to draw lines between cells
private void drawPath() {
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
if((path != null) && path.contains(new int[] {r,c})) {
grid[r][c].setBackground(Color.YELLOW);
} else {
grid[r][c].setBackground(Color.WHITE);
}
}
}
}
void refresh() {
mainPanel.repaint();
}
}
路径类以处理路径查找(仍需要进行一些调试)
Path class to handle path finding (still needs some debugging)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Stack;
//a stack representing cells in the path
//each cell represented by [row,col]
class Path extends Stack<int[]>{
private Token[][] grid;
//a path shorter than min can not surround any cell
private static final int MIN_PATH_LEGTH = 3;
//a collection of cells that has been tested
private ArrayList<int[]>checked;
//represents the cell where the search starts from
int[] origin;
//represents the token of the origin
Token originToken;
private int rows;
private int cols;
Path(Token[][] grid){
this.grid = grid;
rows = grid.length;
cols = grid[0].length;
}
//search for a path
boolean findPath(int[] origin) {
this.origin = origin;
int row = origin[0] , col = origin[1];
//represents the token of the origin
originToken = grid[row][col];
//initialize list of checked items
checked = new CellsList();
boolean found = findPath(row, col);
if(found) {
printPath();
} else {
System.out.println("No path found");
}
return found;
}
//recursive method to find path. a cell is represented by its row, col
//returns true when path was found
private boolean findPath(int row, int col) {
//check if cell has the same token as origin
if(grid[row][col] != originToken) {
return false;
}
int[] cell = new int[] {row, col};
//check if this cell was tested before to avoid checking again
if(checked.contains(cell)) {
return false;
}
//get cells neighbors
CellsList neighbors = getNeighbors(row, col);
//check if solution found. If path size > min and cell
//neighbors contain the origin it means that path was found
if((size() >= MIN_PATH_LEGTH) && neighbors.contains(origin) ) {
add(cell);
return true;
}
//add cell to checked
checked.add(cell);
//add cell to path
add(cell);
//if path was not found check cell neighbors
for(int[] neighbor : neighbors ) {
boolean found = findPath(neighbor[0],neighbor[1]);
if(found) {
return true;
}
}
//path not found
pop(); //remove last element from stack
return false;
}
//return a list of all neighbors of cell row, col
private CellsList getNeighbors(int row, int col) {
CellsList neighbors = new CellsList();
for (int colNum = col - 1 ; colNum <= (col + 1) ; colNum +=1 ) {
for (int rowNum = row - 1 ; rowNum <= (row + 1) ; rowNum +=1 ) {
if(!((colNum == col) && (rowNum == row))) {
if(withinGrid (rowNum, colNum ) ) {
neighbors.add( new int[] {rowNum, colNum});
}
}
}
}
return neighbors;
}
private boolean withinGrid(int colNum, int rowNum) {
if((colNum < 0) || (rowNum <0) ) {
return false;
}
if((colNum >= cols) || (rowNum >= rows)) {
return false;
}
return true;
}
//use for testing
private void printPath() {
System.out.print("Path : " );
for(int[] cell : this) {
System.out.print(Arrays.toString(cell));
}
System.out.println("");
}
public CellsList getPath() {
CellsList cl = new CellsList();
cl.addAll(this);
return cl;
}
}
令牌枚举,如OP
public enum Token {
VIDE, CERCLE_BLEU, CERCLE_ROUGE
}
简单集合覆盖
import java.util.ArrayList;
import java.util.Arrays;
class CellsList extends ArrayList<int[]>{
@Override //override to check by the value of int[]
public boolean contains(Object o) {
for (int[] a : this) {
if(Arrays.equals(a, (int[]) o)) {
return true;
}
}
return false;
}
}
解决方案很长,但不是很复杂.它确实需要仔细研究.
希望对您有所帮助.
The solution is long, but not very complex. It does need careful studying.
I hope you'll find it helpful.
这篇关于实施MVC模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!