Java五子棋开发思路【蓝杰项目】

本文介绍了如何使用Java开发五子棋游戏,包括绘制窗体、棋盘和棋子,实现鼠标监听器来响应玩家操作。此外,还详细讲解了计算棋子位置的算法以及判断是否连成线的逻辑。最后,探讨了人机对战中的权值算法,通过评估棋局状态来决定最佳落子位置,确保游戏趣味性和挑战性。
摘要由CSDN通过智能技术生成

绘制窗体

针对一个项目来说,人机交互是必须的,那么先来绘制一个窗体吧
用到的类是JFrame,上代码

this.setSize(800, 800);
this.setTitle("五子棋游戏");
//设置居中显示
this.setLocationRelativeTo(null);
//退出进程
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);

这时候就有问题了,不是说好JFrame对象吗,this又是啥?

public class GameUI extends JFrame implements Config

哦,原来继承了JFrame这个类,this其实就是下文的jf

JFrame jf = new JFrame();
jf.setSize(800, 800);
jf.setTitle("五子棋游戏");
//设置居中显示
jf.setLocationRelativeTo(null);
//退出进程
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);

画棋盘

        for(int i=0;i<LINE;i++) {
            g.drawLine(X0, Y0+i*SIZE, X0+(LINE-1)*SIZE, Y0+i*SIZE);
            g.drawLine(X0+i*SIZE, Y0, X0+i*SIZE, Y0+(LINE-1)*SIZE);
        }

你现在随便调整一下窗体 咦 奇怪 怎么没了
这就需要重写一个paint函数 每次都重绘框体 自然棋子也保存了

        //重写绘制组件的方法
    public void paint(Graphics g) {
        //1.绘制组件
        super.paint(g);

        System.out.println("paint");

        //2.绘制棋盘/棋子
        //硬编码
        for(int i=0;i<LINE;i++) {
            g.drawLine(X0, Y0+i*SIZE, X0+(LINE-1)*SIZE, Y0+i*SIZE);
            g.drawLine(X0+i*SIZE, Y0, X0+i*SIZE, Y0+(LINE-1)*SIZE);
        }

        for (int i=0;i<chess.length;i++){
            Chess chess2 = chess[i];
            if(chess2!=null){
                g.setColor(chess2.getColor());
                g.fillOval(chess2.getX(),chess2.getY(),CHESS,CHESS);
            }
        }
    }

画棋子

画完窗口画棋子 画画画
图形内容显示在哪个组件上,画笔就从该组件上获取
从窗体上获取画笔对象,获取画笔对象
在这介绍一下画笔工具Graphics类的使用

Graphics g = jf.getGraphics();

画笔有了 那画在哪里了 就靠鼠标点击了
来吧监听器登场 用于获取鼠标点击位置

public interface MouseListener extends EventListener {

    /**
     * Invoked when the mouse button has been clicked (pressed
     * and released) on a component.
     */
    public void mouseClicked(MouseEvent e);

    /**
     * Invoked when a mouse button has been pressed on a component.
     */
    public void mousePressed(MouseEvent e);

    /**
     * Invoked when a mouse button has been released on a component.
     */
    public void mouseReleased(MouseEvent e);

    /**
     * Invoked when the mouse enters a component.
     */
    public void mouseEntered(MouseEvent e);

    /**
     * Invoked when the mouse exits a component.
     */
    public void mouseExited(MouseEvent e);
}

什么鬼 看不懂!!!
别急 慢慢解释 这是java提供的监听器的接口interface
所以我们需要干嘛了 创建一个类 将这些接口写好方法
我创建的就是GameMouse类

        GameMouse mouse = new GameMouse();
        this.addMouseListener(mouse);

监听器写好了,我们需要监听器去干什么了
自然是要把棋子绘制出来 绘制棋子的代码

        g.setColor(Color.WHITE);
        g.fillOval(x, y, CHESS, CHESS);

CHESS是什么,这是我定义的常量,代表棋子大小,这样方便与之后的代码修改,避免了硬编码

计算棋子位置

现在棋子是点哪画哪 那咋办了 就需要算法了
靠近那个棋盘放在哪

            int x = e.getX();
            if ((x - X0) % SIZE > SIZE / 2)
                x = ((x - X0) / SIZE + 1) * SIZE + X0 - CHESS / 2;
            else
                x = (x - X0) / SIZE * SIZE + X0 - CHESS / 2;
            int y = e.getY();
            if ((y - Y0) % SIZE > SIZE / 2)
                y = ((y - Y0) / SIZE + 1) * SIZE + Y0 - CHESS / 2;
            else
                y = (y - Y0) / SIZE * SIZE + Y0 - CHESS / 2;

PS:SIZE是棋盘两条线直接的距离

判断是否连成线

只有在下完棋子之后 判断这个棋子周边是否连成线就可以了
算法思想就是计算左边几个棋子右边几个棋子 加一起是5个吗
一共是四个方向哈

public void JudgeRow(int x,int y){
        int count = 0;
        for (int i = (x - X0 + CHESS / 2) / SIZE + 1; i < LINE; i++) {
            if (chessBoard[i][(y - Y0 + CHESS / 2) / SIZE] == chessBoard[(x - X0 + CHESS / 2) / SIZE][(y - Y0 + CHESS / 2) / SIZE]) {
                count++;
            } else break;
        }
        for (int i = (x - X0 + CHESS / 2) / SIZE; i >= 0; i--) {
            if (chessBoard[i][(y - Y0 + CHESS / 2) / SIZE] == chessBoard[(x - X0 + CHESS / 2) / SIZE][(y - Y0 + CHESS / 2) / SIZE]) {
                count++;
            } else break;
        }
        if (count == 5) {
            this.startFlag=0;
            if (chessBoard[(x - X0 + CHESS / 2) / SIZE][(y - Y0 + CHESS / 2) / SIZE] == 1)
                JOptionPane.showMessageDialog(null, "黑棋胜利");
            else
                JOptionPane.showMessageDialog(null, "白棋胜利");
        }
    }

五子棋就写完了 但是很孤独啊 没有人陪你玩 🐕

人机对战(权值算法)

其实五子棋的目的是阻止对方五个子连成线,所以我们可以判断棋局的情况,赋予不同的权值,在权值大的地方落子,保证输不了
权值:可选择落子的地点,计算8个方向的棋子情况,将权值累积
我的权值赋值如下

public void InitHm(){
        hm.put("1111112",9000);
        hm.put("111112",8000);
        hm.put("1111",6000);
        hm.put("11112",4000);
        hm.put("111",200);
        hm.put("1112",40);
        hm.put("11",40);
        hm.put("112",20);
        hm.put("1",20);
        hm.put("12",2);
        hm.put("2",1);
        hm.put("",0);
    }

hm是什么了 哈哈 就是

private HashMap<String,Integer> hm = new HashMap<String,Integer>();

给个算法示例就结束啦

    public int CountRowZuo(int i,int j){
        int color = 0;
        String chessString = new String();
        for(int z = 1;(i-z) > 0 &&chessBoard[i-z][j]!=0;z++) {
            color = chessBoard[i - 1][j];
            if (chessBoard[i - z][j] == color) {
                chessString = chessString + "1";
            } else {
                chessString = chessString + "2";
                break;
            }
        }
        return hm.get(chessString).intValue();
    }

git还没建好(懒) 就先不开源了 哈哈

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值