Java实现-五子棋

因为是用awt,swing的所做,是现在几乎被淘汰的java早期技术了,但是用来在开始学java时去串联其他知识点还是很好用的一个方式。

这个主要用了三个类,也是参考着现成的写的,不过优化了几个地方的代码,使得更符合逻辑一些,当然其中也可能会有更好的优化点,在用的时候可以自行优化。

三个类:棋盘类、棋子类、启动(设置)类

1.棋盘类(核心的设置类,先创建棋子类建议)

package com.sheng;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;//鼠标监听类
import java.awt.event.MouseMotionListener;
import java.awt.geom.Ellipse2D;

//棋盘类
public class ChessBoard extends JPanel implements MouseListener {
    //定义初始棋盘数据
    public static final int MARGIN = 30; //边距
    public static final int GRID_SPAN = 35; //网格间距
    public static final int ROWS = 20;  //行数(可以自行设置行列数,此处修改即可)
    public static final int COLS = 20;  //列数

    //初始化数据
    Point[] chessList = new Point[(ROWS+1)*(COLS+1)];//初始化每个棋盘元素为null
    Boolean isBlack = true; //黑棋优先
    Boolean gameOver = false;   //判断是否结束
    int chessCount; //当前棋盘上的棋子数
    int xIndex,yIndex;//所下棋子位置

    //棋子颜色
    Color colortemp;

    public ChessBoard(){//构造函数
        addMouseListener(this);
        addMouseMotionListener(new MouseMotionListener() {//对于鼠标移动与拖拽的设置
            @Override
            public void mouseDragged(MouseEvent e) {}

            @Override
            public void mouseMoved(MouseEvent e) {  //移动
                //将鼠标点击位置转成网格的索引
                int x = (e.getX() - MARGIN + GRID_SPAN/2)/GRID_SPAN;
                int y = (e.getY() - MARGIN + GRID_SPAN/2)/GRID_SPAN;

                //对下棋位置进行判断(超界限,游戏结束,位置有棋)
                if (x<0 || x>ROWS || y<0 || y>COLS || gameOver || findChess(x,y))
                    setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
                else//设置为默认状态
                    setCursor(new Cursor(Cursor.HAND_CURSOR));
            }
        });
    }

    public Boolean findChess(int x , int y){//查找该位置是否有棋子已经存在
        for (Point p : chessList){
            if ( p != null && p.getX() == x && p.getY() == y)
                return true;
        }
        return false;
    }

    //绘制
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);    //绘制棋盘

        //得到窗口的宽高
        int fWidth = getWidth();
        int fHeight = getHeight();

        g.drawImage(null, fWidth /2,fHeight/2,null);

        for (int i = 0; i<=ROWS; i++)//画横线
            g.drawLine(MARGIN,MARGIN+i*GRID_SPAN,MARGIN+COLS*GRID_SPAN,MARGIN+i*GRID_SPAN);

        for (int i = 0; i<=ROWS; i++)//画竖线
            g.drawLine(MARGIN+i*GRID_SPAN,MARGIN,MARGIN+i*GRID_SPAN,MARGIN+ROWS*GRID_SPAN);

        //画棋子
        for (int i = 0; i<chessCount; i++){
            //网格交叉点x,y坐标
            int xPos = (int) chessList[i].getX()*GRID_SPAN+MARGIN;
            int yPos = (int) chessList[i].getY()*GRID_SPAN+MARGIN;

            g.setColor(chessList[i].getColor());//设置颜色
            colortemp = chessList[i].getColor();

            RadialGradientPaint paint;
            if (colortemp == Color.BLACK){
                paint = new RadialGradientPaint(xPos-Point.DIAMETER/2+25, yPos-Point.DIAMETER/2+10,
                       20, new float[]{0f,1f}, new Color[]{Color.WHITE,Color.BLACK});
            }else{
                paint = new RadialGradientPaint(xPos-Point.DIAMETER/2+25, yPos-Point.DIAMETER/2+10,
                        70, new float[]{0f,1f}, new Color[]{Color.WHITE,Color.BLACK});
            }
            ((Graphics2D) g).setPaint(paint);
            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT);

            Ellipse2D e = new Ellipse2D.Float(xPos - Point.DIAMETER/2,yPos - Point.DIAMETER/2,34,35);
            ((Graphics2D) g).fill(e);

            if (i == chessCount - 1){//如果是最后一个棋子
                g.setColor(Color.red);
                g.drawRect(xPos - Point.DIAMETER/2,yPos - Point.DIAMETER/2,34,35);
            }
        }


    }

    //实现MouseListener中的方法
    @Override
    public void mousePressed(MouseEvent e) {//按下
        //游戏结束,不能再下
        if (gameOver) return;

        String colorName = isBlack?"黑棋":"白棋";

        //将鼠标点击的坐标位置转换为网格索引
        xIndex = (e.getX() - MARGIN + GRID_SPAN/2)/GRID_SPAN;
        yIndex = (e.getY() - MARGIN + GRID_SPAN/2)/GRID_SPAN;

        //棋盘外不能下
        if (xIndex<0 || xIndex>ROWS || yIndex<0 || yIndex>COLS)
            return;

        //如果该位置有棋,不可下
        if (findChess(xIndex,yIndex))
            return;

        //符合条件是进行的处理
        Point ch = new Point(xIndex,yIndex,isBlack?Color.BLACK:Color.WHITE);
        chessList[chessCount++] = ch;
        repaint();//通知系统重新绘制

        //如果胜出则给出提示信息不能继续下棋
        if (isWin()){
            String msg = String.format("恭喜%s赢了",colorName);
            JOptionPane.showMessageDialog(this,msg);
        }
        isBlack = !isBlack;
    }
    @Override
    public void mouseClicked(MouseEvent e) {//点击
    }

    @Override
    public void mouseReleased(MouseEvent e) {//释放
    }
    @Override
    public void mouseEntered(MouseEvent e) {//进入
    }
    @Override
    public void mouseExited(MouseEvent e) {//退出
    }

    private Boolean isWin(){
        int continueCount = 1;  //连续棋子的个数
    //四种情况 水平 竖直 左上到右下 左下到右上
    //横向
        //横向向西寻找
        for (int x=xIndex-1; x>=0; x--){
            Color c = isBlack?Color.BLACK:Color.WHITE;
            if (getChess(x,yIndex,c) != null){
                continueCount++;
            }else
                break;
        }
        //横向向东寻找
        for (int x=xIndex+1; x<=COLS; x++){
            Color c = isBlack?Color.BLACK:Color.WHITE;
            if (getChess(x,yIndex,c) != null){
                continueCount++;
            }else
                break;
        }
        if (continueCount >= 5)//判断横向是否已经有结果,反之重置为1
            return true;
        else
            continueCount = 1;

    //纵向
        // 向上查找
        for (int y = yIndex-1; y>=0; y--){
            Color c = isBlack?Color.BLACK:Color.WHITE;
            if (getChess(xIndex,y,c) != null){
                continueCount++;
            }else
                break;
        }
        //纵向向下查找
        for (int y = yIndex+1; y<=ROWS; y++){
            Color c = isBlack?Color.BLACK:Color.WHITE;
            if (getChess(xIndex,y,c) != null){
                continueCount++;
            }else
                break;
        }
        if (continueCount >= 5)//判断横向是否已经有结果,反之重置为1
            return true;
        else
            continueCount = 1;

    //斜向 左上到右下
        //东北
        for (int x = xIndex+1,y = yIndex-1; y>=0&&x<=COLS; x++,y--){
            Color c = isBlack?Color.BLACK:Color.WHITE;
            if (getChess(x,y,c) != null){
                continueCount++;
            }else
                break;
        }
        //西南两向
        for (int x = xIndex-1,y = yIndex+1; y<=ROWS&&x>=0; x--,y++){
            Color c = isBlack?Color.BLACK:Color.WHITE;
            if (getChess(x,y,c) != null){
                continueCount++;
            }else
                break;
        }
        if (continueCount >= 5)//判断横向是否已经有结果,反之重置为1
            return true;
        else
            continueCount = 1;

    //斜向 左下到右上
        //西北
        for (int x = xIndex-1,y = yIndex-1; y>=0&&x>=0; x--,y--){
            Color c = isBlack?Color.BLACK:Color.WHITE;
            if (getChess(x,y,c) != null){
                continueCount++;
            }else
                break;
        }
        //东南
        for (int x = xIndex+1,y = yIndex+1; y<=ROWS&&x<=COLS; x++,y++){
            Color c = isBlack?Color.BLACK:Color.WHITE;
            if (getChess(x,y,c) != null){
                continueCount++;
            }else
                break;
        }
        if (continueCount >= 5)//判断横向是否已经有结果,反之重置为1
            return true;
        else
            return false;
    }

    private Point getChess(int xIndex, int yIndex, Color color){
        for (Point p: chessList){
            if (p!=null && p.getX()==xIndex && p.getY()==yIndex && p.getColor()==color){
                return p;
            }
        }
        return null;
    }

    public void restartGame(){//重新开始
        //清空棋盘
        for (int i = 0; i<chessList.length ;i++)
            chessList[i] = null;

        //恢复游戏初始变量
        isBlack = true;
        gameOver = false;
        chessCount = 0;
        repaint();
    }

    public void goBack(){//悔棋
        if (chessCount == 0)
            return;

        chessList[chessCount-1] = null;
        chessCount--;

        if (chessCount > 0){
            xIndex = chessList[chessCount-1].getX();
            yIndex = chessList[chessCount-1].getY();
        }
        isBlack = !isBlack;
        repaint();
    }

    //矩形Dimension
    public Dimension getPreferredSize(){
        return new Dimension(MARGIN*2+GRID_SPAN*COLS,MARGIN*2+GRID_SPAN*ROWS);
    }
}

2.棋子类

package com.sheng;

import java.awt.*;

public class Point {
    private int x;//横坐标
    private int y;//纵坐标
    private Color color;//颜色
    public static final int DIAMETER = 30;//半径

    public Point(int x, int y, Color color) {
        this.x = x;
        this.y = y;
        this.color = color;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public Color getColor() {
        return color;
    }
}

3.启动(设置)类

package com.sheng;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class StartChessJFrame extends JFrame {

    private ChessBoard chessBoard;
    private JPanel toolbar;
    private JButton startButton,backButton,exitButton;

    private JMenuBar menuBar;
    private JMenu sysMenu;
    private JMenuItem startMenuItem,backMenuItem,exitMenuItem;

    public StartChessJFrame(){
        setTitle("单机版五子棋");

        chessBoard = new ChessBoard();

        Container contentPane = getContentPane();
        contentPane.add(chessBoard);
        chessBoard.setOpaque(true);

        //创建和添加菜单
        menuBar = new JMenuBar();//初始化菜单栏
        sysMenu = new JMenu("系统");//初始化菜单

        //初始化菜单项
        startMenuItem = new JMenuItem("重新开始");
        exitMenuItem = new JMenuItem("退出");
        backMenuItem = new JMenuItem("悔棋");
        //将三个菜单项添加到菜单上
        sysMenu.add(startMenuItem);
        sysMenu.add(exitMenuItem);
        sysMenu.add(backMenuItem);

        //初始化按钮事件监听内部类
        MyItemListener myItemListener = new MyItemListener();
        //将三个菜单栏添加到时间监听器上
        this.startMenuItem.addActionListener(myItemListener);
        this.backMenuItem.addActionListener(myItemListener);
        this.exitMenuItem.addActionListener(myItemListener);
        menuBar.add(sysMenu);//将系统菜单添加到菜单栏上
        setJMenuBar(menuBar);//将menuBar设置为菜单栏

        toolbar = new JPanel();//工具面板实例化
        //三个按钮初始化
        startButton = new JButton("重新开始");
        backButton = new JButton("悔棋");
        exitButton = new JButton("退出");

        //将工具面板按钮用FlowLayout布局
        toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));
        //将三个按钮添加到工具面板
        toolbar.add(startButton);
        toolbar.add(backButton);
        toolbar.add(exitButton);
        //将三个按钮注册监听事件
        startButton.addActionListener(myItemListener);
        backButton.addActionListener(myItemListener);
        exitButton.addActionListener(myItemListener);
        //将工具面板布局到界面的下方(南方)
        add(toolbar,BorderLayout.SOUTH);
        add(chessBoard);
        //设置界面关闭事件
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        pack();//自适应大小

    }
    private class MyItemListener implements ActionListener{//内部类
        @Override
        public void actionPerformed(ActionEvent e) {
            Object obj = e.getSource();
            if (obj == StartChessJFrame.this.startMenuItem || obj == startButton){
                //重新开始
                //JFiveFrame.this 内部类引用外部类
                System.out.println("重新开始");
                chessBoard.restartGame();
            }else if (obj == exitMenuItem || obj == exitButton){
                System.exit(0);
            }else if(obj == backMenuItem || obj == backButton){
                System.out.println("悔棋");
                chessBoard.goBack();
            }
        }
    }

    public static void main(String[] args) {
        StartChessJFrame startChessJFrame = new StartChessJFrame();
        startChessJFrame.setVisible(true);
    }
}

最后运行后会出现java特有的窗口界面,然后就可以来与小伙伴愉快的下五子棋了。

结果展示:

 

  • 6
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值