Java 中的环绕游戏使用枚举 class - 如何找到赢家

Surround Game in Java using enum class - how to find a winner

我正在为 class 项目创建 "Surround Game"。这个想法是,如果一名球员在所有四个方面(如果适用)都被包围,那么该球员就会输,而围绕他们的球员将获胜。这是胜利应该是什么样子的一个例子。我做的有点不同,因为我使用图标而不是数字来显示,但这是相同的想法。在以下所有情况下,玩家 1 获胜。

所以我的问题是在 surroundGame class 中,我不知道如何判断它是否有赢家。我有一个带有单元格图标的枚举 class,一个是玩家 1,等等

public enum Cell {
ONE, TWO, EMPTY;
}

另外,我有一个枚举 gameStatus class:

public enum GameStatus {
 PLAYER1_WON, PLAYER2_WON, TIE, IN_PROGRESS
} 

这是 surroundGame class,问题出在名为 isWinner 和 isSurrounded 的方法中。

package project2;

import java.awt.Point;
import java.util.*;


public class SurroundGame {
private Cell[][] board;
private GameStatus status;
private int size;
private Cell turn;
private Cell whoStarts;

some code edited out....

private GameStatus isWinner() {

    for (int r = 0; r < size; r++) {
        for (int c = 0; c < size; c++) {
            if (board[r][c] == Cell.EMPTY) {
                return GameStatus.IN_PROGRESS;
            }
        }
    }
    for (int r = 0; r < size; r++) {
        for (int c = 0; c < size; c++) {
            if (isSurrounded(Cell.ONE)) {
                return GameStatus.PLAYER1_WON;
            }
            if (isSurrounded(Cell.TWO)) {
                return GameStatus.PLAYER2_WON;
            }
        }
    }
        return GameStatus.TIE;
}

private boolean isSurrounded(Cell type) {
    for (int r = 0; r < size; r++) {
        for (int c = 0; c < size; c++) {
            if (board[r][c + 1] == type && board[r][c - 1] == type) {
                if (board[r + 1][c] == type && board[r - 1][c] == type) {
                    return true;
            }
            }
        }
    }

    return false;
}


public GameStatus getGameStatus() {
    return status;
}

}

问题是我不知道如何判断玩家何时获胜。当我测试 GUI 时,如果它以平局结束(没有人获胜)并且所有其他功能都正常工作,所以我知道唯一的问题是玩家实际获胜的特定实例。我在 isWinner 方法中使用辅助方法 isSurrounded,但我不能正确使用循环逻辑,因为它不起作用。我尝试使用两种辅助方法,一种是查看单元格的列是否被包围,第二种是查看单元格的行是否被包围,然后检查 isWinner 中的这两个方法以产生赢家,但这也确实如此不行。 此外,我想出了如何显式声明左上角获胜的方法,但是为每次获胜编写代码需要做很多工作,尤其是因为游戏板的大小可以在 3 到 10 之间变化,我最终计划添加多个玩家。但无论如何,这就是我在 isWinner 方法中的做法

int row = 0;
    int col = 0;
    if (board[row][col] == Cell.ONE && board[row][col + 1] == Cell.TWO
            && board[row + 1][col] == Cell.TWO) {
        return GameStatus.PLAYER2_WON;
    }
    if (board[row][col] == Cell.TWO && board[row][col + 1] == Cell.ONE
            && board[row + 1][col] == Cell.ONE) {
        return GameStatus.PLAYER1_WON;
    }

我真的不想对所有可能的情况都这样做,而且我确信有一种更有效的方法可以像我在上面尝试的那样通过循环找到获胜者。任何帮助将不胜感激!谢谢!

在 isWinner() 的第一个循环中,您正在检查每个位置是否有空单元格。由于您的获胜解决方案无疑仍然有开放的单元格,因此在您检查 isSurrounded() 之前它会返回 IN_PROGRESS。您应该先检查是否有任何位置被包围,然后检查游戏是否处于平局或仍在继续。

此外,您正在循环调用 isSurround 并在 isSurround 内部循环。这是很多不必要的调用和循环,只需在每个单元格类型的循环外调用 isSurround 并让该函数按照您设置的方式执行所有循环。

这应该会好一点

private GameStatus isWinner(){
    if(isSurrounded(Cell.ONE)){
        return GameStatus.PLAYER1_WON;
    }
    if(isSurrounded(Cell.TWO)){
        return GameStatus.PLAYER2_WON;
    }
    for (int r = 0; r < size; r++) {
        for (int c = 0; c < size; c++) {
            if (board[r][c] == Cell.EMPTY) {
                return GameStatus.IN_PROGRESS;
            }
        }
    return GameStatus.TIE;
}

我相信如果将坐标 (row, col) 封装在 class 中,您会让自己的生活更轻松。然后,您可以实现 listSurroundingCoordinates:

等方法
class Coord {
    private final int row;
    private final int col;
    private final static int SIZE = 4;

    public List<Coord> listSurroundingCoordinates() {
        List<Coord> coords = new ArrayList<>();
        if (row > 0)
            coords.add(new Coords(row - 1, col));
        if (row < SIZE - 1)
            coords.add(new Coords(row + 1, col));
        if (col > 0)
            coords.add(new Coords(row, col - 1));
        if (col < SIZE - 1)
            coords.add(new Coords(row, col + 1));
        return coords;
    }

    // need equals and hashCode to be defined
}

您的看板然后变成 Map<Coord, Player> board - 您不再需要 'empty' 值,因为地图中没有坐标。

一旦你实现了检查获胜是一件相当简单的事情(我在这里使用了 Java 8):

public boolean hasWon(CellValue player) {
    return board.keySet().stream()
        .filter(c -> !board.get(c).equals(player))
        .filter(c -> c.listSurroundingCoords().stream()
            .allMatch(s -> board.containsKey(s) && board.get(s).equals(player)))
        .findAny().isPresent();
}

如果您不使用 Java 8 或必须使用数组,请告诉我,我可以 post 等效地使用标准迭代并避免 Map.

嘿,你也在 Jags class?

我刚刚完成项目并使用以下作为我的 isSurrounded() 方法。它当然不像上面的其他课程那么复杂,但它为较低级别的课程提供了重点:

private boolean isSurrounded(Cell type, Cell other) {
    for (int r = 0; r < size; r++) {
        for (int c = 0; c < size; c++) {
            if(board[r][c] == type){
                int count = 0;
                int win_count = 0;
                log(c + " " + r);
                if((r-1) >= 0 && (r - 1) < size){
                    win_count++;
                    if (board[r - 1][c] == other) {
                        count++;
                    }
                }

                if((r + 1) >= 0 && (r + 1) < size){
                    win_count++;
                    if (board[r + 1][c] == other) {
                        count++;
                    }
                }

                if((c + 1) >= 0 && (c + 1) < size){
                    win_count++;
                    if (board[r][c + 1] == other) {
                        count++;
                    }
                }

                if((c - 1) >= 0 && (c - 1) < size){
                    win_count++;
                    if (board[r][c - 1] == other) {
                        count++;
                    }
                }
                if(win_count == count){
                    return true;
                }
            }
        }
    }
    return false;
}