Java学习笔记(十)——开发个小项目(GoBang2.0)

接上一篇,继续完善功能。

画个大纲(跟随慢慢开发过程不断完善,今天分类方法改一改)

1.用户

两个用户对战  一黑一白

用户可以是人,也可以是AI。对战模式支持人人,人机,机机。

  • 属性

执棋颜色

用户名

游戏得分

  • 方法

下棋

输赢

2.比赛规则

一黑一白交替轮流下棋

可以决定哪个玩家先手

不可以重复下棋到同一个位置

不可以将棋子下到边界外

可以撤回刚刚下的棋,不可以撤回上一步的棋

哪一方横竖斜到达5个棋子赢一局

3.界面

  • 登录界面

用户登录:

用户名、密码输入栏(带提示,用户密码匹配检验),登录按键;

登录图像。     

  • 菜单界面

选择功能:

新游戏

游戏积分——获胜局数

对战模式 —— 人人,人机,机机

  • 游戏界面

下棋主界面

设置棋盘、背景板、菜单栏、棋子计数板、计分板、棋子、下棋指示器,刷新窗体后这些都不会消失。

背景板、棋盘:17*17,棋盘在背景板之上。

菜单栏:撤回、清空界面——撤回/清空时,计数器要跟着变化。

棋子计数板:记录当前棋盘上黑白棋子个数。(图像不重叠,随撤回清空等操作实时刷新)。

计分板:记录目前双方赢得局数。

棋子:下到交叉线(棋子校准)、不重复、不越出棋盘、刷新保存,可以撤回,可以识别获胜。

当前局数计时器:距离游戏开始的耗时。

  • 获胜界面

当有一方获胜后弹出

显示哪方获胜

显示获胜图片

菜单:

再战一局:触发游戏界面     

退出游戏:回到菜单界面

回顾棋局:显示重新下棋步骤(撤回步骤显示?)

乱七八糟的功能

存档

读档

软件使用日志

第二天 —— 实现登录界面、菜单界面、获胜界面、

实现棋子不重复、撤销、清空棋盘、棋子计数、判定谁赢

实现方式

1. 棋子不重复:设置一个二维int数组储存棋盘对应位置上放的是黑、白、空棋(2、1、0)代替。

                          当算出当前位置时,先判断这个位置是否为空也就是0,如果不是则不放(后续一

                          系列画棋子,计数板变化等不做)。 

注意:

1.在窗体(面板)上x为横轴,y为纵轴。二位数数组chess[列][行],对应的是chess[y][x]。

2.当发生撤销、清空、新游戏等情况是,要对这个二维数组做更新。

2. 撤销:撤回上一步。除了二维数组,还需要一个ArrayList<chess>来储存棋子放置顺序,设置

               棋子类,属性有x、y坐标,棋子颜色,设置构造方法可以直接传3个参数进去,设置 get

               方法获得三个属性值,最好再设置set方法设置3个属性。(在下棋的时候,将棋子加入到

                ArrayList,加入的坐标x,y是棋子的圆心坐标,重画时自己偏移)。当点击撤销时,调

               用界面重写的paint方法,将最后一个加入的棋子删去,然后for循环重画棋子。

ArrayList目前用到的方法   (序号排序从0开始)

.add(chessShape obj);加入一个目标类型对象

.remove(index);         根据序号index移除列表内的对象

.size();                          得出数组目前的长度

.clear();                        清除所有对象

.get(index);                  获取序号为index的对象

注意:  

当撤销时,ArrayList要移除最后一个对象,二维数组改棋盘值。

3. 清空:清空棋盘上所有棋子。调用界面的 repaint 函数。

遇到的问题

1.repaint函数好像是调用的paint函数。当想要设置刷新窗口棋子不丢失时,就把棋子重写放在了重

   写的paint函数中。但当你想要清空棋盘时,调用了repaint函数,就会让棋子仍然重画无法消掉。

解决办法:

1. 棋子重写仍然写在paint函数里,但是清空的时候先将ArrayList清空,chesses二维数组更

    新,再调用repaint方法。

2.棋子重写在撤回方法实现的时候写,不写入paint函数。在清空时,直接调用repaint方法。

综上而言第一个方法更好。

2.界面布局有点麻烦,想要设置坐标布局好像不太管用,(边框布局只能设置一次,重复只会保留

   最后的)(流式布局只会横行排列,然后排到下面,不灵活)。面板、按键大小和布局调整时设 

   置xy坐标貌似不管用,还未解决,有待多加尝试。以及字体大小设置虽不是问题但有待改进。

3.在设置判断胜方之后弹出winner界面,要实现在这个界面画照片和写字,但是界面无法给监听器

   传画笔、监听器传给界面的画笔是画在主界面棋盘格上的。矛盾暂无法解决。有待更新解决方

   法。

代码

//有些类的注释还没全,后续补齐
//BiangGoBangUI.java
/**
 * GoBang界面
 * 继承JFRame ,重写paint方法
 *
 * 属性:
 * 1.bgimg 背景图
 * 2.mylis GoBang棋盘操作监听器 ———— BiangGoBangListener mylis
 * 3.loginListener GOBang 登录页面监听器  ————— LoginListener loginListener
 * 4.二维int 数组 chessIf 存放棋盘放棋子 黑 白 空 棋情况  2 1 0    0-16 共 17*17个点
 * 5.一维int 数组 chessIndexX 按顺序存放棋子横坐标
 * 6.一维int 数组 chessIndexY 按顺序存放棋子纵坐标
 *
 *
 * 方法:
 * 1.initBiangGoBangUI() 初始化界面方法
 * 2.startGame()  开始游戏方法  点击开始游戏跳转棋盘界面
 * 3.loginGame()  登录游戏方法  开始实现用户名登录 跳转开始游戏界面
 *
 * 重写方法:
 * 1.paint() 实现窗体刷新之后重画 背景图 棋盘
 */
public class BiangGoBangUI extends JFrame implements BiangGoBangInterface {
    public static final Image bgimg = new ImageIcon("img/bg50.jpg").getImage();
    public static final Image winImg = new ImageIcon("img/winne2" +
            ".jpg").getImage();
    public BiangGoBangListener mylis = new BiangGoBangListener();
    public LoginListener loginListener = new LoginListener();
    public int[][] chesses = new int[17][17];
    public ArrayList<chessShape> chessIndex = new ArrayList<chessShape>(300);
//    public int[] chessIndexX = new int [];
//    public int[] ChessIndexY = new int [];

    public void initBiangGoBangUI() {
        for(int i=0;i<17;i++){
            for(int j=0;j<17;j++)
                System.out.print(chesses[i][j]);
            System.out.println();
        }

        //JFrame bgb = new JFrame("Biang's五子棋v 1.0");
        this.setTitle("Biang's 五子棋 v1.0");
        this.setSize(SIZE * LINE+X*2, SIZE * ROW+Y*3);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mylis.setGoBangUi(this);

        JPanel downBar = new JPanel();
        downBar.setBackground(Color.GRAY);
        Dimension dim = new Dimension(downWidth,downWidth);
        downBar.setPreferredSize(dim);

        JButton BeginBtn = new JButton("开始");
        BeginBtn.setBackground(Color.WHITE);
        BeginBtn.setSize(btnWidth,btnHeight);
        downBar.add(BeginBtn);

        JButton ClearBtn = new JButton("清空");
        ClearBtn.setBackground(Color.WHITE);
        ClearBtn.setSize(btnWidth,btnHeight);
        downBar.add(ClearBtn);

        JButton backBtn = new JButton("撤回");
        backBtn.setBackground(Color.WHITE);
        backBtn.setSize(btnWidth,btnHeight);
        downBar.add(backBtn);

        ClearBtn.addActionListener(mylis);
        backBtn.addActionListener(mylis);
        this.add(downBar,BorderLayout.SOUTH);
        //BeginBtn.addActionListener(mylis);

//  实现下棋子下在面板之内:特别为棋盘设置面板画笔不一致,需要重新写继承JPanel的paint方法,所以换在监听器里实现
//        this.setLayout(null);
//        JPanel chessBoard = new JPanel();
//        chessBoard.setLocation(X,Y);
//        Dimension dim = new Dimension(SIZE*ROW,SIZE*LINE);
//        //chessBoard.setPreferredSize(dim);
//        chessBoard.setSize(SIZE*ROW,SIZE*LINE);
//        chessBoard.setBackground(Color.BLUE);
//        this.add(chessBoard);

        this.setVisible(true);
        this.addMouseListener(mylis);
        Graphics pen = this.getGraphics();
        mylis.setGraphics(pen);
    }
    @Override
    public void paint(Graphics g){
        super.paint(g);
        g.drawImage(bgimg,X-SIZE,Y-SIZE,(ROW+2)*SIZE,(LINE+2)*SIZE,null);
        g.setColor(Color.BLACK);
        for(int i=0;i<=ROW;i++){
            g.drawLine(X,Y+i*SIZE,X+SIZE*LINE,Y+i*SIZE);  //y不变,画横线
            g.drawLine(X+i*SIZE,Y,X+i*SIZE,Y+SIZE*ROW);   //x不变,画竖线
        }
//        for(int i=0;i<17;i++){
//            for(int j=0;j<17;j++){
//                if(chesses[i][j]==2){
//                    g.setColor(Color.BLACK);
//                    g.fillOval(X+j * SIZE-SIZE/2,Y+i*SIZE-SIZE/2,SIZE,SIZE);
//                }
//                else if(chesses[i][j]==1) {
//                    g.setColor(Color.WHITE);
//                    g.fillOval(X + j * SIZE - SIZE / 2, Y + i * SIZE - SIZE / 2, SIZE, SIZE);
//                }
//            }
//        }
    }

    public void startGame(){
        JFrame startjf = new JFrame("Biang 's 五子棋v2.0");
        startjf.setSize(700,700);
        startjf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JButton btn1 = new JButton("开始游戏");
        btn1.addActionListener(mylis);
        startjf.add(btn1,BorderLayout.NORTH);

        startjf.setVisible(true);
        mylis.setGoBangUi(this);   //全局??
        mylis.setStartJf(startjf);
    }

    public void loginGame(){
        JFrame loginJf = new JFrame("欢迎登录 Biang 's 五子棋v2.0");
        loginJf.setSize(800,800);
        loginJf.setLayout(null);
        loginJf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        FlowLayout fl = new FlowLayout();
        loginJf.setLayout(fl);

        JTextField jTFLoginUser = new JTextField(12);
        JTextField jTFLoginPassword = new JTextField(12);

        JButton btn0 = new JButton("登录");
        btn0.addActionListener(loginListener);

        loginJf.add(jTFLoginUser);
        loginJf.add(jTFLoginPassword);
        loginJf.add(btn0);

//        btn0.setLocation(100,200);
//        jTFLoginUser.setLocation(100,100);
//        jTFLoginPassword.setLocation(100,150);
//        btn0.setSize();

//        loginJf.add(jTFLoginUser,BorderLayout.SOUTH);
//        loginJf.add(jTFLoginPassword,BorderLayout.SOUTH);
//        loginJf.add(btn0,BorderLayout.SOUTH);

        loginJf.setVisible(true);
        loginListener.setGoBangUi(this);
        loginListener.setLoginJf(loginJf);
        loginListener.setjTFUser(jTFLoginUser);
        loginListener.setjTFPassword(jTFLoginPassword);

    }

    public void WinGameUI(int Winner,Graphics wpen){

        JFrame winJf = new JFrame("兄弟!太厉害了");
        winJf.setSize(400,500);
        winJf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        if(Winner==2)
            wpen.drawString("恭喜黑方获胜!",100,100);
        else
            wpen.drawString("恭喜白方获胜!",100,100);
        wpen.drawImage(winImg,100,200,100,100,null);

        JButton btn1 = new JButton("再战一局");
        btn1.addActionListener(mylis);
        winJf.add(btn1,BorderLayout.SOUTH);

        winJf.setVisible(true);
//        Graphics wpen = winJf.getGraphics();
//        mylis.setGraphics(wpen);


//        JButton btn2 = new JButton("结束游戏");
//        btn2.addActionListener(mylis);
//        WinJf.add(btn2,BorderLayout.NORTH);
//
//        JButton btn3 = new JButton("回顾棋局");
//        btn3.addActionListener(mylis);
//        WinJf.add(btn3,BorderLayout.NORTH);
        mylis.setGoBangUi(this);   //全局??
        mylis.setWinJf(winJf);

    }
}

//BiangGoBangInterface.java
/**
 * 五子棋接口 设置固定参数
 * 属性
 * 1.SIZE:棋盘间距 & 棋子直径
 * 2.棋盘左上角坐标 X
 * 3.棋盘左上角坐标 Y
 * 4.棋盘行列数 ROW LINE
 * 5.下拉栏宽度
 * 6.按钮的宽度 btnWidth
 * 7.按钮的高度 btnHeight
 */
public interface BiangGoBangInterface {
    int SIZE = 30;
    int X = 100;
    int Y = 100;
    int ROW = 16;
    int LINE = 16;
    int downWidth = 100;
    int btnWidth = 100;
    int btnHeight = 50;
}

//BiangGoBangLinstener.java
/**
 * 棋盘操作下棋监听器 (实现鼠标 鼠标拖动接口)
 * 属性:
 * 1.chessX chessY当前下棋的坐标
 * 2.pen 绘制棋子的画笔组件
 * 3.controlColor 控制棋子颜色交替  0 黑 1 白
 * 4.countBlack countWhite 计数黑棋 白棋个数
 * 5.goBangUi ———— BiangGoBangUI 棋盘界面对象
 * 6.startJf  ———— JFrame 开始游戏界面对象
 * 7.
 *
 * 方法:
 * 1.void setGraphics(Graphics pen)  向监听器传入界面的画笔对象
 * 2.void setGoBangUi(BiangGoBangUI goBangUi) 向监听器传入棋盘界面对象
 * 3.void setStartJf(JFrame startJf) 向监听器传入开始界面对象
 * 4.
 *
 * 重写的方法:
 * 1.mousePressed 实现点击下棋 棋子校正 控制下棋范围 棋盘保存 不重复下棋
 * 2.actionPerformed 实现开始游戏按钮——跳转棋盘  清空 撤回
 *
 */


public class BiangGoBangListener implements MouseListener , ActionListener, MouseMotionListener ,BiangGoBangInterface{
    int chessX,chessY;
    Graphics pen;
    int controlColor=0;
    int countBlack=0, countWhite=0;
    BiangGoBangUI goBangUi;
    JFrame startJf ;
    JFrame winJf;
    int[][] changeLocation =new int[][]{{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1}};//04 15 26 37

    public void setGraphics(Graphics pen){
        this.pen = pen;
    }
    public void setGoBangUi(BiangGoBangUI goBangUi) {this.goBangUi = goBangUi; }
    public void setStartJf(JFrame startJf) {this.startJf = startJf; }
    public void setWinJf(JFrame winJf) {this.winJf = winJf; }

    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        if(x>X-SIZE && x<X+SIZE*ROW+SIZE && y>Y-SIZE && y<Y+SIZE*LINE+SIZE ){
            //棋子校正:点中间线归上左
            int baseX = X + ((x - X) / SIZE) * SIZE;
            int baseY = Y + ((y - Y) / SIZE) * SIZE;
            if ((x - baseX) > (SIZE / 2))
                chessX = baseX + SIZE;
            else
                chessX = baseX;
            if ((y - baseY) > (SIZE / 2))
                chessY = baseY + SIZE;
            else
                chessY = baseY;
            if(goBangUi.chesses[(chessY-Y)/SIZE][(chessX-X)/SIZE]!=0)
                return;
            if((controlColor%2)==0) {
                countBlack++;
                pen.setColor(Color.BLACK);
                goBangUi.chesses[(chessY-Y)/SIZE][(chessX-X)/SIZE]=2;
            }
            else {
                countWhite++;
                pen.setColor(Color.WHITE);
                goBangUi.chesses[(chessY-Y)/SIZE][(chessX-X)/SIZE]=1;
            }
            System.out.println(controlColor);
            controlColor=(controlColor+1)%2;
            goBangUi.chessIndex.add(new chessShape(chessX,chessY,pen.getColor())); //存的是棋子圆心,画的时候要偏移
            pen.fillOval(chessX - SIZE / 2, chessY - SIZE / 2, SIZE, SIZE);
            pen.setColor(Color.WHITE);
            pen.fillRect(100,30,500,30);
            pen.setColor(Color.BLACK);
            pen.drawString("黑色棋子计数: "+countBlack,150,50);
            pen.drawString("黑色棋子计数: "+countWhite,450,50);

            if(ifWin(((chessY-Y)/SIZE),((chessX-X)/SIZE),goBangUi.chesses[(chessY-Y)/SIZE][(chessX-X)/SIZE])!=0){
                if(goBangUi.chesses[(chessY-Y)/SIZE][(chessX-X)/SIZE]==2){
                    System.out.println("黑方获胜!");
                    goBangUi.WinGameUI(2,pen);
                }
                else {
                    System.out.println("白方获胜!");
                    goBangUi.WinGameUI(1,pen);
                }
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String btnStr = e.getActionCommand();
        if(btnStr.equals("开始游戏")){
            startJf.setVisible(false);
            goBangUi.initBiangGoBangUI();
        }
        else if(btnStr.equals("再战一局")){
            winJf.setVisible(false);
            goBangUi.initBiangGoBangUI();
        }
        else if(btnStr.equals("清空")){
            System.out.println("我感受到了清空的召唤!");
            goBangUi.repaint();
            //棋盘记录改
            for(int i=0;i<17;i++){
                for(int j=0;j<17;j++)
                    goBangUi.chesses[i][j]=0;
            }
            //步数记录改
            goBangUi.chessIndex.clear();
        }
        else if(btnStr.equals("撤回")){
            goBangUi.paint(pen);
            if(goBangUi.chessIndex.get(goBangUi.chessIndex.size()-1).getColor().equals(Color.BLACK))
                countBlack--;
            else
                countWhite--;
            //棋盘记录改
            goBangUi.chesses[goBangUi.chessIndex.get(goBangUi.chessIndex.size()-1).getChessX()/SIZE][goBangUi.chessIndex.get(goBangUi.chessIndex.size()-1).getChessY()/SIZE]=0;

            //System.out.println("撤回前:"+goBangUi.chessIndex.size());
            //步数记录改
            goBangUi.chessIndex.remove(goBangUi.chessIndex.size()-1);
            //System.out.println("撤回后:"+goBangUi.chessIndex.size());
            for(int i=0;i<goBangUi.chessIndex.size();i++){
                pen.setColor(goBangUi.chessIndex.get(i).getColor());
                System.out.println(i);
                System.out.println(goBangUi.chessIndex.get(i).getChessX()+"  "+goBangUi.chessIndex.get(i).getChessY());
                pen.fillOval(goBangUi.chessIndex.get(i).getChessX()-SIZE/2, goBangUi.chessIndex.get(i).getChessY()-SIZE/2,SIZE,SIZE);
            }
            //计数板改变
            pen.setColor(Color.WHITE);
            pen.fillRect(100,30,500,30);
            pen.setColor(Color.BLACK);
            pen.drawString("黑色棋子计数: "+countBlack,150,50);
            pen.drawString("白色棋子计数: "+countWhite,450,50);

            //步数记录改
            //goBangUi.chessIndex.remove(goBangUi.chessIndex.size()-1);
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    public void mouseDragged(MouseEvent e) {

    }

    @Override
    public void mouseMoved(MouseEvent e) {

    }

    public int ifWin(int x,int y,int colorNum){
        int countNumFive=4;
        int currX=x,currY=y;
        int flag=1;
        for(int i=0;i<4;i++) {    //左上到右下  竖  右上到左下  横
            countNumFive=4;
            while (countNumFive > 0) {
                if (flag == 1 && currX + changeLocation[i][0] >= 0 && currX + changeLocation[i][0] <= 16 && currY + changeLocation[i][1] >= 0 && currY + changeLocation[i][1] <= 16) {
                    if (goBangUi.chesses[currX + changeLocation[i][0]][currY + changeLocation[i][1]] == colorNum) {
                        currX += changeLocation[i][0];
                        currY += changeLocation[i][1];
                        countNumFive--;
                    }
                    else {          //换方向
                        flag = 2;
                        currX = x;
                        currY = y;
                    }
                }
                else if (flag == 2 && currX + changeLocation[i+4][0] >= 0 && currX + changeLocation[i+4][0] <= 16 && currY + changeLocation[i+4][1] >= 0 && currY + changeLocation[i+4][1] <= 16) {
                    if (goBangUi.chesses[currX + changeLocation[i+4][0]][currY + changeLocation[i+4][1]] == colorNum) {
                        currX += changeLocation[i+4][0];
                        currY += changeLocation[i+4][1];
                        countNumFive--;
                    }
                    else {         //这个方向没连够
                        flag = 1;
                        currX = x;
                        currY = y;
                        break;
                    }
                }
                if (countNumFive == 0)
                    return colorNum;
            }
        }
        //if(countNumFive!=0)
            return 0;
    }
}


//loginListener.java
public class LoginListener implements ActionListener {
    private JTextField jTFUser;
    private JTextField jTFPassword;
    BiangGoBangUI goBangUi;
    //JFrame startJf ;
    JFrame loginJf ;

    public void setjTFUser(JTextField jTFUser) {this.jTFUser = jTFUser; }
    public void setjTFPassword(JTextField jTFPassword) {this.jTFPassword = jTFPassword; }
    public void setGoBangUi(BiangGoBangUI goBangUi) {this.goBangUi = goBangUi; }
    //public void setStartJf(JFrame startJf) {this.startJf = startJf; }
    public void setLoginJf(JFrame loginJf) {this.loginJf = loginJf; }

    @Override
    public void actionPerformed(ActionEvent e) {
        String btnStr = e.getActionCommand();
        String jTFUserStr = jTFUser.getText();
        String jTFPasswordStr = jTFPassword.getText();
        if(btnStr.equals("登录")){
            if(jTFUserStr.equals("Stefan") && jTFPasswordStr.equals("0410")){

                loginJf.setVisible(false);
                goBangUi.startGame();
            }
        }
    }
}

//chessShape.java
public class chessShape {
    int chessX;
    int chessY;
    Color color;
    public chessShape(int x,int y,Color cc){
        this.chessX=x;
        this.chessY=y;
        this.color=cc;
    }
    public int getChessX(){
        return chessX;
    }

    public int getChessY(){
        return chessY;
    }

    public Color getColor() {
        return color;
    }
}

//StartGameUI.java
public class StartGameUI {
    public static void main(String[] args){
        BiangGoBangUI goBangUI = new BiangGoBangUI();
        goBangUI.loginGame();
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的五子棋人机对弈小程序的示例代码,基于 Java Swing 编写。 ```java import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Gobang extends JFrame implements ActionListener, MouseListener { private static final long serialVersionUID = 1L; private JPanel panel; private JButton button; private JLabel label1, label2; private int[][] chessBoard; private boolean isBlack = true; private boolean gameOver = false; private final int ROWS = 15; private final int COLS = 15; private final int SIZE = 30; private final int MARGIN = 30; public Gobang() { setTitle("五子棋"); setSize(600, 600); setResizable(false); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); init(); setVisible(true); } private void init() { panel = new JPanel(); panel.setBackground(new Color(255, 204, 102)); panel.setLayout(null); panel.addMouseListener(this); button = new JButton("重新开始"); button.addActionListener(this); button.setBounds(450, 120, 100, 40); label1 = new JLabel("黑方先手"); label1.setFont(new Font("宋体", Font.BOLD, 20)); label1.setBounds(450, 200, 150, 40); label2 = new JLabel("轮到黑方"); label2.setFont(new Font("宋体", Font.BOLD, 20)); label2.setBounds(450, 250, 150, 40); panel.add(button); panel.add(label1); panel.add(label2); add(panel); chessBoard = new int[ROWS][COLS]; } private void drawChessBoard(Graphics g) { for (int i = 0; i <= ROWS; i++) { g.drawLine(MARGIN, MARGIN + i * SIZE, MARGIN + COLS * SIZE, MARGIN + i * SIZE); } for (int i = 0; i <= COLS; i++) { g.drawLine(MARGIN + i * SIZE, MARGIN, MARGIN + i * SIZE, MARGIN + ROWS * SIZE); } } private void drawChessPiece(Graphics g, int row, int col, boolean isBlack) { int x = MARGIN + col * SIZE; int y = MARGIN + row * SIZE; g.setColor(isBlack ? Color.BLACK : Color.WHITE); g.fillOval(x - SIZE / 2, y - SIZE / 2, SIZE, SIZE); } private boolean checkWin(int row, int col) { int count = 1; int color = chessBoard[row][col]; int r, c; // 检查水平方向 r = row; c = col - 1; while (c >= 0 && chessBoard[r][c] == color) { count++; c--; } c = col + 1; while (c < COLS && chessBoard[r][c] == color) { count++; c++; } if (count >= 5) { return true; } // 检查竖直方向 count = 1; r = row - 1; c = col; while (r >= 0 && chessBoard[r][c] == color) { count++; r--; } r = row + 1; while (r < ROWS && chessBoard[r][c] == color) { count++; r++; } if (count >= 5) { return true; } // 检查左斜方向 count = 1; r = row - 1; c = col - 1; while (r >= 0 && c >= 0 && chessBoard[r][c] == color) { count++; r--; c--; } r = row + 1; c = col + 1; while (r < ROWS && c < COLS && chessBoard[r][c] == color) { count++; r++; c++; } if (count >= 5) { return true; } // 检查右斜方向 count = 1; r = row - 1; c = col + 1; while (r >= 0 && c < COLS && chessBoard[r][c] == color) { count++; r--; c++; } r = row + 1; c = col - 1; while (r < ROWS && c >= 0 && chessBoard[r][c] == color) { count++; r++; c--; } if (count >= 5) { return true; } return false; } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == button) { chessBoard = new int[ROWS][COLS]; isBlack = true; gameOver = false; label1.setText("黑方先手"); label2.setText("轮到黑方"); panel.repaint(); } } @Override public void mouseClicked(MouseEvent e) { if (gameOver) { return; } int x = e.getX(); int y = e.getY(); if (x < MARGIN || x > MARGIN + COLS * SIZE || y < MARGIN || y > MARGIN + ROWS * SIZE) { return; } int row = Math.round((float) (y - MARGIN) / SIZE); int col = Math.round((float) (x - MARGIN) / SIZE); if (chessBoard[row][col] != 0) { return; } chessBoard[row][col] = isBlack ? 1 : 2; panel.repaint(); if (checkWin(row, col)) { gameOver = true; String winner = isBlack ? "黑方" : "白方"; JOptionPane.showMessageDialog(panel, winner + "获胜!", "游戏结束", JOptionPane.INFORMATION_MESSAGE); return; } isBlack = !isBlack; label1.setText(isBlack ? "黑方先手" : "白方先手"); label2.setText(isBlack ? "轮到黑方" : "轮到白方"); if (!isBlack) { // AI 下棋 int[] pos = computeNextMove(); row = pos[0]; col = pos[1]; chessBoard[row][col] = 2; panel.repaint(); if (checkWin(row, col)) { gameOver = true; JOptionPane.showMessageDialog(panel, "白方获胜!", "游戏结束", JOptionPane.INFORMATION_MESSAGE); return; } isBlack = !isBlack; label1.setText(isBlack ? "黑方先手" : "白方先手"); label2.setText(isBlack ? "轮到黑方" : "轮到白方"); } } private int[] computeNextMove() { int[] pos = new int[2]; // TODO: AI 算法 return pos; } @Override public void paint(Graphics g) { super.paint(g); drawChessBoard(g); for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { if (chessBoard[i][j] == 1) { drawChessPiece(g, i, j, true); } else if (chessBoard[i][j] == 2) { drawChessPiece(g, i, j, false); } } } } @Override public void mousePressed(MouseEvent e) {} @Override public void mouseReleased(MouseEvent e) {} @Override public void mouseEntered(MouseEvent e) {} @Override public void mouseExited(MouseEvent e) {} public static void main(String[] args) { new Gobang(); } } ``` 这个程序由一个主窗口和一个 JPanel 组成。主窗口负责创建并显示 JPanel,JPanel 则绘制棋盘和棋子,并处理用户交互和游戏逻辑。 在 JPanel 的构造函数中,我们初始化了棋盘数组 `chessBoard`,表示棋盘上每个格子的状态。1 表示黑子,2 表示白子,0 表示空格。我们还添加了一个按钮和两个标签,用于重新开始游戏和显示游戏状态。 在 `drawChessBoard` 方法中,我们使用 Graphics 类的 `drawLine` 方法绘制棋盘的线条。 在 `drawChessPiece` 方法中,我们使用 Graphics 类的 `fillOval` 方法绘制棋子。黑子用黑色填充,白子用白色填充。 在 `checkWin` 方法中,我们检查棋盘上某个格子所处的行、列、左斜方向和右斜方向是否有连续五个相同颜色的棋子。如果有,则游戏结束。 在 `actionPerformed` 方法中,我们对重新开始按钮的点击事件进行处理。重新初始化棋盘数组、重置游戏状态和标签,并调用 JPanel 的 `repaint` 方法刷新界面。 在 `mouseClicked` 方法中,我们处理鼠标点击事件。如果游戏已经结束或点击了棋盘外部或已经有棋子存在,则不做任何处理。否则,我们根据鼠标点击坐标计算出所在的行和列,将这个位置设为当前玩家下的棋子。然后检查游戏是否结束,并切换当前玩家。如果当前玩家是电脑,则调用 `computeNextMove` 方法计算出下一个位置,并执行相同的操作。 在 `paint` 方法中,我们使用 Graphics 类的 `paint` 方法绘制棋盘和棋子。 在 `computeNextMove` 方法中,我们需要实现一个 AI 算法,来计算出电脑下一步应该走的位置。这里我们暂时留空,可以自己实现一个简单的算法,比如随机生成一个空白位置,作为电脑的下一步。 最后,在 `main` 方法中,我们创建一个新的 Gobang 对象,启动程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值