0

Javaでリバーシ(オセロ)ゲームを作っています。以下に含まれるのは、タイルを選択したピースの左、右、下、または上に反転する必要がある場合の私の関数です。何らかの理由で、垂直反転が開始されるたびに、常に正しく機能します。ただし、水平方向の反転が開始されると、(何かを行う必要があるときに) 何もしないか、反転するはずのない空白のタイルが反転することがあります。ゲームボードは、BlankPiece と呼ばれる拡張 JButton を使用した 8 x 8 のマトリックスです。関数に加えて投稿します。このゲームをバグなしで実行するためのより効率的/より良い方法を提案できる人はいますか? どんな助けでも大歓迎です!説明が必要な場合は、質問してください。

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

以上が私の 4 つの機能です (西、東、北、南に 1 つ)。BlankPiece は以下のとおりです。

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 関数の何かです...

編集: リクエストによる完全な作業例。

2 つのファイルを含むフォルダーを作成する

1 つは Reversi.java と呼ばれ、もう 1 つは 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);
        }

    }

}
4

1 に答える 1

1

残念ながら、画像を使用しているため、コードを実行できませんでした。画像がないと、どの部分が機能しているかどうかを判断できません。ただし、問題の解決に役立つと思われる別のアプローチの提案があります (必ずしもコードではなく、説明されているアイデアに注意してください)。

問題の説明: (私が理解しているように) プレーヤーが 1 つの色のピースをボードに置くと (ゲームには 2 つの色があり、各プレーヤーに 1 つ)、システムはすべてのブロックをすべての方向に沿ってトラバースする必要があります (8 つの色があります)。次のいずれかに遭遇するまで:

  • 同じ色のピース: この場合、中間の反対色のピースはすべてプレイヤーの色に反転します (つまり、それらは「キャプチャ」されます)。
  • 空白のピース/ブロック: この場合、色の反転は発生しません
  • ボードの端: ここでもフリップは発生しません。

上記の説明は、最初に解決する必要があるより小さな問題に問題をさらに分割できることを意味します。

解決すべき問題:

  • 「方向」をどのように特定できますか
  • 次のブロックを毎回考慮して、方向に沿ってどのようにトラバースできますか
  • キャプチャするはずのピースをどのように識別できますか
  • ボードの端をどのように識別できますか

あなたのアプローチは、上記の問題をすべて一緒に解決しようとします。これは複雑になります。さらに、異なる方向に対して同じ作業が繰り返されますが、そうである必要はありません。上記の説明のとおり、特定の方向に対して特別なアクションは必要ありません。単一方向の問題を解決する場合、すべての問題を解決する必要があります。

推奨されるアプローチ:以下に、キャプチャするすべてのピースを見つけるために使用するアルゴリズム (疑似コード) を示します。ピース自体が問題を解決しようとして、キャプチャされたすべてのピースが見つかるまで作業を次のピースに伝播する方法に注意してください。この方法では、問題を自分で解決することはできません。オブジェクトに正しく説明するだけです。各クラスがどうあるべきかを説明するためにコメントをインラインに入れました。わかりやすく、役に立つことを願っています。

// 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();
            }
        } 
    }
}
于 2013-08-02T13:13:09.637 に答える