【问题标题】:'Undo Move' feature Implementation for a 2D Array Board Game2D 阵列棋盘游戏的“撤消移动”功能实现
【发布时间】:2016-12-06 08:56:48
【问题描述】:

二维阵列棋盘游戏的“撤消移动”功能实现

大家好

使用 ArrayList,我正在尝试实现撤消移动功能,用户可以选择“Z”选项,这使得多级“撤消”成为可能。换句话说,如果用户选择了“Z”,那么之前的移动就被撤消,如果他立即再次选择“Z”,那么之前的移动就被撤消,以此类推。

每次进行有效的移动“U”、“D”、“L”、“R”时,我都能够获取代码来添加新的移动对象,并且每次“Z”时也可以删除最后一个对象' 被按下。

我的问题是,如何让玩家的动作(坐标)和吃掉的甜甜圈(布尔值)依赖于 ArrayList 中的最后一个对象,这样当按下“Z”并移除 ArrayList 中的最后一个对象时,玩家动作和吃掉的甜甜圈现在将依赖 ArrayList 中新的最后一个对象来创建“撤消”效果?希望我的问题有意义。

“Z”实现是 move 方法中 switch 语句中的最后一种情况。

我的课程如下:

package secondproject;

import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class Game {

    private static final int BOARD_SIZE = 10;
    private static final int INITIAL_PLAYER_COL = 0;
    private static final int INITIAL_PLAYER_ROW = BOARD_SIZE - 1;
    private static final int HOME_COL = BOARD_SIZE - 1;
    private static final int HOME_ROW = 0;
    private static final int WALL_LENGTH = 5;
    private static final char PLAYER_CHAR = 'P';
    private static final char HOME_CHAR = 'H';
    private static final char WALL_CHAR = 'X';
    private static final char FREE_SQUARE_CHAR = '.';
    private static final char DOUGHNUT_CHAR = '@';
    private static final char UP_MOVE_CHAR = 'U';
    private static final char DOWN_MOVE_CHAR = 'D';
    private static final char LEFT_MOVE_CHAR = 'L';
    private static final char RIGHT_MOVE_CHAR = 'R';
    private static final char UNDO_MOVE_CHAR = 'Z';
    private static final char TRAIL_CHAR = 'M';

    private static char[][] board = new char[BOARD_SIZE][BOARD_SIZE];
    private static Scanner scan = new Scanner(System.in);
    private static Scanner keyBoard = new Scanner(System.in);

    private static int playerCol = INITIAL_PLAYER_COL;
    private static int playerRow = INITIAL_PLAYER_ROW;
    private static int nbrDoughnuts = 0;
    private static int nbrMoves = 0;
    private static Random random = new Random();

    private static int lives = 1;
    private static int doughnutLives;
    private static boolean doughnutCheck;
    static ArrayList<Move> movement = new ArrayList<Move>();

    public static void main(String[] args) {

        setUpBoard();
        showBoard();
        String opt;
        do {
            System.out.print("Next option ?");
            opt = scan.next();
            char opt1 = opt.charAt(0);
            if (opt1 == UP_MOVE_CHAR || opt1 == DOWN_MOVE_CHAR || opt1 == LEFT_MOVE_CHAR || opt1 == RIGHT_MOVE_CHAR || opt1 == UNDO_MOVE_CHAR) {
                move(opt1);
            } else {
                System.out.println("Allowed commands are: + " + UP_MOVE_CHAR + "," + DOWN_MOVE_CHAR + "," + LEFT_MOVE_CHAR + "," + RIGHT_MOVE_CHAR);
            }
            showBoard();
            System.out.println("Number of moves made = " + nbrMoves);
            System.out.println("Number of doughnuts eaten = " + nbrDoughnuts);
            System.out.println("Lives = " + lives);
        } while (board[HOME_ROW][HOME_COL] == HOME_CHAR);
        System.out.println("Thank you and goodbye");
    }

    /**
     * Set up the initial state of the board
     */
    private static void setUpBoard() {
        intialiseBoard(); // Fill the board with . characters
        //Add  the first vertical wall
        int v1StartCol = 1 + random.nextInt(BOARD_SIZE - 2);
        int v1StartRow = 1 + random.nextInt(BOARD_SIZE - WALL_LENGTH - 1);
        addVerticalWall(v1StartCol, v1StartRow, WALL_LENGTH);

        //Add the second vertical wall
        int v2StartCol;
        do {
            v2StartCol = 1 + random.nextInt(BOARD_SIZE - 2);
        } while (v2StartCol == v1StartCol);
        int v2StartRow = 1 + random.nextInt(BOARD_SIZE - WALL_LENGTH - 1);
        addVerticalWall(v2StartCol, v2StartRow, WALL_LENGTH);

        //Add the horizontal wall
        int h1StartRow = 1 + random.nextInt(BOARD_SIZE - 2);
        int h1StartCol = 1 + random.nextInt(BOARD_SIZE - WALL_LENGTH - 1);
        addHorizontalWall(h1StartCol, h1StartRow, WALL_LENGTH);

        //Add the dougnuts
        int nbrDoughnutsAdded = 0;
        while (nbrDoughnutsAdded < 5) {
            int dRow = 1 + random.nextInt(BOARD_SIZE - 2);
            int dCol = 1 + random.nextInt(BOARD_SIZE - 2);
            if (board[dRow][dCol] == FREE_SQUARE_CHAR) {
                board[dRow][dCol] = DOUGHNUT_CHAR;
                nbrDoughnutsAdded++;
            }
        }

        //Add the player and the home square
        board[playerRow][playerCol] = PLAYER_CHAR;
        board[HOME_ROW][HOME_COL] = HOME_CHAR;
    }

    /**
     * Add a vertical wall to the board
     *
     * @param startCol Column on which wall is situated
     * @param startRow Row on which top of wall is situated
     * @param length Number of squares occupied by wall
     */
    private static void addVerticalWall(int startCol, int startRow, int length) {
        for (int row = startRow; row < startRow + length; row++) {
            board[row][startCol] = WALL_CHAR;
        }
    }

    /**
     * Add a horizontal wall to the board
     *
     * @param startCol Column on which leftmost end of wall is situated
     * @param startRow Row on which wall is situated
     * @param length Number of squares occupied by wall
     */
    private static void addHorizontalWall(int startCol, int startRow, int length) {
        for (int col = startCol; col < startCol + length; col++) {
            board[startRow][col] = WALL_CHAR;
        }
    }

    /**
     * Display the board
     */
    private static void showBoard() {
        for (int row = 0; row < board.length; row++) {
            for (int col = 0; col < board[row].length; col++) {
                System.out.print(board[row][col]);
            }
            System.out.println();
        }
    }

    /**
     * Fill the board with FREE_SQUARE_CHAR characters.
     */
    private static void intialiseBoard() {
        for (int row = 0; row < board.length; row++) {
            for (int col = 0; col < board[row].length; col++) {
                board[row][col] = FREE_SQUARE_CHAR;
            }
            System.out.println();
        }
    }

    /**
     * Move the player
     *
     * @param moveChar Character indicating the move to be made
     */
    private static void move(char moveChar) {
        int newCol = playerCol;
        int newRow = playerRow;

        switch (moveChar) {
            case UP_MOVE_CHAR:
                if (lives == 1) {
                    newRow--;
                } else if (lives > 1) {
                    int number = keyBoard.nextInt();
                    if (number <= lives) {
                        newRow = newRow - number;
                    } else {
                        checkLives();
                    }
                }
                break;
            case DOWN_MOVE_CHAR:
                if (lives == 1) {
                    newRow++;
                } else if (lives > 1) {
                    squareNumberPrompt();
                    int number = keyBoard.nextInt();
                    if (number <= lives) {
                        newRow = newRow + number;
                    } else {
                        checkLives();
                    }
                }
                break;
            case LEFT_MOVE_CHAR:
                if (lives == 1) {
                    newCol--;
                } else if (lives > 1) {
                    squareNumberPrompt();
                    int number = keyBoard.nextInt();
                    if (number <= lives) {
                        newCol = newCol - number;
                    } else {
                        checkLives();
                    }
                }
                break;
            case RIGHT_MOVE_CHAR:
                if (lives == 1) {
                    newCol++;
                } else if (lives > 1) {
                    squareNumberPrompt();
                    int number = keyBoard.nextInt();
                    if (number <= lives) {
                        newCol = newCol + number;
                    } else {
                        checkLives();
                    }
                }
                break;
            case UNDO_MOVE_CHAR:
                if (movement.size() >= 1) {
                    movement.remove(movement.size() - 1);
                    System.out.println("The decreasing  size of the arraylist is now " + movement.size());
                } else if (movement.size() < 1) {
                    System.out.println("There is no move to be undone!");
                }
                break;
        }
        if (newRow < 0 || newRow >= BOARD_SIZE || newCol < 0 || newCol >= BOARD_SIZE) {
            System.out.println("Sorry that move takes you off the board!");
        } else {
            char dest = board[newRow][newCol];
            if (dest == WALL_CHAR) {
                System.out.println("Sorry you landed on a wall!");
            } else {
                nbrMoves++;
                if (dest == DOUGHNUT_CHAR) {
                    doughnutCheck = true;
                    nbrDoughnuts++;
                    doughnutLives++;
                    lives = (doughnutLives + 1);
                }
                board[playerRow][playerCol] = FREE_SQUARE_CHAR;
                playerCol = newCol;
                playerRow = newRow;
                board[playerRow][playerCol] = PLAYER_CHAR;
            }
        }
        if (moveChar == UP_MOVE_CHAR || moveChar == DOWN_MOVE_CHAR || moveChar == LEFT_MOVE_CHAR || moveChar == RIGHT_MOVE_CHAR) {
            movement.add(new Move(playerCol, playerRow, newCol, newRow, doughnutCheck));
            System.out.println("The increasing  size of the arraylist is now " + movement.size());
        }
    }

    public static void squareNumberPrompt() {
        System.out.println("Enter the number of squares to be moved");
    }

    public static void checkLives() {
        System.out.println("Invalid number! The number must be"
                + " equal to or less than the number of lives you have");
    }
}





package secondproject;

import java.util.ArrayList;

public class Move {

    private static int pColumn;
    private static int pRow;
    private static int nCol;
    private static int nRow;
    private static boolean dCheck;

    public Move(int playerCol, int playerRow, int newCol, int newRow, boolean doughnutCheck) {
        pColumn = playerCol;
        pRow = playerRow;
        nCol = newCol;
        nRow = newRow;
        dCheck = doughnutCheck;
    }

    public int getFromCol() {
        return pColumn;
    }

    public int getFromRow() {
        return pRow;
    }

    public int getToCol() {
        return nCol;
    }

    public int getToRow() {
        return nRow;
    }

    public boolean isDoughnutEaten() {
        return dCheck;
    }
}

【问题讨论】:

  • 保存一堆坐标。只要不是撤消移动,就将坐标推入堆栈。撤消移动时从堆栈中弹出。
  • 要么保存一个在一个动作中吃掉的每个甜甜圈的列表,要么你需要从头开始重新创建游戏,从动作 1 开始。也可以使用记住玩家已经在哪里的数据结构如果撤消删除了其中一个点,则再次将甜甜圈放在那里。虽然如果玩家不止一次访问一个图块,这可能会变得复杂,但你可以记住计数。
  • 当然,除非每个图块上都有一个甜甜圈并且只能访问一次,那么你实际上只需要知道你去了哪里,这样你就可以在那里更换甜甜圈......我怀疑它是这样的不过。
  • @RafiduzzamanSonnet 对不起,我不太了解,因为我是 Java 新手,无论多么简短,您能否以编程方式详细说明?
  • @Mark 游戏只有五个甜甜圈。您对甜甜圈列表的第一个建议听起来很聪明,请您愿意扩展一下吗?

标签: java arrays arraylist multidimensional-array


【解决方案1】:

在仔细查看您的代码之后,您基本上已经拥有了撤消所需的一切。 甚至可能有点太多 :D 你实际上并不需要 from 和 to 职位。只有移动让你进入的位置就足够了。

所以当你按下 Z 时,你的代码应该看起来像这样:

Move lastMove = movement.remove(movement.size() - 1);
playerCol = movement.get(movement.size() - 1).getToCol();
playerRow = movement.get(movement.size() - 1).getToRow();
board[playerRow][playerCol] = PLAYER_CHAR;
if (lastMove.isDoughnutEaten()) {
    int dCol = lastMove.getToCol();
    int dRow = lastMove.getToRow();
    board[dRow][dCol] = DOUGHNUT_CHAR;
    nbrDoughnutsAdded--;
}

现在,您可以从 lastMove 的 pColumn 和 pRow 值读取新的玩家位置,但正如我所说,这有点矫枉过正,因为无论如何您都可以从列表的新最后一个元素中读取它。

请记住,您仍然需要捕捉特殊情况(例如当您撤消第一步时。在这种情况下,您需要从定义起点的静态变量中读取前玩家位置,而不是列表的最后一个元素(不再存在))

【讨论】:

  • 是的,我相信我已经实现了这个机制。我的困惑在于如何编码恢复到最后一个位置和甜甜圈状态。我只是无法理解它。
  • 我稍微编辑了代码示例,希望没有遗漏任何内容,但这基本上是如何编写恢复代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多