棋类游戏-五子棋小游戏


活动地址:CSDN21天学习挑战赛

界面效果:

 实现:

第一步:定义好设计该游戏要用到的组件以及相关数据;

第二步:组装组件,给组件设置相对应的功能;

第三步:调用init()方法;

具体

第一步

用到的组件:f游戏窗口,存放四张图的bufferedImage对象分别代表棋盘,黑棋,白棋,选中框;以及3个按钮button,还有结束界面result。

相关数据:例如:棋盘的宽(TABLE_WIDTH)高(TABLE_HEIGHT),棋盘横向纵向分别能下多少棋子BOARD_SIZE,每个棋子占用棋RATE,还有最棋子们对棋盘最左边框的偏移量X_OFFSET,对上边框的偏移量Y_OFFSET,棋子:board_type 值为0 -没有棋子 1-白棋 2-黑棋。

声明一个二维数组board[][]来记录棋子,如果board[ i ][ j ]值为0 -没有棋子 1-白棋 2-黑棋

定义一个选择框的坐标,用selected_X记录横坐标,用selected_Y记录纵坐标,默认值都为-1;

还自定义一个类:ChessBoard,重写paint方法用来绘画棋盘,棋子,选择框;

第二步

给按钮添加事件监听器,添加颜色变换效果,并通过改变board_type来选择下黑棋还是白棋或者是没有棋子,调用repaint方法;

给棋盘添加一个鼠标移动监听器,用来记录选选择框的位置;

定义一个判断是否获胜方法isOwn;

然后再给棋盘添加一个鼠标监听器,用来记录鼠标左击之后新棋子的坐标pos_X,pos_Y;

在左击之后,判断在玩家的棋子是否成五子,若成五子,则结束游戏,弹出(白/黑)玩家获胜;若不成五子,则继续比赛,并将选择框的坐标值select_X和select_Y重新赋值为-1;

最后设置checkboard的大小,checkboard添加到f窗口中,将f设置合适的大小,并使它可见

另外我额外给窗口添加了一个窗口关闭的事件监听器,方便大家关闭窗口;

第三步

调用init()方法

代码最核心的地方可能就是判断输赢(哪个玩家)

boolean isOwn(int pos_X,int pos_Y,int board_type)

pos_X :下的棋子横坐标,pos_Y:下的棋子纵坐标,board_type表示(执(白/黑)棋)玩家

主要思路:在玩家接下来一个棋子下落时,我们要立刻对下棋位置周围八个方向进行检验,其分大体来说是4条边,从上到下,从左到右,从左上到右下,从右上到左下;用count来记录每条边棋子的情况,当一种棋子在每条边上连续出现5个时,直接return true;结束该方法;记住在每一条边上遍历完之后要重新更新count,将其赋值为1.

isOwn()方法代码实现:

//    某玩家是否赢了
    private boolean isOwn(int x,int y,int board_type) {
        int temp=board[x][y]==board_type?1:0;
        int count = temp;
        int posX = 0;
        int posY = 0;
//        水平方向
//        向左遍历
        for (posX = x - 1; posX > 0; posX--) {
            if (board[posX][y] == board_type) {
                count++;
                if (count >= 5) {
                    return true;
                }
            } else {
                break;
            }
        }
//        向右遍历
        for (posX = x + 1; posX <= BOARD_SIZE; posX++) {
            if (board[posX][y] == board_type) {
                count++;
                if (count >= 5) {
                    return true;
                }
            } else {
                break;
            }
        }
//        垂直方向
//        重新更count值
        count = temp;
//        向上遍历
        for (posY = y - 1; posY > 0; posY--) {
            if (board[x][posY] == board_type) {
                count++;
                if (count >= 5) {
                    return true;
                }
            } else {
                break;
            }
        }
//        向下遍历
        for (posY = y + 1; posY <= BOARD_SIZE; posY++) {
            if (board[x][posY] == board_type) {
                count++;
                if (count >= 5) {
                    return true;
                }
            } else {
                break;
            }
        }
//        左下-右上方向
//        重新更新count值
        count=temp;
//        向左下角遍历
        for (posX = x - 1, posY = y - 1; posX > 0 && posY > 0; posX--, posY--) {
            if (board[posX][posY] == board_type) {
                count++;
                if (count >= 5) {
                    count = 1;
                    return true;
                }
            } else {
                break;
            }
        }
//        向右上角遍历
        for (posX = x + 1, posY = y + 1; posX <= BOARD_SIZE && posY <= BOARD_SIZE; posX++, posY++) {
            if (board[posX][posY] == board_type) {
                count++;
                if (count >= 5) {
                    count = 1;
                    return true;
                }
            } else {
                break;
            }
        }
//        左上-右下
//        更新count值
        count=temp;
//      向右下角遍历
        for (posX = x + 1, posY = y - 1; posX <= BOARD_SIZE && posY > 0; posX++, posY--) {
            if (board[posX][posY] == board_type) {
                count++;
                if (count >= 5) {
                    return true;
                }
            } else {
                break;
            }
        }
//        向左上角遍历
        for (posX = x - 1, posY = y + 1; posX > 0 && posY <= 15; posX--, posY++) {
            if (board[posX][posY] == board_type) {
                count++;
                if (count >= 5) {
                    return true;
                }
            } else {
                break;
            }
        }
        return false;
    }

五子棋代码实现: 

public class Gobang {
    TextArea result=new TextArea();
    //定义五子棋游戏窗口
    private JFrame f = new JFrame("五子棋游戏");

    //声明四个BufferedImage对象,分别记录四张图片
    BufferedImage table;
    BufferedImage black;
    BufferedImage white;
    BufferedImage selected;


    //声明棋盘的宽和高
    final int TABLE_WIDTH = 535;
    final int TABLE_HEIGHT = 536;

    //声明棋盘横向和纵向分别可以下多少子,他们的值都为15
    final int BOARD_SIZE = 15;

    //声明每个棋子占用棋盘的比率
    final int RATE = TABLE_WIDTH / BOARD_SIZE;

    //声明变量,记录棋子对于x方向和y方向的偏移量
    final int X_OFFSET = 5;
    final int Y_OFFSET = 6;

    //声明一个二维数组,记录棋子, 如果索引[i][j]处的值为  0-没有棋子  1-白棋  2-黑棋
    int[][] board = new int[BOARD_SIZE][BOARD_SIZE];

    //声明红色选择框的坐标  该坐标其实就是二维数组board中的索引
    int selected_X = -1;
    int selected_Y = -1;

    //自定义类,继承Canvas
    private class ChessBoard extends JPanel {
        @Override
        public void paint(Graphics g) {
            //绘图

            //绘制棋盘
            g.drawImage(table,0,0,null);

            //绘制选择框
            if (selected_X>0 && selected_Y>0){
                g.drawImage(selected,selected_X*RATE+X_OFFSET,selected_Y*RATE+Y_OFFSET,null);
            }

            //绘制棋子
            for (int i = 0; i < BOARD_SIZE; i++) {
                for (int j = 0; j < BOARD_SIZE; j++) {

                    //绘制黑棋
                    if (board[i][j] == 2){
                        g.drawImage(black,i*RATE+X_OFFSET,j*RATE+Y_OFFSET,null);

                    }
                    //绘制白棋
                    if (board[i][j] == 1){
                        g.drawImage(white,i*RATE+X_OFFSET,j*RATE+Y_OFFSET,null);
                    }
                }
            }
        }
    }

    ChessBoard chessBoard = new ChessBoard();


    //声明变量,记录当前下棋的颜色
    int board_type = 2;

    //声明底部需要用到的组件
    Panel p = new Panel();
    Button whiteBtn = new Button("白棋");
    Button blackBtn = new Button("黑棋");
    Button deleteBtn = new Button("删除");

    public void refreshBtnColor(Color whiteBtnColor,Color blackBtnColor,Color deleteBtnColor){
        whiteBtn.setBackground(whiteBtnColor);
        blackBtn.setBackground(blackBtnColor);
        deleteBtn.setBackground(deleteBtnColor);
    }

    public void init() throws Exception {
        //组装视图,编写逻辑
        whiteBtn.addActionListener(e->{
            // 修改当前要下的棋子的标志为1
            board_type = 1;
            // 刷新按钮的颜色
            refreshBtnColor(Color.GREEN,Color.GRAY,Color.GRAY);
        });

        blackBtn.addActionListener(e->{
            // 修改当前要下的棋子的标志为2
            board_type = 2;
            // 刷新按钮的颜色
            refreshBtnColor(Color.GRAY,Color.GREEN,Color.GRAY);
        });

        deleteBtn.addActionListener(e->{
            // 修改当前要下的棋子的标志为0
            board_type = 0;
            // 刷新按钮的颜色
            refreshBtnColor(Color.GRAY,Color.GRAY,Color.GREEN);
        });

        p.add(whiteBtn);
        p.add(blackBtn);
        p.add(deleteBtn);

        f.add(p,BorderLayout.SOUTH);

        //组装棋盘

        //初始化图片
        table = ImageIO.read(new File("src\\awt\\img\\board.jpg"));
        white = ImageIO.read(new File("src\\awt\\img\\white.gif"));
        black = ImageIO.read(new File("src\\awt\\img\\black.gif"));
        selected = ImageIO.read(new File("src\\awt\\img\\selected.gif"));

        //处理鼠标移动
        chessBoard.addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                selected_X = (e.getX()-X_OFFSET)/RATE;
                selected_Y = (e.getY()-Y_OFFSET)/RATE;

                chessBoard.repaint();
            }


        });

        //处理鼠标点击
        chessBoard.addMouseListener(new MouseAdapter() {
            //当鼠标被点击后 会调用这个方法
            @Override
            public void mouseClicked(MouseEvent e) {
                int xPos = (e.getX()-X_OFFSET)/RATE;
                int yPos = (e.getY()-Y_OFFSET)/RATE;

                board[xPos][yPos] = board_type;
               if(isOwn(xPos,yPos,1)){
                   result.append("白棋获胜");
                   chessBoard.setVisible(false);
                   p.setVisible(false);
                   f.add(result);
               }
               if(isOwn(xPos,yPos,2)){
                   result.append("黑棋获胜");
                   chessBoard.setVisible(false);
                   p.setVisible(false);
                   f.add(result);
               }
                chessBoard.repaint();
            }

            @Override
            public void mouseExited(MouseEvent e) {
                selected_X=-1;
                selected_Y=-1;

                chessBoard.repaint();
            }
        });

        chessBoard.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));
        f.add(chessBoard);

//        关闭窗口
        f.addWindowFocusListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        //设置frame最佳大小并可见
        f.pack();
        f.setVisible(true);

    }
//    某玩家是否赢了
    private boolean isOwn(int x,int y,int board_type) {
        int temp=board[x][y]==board_type?1:0;
        int count = temp;
        int posX = 0;
        int posY = 0;
//        水平方向
//        向左遍历
        for (posX = x - 1; posX > 0; posX--) {
            if (board[posX][y] == board_type) {
                count++;
                if (count >= 5) {
                    return true;
                }
            } else {
                break;
            }
        }
//        向右遍历
        for (posX = x + 1; posX <= BOARD_SIZE; posX++) {
            if (board[posX][y] == board_type) {
                count++;
                if (count >= 5) {
                    return true;
                }
            } else {
                break;
            }
        }
//        垂直方向
//        重新更count值
        count = temp;
//        向上遍历
        for (posY = y - 1; posY > 0; posY--) {
            if (board[x][posY] == board_type) {
                count++;
                if (count >= 5) {
                    return true;
                }
            } else {
                break;
            }
        }
//        向下遍历
        for (posY = y + 1; posY <= BOARD_SIZE; posY++) {
            if (board[x][posY] == board_type) {
                count++;
                if (count >= 5) {
                    return true;
                }
            } else {
                break;
            }
        }
//        左下-右上方向
//        重新更新count值
        count=temp;
//        向左下角遍历
        for (posX = x - 1, posY = y - 1; posX > 0 && posY > 0; posX--, posY--) {
            if (board[posX][posY] == board_type) {
                count++;
                if (count >= 5) {
                    count = 1;
                    return true;
                }
            } else {
                break;
            }
        }
//        向右上角遍历
        for (posX = x + 1, posY = y + 1; posX <= BOARD_SIZE && posY <= BOARD_SIZE; posX++, posY++) {
            if (board[posX][posY] == board_type) {
                count++;
                if (count >= 5) {
                    count = 1;
                    return true;
                }
            } else {
                break;
            }
        }
//        左上-右下
//        更新count值
        count=temp;
//      向右下角遍历
        for (posX = x + 1, posY = y - 1; posX <= BOARD_SIZE && posY > 0; posX++, posY--) {
            if (board[posX][posY] == board_type) {
                count++;
                if (count >= 5) {
                    return true;
                }
            } else {
                break;
            }
        }
//        向左上角遍历
        for (posX = x - 1, posY = y + 1; posX > 0 && posY <= 15; posX--, posY++) {
            if (board[posX][posY] == board_type) {
                count++;
                if (count >= 5) {
                    return true;
                }
            } else {
                break;
            }
        }
        return false;
    }

        public static void main(String[] args) throws Exception {
        new Gobang().init();
    }

}

如果有些小伙在运行时,出现下面这个问题。可以把new File()中的相对路径改成关于盘符的绝对路径。

代码中使用的图片在下面的百度网盘中

链接:https://pan.baidu.com/s/1CQSk_rU0S0C7Y1XXiHs56Q?pwd=xzhf 
提取码:xzhf

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Luck&Strive

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值