Java实现五子棋小游戏(对新手极为友好的版本)

写在前面的话:“ 你现在的状态,是过去的你用努力换来的,而你未来的状态,是现在的你用努力决定的。”
九月你好,还未还得及感受,你就要离去。以前总是担心着未来的未发生的事情,前几天听完bilibi架构师学长对我问题的回答后。有所感触。我想,现在的我,规划好以后要做的事情,把目前手里的事情做好,不好高骛远,脚踏实地,充实自己,机会是留给有准备的人的。我是梦阳辰,快和我一起加油吧!

效果预览:
在这里插入图片描述

系统设计:

1.设计棋盘类用来构建棋盘。

2.设计棋局类,用来保存棋局情况(用二维数组存储)。

3.设计物理地址类用来表示物理地址。

4.设计逻辑地址类用来表示棋盘上逻辑坐标。

5.系统游戏类,也为主类。用来绘制棋盘,绘制棋子,并对用户单击鼠标(下棋)进行响应(做相应的处理)。

6.因为监听鼠标单击一直在进行,所以游戏可以一直运行,知道用户主动退出游戏。

判断输赢的核心算法:
通过判断当前所下棋子是否与周围(米字方向)同色棋子组成五连珠。

 /**S
     * 判断棋局是否获胜(落点位置周围是否有5个相同颜色的棋子
     * @return -1黑色方赢  0平局 1白色方赢
     */
    public int isWin(CoordinateLogical c,int color){
        //竖直方向
        int count=-1;//初值为-1的原因:(当前所下棋子算了两次)
        for(int i=c.getRow();i>=0;i--){
            if(situation[i][c.getCol()]==color){
                count++;
            }
            else {
                break;
            }
        }
        for(int i=c.getRow();i<Chessboard.getRows();i++){
            if(situation[i][c.getCol()]==color){
                count++;
            }
            else {
                break;
            }
        }
        if(count==5){
            return color;
        }

        //水平方向
        count=-1;
        for(int i=c.getCol();i>=0;i--){
            if(situation[c.getRow()][i]==color){
                count++;
            }
            else {
                break;
            }
        }
        for(int i=c.getCol();i<Chessboard.getCols();i++){
            if(situation[c.getRow()][i]==color){
                count++;
            }
            else {
                break;
            }
        }
        if(count==5){
            return color;
        }
        //斜左下到右上方向
        count=-1;
        for(int i=c.getRow(),j=c.getCol();i>=0&&j<=Chessboard.getCols()-1;i--,j++){//右上
            if(situation[i][j]==color){
                count++;
            }
            else {
                break;
            }
        }
        for(int i=c.getRow(),j=c.getCol();j>=0&&i<=Chessboard.getRows()-1;i++,j--){//左下
            if(situation[i][j]==color){
                count++;
            }
            else {
                break;
            }
        }
        if(count==5){
            return color;
        }

        //斜左上到右下方向
        count=-1;
        for(int i=c.getRow(),j=c.getCol();i>=0&&j>=0;i--,j--){//左上
            if(situation[i][j]==color){
                count++;
            }
            else {
                break;
            }
        }
        for(int i=c.getRow(),j=c.getCol();i<=Chessboard.getRows()-1&&j<=Chessboard.getCols()-1;i++,j++){//右下
            if(situation[i][j]==color){
                count++;
            }
            else {
                break;
            }
        }
        if(count==5){
            return color;
        }
        return 0;
    }

在这里插入图片描述

01.设计棋局类

属性

1.属性situation:用二维数组存储棋局每个点位的情况。

2.棋子属性:定义黑棋(black),白棋的属性(white)。

3.先手属性:定义当前移动方(mover)。

方法

1.判断逻辑地址是否存在棋子(exist)

2.落子(add)

3.判断棋局是否获胜(isWin)

程序代码:

package GoBang_Game;

//棋局类
public class ChessSituation {

    public  final static int BLACK = -1;//黑色棋子
    public  final static int NONE = 0;//无棋子
    public  final static int WHITE = 1;//白色棋子

    private int[][] situation;//棋局所有落点的情况
    private  int mover;//表示当前谁落子,1为白子,-1为黑子

    /**
     * 确定落点
     * 构造函数
     */
    public ChessSituation(int rows,int cols) {
        situation = new int[rows][cols];//默认值为0
        mover = BLACK;//黑方先动
    }

    /**
     * 判断逻辑地址是否存在棋子
     * @return true or false
     */
    public  boolean exist(CoordinateLogical c){
        return situation[c.getRow()][c.getCol()]!=ChessSituation.NONE;
    }

    /**
     * 落子
     * @param c 落子的位置
     * @return 落子的颜色
     */
    public int add(CoordinateLogical c){
        int color = mover;
        situation[c.getRow()][c.getCol()] = color;//存储了颜色,也就代表了哪一方
        mover = -mover;//切换谁下棋
        return  color;
    }

    /**S
     * 判断棋局是否获胜(落点位置周围是否有5个相同颜色的棋子
     * @return -1黑色方赢  0平局 1白色方赢
     */
    public int isWin(CoordinateLogical c,int color){
        //竖直方向
        int count=-1;
        for(int i=c.getRow();i>=0;i--){
            if(situation[i][c.getCol()]==color){
                count++;
            }
            else {
                break;
            }
        }
        for(int i=c.getRow();i<Chessboard.getRows();i++){
            if(situation[i][c.getCol()]==color){
                count++;
            }
            else {
                break;
            }
        }
        if(count==5){
            return color;
        }

        //水平方向
        count=-1;
        for(int i=c.getCol();i>=0;i--){
            if(situation[c.getRow()][i]==color){
                count++;
            }
            else {
                break;
            }
        }
        for(int i=c.getCol();i<Chessboard.getCols();i++){
            if(situation[c.getRow()][i]==color){
                count++;
            }
            else {
                break;
            }
        }
        if(count==5){
            return color;
        }
        //斜左下到右上方向
        count=-1;
        for(int i=c.getRow(),j=c.getCol();i>=0&&j<=Chessboard.getCols()-1;i--,j++){//右上
            if(situation[i][j]==color){
                count++;
            }
            else {
                break;
            }
        }
        for(int i=c.getRow(),j=c.getCol();j>=0&&i<=Chessboard.getRows()-1;i++,j--){//左下
            if(situation[i][j]==color){
                count++;
            }
            else {
                break;
            }
        }
        if(count==5){
            return color;
        }

        //斜左上到右下方向
        count=-1;
        for(int i=c.getRow(),j=c.getCol();i>=0&&j>=0;i--,j--){//左上
            if(situation[i][j]==color){
                count++;
            }
            else {
                break;
            }
        }
        for(int i=c.getRow(),j=c.getCol();i<=Chessboard.getRows()-1&&j<=Chessboard.getCols()-1;i++,j++){//右下
            if(situation[i][j]==color){
                count++;
            }
            else {
                break;
            }
        }
        if(count==5){
            return color;
        }
        return 0;
    }

    public int[][] getSituation() {
        return situation;
    }

    public void setSituation(int[][] situation) {
        this.situation = situation;
    }

    public int getMover() {
        return mover;
    }

    public void setMover(int mover) {
        this.mover = mover;
    }
}

02.棋盘类

属性

1.行数(rows)
2.列数(cols)
3.间距(size)
4.棋盘的位置(margin)

方法

1.初始化棋盘(init)

2.将物理地址转换为逻辑坐标(convert)。
注意:将物理地址转换成逻辑坐标时:
横坐标转化成列号。
纵坐标转换成行号。

3.将逻辑坐标转换成物理地址(convert)。
目的是为了在物理地址画棋子。

程序代码:

package GoBang_Game;

//棋盘类
public class Chessboard {
    private static int rows;//行数
    private static int cols;//列数
    private static int size;//间距
    private static int margin;//棋盘的位置

    /**
     * 初始化
     * @param n1 行数
     * @param n2 列数
     * @param n3 间距
     * @param n4 外边距
     */
    public static void init(int n1, int n2,int n3, int n4) {
        rows = n1;
        cols = n2;
        size = n3;
        margin = n4;
    }

    /**
     * 将物理地址装换成逻辑坐标
     * @param c 物理坐标
     * @return 逻辑坐标
     */
    public static CoordinateLogical convert(CoordinatePhysical c){
        CoordinateLogical c1 = new CoordinateLogical();
        c1.setCol(Math.round((float)(c.getX()-margin)/size));//行号
        c1.setRow(Math.round((float)(c.getY()-margin)/size));//列号
        return c1;
    }

    /**
     * 将逻辑坐标装换成物理地址
     * @param c 逻辑坐标
     * @return 物理坐标
     */
    public static CoordinatePhysical convert(CoordinateLogical c){//便于画棋子
        CoordinatePhysical c1 = new CoordinatePhysical();
        c1.setX(c.getCol()*size+margin);//横坐标
        c1.setY(c.getRow()*size+margin);//纵坐标
        return c1;
    }

    public static int getRows() {
        return rows;
    }

    public static void setRows(int rows) {
        Chessboard.rows = rows;
    }

    public static int getCols() {
        return cols;
    }

    public static void setCols(int cols) {
        Chessboard.cols = cols;
    }

    public static int getSize() {
        return size;
    }

    public static void setSize(int size) {
        Chessboard.size = size;
    }

    public static int getMargin() {
        return margin;
    }

    public static void setMargin(int margin) {
        Chessboard.margin = margin;
    }

    public static int getWidth() {
        return (margin*2+size*(cols-1));
    }

    public static int getHight() {
        return (margin*2+size*(rows-1));
    }
}

03.物理地址类

属性

1.横坐标(x)

2.纵坐标(y)

程序代码:

package GoBang_Game;

public class CoordinatePhysical {
    private int x;//横坐标
    private int y;//纵坐标

    public CoordinatePhysical() {
    }

    public CoordinatePhysical(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

04.逻辑坐标类

属性

1.行号(row)

2.列号(col)

程序代码:

package GoBang_Game;

public class CoordinateLogical {
    private int row;//行号
    private int col;//列号

    public CoordinateLogical() {
    }

    public CoordinateLogical(int row, int col) {
        this.row = row;
        this.col = col;
    }

    public int getRow() {
        return row;
    }

    public void setRow(int row) {
        this.row = row;
    }

    public int getCol() {
        return col;
    }

    public void setCol(int col) {
        this.col = col;
    }
}

05.系统游戏类

属性:

1.窗体

2.画布

3.绘图对象

4.按钮

5.棋局属性

方法

1.主方法:(main)
创建游戏对象

2.构造方法:(Game)
创建窗口,画布,增加按钮,响应按钮,并响应鼠标做对应处理。

3.绘制棋盘(drawBoard)

4.绘制棋子(drawChess)

5.处理鼠标单击(下棋)

程序代码:

package GoBang_Game;


import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class Game {
    private static Frame frame;//窗体
    private static Canvas canvas;//画布
    private Graphics graphics;//绘图对象
    private Button button;//按钮
    private ChessSituation chessSituation;//棋局


    public static void main(String[] args) {
        Game game = new Game(15,15,50,50);
    }

    public Game(int rows, int cols, int size , int margin){

        Chessboard.init(rows,cols,size,margin);
        chessSituation = new ChessSituation(rows,cols);
        //初始化窗口
        int width = Chessboard.getWidth();
        int height = Chessboard.getHight()+100;
        frame = new Frame("五子棋-梦阳辰");
        frame.setSize(width,height);
        frame.setLayout(new FlowLayout());
        frame.setVisible(true);//显示窗体

        //准备画布
        canvas = new Canvas();
        canvas.setSize(width,height);//指定尺寸
        frame.add(canvas);

        //画布单击响应
        canvas.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

                CoordinatePhysical c  = new CoordinatePhysical(e.getX(),e.getY());
                int a =handle(c);
                if(a==1){
                    JOptionPane.showMessageDialog(null, "白色方赢了", "游戏结束",JOptionPane.INFORMATION_MESSAGE);
                    drawBoard();//重新绘制棋盘
                    chessSituation.setSituation(new int [Chessboard.getRows()][Chessboard.getCols()]);//将棋局情况 清0
                    chessSituation.setMover(chessSituation.BLACK);//设置黑色方为先手
                }
                else if(a==-1){
                    JOptionPane.showMessageDialog(null, "黑色方赢了", "游戏结束",JOptionPane.INFORMATION_MESSAGE);
                    drawBoard();//重新绘制棋盘
                    chessSituation.setSituation(new int [Chessboard.getRows()][Chessboard.getCols()]);//将棋局情况 清0
                    chessSituation.setMover(chessSituation.BLACK);//设置黑色方为先手
                }
                super.mouseClicked(e);
            }
        });

        //增加按钮
        button = new Button("Start Game");
        button.setSize(130,80);
        frame.add(button);

        //响应按钮
        button.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent mouseEvent) {
                graphics = canvas.getGraphics();
                drawBoard();//绘制棋盘
                chessSituation.setSituation(new int [Chessboard.getRows()][Chessboard.getCols()]);//将棋局情况 清0
                chessSituation.setMover(chessSituation.BLACK);//设置黑色方为先手
                super.mouseClicked(mouseEvent);
            }
        });

        //增加按钮
        button = new Button("Exit Game");
        button.setSize(130,80);
        frame.add(button);

        //响应按钮
        button.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent mouseEvent) {
                graphics = canvas.getGraphics();
                frame.setVisible(false);//退出窗体
                System.exit(0);//退出程序
                super.mouseClicked(mouseEvent);
            }
        });


    }


    /**
     * 绘制棋盘
     */
    public void drawBoard(){
        graphics.setColor(Color.YELLOW);
        graphics.fillRect(0,0,Chessboard.getWidth(),Chessboard.getHight());
        graphics.setColor(Color.BLACK);
        //绘制纬线
        int x1 = Chessboard.getMargin();
        int y1 = Chessboard.getMargin();
        int x2 = x1+(Chessboard.getSize()*(Chessboard.getCols()-1));
        int y2 = y1;
        for(int i=0;i<Chessboard.getRows();i++){
            graphics.drawLine(x1,y1,x2,y2);
            y1 += Chessboard.getSize();
            y2 += Chessboard.getSize();
        }
        //绘制纬线
         x1 = Chessboard.getMargin();
         y1 = Chessboard.getMargin();
         x2 = x1;
         y2 = y1+(Chessboard.getSize()*(Chessboard.getRows()-1));
        for(int i=0;i<Chessboard.getCols();i++){
            graphics.drawLine(x1,y1,x2,y2);
            x1 += Chessboard.getSize();
            x2 += Chessboard.getSize();
        }
    }

    /**
     * 绘制棋子
     * @param c
     * @param color 颜色(1黑色,-1白色)
     */
    public  void drawChess(CoordinateLogical c, int color){
        int r = (int) (Chessboard.getSize()*0.4);
        CoordinatePhysical c1= Chessboard.convert(c);//得到物理坐标
        //计算外切正方形的起点和宽高
        int x = c1.getX() -r ;
        int y = c1.getY() -r ;
        int width  = 2*r;
        int heigth = 2*r;
        graphics.setColor(color==chessSituation.BLACK?Color.BLACK:Color.WHITE);
        graphics.fillArc(x,y,width,heigth,0,360);
    }

    /**
     * 用户在棋盘上单击之后的处理
     * @param c 单击的位置
     * @return  输赢结果
     */
    public  int handle(CoordinatePhysical c) {
        CoordinateLogical c1 = Chessboard.convert(c);
        if(!chessSituation.exist(c1)){
            //落子
            int color = chessSituation.add(c1);
            //绘制棋子
            drawChess(c1,color);
            //返回落子后的输赢
            return chessSituation.isWin(c1,color);
        }
        return chessSituation.NONE;
    }
}

关注公众号【轻松玩编程】回复关键字“电子书”,“计算机资源”,“Java从入门到进阶”,”JavaScript教程“,“算法”,“Python学习资源”,“人工智能”等即可获取学习资源。

喜欢就争取,得到就珍惜,生活就是这样,脚长在自己身上,往前走就对了,直到向往的风景,变成走过的地方。

在这里插入图片描述

以梦为马,不负韶华。
原文地址:https://www.cnblogs.com/huangjiahuan1314520/p/13743555.html