在Java中实现计算机转板的简单方法

时间:2009-10-16 09:18:22

标签: java graphics

我想制作一个简单的Go棋盘来设计Computer Go游戏。

在游戏中,你会在水平线和垂直线相交的位置上躺着一块“石头”(白色或黑色)。

有哪些简单方法可以限制用户将宝石放在其他位置? 也许我只是没有看到一个简单的解决方案。

修改
我想我应该更好地改写我的问题: 我想知道如何做Go板的背景图像,这样我就可以把石头放在水平线和垂直线的交点上。我正在考虑获得一个普通的Go棋盘图像,当我实际渲染石头时,我发现像素的正确位置可以找到石头。然而,这个解决方案似乎并不是最好的解决方案,因为我需要担心石头图像的大小,并在扩展或缩小板窗口时考虑比例。

5 个答案:

答案 0 :(得分:2)

我在这里使用枚举:

enum Stone {BLAC, WHITE, NONE}

class Board {
    static final int dimension = 19;
    private Stone[][] board = new Stone[dimension][dimension];
    // ...
}

修改

这是一个小型演示(没有调整电路板大小,没有图像,只是很好的旧图形!):

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

public class GoBoardDemo {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setLayout(new BorderLayout());
        frame.add(new GoPanel(19), BorderLayout.CENTER);
        frame.setSize(600, 625);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setVisible(true);
    }
}


@SuppressWarnings("serial")
class GoPanel extends JPanel {

    Square[][] board;
    boolean whiteToMove;

    GoPanel(int dimension) {
        board = new Square[dimension][dimension];
        whiteToMove = true;
        initBoard(dimension);
    }

    private void initBoard(int dimension) {
        super.setLayout(new GridLayout(dimension, dimension));
        for(int row = 0; row < dimension; row++) {
            for(int col = 0; col < dimension; col++) {
                board[row][col] = new Square(row, col);
                super.add(board[row][col]);
            }
        }
        repaint();
    }

    private class Square extends JPanel {

        Stone stone;
        final int row;
        final int col;

        Square(int r, int c) {
            stone = Stone.NONE;
            row = r;
            col = c;
            super.addMouseListener(new MouseAdapter(){
                @Override
                public void mouseClicked(MouseEvent me) {
                    if(stone != Stone.NONE) return;
                    stone = whiteToMove ? Stone.WHITE : Stone.BLACK;
                    whiteToMove = !whiteToMove;
                    repaint();
                }
            });
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            int w = super.getWidth();
            int h = super.getHeight();
            g.setColor(new Color(0xB78600));
            g.fillRect(0, 0, w, h);
            g.setColor(Color.BLACK);   
            if(row == 0 || row == board.length-1 || col == 0 || col == board.length-1) {
                if(col == 0) {
                    g.drawLine(w/2, h/2, w, h/2);
                    if(row == 0) g.drawLine(w/2, h/2, w/2, h);
                    else if(row == 18) g.drawLine(w/2, h/2, w/2, 0);
                    else g.drawLine(w/2, 0, w/2, h);
                }
                else if(col == 18) {
                    g.drawLine(0, h/2, w/2, h/2);
                    if(row == 0) g.drawLine(w/2, h/2, w/2, h);
                    else if(row == 18) g.drawLine(w/2, h/2, w/2, 0);
                    else g.drawLine(w/2, 0, w/2, h);
                }
                else if(row == 0) {
                    g.drawLine(0, h/2, w, h/2);
                    g.drawLine(w/2, h/2, w/2, h);
                }
                else {
                    g.drawLine(0, h/2, w, h/2);
                    g.drawLine(w/2, h/2, w/2, 0);
                }
            } else {
                g.drawLine(0, h/2, w, h/2);
                g.drawLine(w/2, 0, w/2, h);
            }
            stone.paint(g, w);
        }
    }
}

enum Stone { 

    BLACK(Color.BLACK), WHITE(Color.WHITE), NONE(null);

    final Color color;
    private final static Random rand = new Random();

    private Stone(Color c) {
        color = c;
    }

    public void paint(Graphics g, int dimension) {
        if(this == NONE) return;
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(color);
        int x = 5;
        g2d.fillOval(rand.nextInt(x), rand.nextInt(x), dimension-x, dimension-x);
    }
}

随机的东西是CPerkins谈论的有机感觉的实现。好吧,无论如何我都试着这样做。

答案 1 :(得分:2)

如何实施职位已得到解答。但你问的是如何限制用户的位置,这是另一回事。

据推测,您计划创建一个绘图区域,然后您将检测鼠标点击。如何限制石头放置到交叉点就像绘图程序实现一个名为“snap”的功能(如“对齐网格”)。

基本上,这只是意味着将每个维度中的像素范围内的点击数减少到其中一条线上。在两个维度中执行此操作会将移动的单击放在一个点上。

基本上,你所做的是找到每个细胞的中点,任何落在一个细胞中点和下一个细胞中间的点击将被计算在这些中点之间的线上。

所以基本上,这将是这样的:


    // Since traditionally, boards are not square, you'd call this twice: once with the
    //   width in X for the X click, and once again for Y.
    // Naturally, you'll want to accomodate e.g., 9x9 boards for short games.
    int snapClick (int gridWidth, int clickPos, int numCells) {
        int cellWidth = (int) (gridWidth / numCells);
        int snappedClick = Math.round ((clickPos + (cellWidth/2)) / cellWidth);
        return snappedClick;
    }

顺便提一下,在实际游戏中,石头并不是完美的放置,因此游戏具有令人愉悦的有机感。您可能需要考虑一种解决方案,您不仅可以在其中存储宝石在网格中的位置,还可以在屏幕上稍微不完美地对齐以进行显示。

答案 2 :(得分:1)

不要考虑线条。想想交叉点。交叉点可以表示为网格,方式与棋盘上的方块形成网格相同。

在Java中,最简单的表示形式是方形数组。类似的东西:

Location[MAX_Y][MAX_X];

其中Location是一个表示交集的对象,并保存对放置在那里的作品的引用(如果有的话)。

答案 3 :(得分:1)

int[][] grid = new int[19][19];

你的网格。此数组中的每个位置代表一条线交点。

答案 4 :(得分:0)

如果您的主要目标是实施AI,我建议实施Go Text Protocol,并使用众多现有GTP前端之一。如果您想将GUI构建为学习体验,那么请继续(没有双关语)。作为一个编写商业广告GUI的人,我警告你,它比看起来要困难得多(相比之下国际象棋应用程序会很简单)。