【问题标题】:Othello - Algorithm for finding the available options to play奥赛罗 - 寻找可用选项的算法
【发布时间】:2017-06-24 13:03:32
【问题描述】:

我正在尝试使用 Java 开发游戏奥赛罗,我正在努力寻找玩家拥有(不是计算机)的可用动作。

例如,我是玩家 1,我正在玩白色棋子,

  1. 检查按钮是否为空。 (我将按钮用作图块)
  2. 检查是否有颜色相反的邻居。
  3. 如果有,继续检查每个方向是否有相反的颜色,直到
  4. 如果我们到达边界 - 返回 false。
  5. 如果我们达到我们的颜色 - 将所有部分都变成我的颜色。

我正在努力实现 3. 和 5.

我如何遍历所有方向(如果我在棋盘的内部,最多 8 个方向),我如何才能进一步检查每个方向的颜色?

我考虑过为内板实现所有 8 个方向,然后在外板中实现所有可能性并检查非常低效的边缘选项,我不想这样编码。

您不必查看代码,我正在尝试弄清楚如何处理它(考虑 2 个 for 循环),但下面是函数和整个代码:(每个按钮都有一个图标 -黑白片)

private void checkLegalPlay(int row, int col) {

        if(playerNum == 0){ //Black player
            if(row > 0 && row < 7 && col > 0 && col < 7){ //Inner board - 
                     //not good, i want from any point of the board
                    for(int i = col-1; i != 0; i--)
                        if(squares[row][i].getIcon() != null){
                            if(squares[row][i].getIcon() == blackPiece){
                                //Advance until boundary - return false
                                //Advance if there're black pieces
                                //If we get to white piece, turn all to 
                                //  white pieces
                            }
                        }
                }
            }
        }

已经有将近 300 行代码了,所以如果你真的想看看我到目前为止做了什么,我更愿意提供一个链接:-deleted-

【问题讨论】:

  • 您可以创建一个邻接列表和另一个布尔列表来表示单元格中的颜色,然后递归地遍历它们并在迭代中添加一些条件。
  • 我仍然对如何递归地遍历列表感到困惑。 @Yahya

标签: java algorithm swing user-interface matrix


【解决方案1】:

软件开发是一门抽象的艺术。您应该尝试培养一种技能,以查看逻辑片段之间的相似性并将它们抽象出来。例如,要检查移动是否合法,您必须应用相同的检查逻辑从单元格沿不同方向进行迭代。此外,检查移动和应用移动(翻转棋子)共享相同的迭代逻辑。所以让我们把它抽象出来,即让我们将迭代与我们在迭代内部执行的逻辑分开:

    private static final int SIZE = 8;

    static boolean isValidPos(int pos) {
        return pos >= 0 && pos < SIZE;
    }


    static class Point {
        public final int row;
        public final int col;

        public Point(int row, int col) {
            this.row = row;
            this.col = col;
        }
    }


    private static final Point[] ALL_DIRECTIONS = new Point[]{
            new Point(1, 0),
            new Point(1, 1),
            new Point(0, 1),
            new Point(-1, 1),
            new Point(-1, 0),
            new Point(-1, -1),
            new Point(0, -1),
            new Point(1, -1),
    };


    interface CellHandler {
        boolean handleCell(int row, int col, Icon icon);
    }


    void iterateCells(Point start, Point step, CellHandler handler) {
        for (int row = start.row + step.row, col = start.col + step.col;
             isValidPos(row) && isValidPos(col);
             row += step.row, col += step.col) {
            Icon icon = squares[row][col].getIcon();
            // empty cell
            if (icon == null)
                break;
            // handler can stop iteration
            if (!handler.handleCell(row, col, icon))
                break;

        }
    }


    static class CheckCellHandler implements CellHandler {
        private final Icon otherIcon;
        private boolean hasOtherPieces = false;
        private boolean endsWithMine = false;

        public CheckCellHandler(Icon otherIcon) {
            this.otherIcon = otherIcon;
        }

        @Override
        public boolean handleCell(int row, int column, Icon icon) {
            if (icon == otherIcon) {
                hasOtherPieces = true;
                return true;
            } else {
                endsWithMine = true;
                return false;
            }
        }

        public boolean isGoodMove() {
            return hasOtherPieces && endsWithMine;
        }
    }

    class FlipCellHandler implements CellHandler {
        private final Icon myIcon;
        private final Icon otherIcon;
        private final List<Point> currentFlipList = new ArrayList<Point>();

        public FlipCellHandler(Icon myIcon, Icon otherIcon) {
            this.myIcon = myIcon;
            this.otherIcon = otherIcon;
        }

        @Override
        public boolean handleCell(int row, int column, Icon icon) {
            if (icon == myIcon) {
                // flip all cells
                for (Point p : currentFlipList) {
                    squares[p.row][p.col].setIcon(myIcon);
                }
                return false;
            } else {
                currentFlipList.add(new Point(row, column));
                return true;
            }
        }
    }


    private boolean checkLegalPlay(int row, int col) {
        ImageIcon otherIcon = (playerNum == 0) ? whitePiece : blackPiece;
        Point start = new Point(row, col);
        for (Point step : ALL_DIRECTIONS) {
            // handler is stateful so create new for each direction
            CheckCellHandler checkCellHandler = new CheckCellHandler(otherIcon);
            iterateCells(start, step, checkCellHandler);
            if (checkCellHandler.isGoodMove())
                return true;
        }
        return false;
    }

ALL_DIRECTIONS 代表您可以导航的所有 8 个方向。 iterateCells 方法接受某个方向并通过它导航,直到它碰到空单元格或边框。对于传递的CellHandler 中的每个非空单元格handleCell,都会被调用。所以现在你的checkLegalPlay 变得简单:实现CheckCellHandler 并遍历所有可能的方向,看看我们是否可以朝那个方向翻转。实现实际的翻转逻辑实际上非常相似:只需实现FlipCellHandler 并类似地使用它。请注意,您还可以通过将 myIconotherIcon 显式传递给处理程序来抽象出“当前玩家”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-02
    • 2012-10-30
    • 1970-01-01
    • 2017-05-18
    • 1970-01-01
    • 2012-05-20
    • 2021-07-06
    相关资源
    最近更新 更多