问题描述
考虑一个具有 n 行 和 n 列(此处为 75x75)的 2D 网格.鼠标单击时在每个单元格中绘制符号(标记).下面的代码用于在单元格内绘制网格线和符号:
Consider a 2D grid with n rows and n columns (here 75x75). The symbols (tokens) are drawn in each cell on mouse click. The code below is used to draw grid lines and symbols within cells:
class DrawCanvas extends JPanel{ @Override public void paintComponent(Graphics g){ super.paintComponent(g); setBackground(Color.WHITE); //Lines 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); } //Symbols 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); } } }
使用下面的代码,我可以找到给定单元格的所有邻居:
With the code below, I can find all neighbors of a given cell:
private void neighbours(int col, int row) { //find all serouding cell by adding +/- 1 to col and row for (int colNum = col - 1 ; colNum <= (col + 1) ; colNum +=1 ) { for (int rowNum = row - 1 ; rowNum <= (row + 1) ; rowNum +=1 ) { //if not the center cell if(! ((colNum == col) && (rowNum == row))) { //make sure it is within grid if(withinGrid (colNum, rowNum)) { System.out.println("Neighbor of "+ col+ " "+ row + " - " + colNum +" " + rowNum ); } } } } } //define if cell represented by colNum, rowNum is inside grid private boolean withinGrid(int colNum, int rowNum) { if((colNum < 0) || (rowNum <0) ) { return false; //false if row or col are negative } if((colNum >= COLS) || (rowNum >= ROWS)) { return false; //false if row or col are > 75 } return true; }
考虑单元格内容:
public enum Token{ VIDE, CERCLE_BLEU, CERCLE_ROUGE }
现在我想知道是否有办法确定单元格包含的内容:是否为空:Token.VIDE、有 Token.CERCLE_BLEU 还是有 Token.CERCLE_ROUGE. 以及如何实现.
Now I want to know if there is a way to determinate what a cell contains: is it empty: Token.VIDE, has Token.CERCLE_BLEU or has Token.CERCLE_ROUGE. And how I can achieve that.
更新:以下是我的代码:
UPDATE: Below is my code:
import javax.swing.JFrame; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.*; public final class Pha extends JFrame { public static int ROWS = 75; public static int COLS = 75; public static int cellSize = 15; public static int canvasWidth = cellSize * COLS + (ROWS *4) ; public static int canvasHeight = cellSize * ROWS ; public static int gridWidth = 1; public static int halfGridWidth = gridWidth / 2; public static int cellPadding = cellSize / 5; public static int symbolSize = cellSize - cellPadding * 2; public static int symbolStrokeWidth = 3; public enum GameState{ JOUE, NUL, CERCLE_ROUGE_GAGNE, CERCLE_BLEU_GAGNE } private GameState actualState; public enum Token{ VIDE, CERCLE_ROUGE, CERCLE_BLEU } private Token actualPlayer; private Token[][] board; private final DrawCanvas canvas; private JLabel statusBar; 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; 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; neighbours(selectedRow, selectedCol); } } else { initGame(); } repaint(); } }); statusBar = new JLabel(" "); statusBar.setFont(new Font(Font.DIALOG_INPUT, Font.ITALIC, 15)); statusBar.setBorder(BorderFactory.createEmptyBorder(2, 5, 4, 5)); Container cp = getContentPane(); cp.setLayout(new BorderLayout()); cp.add(canvas, BorderLayout.EAST); cp.add(statusBar, BorderLayout.NORTH); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); setTitle("Pha par esQmo"); setVisible(true); board = new Token[ROWS][COLS]; initGame(); } public 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)) { actualState= (theSeed == Token.CERCLE_ROUGE) ? GameState.CERCLE_ROUGE_GAGNE : GameState.CERCLE_BLEU_GAGNE; } else if (estNul()) { actualState = GameState.CERCLE_BLEU_GAGNE; } } public boolean estNul() { /*for (int row = 0; row < ROWS; ++row) { for (int col = 0; col < COLS; ++col) { if (board[row][col] == Token.VIDE) { return false; } } }*/ return false; } public boolean aGagne(Token token, int ligneSelectionnee, int colonneSelectionnee) { return false; } public void neighbours(int row, int col) { 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 )) { System.out.println("Neighbor of "+ row + " " + col + " is " + rowNum +" " + colNum ); } } } } } private boolean withinGrid(int colNum, int rowNum) { if((colNum < 0) || (rowNum <0) ) { return false; } if((colNum >= COLS) || (rowNum >= ROWS)) { return false; } return true; } class DrawCanvas extends JPanel{ @Override public void paintComponent(Graphics g){ //Invoqué via repaint() super.paintComponent(g); //Pour remplir l'arriere plan setBackground(Color.WHITE); //Defini la couleur de l'arriere plan 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); } } } if(actualState == GameState.JOUE){ if(actualPlayer == Token.CERCLE_ROUGE){ statusBar.setText("ROUGE, c'est votre tour"); statusBar.setForeground(Color.RED); } else { statusBar.setText("BLEU, c'est votre tour"); statusBar.setForeground(Color.BLUE); statusBar.addMouseMotionListener(null); } } else if(actualState == GameState.NUL){ statusBar.setForeground(Color.yellow); statusBar.setText("Match nul! Cliquez pour rejouer"); } else if(actualState == GameState.CERCLE_ROUGE_GAGNE){ statusBar.setText("Le jouer X a remporté la partie, cliquez pour rejouer"); statusBar.setForeground(Color.RED); } else if(actualState == GameState.CERCLE_BLEU_GAGNE){ statusBar.setForeground(Color.BLUE); statusBar.setText("Le joueur O a remporté la partie, cliquez pour rejouer"); } } } public static void main(String[] args){ SwingUtilities.invokeLater(() -> { Pha pha = new Pha(); }); } }
推荐答案
在 board 数组中存储每个单元格的 Token.
要检索此信息,您可以更改
In board array you store the Token for each cell.
To retrieve this information you could change
System.out.println("Neighbor of "+ row + " " + col + " is " + rowNum +" " + colNum );
在neighbors()中:
System.out.println("Neighbor of "+ row + " " + col + " is " + rowNum +" " + colNum + " Contains "+ board[rowNum][colNum]);
单击中间单元格 (17,19):
Clicking the middle cell (17,19):
打印出来:
17 19 的邻居是 16 18 包含 CERCLE_ROUGE
17 19 的邻居是17 18 包含 CERCLE_BLEU
17 19 的邻居是 18 18 包含CERCLE_ROUGE
17 19 的邻居是 16 19 包含 CERCLE_BLEU
邻居17 19 是 18 19 包含 CERCLE_BLEU
17 19 的邻居是 16 20包含 CERCLE_ROUGE
17 19 的邻居是 17 20 包含 CERCLE_BLEU
17 19 的邻居是 18 20 包含 CERCLE_ROUGE
Neighbor of 17 19 is 16 18 Contains CERCLE_ROUGE
Neighbor of 17 19 is 17 18 Contains CERCLE_BLEU
Neighbor of 17 19 is 18 18 Contains CERCLE_ROUGE
Neighbor of 17 19 is 16 19 Contains CERCLE_BLEU
Neighbor of 17 19 is 18 19 Contains CERCLE_BLEU
Neighbor of 17 19 is 16 20 Contains CERCLE_ROUGE
Neighbor of 17 19 is 17 20 Contains CERCLE_BLEU
Neighbor of 17 19 is 18 20 Contains CERCLE_ROUGE