Java 黑白棋游戏翻转瓷砖

标签 java reversi

我正在 Java 上创建一个黑白棋(奥赛罗)游戏。下面是我的函数,用于当图 block 需要向左、向右、下方或上方翻转所选 block 时。由于某种原因,每当启动垂直翻转时,它总是能正常工作。但是,当启动水平翻转时,有时它什么也不做(当它应该做某事时),或者翻转不应该翻转的空白图 block 。游戏板是一个 8 x 8 矩阵,使用名为 BlankPiece 的扩展 JButton。除了功能之外,我还将发布该内容。谁能建议一种更有效/更好的方式来运行这个游戏而不出现错误?任何帮助是极大的赞赏!如果您需要澄清,请询问。

   public void checkFlipDown(BlankPiece temp)
    {
        for(int j = temp.getRow() - 1; j>=0; j--){
            // j equals the square right above the clicked one, and it keeps going up until it hits the top of the board
        if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() != temp.pieceType())){
            //if the spot right above the clicked one is not black AND it is the other player's color,
            continue;
            // keep going with the block statement
        }
        if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() == temp.pieceType())){
        // if the spot right above is not black AND it is the same player's color,
            for(int i = temp.getRow(); i >= j; i--)
                // i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
                {
                // change the colors of all colors in the clicked color's column and rows in between the other border piece
                    gameboard[i][temp.getCol()].change(temp.pieceType());
                }
            }
        else
        {
            // if no other border pieces exist, go out of the loop
            break;
        }
        }
    }
    public void checkFlipUp(BlankPiece temp)
    {
        for(int j = temp.getRow() + 1; j<=7; j++){
            // j equals the square right below the clicked one, and it keeps going down until it hits the bottom of the board
        if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() != temp.pieceType())){
            //if the spot right above the clicked one is not black AND it is the other player's color,
            continue;
            // keep going with the block statement            2,4 jj = 3,4,5,6,7
        }
        if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() == temp.pieceType())){
        // if the spot right above is not black AND it is the same player's color,
            for(int i = temp.getRow(); i <= j; i++)
                // i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
                {
                // change the colors of all colors in the clicked color's column and rows in between the other border piece
                    gameboard[i][temp.getCol()].change(temp.pieceType());
                }
            }
        else
        {
            break;
        }
        }
    }
    public void checkFlipLeft(BlankPiece temp)
    {
        for(int j = temp.getCol() + 1; j<=7; j++){
            // j equals the square right below the clicked one, and it keeps going down until it hits the bottom of the board
        if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() != temp.pieceType())){
            //if the spot right above the clicked one is not black AND it is the other player's color,
            continue;
            // keep going with the block statement            2,4 jj = 3,4,5,6,7
        }
        if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() == temp.pieceType())){
        // if the spot right above is not black AND it is the same player's color,
            for(int i = temp.getCol(); i <= j; i++)
                // i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
                {
                // change the colors of all colors in the clicked color's column and rows in between the other border piece
                    gameboard[temp.getRow()][i].change(temp.pieceType());
                }
            }
        else
        {
            break;
        }
        }
    }
    public void checkFlipRight(BlankPiece temp)
    {
        for(int j = temp.getCol() - 1; j>=0; j--){
            // j equals the square to the right of the clicked one, and it keeps going down until it hits the bottom of the board
        if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() != temp.pieceType())){
            //if the spot right above the clicked one is not black AND it is the other player's color,
            continue;
            // keep going with the block statement            2,4 jj = 3,4,5,6,7
        }
        if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() == temp.pieceType())){
        // if the spot right above is not black AND it is the same player's color,
            for(int i = temp.getCol(); i >= j; i--)
                // i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
                {
                // change the colors of all colors in the clicked color's column and rows in between the other border piece
                    gameboard[temp.getRow()][i].change(temp.pieceType());
                }
            }
        else if (gameboard[j][temp.getRow()].pieceType() == 0)
        {
            break;
        }
        }
    }

这就是我的四个功能(西、东、北、南各一个)。空白部分如下:

import java.awt.Color;

import javax.swing.*;


public class BlankPiece extends JButton
{
    private final ImageIcon bbutton = new ImageIcon("bbutton.png");
    private final ImageIcon gbutton = new ImageIcon("gbutton.jpg");
    private final ImageIcon pbutton = new ImageIcon("pbutton.png");
    private int x;
    private int y;

    BlankPiece(int x, int y)
    {
      this.setBackground(Color.BLACK);
      this.setIcon(bbutton);
      this.x = x;
      this.y = y;
    }
    public void setGreen()
    {
          this.setBackground(Color.BLACK);
          this.setIcon(gbutton);
    }
    public void setPurple()
    {
          this.setBackground(Color.BLACK);
          this.setIcon(pbutton);
    }
    public int getRow() {
        // TODO Auto-generated method stub
        return x;
    }
    public int getCol() {
        return y;
    }
    public void resetImage(int count)
    {
        if (count % 2 == 0)
        {
              this.setIcon(gbutton);
        }
        else
        {
            this.setIcon(pbutton);
        }
    }

    public boolean isSet()
    {

        String image = "" + this.getIcon();

        if((image.equals("pbutton.png")) || (image.equals("gbutton.jpg")))
        {
        }
        return false;
    }
    public int pieceType()
    {
        if(getIcon().equals(pbutton)) // purple
        {
            return -1;
        }
        else if(getIcon().equals(bbutton)) // blank
        {
            return 0;
        }
        else // green
        {
            return 1;
        }
    }
    public void change(int i) {
        if (i == -1)
        {
            setIcon(pbutton);
        }
        else if(i == 1)
        {
            setIcon(gbutton);
        }
        else
        {
            setIcon(bbutton);
        }

    }

}

问题不在于任何 checkflip 未被调用(它们都使用相同的正确参数调用),而是 checkFlipRight 或 CheckFlipLeft 函数中的某些内容...

编辑:根据要求提供完整的工作示例。

创建一个包含两个文件的文件夹

其中一个名为 Reversi.java 另一个是BlankPiece.java

黑白棋.JAVA:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Reversi extends JPanel {
    BlankPiece [][] gameboard = new BlankPiece[8][8];
    JPanel toparea = new JPanel();
    JPanel gamearea = new JPanel();
    JPanel greenarea = new JPanel();
    JPanel purplearea = new JPanel();
    JPanel logo = new JPanel();
    JLabel logoarea = new JLabel();
    JLabel greenlogo = new JLabel();
    JLabel purplelogo = new JLabel();
    ImageIcon blackicon = new ImageIcon("bbutton.png");
    ImageIcon icon = new ImageIcon("reversilogo.png");
    ImageIcon dgreen = new ImageIcon("DarkGreen.png");
    ImageIcon lgreen = new ImageIcon("LightGreen.png");
    ImageIcon dpurple = new ImageIcon("DarkPurple.png");
    ImageIcon lpurple = new ImageIcon("LightPurple.png");
    int count = 0;
    int jplus = 0;
    public Reversi()
    {  
        gamearea.setLayout(new GridLayout(8,8));
        for (int row = 0; row < gameboard.length; row++)
        {
            for(int col = 0; col < gameboard.length; col++)
            {
                gameboard[row][col] = new BlankPiece(row, col);
                gamearea.add(gameboard[row][col]);
                gameboard[row][col].addActionListener(new ButtonListener());

            }
        }
        logoarea.setPreferredSize(new Dimension(304,73));
        toparea.setLayout(new BorderLayout());
        this.setLayout(new BorderLayout());
        toparea.setBackground(new Color(97,203,242));
        gamearea.setBackground(new Color(83,35,215));
        logo.setBackground(new Color(97,203,242));
        logoarea.setIcon(icon);
        greenlogo.setIcon(dgreen);
        purplelogo.setIcon(lpurple);
        toparea.add(greenlogo, BorderLayout.WEST);
        toparea.add(purplelogo, BorderLayout.EAST);
        toparea.add(logo, BorderLayout.CENTER);
        logo.add(logoarea);
        this.add(toparea, BorderLayout.NORTH);
        this.add(gamearea, BorderLayout.CENTER);
        gameboard[3][3].setGreen();
        gameboard[3][4].setPurple();
        gameboard[4][3].setPurple();
        gameboard[4][4].setGreen();
    }
    private class ButtonListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            BlankPiece temp = (BlankPiece)e.getSource();  // #1
            int row = temp.getRow();  // #2
            System.out.println(row);
            int col = temp.getCol();
            System.out.println(col);

            temp.isSet();

            // col and row are the column and row of blankpiece that was clicked
            String image = "" + temp.getIcon();
            if((image.equals("pbutton.png")) || (image.equals("gbutton.jpg")))
            {
                JOptionPane.showMessageDialog(null, "This spot is already occupied by " +
                        "a piece. Please pick an empty tile.");
            }
            else 
            {
                temp.resetImage(count++);
                System.out.println("About to check");
                checkFlipDown(gameboard[row][col]);
                checkFlipUp(gameboard[row][col]);
                checkFlipLeft(gameboard[row][col]);
                checkFlipRight(gameboard[row][col]);
            }
            if (count % 2 == 0)
            {
                greenlogo.setIcon(dgreen);
                purplelogo.setIcon(lpurple);
            }
            else
            {
                greenlogo.setIcon(lgreen);
                purplelogo.setIcon(dpurple);
            }
        } 
    } 
    public void checkFlipDown(BlankPiece temp)
    {
        for(int j = temp.getRow() - 1; j>=0; j--){
            // j equals the square right above the clicked one, and it keeps going up until it hits the top of the board
        if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() != temp.pieceType())){
            //if the spot right above the clicked one is not black AND it is the other player's color,
            continue;
            // keep going with the block statement
        }
        if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() == temp.pieceType())){
        // if the spot right above is not black AND it is the same player's color,
            for(int i = temp.getRow(); i >= j; i--)
                // i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
                {
                // change the colors of all colors in the clicked color's column and rows in between the other border piece
                    gameboard[i][temp.getCol()].change(temp.pieceType());
                }
            }
        else
        {
            // if no other border pieces exist, go out of the loop
            break;
        }
        }
    }
    public void checkFlipUp(BlankPiece temp)
    {
        for(int j = temp.getRow() + 1; j<=7; j++){
            // j equals the square right below the clicked one, and it keeps going down until it hits the bottom of the board
        if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() != temp.pieceType())){
            //if the spot right above the clicked one is not black AND it is the other player's color,
            continue;
            // keep going with the block statement            2,4 jj = 3,4,5,6,7
        }
        if ((gameboard[j][temp.getCol()].pieceType() != 0) && (gameboard[j][temp.getCol()].pieceType() == temp.pieceType())){
        // if the spot right above is not black AND it is the same player's color,
            for(int i = temp.getRow(); i <= j; i++)
                // i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
                {
                // change the colors of all colors in the clicked color's column and rows in between the other border piece
                    gameboard[i][temp.getCol()].change(temp.pieceType());
                }
            }
        else
        {
            break;
        }
        }
    }
    public void checkFlipLeft(BlankPiece temp)
    {
        for(int j = temp.getCol() + 1; j<=7; j++){
            // j equals the square right below the clicked one, and it keeps going down until it hits the bottom of the board
        if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() != temp.pieceType())){
            //if the spot right above the clicked one is not black AND it is the other player's color,
            continue;
            // keep going with the block statement            2,4 jj = 3,4,5,6,7
        }
        if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() == temp.pieceType())){
        // if the spot right above is not black AND it is the same player's color,
            for(int i = temp.getCol(); i <= j; i++)
                // i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
                {
                // change the colors of all colors in the clicked color's column and rows in between the other border piece
                    gameboard[temp.getRow()][i].change(temp.pieceType());
                }
            }
        else
        {
            break;
        }
        }
    }
    public void checkFlipRight(BlankPiece temp)
    {
        for(int j = temp.getCol() - 1; j>=0; j--){
            // j equals the square to the right of the clicked one, and it keeps going down until it hits the bottom of the board
        if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() != temp.pieceType())){
            //if the spot right above the clicked one is not black AND it is the other player's color,
            continue;
            // keep going with the block statement            2,4 jj = 3,4,5,6,7
        }
        if ((gameboard[j][temp.getRow()].pieceType() != 0) && (gameboard[j][temp.getRow()].pieceType() == temp.pieceType())){
        // if the spot right above is not black AND it is the same player's color,
            for(int i = temp.getCol(); i >= j; i--)
                // i equals the row of the clicked spot, it goes until it finds J, where the other green / purple end piece is
                {
                // change the colors of all colors in the clicked color's column and rows in between the other border piece
                    gameboard[temp.getRow()][i].change(temp.pieceType());
                }
            }
        else if (gameboard[j][temp.getRow()].pieceType() == 0)
        {
            break;
        }
        }
    }

}

BLANKPIECE.JAVA

import java.awt.Color;

import javax.swing.*;


public class BlankPiece extends JButton
{
    private final ImageIcon bbutton = new ImageIcon("bbutton.png");
    private final ImageIcon gbutton = new ImageIcon("gbutton.jpg");
    private final ImageIcon pbutton = new ImageIcon("pbutton.png");
    private int x;
    private int y;

    BlankPiece(int x, int y)
    {
      this.setBackground(Color.BLACK);
      this.setIcon(bbutton);
      this.x = x;
      this.y = y;
    }
    public void setGreen()
    {
          this.setBackground(Color.BLACK);
          this.setIcon(gbutton);
    }
    public void setPurple()
    {
          this.setBackground(Color.BLACK);
          this.setIcon(pbutton);
    }
    public int getRow() {
        // TODO Auto-generated method stub
        return x;
    }
    public int getCol() {
        return y;
    }
    public void resetImage(int count)
    {
        if (count % 2 == 0)
        {
              this.setIcon(gbutton);
        }
        else
        {
            this.setIcon(pbutton);
        }
    }

    public boolean isSet()
    {

        String image = "" + this.getIcon();

        if((image.equals("pbutton.png")) || (image.equals("gbutton.jpg")))
        {
        }
        return false;
    }
    public int pieceType()
    {
        if(getIcon().equals(pbutton)) // purple
        {
            return -1;
        }
        else if(getIcon().equals(bbutton)) // blank
        {
            return 0;
        }
        else // green
        {
            return 1;
        }
    }
    public void change(int i) {
        if (i == -1)
        {
            setIcon(pbutton);
        }
        else if(i == 1)
        {
            setIcon(gbutton);
        }
        else
        {
            setIcon(bbutton);
        }

    }

}

最佳答案

不幸的是,我无法运行你的代码,因为它使用图像,如果没有它们,就不可能知道哪个部分正在工作或不工作。不过,我有一个不同方法的建议,我认为它会帮助您解决问题(请注意所描述的想法,而不一定是代码)。

问题描述:(据我理解)当玩家将一种颜色的棋子放在棋盘上时(游戏中有两种颜色,每个玩家一种),系统需要沿各个方向遍历所有 block (共有8个),直到遇到以下之一:

  • 相同颜色的棋子:在这种情况下,所有中间相反颜色的棋子都会翻转为玩家的颜色(即它们被“捕获”)
  • 空白 block / block :在这种情况下不会发生颜色翻转
  • 板的边缘:同样不会发生翻转。

上面的描述意味着问题可以进一步划分为我们需要首先解决的更小的问题。

要解决的问题:

  • 我们如何识别“方向”
  • 我们如何沿着一个方向遍历,考虑每次下一个 block
  • 我们如何识别应该被捕获的棋子
  • 我们如何识别木板的边缘

您的方法试图一起解决上述所有问题。这使得事情变得复杂。此外,对于不同的方向重复相同的工作,但情况并非如此。根据上面的描述,对于特定方向不需要特殊的操作。如果我们解决一个方向的问题,那么它应该解决所有的问题。

建议方法:您可以在下面找到用于查找所有要捕获的片段的算法(伪代码)。请注意该片段本身如何尝试解决问题并将工作传播到下一个片段,直到找到所有捕获的片段。这样你就不用自己解决问题了。您只需向您的对象正确地描述它即可。我已经内嵌了注释来解释每个类应该是什么。我希望它对您来说清晰且有用。

// Convenient class to hold together a row and a column pair
public class Index { ... }

// Checks if an index falls out of board edges
public static boolean isValid(Index index) {...}

// Holds the array of pieces. Has method to get a piece by index
public class Board { ... } 

public enum ColorType { BLANK, WHITE, BLACK; } // the types of a Piece    

// The possible directions to traverse
public enum Direction {
    UP_LEFT, UP, UP_RIGHT, RIGHT, BOTTOM_RIGHT, BOTTOM, BOTTOM_LEFT, LEFT;

    // given an index it returns the next index along the same direction
    public Index next(Index index) {
        switch (this) {
        case UP_LEFT:
            return new Index(index.row() - 1, index.column() - 1);
        case BOTTOM:
            return new Index(index.row() + 1, index.column());
        ... // similar for the rest of cases
        }
    }
}

public class Piece {

    private Board board;
    private ColorType color = ColorType.BLANK;
    private Index index;

    ....

    // Should be called privately when the piece is put on the board and from BLANK becomes WHITE or BLACK
    private void checkCaptures() {
        Direction[] directions = Direction.values();

        for (Direction direction : directions) {
            // get next piece's index along the direction
            Index nextIndex = direction.next(this.index);

            if ( isValid(nextIndex) ) { // if the index is not valid (i.e. edge of the board) ignore it

                // get next piece in the same direction
                Piece piece = board.getPiece(nextIndex);

                // find all pieces that should be captured in this direction 
                List<Piece> candidatesToCapture = new ArrayList<Piece>();
                piece.findCaptureCandidates(candidatesToCapture, this.color, direction);

                for (Piece candidate : candidatesToCapture) {
                    // flip the color (WHITE to BLACK and vice-versa)
                    candidate.capture(); 
                }
            } 
        }
    }

    private void findCaptureCandidates(List<Piece> captured, ColorType firstColor, Direction d) {

        Index next = d.next(this.index);

        if (this.color == firstColor) {
            // This piece has the same color with the first one.
            // No need to search further for this direction. All pieces collected in the list
            // between the first one and this one, have opposite color and should be captured.

        } else if (this.color == ColorType.BLANK) {
            // found a blank piece. Stop the search and clear any captured pieces found so far
            captured.clear();
        } else {
            // this piece has the opposite color of the first
            if ( isValid(next) ) {
                // this is not the last piece in this direction. 
                // Since it has a flipped color it is a candidate for capturing
                captured.add(this);

                // ask the next piece recursively to also check itself
                Piece piece = board.getPiece(next);
                piece.findCaptureCandidates(captured, firstColor, d);
            } else {
                // next index is not valid i.e. we have reached board edge. 
                // Stop the search and clear any captured pieces found so far
                captured.clear();
            }
        } 
    }
}

关于Java 黑白棋游戏翻转瓷砖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18003301/

相关文章:

java - 为什么有 26 个 GMT 偏移量?

java - Launch4J 输入互斥体错误

heuristics - 需要启发式功能以用于黑白棋(Othello)创意

java - 如果距离大于 2,寻路搜索崩溃

java - NoClassDefFounderror 安卓

java - 如何使用 Spring MVC 正确记录 http 请求

java - 如何在 spring-boot 多模块 Java 11 项目中添加 Spark 依赖项

java - 在 JButton 顶部绘制一个椭圆形

algorithm - 黑白棋评价函数