五子棋游戏 - 棋盘类实现

该代码实现了一个简单的五子棋游戏棋盘类,包含以下功能:

  • 棋盘绘制: 使用 Graphics 对象绘制棋盘格子和棋子,并使用 RadialGradientPaint 实现棋子渐变效果。
  • 棋子放置: 监听鼠标点击事件,将棋子放置在点击的位置。
  • 游戏状态判断: 判断游戏是否结束,并根据结果提示用户。
  • 悔棋功能: 撤销最后一步棋子。
  • 游戏暂停功能: 暂停游戏,并防止在暂停状态下进行下棋操作。

代码实现:

package cn.edu.ouc.fiveChess;

import sun.awt.image.ToolkitImage;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.*;
/**
 * 五子棋--棋盘类
 */
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=15;//棋盘行数
    public static final int COLS=15;//棋盘列数
    Point[] chessList=new Point[(ROWS+1)*(COLS+1)];//初始每个数组元素为null
    boolean isBlack=true;//默认开始是黑棋先
    boolean gameOver=false;//游戏是否结束
    int chessCount;//当前棋盘棋子的个数
    int xIndex,yIndex;//当前刚下棋子的索引
    //声明变量
    Image img;
    Image shadows;
    Color colortemp;
    //程序暂停,true为暂停
    private boolean paused;
    //创建ChessBoard类
    public ChessBoard(){
        //使用Toolkit类的getDefaultToolkit方法获取默认工具包
        img= Toolkit.getDefaultToolkit().getImage("");
        shadows=Toolkit.getDefaultToolkit().getImage("");
        //添加鼠标监视器
        addMouseListener(this);
        //添加一个鼠标移动监听器
        addMouseMotionListener(new MouseMotionListener(){
            public void mouseDragged(MouseEvent e){
            }
            public void mouseMoved(MouseEvent e){
                int x1=(e.getX()-MARGIN+GRID_SPAN/2)/GRID_SPAN;
                //将鼠标点击的坐标位置转成网格索引
                int y1=(e.getY()-MARGIN+GRID_SPAN/2)/GRID_SPAN;
                //游戏已经结束不能下
                //落在棋盘外不能下
                //x,y位置已经有棋子存在,不能下
                if(x1<0||x1>ROWS||y1<0||y1>COLS||gameOver||findChess(x1,y1))
                    setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
                    //设置成默认状态
                else setCursor(new Cursor(Cursor.HAND_CURSOR));
            }
        });
    }
    private boolean isPaused = false;//添加一个标志位记录游戏是否暂停
    //绘制
    public void paintComponent(Graphics g){
        super.paintComponent(g);//画棋盘
        int imgWidth= img.getWidth(this);
        int imgHeight=img.getHeight(this);//获得图片的宽度与高度
        int FWidth=getWidth();
        int FHeight=getHeight();//获得窗口的宽度与高度
        int x=(FWidth-imgWidth)/2;
        int y=(FHeight-imgHeight)/2;
        g.drawImage(img, x, y, null);
        for(int i=0;i<=ROWS;i++){//画横线
            for(int j=0;j<COLS;j++) {
                g.drawLine(MARGIN, MARGIN + i * GRID_SPAN, MARGIN + COLS * GRID_SPAN, MARGIN + i * GRID_SPAN);
            }
        }
        //判断游戏是否暂停,如果暂停则不进行绘制
        if(!isPaused) {//如果游戏未暂停,进行绘制
            for (int i = 0; i <= COLS; 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 = chessList[i].getX() * GRID_SPAN + MARGIN;
                int yPos = chessList[i].getY() * GRID_SPAN + MARGIN;
                g.setColor(chessList[i].getColor());//设置颜色
                colortemp = chessList[i].getColor();
                if (colortemp == Color.black) {
                    RadialGradientPaint paint = new RadialGradientPaint(xPos - Point.DIAMETER / 2 + 25, yPos - Point.DIAMETER / 2 + 10, 20, 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);

                } else if (colortemp == Color.white) {
                    RadialGradientPaint 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);
                //标记最后一个棋子的红矩形框
            }
        }
    }
    public void mousePressed(MouseEvent e){
        //游戏结束时,不再能下
        if (gameOver || paused) {
            JOptionPane.showMessageDialog(this, "当前处于暂停模式,请点击继续按钮继续游戏");
            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) {
            JOptionPane.showMessageDialog(this, "该位置不在界面内,请在界面内下棋");
            return;
        }
        //如果点击的位置已经有棋子存在,不能下
        if(findChess(xIndex,yIndex)) {
            JOptionPane.showMessageDialog(this, "该位置已经有棋子,请重新选择位置下棋!");
            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);
            gameOver=true;
        }
        isBlack=!isBlack;
    }
    //覆盖mouseListener的方法
    public void mouseClicked(MouseEvent e) {
        //判断游戏是否暂停,如果暂停则不进行下棋
        if (isPaused) {
            JOptionPane.showMessageDialog(this, "游戏已暂停,请点击继续按钮继续游戏", "提示", JOptionPane.INFORMATION_MESSAGE);
            return;
        }
    }
    public void mouseEntered(MouseEvent e){
        //鼠标进入到组件上时调用
    }
    public void mouseExited(MouseEvent e){
        //鼠标离开组件时调用
    }
    public void mouseReleased(MouseEvent e){
        //鼠标按钮在组件上释放时调用
    }
    //在棋子数组中查找是否有索引为x,y的棋子存在
    private boolean findChess(int x,int y){
        for(Point c:chessList){
            if(c!=null&&c.getX()==x&&c.getY()==y)
                return true;
        }
        return false;
    }
    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){
            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)
            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;x>=0&&y<=ROWS;x--,y++){
            Color c=isBlack?Color.black:Color.white;
            if(getChess(x,y,c)!=null){
                continueCount++;
            }
            else break;
        }
        if(continueCount>=5)
            return true;
        else continueCount=1;
        //继续另一种情况的搜索:斜向
        //西北寻找
        for(int x=xIndex-1,y=yIndex-1;x>=0&&y>=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;x<=COLS&&y<=ROWS;x++,y++){
            Color c=isBlack?Color.black:Color.white;
            if(getChess(x,y,c)!=null)
                continueCount++;
            else break;
        }
        if(continueCount>=5)
            return true;
        else continueCount=1;

        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);
    }
    public void setPaused(boolean paused) {
        this.paused = paused;
    }
}

代码说明:

  1. 类定义: 声明 ChessBoard 类继承 JPanel 并实现 MouseListener 接口。
  2. 成员变量: 声明了棋盘信息、游戏状态、当前棋子信息等变量。
  3. 构造函数: 初始化棋盘信息、添加鼠标监听器和鼠标移动监听器。
  4. 绘制方法 paintComponent: 绘制棋盘格子和棋子,并根据游戏状态进行绘制。
  5. 鼠标点击事件处理: 监听鼠标点击事件,将棋子放置在点击的位置,并判断游戏是否结束。
  6. 悔棋方法 goback: 撤销最后一步棋子。
  7. 游戏暂停方法 setPaused: 暂停游戏,并防止在暂停状态下进行下棋操作。

问题和解决方案:

  1. 图片加载不出来。
    • 解决方案:检查图片路径是否正确,使用绝对路径或者将图片放在项目根目录下。
  2. 棋子绘制不出来。
    • 解决方案:检查绘制代码是否正确,如颜色、位置等是否正确,可以使用调试工具查看变量的值。
  3. 游戏暂停后,点击棋盘仍可以下棋。
    • 解决方案:在鼠标监听器中加入判断,如果游戏暂停,则不执行下棋操作。
  4. 悔棋时棋子消失不彻底。
    • 解决方案:在悔棋方法中将棋子数组对应位置赋值为null,并将棋子个数减1,保证棋子数组中不会出现null与非null交错的情况。

下一步改进:

  • 可以添加游戏开始界面,选择先手棋子等功能。
  • 可以添加计分功能,记录游戏胜负情况。
  • 可以使用更复杂的算法实现人工智能对手,使玩家可以与电脑对战。

总结:

该代码提供了一个五子棋游戏棋盘类实现的简单示例,可以作为学习和参考。通过进一步改进,可以实现更加完善的五子棋游戏功能。

五子棋游戏 - 棋盘类实现

原文地址: https://www.cveoy.top/t/topic/oBhP 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录