Как проверить соседние индексы двумерного массива - Отелло - PullRequest
0 голосов
/ 18 января 2019

Просто чтобы прояснить ситуацию, я обращался к проблемам, в некоторой степени похожим на эту проблему, в Stack Overflow и на других веб-сайтах, прежде чем обращаться за помощью. Я также включил весь приведенный ниже код на всякий случай, чтобы он мог помочь любому понять проблему.

В игре Отелло, также известной как Реверси, есть два игрока, которые используют плитки противоположных цветов. Игрок должен поместить плитку так, чтобы она была рядом с плиткой противоположного цвета, а противоположный цвет должен быть окружен плиткой с обеих сторон в одном и том же направлении. Например, если слева от черной плитки есть белая плитка, то слева от белой плитки должна быть размещена другая черная плитка, чтобы она была окружена. Если плитка окружена, она переворачивается.

(черный - белый - черный) -> (черный - черный - черный)

Окружение может происходить по горизонтали, диагонали или по вертикали.

У меня проблема в том, что я не знаю, как проверить все индексы и посмотреть, работают ли они одновременно. Я попытался проверить значения, смежные с плиткой противоположного цвета, проверив все возможные значения рядом с ним. Это не работает должным образом, так как не позволяет убедиться, что плитка окружена с обеих сторон или применима к линии из нескольких плиток подряд.

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

1 Ответ

0 голосов
/ 18 января 2019

Вы можете получить 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

...