java - 在洪水填充游戏中显示颜色时遇到问题

标签 java arrays

我的洪水填充算法有效,但是,我无法打印游戏的 6 种主要颜色。允许我打印二维数组的 Java 函数位于 GameModel.java 类中,名为 toString():

import java.util.Random;

public class GameModel {


/**
 * predefined values to capture the color of a DotInfo
 */
public static final int COLOR_0           = 0;
public static final int COLOR_1           = 1;
public static final int COLOR_2           = 2;
public static final int COLOR_3           = 3;
public static final int COLOR_4           = 4;
public static final int COLOR_5           = 5;
public static final int NUMBER_OF_COLORS  = 6;

private static DotInfo[][] dots;
private int size;
private int currentColor;
private Random generator;
private int steps;

/**
 * Constructor to initialize the model to a given size of board.
 * 
 * @param size
 *            the size of the board
 */
public GameModel(int size) {
    this.size = size;
    dots = new DotInfo[size][size];
    generator = new Random();
}


/**
 * Resets the model to (re)start a game. The previous game (if there is one)
 * is cleared up . 
 */
public void reset(){
    generator = new Random();
    int color = 0;
    for (int j=0;j<size;j++) {
        for (int i=0;i<size;i++) {
            dots[j][i] = new DotInfo(i, j, generator.nextInt(NUMBER_OF_COLORS)+1);
        }
    }
}


/**
 * Getter method for the size of the game
 * 
 * @return the value of the attribute sizeOfGame
 */   
public int getSize(){
    return size;
}

/**
 * returns the current color  of a given dot in the game
 * 
 * @param i
 *            the x coordinate of the dot
 * @param j
 *            the y coordinate of the dot
 * @return the status of the dot at location (i,j)
 */   
public int getColor(int i, int j){
    return dots[j][i].getColor();
}

/**
 * returns true is the dot is captured, false otherwise
* 
 * @param i
 *            the x coordinate of the dot
 * @param j
 *            the y coordinate of the dot
 * @return the status of the dot at location (i,j)
 */   
public boolean isCaptured(int i, int j){
    return dots[j][i].isCaptured();
}

/**
 * Sets the status of the dot at coordinate (i,j) to captured
 * 
 * @param i
 *            the x coordinate of the dot
 * @param j
 *            the y coordinate of the dot
 */   
public void capture(int i, int j){
    dots[j][i] = new DotInfo(i, j, currentColor);
    dots[j][i].setCaptured(true);
}


/**
 * Getter method for the current number of steps
 * 
 * @return the current number of steps
 */   
public int getNumberOfSteps(){
    return steps;
}

/**
 * Setter method for currentSelectedColor
 * 
 * @param val
 *            the new value for currentSelectedColor
*/   
public void setCurrentSelectedColor(int val) {
    currentColor = val;
}

/**
 * Getter method for currentSelectedColor
 * 
 * @return currentSelectedColor
 */   
public int getCurrentSelectedColor() {
    return currentColor;
}


/**
 * Getter method for the model's dotInfo reference
 * at location (i,j)
 *
  * @param i
 *            the x coordinate of the dot
 * @param j
 *            the y coordinate of the dot
 *
 * @return model[i][j]
 */   
public DotInfo get(int i, int j) {
    return dots[j][i];
}


 /**
 * The metod <b>step</b> updates the number of steps. It must be called 
 * once the model has been updated after the payer selected a new color.
 */
 public void step(){
    steps++;
}

 /**
 * The metod <b>isFinished</b> returns true iff the game is finished, that
 * is, all the dats are captured.
 *
 * @return true if the game is finished, false otherwise
 */
public boolean isFinished(){
    boolean flag=true;
    for (int y=0;y<size;y++) {
        for (int x=0;x<size;x++) {
            if (dots[y][x].isCaptured()==false) {
                flag=false;
            }
        }
    }
    return flag;
}


 /**
 * Builds a String representation of the model
 *
 * @return String representation of the model
 */
public String toString(){
    String rep = "";
    for (int y=0;y<size;y++) {
        for (int x=0;x<size;x++) {
            rep += dots[y][x].getColor()+" ";
        }
        rep+="\n";
    }
    return rep;
}

}

我打印数组的函数位于我的 GameController.java 类中,调用:

System.out.println(model)

.

import java.awt.*;

public class GameController /*implements ActionListener*/ {

private GameModel model;
private MyStack dots;
private int size;

/**
 * Constructor used for initializing the controller. It creates the game's view 
 * and the game's model instances
 * 
 * @param size
 *            the size of the board on which the game will be played
 */
public GameController(int size) {
    this.size = size;
    model = new GameModel(size);
    dots = new MyStack(size*size);
}

/**
 * resets the game
 */
public void reset(){
    model.reset();
    System.out.println(model);
}

/**
 * Callback used when the user clicks a button (reset or quit)
 *
 * @param e
 *            the ActionEvent
 */

/*public void actionPerformed(ActionEvent e) {

}*/

/**
 * <b>selectColor</b> is the method called when the user selects a new color.
 * If that color is not the currently selected one, then it applies the logic
 * of the game to capture possible locations. It then checks if the game
 * is finished, and if so, congratulates the player, showing the number of
 * moves, and gives two options: start a new game, or exit
 * @param color
 *            the newly selected color
 */
public void selectColor(int color){
    model.setCurrentSelectedColor(color);
    capturePointAtZero();
    sendCapturedToStack();
    equalityCheck(color);
    System.out.println(model);
}

private void capturePointAtZero() {
    int x = 0, y = 0;
    if (!model.isCaptured(x, y)) {
        model.capture(x, y);
    }
}

private void sendCapturedToStack() {
    for (int j=0;j<size;j++) {
        for (int i=0;i<size;i++) {
            if (model.isCaptured(i, j)) {
                model.capture(i,j);
                dots.push(model.get(i,j));
            }
        }
    }
}

private void equalityCheck(int newColor) {
    while (!dots.isEmpty()) {
        DotInfo dot = dots.pop();
        int x = dot.getX();
        int y = dot.getY();
        if (model.getColor(x,y+1)==newColor && !model.isCaptured(x,y+1)) {
            model.capture(x, y+1);
            dots.push(model.get(x,y+1));
        } if (model.getColor(x+1,y)==newColor && !model.isCaptured(x+1,y)) {
            model.capture(x+1, y);
            dots.push(model.get(x+1,y));
        } if (model.getColor(x,y-1)==newColor && !model.isCaptured(x,y-1)) {
            model.capture(x, y-1);
            dots.push(model.get(x,y-1));
        } if (model.getColor(x-1,y)==newColor && !model.isCaptured(x-1,y)) {
            model.capture(x-1, y);
            dots.push(model.get(x-1,y));
        }
    }
}
}

当它接近矩阵末尾时,我收到一个 IndexOutOfBoundsError。

如果有人可以提供帮助,我们将不胜感激。

最佳答案

代码中存在太多问题,无法全部解决。快速浏览后我注意到了一些:

  1. 是的,矩阵填充0的原因是currentColor为0,因为你没有调用setCurrentSelectedColor

  2. 更深层次的问题是逻辑问题。让我们看看equalityCheck

        if (model.getColor(x, y + 1) == newColor && !model.isCaptured(x, y + 1))
        {
            model.capture(x, y + 1);
            dots.push(model.get(x, y + 1));
        }

此代码意味着,仅当 (x, y+1) 处的点已经具有newColor时才会更新。显然,如果它与“旧颜色”(即 (0,0) 的颜色)匹配,您希望它被更新,但您甚至不尝试将该颜色保存在您的 capturePointAtZero 中!

  • 代码如
  •     public void capture(int i, int j){
            for (int y=0;y<size;y++) {
                for (int x=0;x<size;x++) {
                    if (x==i && y==j) {
                        dots[y][x] = new DotInfo(x, y, currentColor);
                        dots[y][x].setCaptured(true);
                    }
                }
            }
        }
    

    效率相当低。如果您仍然只更新单个 DotInfo,为什么还需要循环?可以简化一下

        public void capture(int i, int j){
            dots[j][i] = new DotInfo(i, j, currentColor);
            dots[j][i].setCaptured(true);
        }
    

    希望这有帮助。

    更新

    I understand your comments but now I am getting an arrayIndexOutOfBounds whenever i call a number that is at the end of my Matrix.

    异常很可能是因为您没有在equalityCheck中验证索引而发生的。您可以添加方法isValidPosition,例如:

    public class GameModel
    {
    
        ....
    
        public boolean isValidPosition(int x, int y)
        {
            return (x >= 0) && (x < size) && (y >= 0) && (y < size);
        }
    }
    

    然后

    private void equalityCheck(int newColor)
    {
            ...
            if (model.isValidPosition(x, y+1) && model.getColor(x, y + 1) == newColor && !model.isCaptured(x, y + 1))
            {
                model.capture(x, y + 1);
                dots.push(model.get(x, y + 1));
            }
    

    请注意,重要的是 isValidPosition 是复合 if 中的第一个调用。这是有效的,因为 Java 使用 short-circuit evaluation用于 boolean 语句。

    您可以将 isValidPosition 隐藏在 GameModel 中的其他方法中,有时类似的方法是正确的做法。但我认为现在还不是时候,因为 1)它要求您从 getColor 返回一些假值(您现在使用 0,我不太喜欢它)和 2)它隐藏读者的业务逻辑领域不是无限的。

    关于java - 在洪水填充游戏中显示颜色时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42463924/

    相关文章:

    java - 在 Java 中按值从 Map 中删除元素的最快方法是什么?

    java - Tomcat 中的 Spring @Autowired 和 WebApplicationContext

    c - 需要帮助在 C 中创建动态字符数组

    arrays - 如何转换[u8; 4]转换为u8的迭代器?

    C++ array.at(i) 和 array[i] 性能

    php - 如何从键返回 PHP 数组值?

    java - 声明关闭问题后不允许进行任何操作

    java - 没有得到正确的输出

    java - 如何以编程方式设置 Spring log4j 属性文件路径

    javascript - 将重复项组织到有序的单个数组中