如何检查2D数组的相邻索引-Othello

时间:2019-01-18 02:31:12

标签: java multidimensional-array othello

请明确说明,在寻求帮助之前,我已经在Stack Overflow和其他网站上研究了与之类似的问题。我还提供了以下所有代码,以防万一它可以帮助任何人理解问题。

在奥赛罗(Othello)游戏(也称为黑白棋)中,有两个玩家使用相反颜色的瓷砖。玩家需要放置一个瓷砖,使其与相反颜色的瓷砖相邻,并且相反颜色必须在同一方向的任一侧都被瓷砖包围。例如,如果黑色图块的左侧有一个白色图块,则需要在白色图块的左侧放置另一个黑色图块,以便将其包围。如果瓷砖被包围,它将翻转。

(黑色-白色-黑色)->(黑色-黑色-黑色)

包围可以水平,对角或垂直进行。

我遇到的问题是,我不知道如何检查所有索引并查看它们是否一次起作用。我已经尝试通过检查旁边所有可能的值来检查与相反颜色的图块相邻的值。这无法正常工作,因为无法确保瓷砖的两侧都被包围或不能连续应用于多于一个瓷砖的行。

/**
 *  Checks to see if a valid move can be made at the indicated OthelloCell,
 *  for the given player.
 *  @param  xt      The horizontal coordinate value in the board.
 *  @param  yt      The vertical coordinate value in the board.
 *  @param  bTurn   Indicates the current player, true for black, false for white
 *  @return         Returns true if a valid move can be made for this player at
 *                  this position, false otherwise.
 */
public boolean isValidMove(int xt, int yt, boolean bTurn)
{
    int length = board[0].length;

    // checks if the tile has already been picked, meaning it can no longer be selected
    if(board[xt][yt].hasBeenPlayed())
    {
        return false;
    }
    else
    {
        /* For BLACK (Working) */
        if(bTurn)
        {
            // checks tiles one row above
            if(xt + 1 < length && board[xt + 1][yt].getBlackStatus() == false)
            {
                System.out.println("the one 1 row up and in the same column doesn't work");
                return true;
            }
            if(xt + 1 < length && board[xt + 1][yt + 1].getBlackStatus() == false)
            {
                System.out.println("the one 1 row up and in the right column doesn't work");
                return true;
            }
            if(xt + 1 < length && board[xt + 1][yt - 1].getBlackStatus() == false)
            {
                System.out.println("the one 1 row up and in the left column doesn't work");
                return true;
            }
            // checks tiles left and right
            if(yt + 1 < length && board[xt][yt + 1].getBlackStatus() == false)
            {
                System.out.println("the one in the same row and in the right column doesn't work");
                return true;
            }
            if(yt > 1 && board[xt][yt - 1].getBlackStatus() == false)
            {
                System.out.println("the one in the same row and in the left column doesn't work");
                return true;
            }
            // checks tiles one row below
            if(xt > 1 && board[xt - 1][yt].getBlackStatus() == false)
            {
                System.out.println("The one 1 row down and in the same column doesn't work");
                return true;
            }
            if(xt > 1 && board[xt - 1][yt + 1].getBlackStatus() == false)
            {
                System.out.println("The one 1 row down and in the right column doesn't work");
                return true;
            }
            if(xt > 1 && board[xt - 1][yt - 1].getBlackStatus() == false)
            {
                System.out.println("The one 1 row down and in the left column doesn't work");
                return true;
            }
        }

    }
    return false;
}

/**
 *  Checks to see if a valid move can be made at the indicated OthelloCell, in a 
 *  particular direction (there are 8 possible directions).  These are indicated by:
 *  (1,1) is up and right
 *  (1,0) is right
 *  (1,-1) is down and right
 *  (0,-1) is down
 *  (-1,-1) is down and left
 *  (-1,0) is left
 *  (-1,1) is left and up
 *  (0,1) is up
 *  @param  xt      The horizontal coordinate value in the board.
 *  @param  yt      The vertical coordinate value in the board.
 *  @param  i       -1 is left, 0 is neutral, 1 is right,
 *  @param  j       -1 is down, - is neutral, 1 is up.
 *  @param  bTurn   Indicates the current player, true for black, false for white.
 *  @return         Returns true if this direction has pieces to be flipped, false otherwise.
 */
public boolean directionValid(int xt, int yt, int i, int j, boolean bTurn)
{       
    return true;
}

上面是我遇到的两种方法。

public class Othello
{
/**    The board object.  This board will be 8 x 8, and filled with OthelloCells.
 *     The cell may be empty, hold a white game piece, or a black game piece.       */
private OthelloCell [][] board;

/**    The coordinates of the active piece on the board.                            */
private int x, y;

/**    Booleans indicating that the mouse is ready to be pressed, that it is     
 *     black's turn to move (false if white's turn), and that the game is over.     */
private boolean mousePressReady, blackTurn, gameOver;

/**
 *  Creates an Othello object, with a sized graphics canvas, and a 2D (8 x 8) array
 *  of OthelloCell, setting up initial values.
 */
/* COMPLETE */
public Othello ( )
{
    StdDraw.setCanvasSize(500,650);
    StdDraw.setXscale(0,1);
    StdDraw.setYscale(0,1.3);
    StdDraw.enableDoubleBuffering();
    Font font = new Font("Arial", Font.BOLD, 30);
    StdDraw.setFont(font);

    startBoard();
}

/**
 *  Called by the constructor, or when the player hits the "RESET" button,
 *  initializing the game board (an 8 x 8 array of OthelloCell).
 */
/* COMPLETE */
public void startBoard ( )
{
    mousePressReady = blackTurn = true;
    gameOver = false;
    board = new OthelloCell[8][8];
    for ( int i = 0; i < board.length; i++ )
    {
        for ( int j = 0; j < board[i].length; j++ )
        {
            board[i][j] = new OthelloCell(i,j);
        }
    }
    board[3][3].playIt();
    board[3][3].setBlack(true);
    board[4][4].playIt();
    board[4][4].setBlack(true);
    board[4][3].playIt();
    board[4][3].setBlack(false);
    board[3][4].playIt();
    board[3][4].setBlack(false);
}

/**
 *  Sets up and runs the game of Othello.
 */
/* COMPLETE */
public static void main(String [] args)
{
    Othello game = new Othello();
    game.run();
}

/**
 *  Runs an endless loop to play the game.  Even if the game is over, the
 *  loop is still ready for the user to press "RESET" to play again.
 */
/* COMPLETE */
public void run ( )
{
    do
    {
        drawBoard();
        countScoreAnddrawScoreBoard();
        StdDraw.show();
        StdDraw.pause(30);
        makeChoice();
        gameOver = checkTurnAndGameOver();
    }
    while(true);
}

/**
 *  Draws the board, in its current state, to the GUI.
 */
/* COMPLETE */
public void drawBoard ( )
{
    StdDraw.setPenColor(new Color(150,150,150));
    StdDraw.filledRectangle(0.5,0.75,0.5,0.75);
    StdDraw.setPenColor(new Color(0,110,0));
    StdDraw.filledSquare(0.5,0.5,0.45);
    StdDraw.setPenColor(new Color(0,0,0));
    StdDraw.filledSquare(0.5,0.5,0.42);
    for ( int i = 0; i < board.length; i++ )
    {
        for ( int j = 0; j < board[i].length; j++ )
        {
            board[i][j].drawCell();
        }
    }
}

/**
 *  Waits for the user to make a choice.  The user can make a move
 *  placing a black piece or the white piece (depending on whose turn
 *  it is), or click on the "RESET" button to reset the game.
 */
/* COMPLETE */
public void makeChoice ( )
{
    boolean moveChosen = false;
    while(!moveChosen)
    {
        if(mousePressReady && StdDraw.isMousePressed())
        {           
            mousePressReady = false;
            double xval = StdDraw.mouseX();
            double yval = StdDraw.mouseY();
            if(xval > 0.655 && xval < 0.865 && yval > 1.15 && yval < 1.23)    //  This if checks for a reset.
            {
                startBoard();
                return;
            }
            if(xval < 0.1 || xval > 0.9 || yval < 0.1 || yval > 0.9)          //  This if checks for a press off the board.
            {
                return;
            }
            int tempx = (int)(10 * (xval - 0.1));
            int tempy = (int)(10 * (yval - 0.1));
            if(isValidMove(tempx,tempy,blackTurn))                            //  This if checks to see if the move is valid.
            {
                x = tempx;
                y = tempy;
                playAndFlipTiles();
                blackTurn = !blackTurn;
                System.out.println(x + "  " + y);
            }
        }
        if(!StdDraw.isMousePressed() && !mousePressReady)                      //  This if gives back control when the mouse is released.
        {
            mousePressReady = true;
            return;
        }
        StdDraw.pause(20);
    }

}

/**
 *  Checks to see if a valid move can be made at the indicated OthelloCell,
 *  for the given player.
 *  @param  xt      The horizontal coordinate value in the board.
 *  @param  yt      The vertical coordinate value in the board.
 *  @param  bTurn   Indicates the current player, true for black, false for white
 *  @return         Returns true if a valid move can be made for this player at
 *                  this position, false otherwise.
 */
public boolean isValidMove(int xt, int yt, boolean bTurn)
{
    int length = board[0].length;

    // checks if the tile has already been picked, meaning it can no longer be selected
    if(board[xt][yt].hasBeenPlayed())
    {
        return false;
    }
    else
    {

    }
    return false;
}

/**
 *  Checks to see if a valid move can be made at the indicated OthelloCell, in a 
 *  particular direction (there are 8 possible directions).  These are indicated by:
 *  (1,1) is up and right
 *  (1,0) is right
 *  (1,-1) is down and right
 *  (0,-1) is down
 *  (-1,-1) is down and left
 *  (-1,0) is left
 *  (-1,1) is left and up
 *  (0,1) is up
 *  @param  xt      The horizontal coordinate value in the board.
 *  @param  yt      The vertical coordinate value in the board.
 *  @param  i       -1 is left, 0 is neutral, 1 is right,
 *  @param  j       -1 is down, - is neutral, 1 is up.
 *  @param  bTurn   Indicates the current player, true for black, false for white.
 *  @return         Returns true if this direction has pieces to be flipped, false otherwise.
 */
public boolean directionValid(int xt, int yt, int i, int j, boolean bTurn)
{       
    return true;
}

/**
 *  Places a game piece on the current cell for the current player.  Also flips the
 *  appropriate neighboring game pieces, checking the 8 possible directions from the
 *  current cell.
 */
public void playAndFlipTiles ( )
{
    board[x][y].setBlack(blackTurn);
    board[x][y].playIt();       

    //  To be completed by you.
}

/**
 *  A helper method for playAndFlipTiles.  Flips pieces in a given direction.  The
 *  directions are as follows:
 *  (1,1) is up and right
 *  (1,0) is right
 *  (1,-1) is down and right
 *  (0,-1) is down
 *  (-1,-1) is down and left
 *  (-1,0) is left
 *  (-1,1) is left and up
 *  (0,1) is up
 *  @param  xt      The horizontal coordinate value in the board.
 *  @param  yt      The vertical coordinate value in the board.
 *  @param  i       -1 is left, 0 is neutral, 1 is right,
 *  @param  j       -1 is down, - is neutral, 1 is up.
 */
public void flipAllInThatDirection(int xt, int yt, int i, int j)
{

}

/**
 *  Counts the white pieces on the board, and the black pieces on the board.
 *  Displays these numbers toward the top of the board, for the current state
 *  of the board.  Also prints whether it is "BLACK'S TURN" or "WHITE'S TURN"
 *  or "GAME OVER".
 */
 /* COMPLETE */
public void countScoreAnddrawScoreBoard ( )
{
    int whiteCount = 0, blackCount = 0;

    for(int i = 0; i < board.length; i++)
    {
        for(int j = 0; j < board[i].length; j++)
        {
            if(board[i][j].hasBeenPlayed())
            {
                if(board[i][j].getBlackStatus())
                {
                    blackCount++;
                }
                else
                {
                    whiteCount++;
                }
            }
        }
    }

    drawScoresAndMessages(whiteCount,blackCount);
}

/**
 *  A helper method for countScoreAnddrawScoreBoard.  Draws the scores
 *  and messages.
 *  @param  whiteCount      The current count of the white pieces on the board.
 *  @param  blackCount      The current count of the black pieces on the board.
 */
 /* COMPLETE */
public void drawScoresAndMessages(int whiteCount, int blackCount)
{
    StdDraw.setPenColor(new Color(0,0,0));
    StdDraw.filledRectangle(0.41,1.05,0.055,0.045);
    StdDraw.filledRectangle(0.80,1.05,0.055,0.045);
    StdDraw.filledRectangle(0.76,1.19,0.11,0.045);
    StdDraw.setPenColor(new Color(255,255,255));
    StdDraw.filledRectangle(0.41,1.05,0.05,0.04);
    StdDraw.filledRectangle(0.80,1.05,0.05,0.04);
    StdDraw.filledRectangle(0.76,1.19,0.105,0.04);
    StdDraw.setPenColor(new Color(0,0,0));
    StdDraw.text(0.24,1.04,"BLACK");
    StdDraw.text(0.41,1.04,"" + blackCount);
    StdDraw.text(0.63,1.04,"WHITE");
    StdDraw.text(0.80,1.04,"" + whiteCount);
    StdDraw.text(0.76,1.18,"RESET");
    if(gameOver)
    {
        StdDraw.text(0.34,1.18,"GAME OVER");
    }
    else if(blackTurn)
    {
        StdDraw.text(0.34,1.18,"BLACK'S TURN");
    }
    else
    {
        StdDraw.text(0.34,1.18,"WHITE'S TURN");
    }
}

/**
 *  Checks to see if black can play.  Checks to see if white can play.
 *  If neither can play, the game is over.  If black can't go, then set
 *  blackTurn to false.  If white can't go, set blackTurn to true.
 *  @return         Returns true if the game is over, false otherwise.
 */
 /* COMPLETE */
public boolean checkTurnAndGameOver ( )
{
    boolean whiteCanGo = false, blackCanGo = false;

    //  To be completed by you.

    return false;
}
}

/**
 * Represents a single cell in the game of Othello.  By default, a cell is black, and
 * has not been played.  When a game piece is "placed" on the board, the boolean played
 * is set to true.  If the game piece is black, then the boolean black is true, and if
 * the game piece is white, then the boolean black is false.  The ints x and y 
 * represent the coordinate values of the cell within the game board, with the lower
 * left at (0,0) and the upper right at (7,7).
 */
class OthelloCell         
{
/**    The coordinates of the active piece on the board.                              */
private int x, y;

/**    Booleans indicating if a piece has been played (or is empty), and indicating
 *     if the piece is black (or white)                                               */
private boolean played, black;

/**
 *  Creates an OthelloCell object, at the given coordinate pair.
 *  @param  i      The horizontal coordinate value for the cell on the board.
 *  @param  j      The vertical coordinate value for the cell on the board.
 */
 /* COMPLETE */
public OthelloCell(int i, int j)
{
    played = false;
    x = i;
    y = j;
    black = true;
}

/**
 *  Draws the cell on the board, in its current state.
 */
 /* COMPLETE */
public void drawCell ( )   
{
    StdDraw.setPenColor(new Color(0,0,0));
    StdDraw.filledSquare(0.15 + 0.1 * x, 0.15 + 0.1 * y, 0.05);
    StdDraw.setPenColor(new Color(0,110,0));
    StdDraw.filledSquare(0.15 + 0.1 * x, 0.15 + 0.1 * y, 0.048);

    if(played)
    {
        for(int i = 0; i <= 20; i++)
        {
            if(black)
            {
                StdDraw.setPenColor(new Color(5+8*i,5+8*i,5+8*i));
            }
            else
            {
                StdDraw.setPenColor(new Color(255-8*i,255-8*i,255-8*i));
            }
            StdDraw.filledCircle(0.15 + 0.1 * x - i*0.001, 0.15 + 0.1 * y + i*0.001, 0.043-i*0.002);
        }
    }
}

/**
 *  Sets the piece to black (black true) or white (black false).
 *  @param  bool      The value to be assigned to the game piece.
 */
 /* COMPLETE */
public void setBlack(boolean bool)
{
    if(bool)
    {
        black = true;
    }
    else
    {
        black = false;
    }
}

/**
 *  Return the status of black; true for a black piece, false for a white piece.
 *  @return            Returns true for a black piece, false for a white piece.
 */
 /* COMPLETE */
public boolean getBlackStatus ( )
{
    return black;
}

/**
 *  Sets the value of played to true, to indicate that a piece has been placed on this cell.
 */
 /* COMPLETE */
public void playIt ( )   
{
    played = true;
}

/**
 *  Return the status of played, indicating whether or not there is a game piece on this cell.
 *  @return            Returns true if a game piece is on this cell, false otherwise.
 */
 /* COMPLETE */
public boolean hasBeenPlayed ( )
{
    return played;
}
}

2 个答案:

答案 0 :(得分:0)

您可以使用两个不同的数组获得8个相邻的单元格。这些数组用于获取给定单元格的8个邻居的行号和列号

int rowNbr[] = new int[] {-1, -1, -1,  0, 0,  1, 1, 1}; 
int colNbr[] = new int[] {-1,  0,  1, -1, 1, -1, 0, 1}; 

并通过将当前行/列添加到上述数组中来迭代给定矩阵,例如:

for (int k = 0; k < 8; ++k) {
  sop(matrix[row + rowNbr[k], col + colNbr[k]])
}

此外,您可能要检查https://www.geeksforgeeks.org/find-number-of-islands/

希望这会帮助您进行进一步的思考。 thnx

答案 1 :(得分:0)

这是我的方法,尽管我确信它在C#中有一定用处。 还使用了Ashutosh中的部分解决方案。

“我的棋盘”是二维数组“件”,小写的“长度”只是棋盘的大小,而num是颜色的指示器:空是0,num是当前正在播放的东西,1是白色,2是白色黑色。

它所做的全部工作是在任一方向上寻找最接近的匹配颜色,而中间没有空格,然后将当前的播放颜色放置在它们之间的所有数组空间中。

这可能可以更聪明地完成,我什至不喜欢我总是检查各个方向上的整个字段的大小而忽略索引超出范围的异常的方法,但这是最简单的

            int[] rowNbr = { -1, -1, -1, 0, 0, 1, 1, 1 };
            int[] colNbr = { -1, 0, 1, -1, 1, -1, 0, 1 };
            for (int x = 0; x < 8; x++)
            {
                int facX = rowNbr[x];
                int facY = colNbr[x];
                try
                {
                    for (int i = 1; i < length; i++)
                    {
                        if (pieces[click.X + i * facX, click.Y + i * facY] == 0) break;
                        if (pieces[click.X + i * facX, click.Y + i * facY] == (byte)num)
                        {
                            for (int j = i - 1; j > 0; j--)
                            {
                                pieces[click.X + j * facX, click.Y + j * facY] = (byte)num;
                            }
                            break;
                        }
                    }
                }
                catch { } 
            }