我想知道如何找到从一个单元格通过所有具有相同值的单元格返回到起始单元格的路径。这里的“值”是指
考虑
现在我们以
这里的想法是“捕捉”对手的标记,这就是玩家获得分数的方式。 我将在需要时更新任何信息。
更新:
我找到了一个寻路工具,我认为它可以解决这个问题,但我不知道如何实现它:https://gist.github.com/benruijl/3385624 以下是我的代码:
这个枚举类表示一个单元格的状态:
主要类:
Token.CERCLE_ROUGE
或Token.CERCLE_BLEU
。考虑
cell(4,5)==Token.CERCLE_BLEU
并且有邻居:3,4-4,4-5,4-3,5-5,5-3,6-4,6-5,6
,它们全部都等于Token.CERCLE_ROUGE
。现在我们以
cell(3,4)
为起点:如何找到一条经过(4,4),(5,4),(3,5),(5,5),(3,6),(4,6),(5,6)
然后返回到(3,4)
的路径。在这里,我们可以画一条线段从一个单元格到另一个单元格,以使cell(4,5)
位于中心(请参见下面的图像)。这里的想法是“捕捉”对手的标记,这就是玩家获得分数的方式。 我将在需要时更新任何信息。
更新:
我找到了一个寻路工具,我认为它可以解决这个问题,但我不知道如何实现它:https://gist.github.com/benruijl/3385624 以下是我的代码:
这个枚举类表示一个单元格的状态:
public enum Token {
VIDE, CERCLE_BLEU, CERCLE_ROUGE
}
我使用以下代码来检查一个单元格的邻居:
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 +
" Contains "+ board[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;
}
我的整个代码如下。我还不能将其适应MVC,我尝试过的努力似乎到目前为止都没有成功。
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 = 15;
public static int COLS = ROWS;
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){
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);
}
}
}
public static void main(String[] args){
SwingUtilities.invokeLater(() -> {
Pha pha = new Pha();
});
}
}
下面是由Hovercraft Full Of Eels提出的MVC模型,但效果不如预期:
表示单元格状态的枚举类:
public enum Token {
VIDE, CERCLE_BLEU, CERCLE_ROUGE
}
控制:
import java.beans.IndexedPropertyChangeEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JFrame;
public class Control {
private Model model;
private View view;
public Control(Model model, View view) {
this.model = model;
this.view = view;
view.createGrid(model.getRows(), model.getCols());
view.getMainPanel().addPropertyChangeListener(new ViewListener());
model.addPropertyChangeListener(Model.TOKEN, new ModelListener());
}
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) {
token = Token.CERCLE_BLEU;
} else if (token == Token.CERCLE_BLEU) {
token = Token.CERCLE_ROUGE;
} else {
token = Token.VIDE;
}
model.setToken(token, row, col);
}
}
}
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();
view.setCell(token, row, col);
}
}
public void start() {
JFrame frame = new JFrame("MVC");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(view.getMainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
视图:
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.event.MouseListener;
import java.awt.image.BufferedImage;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class View {
private static final int ICON_W = 12;
public static final String CELL_SELECTION = "cell selection";
private int rows;
private int cols;
private JPanel mainPanel = new JPanel();
private JLabel[][] grid;
private Map<Token, Icon> iconMap = new EnumMap<>(Token.class);
private int selectedRow;
private int selectedCol;
public 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));
}
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);
}
public void createGrid(int rows, int cols) {
MyMouse myMouse = new MyMouse();
this.setRows(rows);
this.cols = cols;
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((MouseListener) myMouse); //cast
grid[r][c].setOpaque(true);
grid[r][c].setBackground(Color.WHITE);
mainPanel.add(grid[r][c]);
}
}
}
public JPanel getMainPanel() {
return mainPanel;
}
public int getSelectedRow() {
return selectedRow;
}
public int getSelectedCol() {
return selectedCol;
}
public void setCell(Token token, int row, int col) {
grid[row][col].setIcon(iconMap.get(token));
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
private class MyMouse 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);
}
}
}
}
}
}
这个模型:
import java.beans.PropertyChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;
public class Model {
public static final int ROWS = 75;
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);
public Model() {
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
grid[r][c] = Token.VIDE;
}
}
}
public Token getToken(int row, int col) {
return grid[row][col];
}
public 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);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(name, listener);
}
public int getRows() {
return ROWS;
}
public int getCols() {
return COLS;
}
}
主要类:
import javax.swing.SwingUtilities;
public class Pha {
public static void main(String[] args) {
// run all on the Swing event thread
SwingUtilities.invokeLater(() -> {
Model model = new Model();
View view = new View();
Control control = new Control(model, view);
control.start();
});
}
}