尝试使用堆栈为洪水填充游戏开发撤消功能

时间:2017-03-24 04:21:15

标签: java stack

我正在使用Model-view-controller方法开发floodFill游戏。现在我被困在构建一个堆栈,可以存储我的gameModel对象的克隆。

public class GameModel implements Cloneable { 


/**
 * 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;

/**
 * The current selection color
 */
private int currentSelectedColor;



/**
 * The size of the game.
 */
private  int sizeOfGame;

/**
 * A 2 dimentionnal array of sizeOfGame*sizeOfGame recording the state of each dot
 */
private DotInfo[][] model;


/**
 * The number of steps played since the last reset
 */
private int numberOfSteps;

/**
 * The number of captered dots
 */
private int numberCaptured;

/**
 * Random generator
 */
private Random generator;

/**
 * Constructor to initialize the model to a given size of board.
 * 
 * @param size
 *            the size of the board
 */
public GameModel(int size) {
    generator = new Random();
    sizeOfGame = size;
    reset();
}


/**
 * Resets the model to (re)start a game. The previous game (if there is one)
 * is cleared up . 
 */
public void reset(){

    model = new DotInfo[sizeOfGame][sizeOfGame];

    for(int i = 0; i < sizeOfGame; i++){
        for(int j = 0; j < sizeOfGame; j++){
            model[i][j] = new DotInfo(i,j,generator.nextInt(NUMBER_OF_COLORS));
        }
    }

    numberOfSteps =0;
}


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

/**
 * returns the 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 isCaptured(i, j) ? currentSelectedColor : model[i][j].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 model[i][j].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){
    model[i][j].setCaptured(true);
    numberCaptured++;
}


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

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

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


/**
 * 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 model[i][j];
}


/**
 * 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(){
    numberOfSteps++;
}

/**
 * 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(){
    return numberCaptured == sizeOfGame*sizeOfGame;
}

public GameModel clone(){

    try {
        return (GameModel)super.clone();
    } catch (CloneNotSupportedException e) {
        return null;
    }
}


/**
 * Builds a String representation of the model
 *
 * @return String representation of the model
 */
public String toString(){
    StringBuffer b = new StringBuffer();
    for(int i = 0; i < sizeOfGame; i++){
        for(int j = 0; j < sizeOfGame; j++){
            b.append(getColor(i, j) + " ");
        }
        b.append("\n");
    }
    return b.toString();
}
}

正如您所看到的,我已经实现了cloneable并且已经定义了将clone方法覆盖为抽象类。

我正在尝试克隆模型,以便控制器可以在其actionPerformed undo方法中使用该函数。

public class GameController implements ActionListener{

/**
 * Reference to the view of the board
 */
private GameView gameView;
/**
 * Reference to the model of the game
 */
private GameModel gameModel;

private GameModel oldMove;

private int size;

private int i;

private int j;

private Stack<DotInfo> stack;

private boolean setting1;

private boolean setting2;

Stack<GameModel> steps;

/**
 * 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) {
    gameModel = new GameModel(size);
    gameView = new GameView(gameModel, this);
    reset();
}

/**
 * resets the game
 */
public void reset(){
    steps= new GenericLinkedStack<GameModel>();
    gameModel.reset();
    flood();
    gameView.update();
    setting1 = false;
    setting2 = false;
}

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

public void actionPerformed(ActionEvent e) {
    if (e.getSource() instanceof DotButton) {
        if(gameModel.getNumberOfSteps()==0){
            int row = ((DotButton)(e.getSource())).getRow();
            int column = ((DotButton)(e.getSource())).getColumn();
            gameModel.capture(row,column);
        }
        selectColor(((DotButton)(e.getSource())).getColor());
    } else if (e.getSource() instanceof JButton) {
        JButton clicked = (JButton)(e.getSource());

        if (clicked.getText().equals("Quit")) {
             System.exit(0);
         } else if (clicked.getText().equals("Reset")){
            reset();
         } else if (clicked.getText().equals("Redo")) {

        } else if (clicked.getText().equals("Undo")) {
            steps.pop();
            gameView.update();
        } else if (clicked.getText().equals("Settings")) {
            gameView.settingsMenu();
        }
    } else if (e.getSource() instanceof JRadioButton) {
        JRadioButton clickedR = (JRadioButton)(e.getSource());
        if (clickedR.getText().equals("Torus")) {
            setting1 = true;
        }
        if (clickedR.getText().equals("Diagonal")) {
            setting2 = true;
        }
    }
}

/**
 * <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 to options: start a new game, or exit
 * @param color
 *            the newly selected color
 */
public void selectColor(int color){
    steps.push(gameModel.clone());
    if(color != gameModel.getCurrentSelectedColor()) {
        gameModel.setCurrentSelectedColor(color);
        flood();
        gameModel.step();
        gameView.update();
        finished();
    }      
}

/**
 * <b>flood</b> is the method that computes which new dots should be ``captured'' 
 * when a new color has been selected. The Model is updated accordingly
 */
 private void flood() {
    size = gameModel.getSize()-1;
    stack = new GenericLinkedStack<DotInfo>();
    for(int i =0; i < gameModel.getSize(); i++) {
       for(int j =0; j < gameModel.getSize(); j++) {
            if(gameModel.isCaptured(i,j)) {
                stack.push(gameModel.get(i,j));
            }
       }
    }
    DotInfo dotInfo;
    while(!stack.isEmpty()){
        dotInfo = stack.pop();
        i = dotInfo.getX();
        j = dotInfo.getY();
        orthogonal();
        if (setting1 == true) {
            torus();
        }
        if (setting2 == true) {
            diagonal();
        }
    }
}


 /**
 * <b>shouldBeCaptured</b> is a helper method that decides if the dot
 * located at position (i,j), which is next to a captured dot, should
 * itself be captured
 * @param i
 *            row of the dot
 * @param j
 *            column of the dot
 */

 private boolean shouldBeCaptured(int x, int y) {
    return (!gameModel.isCaptured(x, y) && (gameModel.getColor(x,y) == gameModel.getCurrentSelectedColor())) ? true : false;
}

private void captureAndStack(int x, int y) {
    gameModel.capture(x, y);
    stack.push(gameModel.get(x,y));
}

private void finished() {
    if(gameModel.isFinished()) {
        if (gameView.finishedMenu() == 0) {
            reset();
        } else {
            System.exit(0);
        }
    }
}

我正在使用堆栈来保存游戏的状态,但我不确定如何使用过去的状态更新视图。我不认为你需要看我游戏的视图类。

有人可以引导我走正确的路径,我应该实施哪些方法以及在哪里。

0 个答案:

没有答案