java制作五子棋——初学者

   假期闲来无事,与一位王姓朋友(人美声甜的小仙女)合力制作了一个五子棋小游戏,皆是java初学者,在代码中存在有问题的地方还请各位指出。(内心os:写的代码跟没学过数据结构一样)

   主要采用java.awt以及java.swing的GUI常用包,最初框架搭建可参考B站博主 https://www.bilibili.com/video/BV1SJ411x74E?spm_id_from=333.1007.top_right_bar_window_history.content.click    接下来言归正传,看一段接口类设定代码,在Config.java的接口类中定义了棋盘格属性,定义了线条数等初始属性,便于后期进行组件设计

public interface Config {
    //配置接口
    //定义棋盘属性
    int Start_X=40;     //起始x轴距离,即第一个x轴
    int Start_Y=40;     //起始y轴距离,即第一个y轴
    int Line_Num=15;    //线条数
    int Size=40;   //线条之间间隔
    int Chess_Size=30;  //棋子大小
}

  在Chess.java中定义了棋子属性,包括其行列坐标,在类中定义了获取其行、列数据的方法,在后期进行悔棋操作时有所使用

public class Chess{
    //棋子类
    private int row;    //行
    private int column; //列

    public Chess(int row, int column){
        //构造方法,分配属性
        this.row=row;
        this.column=column;
    }
    public int getRow(){
        //获取行
        return row;
    }
    public int getColumn(){
        //获取列
        return column;
    }
}

    在RenjuListener.java类中定义了监听器中的操作,类中方法对鼠标事务进行了响应,定义了对胜负的判断方法,框架如下:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

public class RenjuListener extends MouseAdapter implements Config, ActionListener{
    Graphics g;
    int x=40, y=40; //设置坐标参数
    int countClick = 0; //设置鼠标点击计数器
    private int stepFlag=0; //记录下棋步数
    private Renju renju;
    private int ChessNum[][] = new int[Line_Num][Line_Num];
    private String com; //获取功能按键命令
    private int startFlag = 0;   //开始标志,保证每一次要点击开始后才能进入游戏
    private ArrayList<Chess> list = new ArrayList<>();  //数组队列,存储Chess类型的对象

    /**
     * 获取窗体上画笔
     * */
    public void getGraphics(Graphics g){
        this.g = g;
    }


    /**
     * 将获得的数据数组传出
     * */
    public int[][] getChessNum(){
        return ChessNum;
    }


    /**
     * 传入主类
     * */
    public void getRenju(Renju renju){
        this.renju = renju;
    }


    /**
     * 对事务响应的整体框架
     * */
    @Override
    public void actionPerformed(ActionEvent e) {
      //详情见后文
    }


    /**
     * 悔棋
     * */
    public void regret(ArrayList list){
        //详情见后文
    }

    /**
     * 确定每次点击过开始后再进入游戏
     * */
    @Override
    public void mouseClicked(MouseEvent e) {
        x = e.getX();   //获取点击位置的x坐标
        y = e.getY();   //获取点击位置的y坐标
        if(startFlag == 1){
            //已点击过开始按键,进入了游戏
                this.man_VS_man();
        }else if(startFlag == 0){
            JOptionPane.showMessageDialog(renju,"请点击开始按键进行游戏!");
        }
    }

    /**
     * 双人对战
     * */
    public void man_VS_man(){
        //详情见后文
    }

    /**
     * 判断输赢方法
     * @param x 棋盘上x个交点的位置
     * @param y 棋盘上y个交点的位置
     * @return 返回棋子连在一起的个数
     * */
    public int CheckRow(int x, int y){
        int count1=0, count2=0, count3=0, count4=0, count=0;

        //判断某行是否连成五子
        for (int i = x+1; i < ChessNum.length; i++) {   //向左判断
            if(ChessNum[i][y] == ChessNum[x][y]){
                count1++;
            }else{
                break;
            }
        }
        for (int i = x; i >=0 ; i--) {  //向右判断
            if(ChessNum[i][y] == ChessNum[x][y]){
                count1++;
            }else{
                break;
            }
        }
        for (int i = y+1; i < ChessNum.length; i++) {   //向上判断
            if(ChessNum[x][i] == ChessNum[x][y]){
                count2++;
            }else{
                break;
            }
        }
        for (int i = y; i >=0; i--) {   //向下判断
            if(ChessNum[x][i] == ChessNum[x][y]){
                count2++;
            }else{
                break;
            }
        }
        int i,j;
        for (i = x, j = y; i >=0 && j>=0; i--,j--) {   //斜右下判断
            if(ChessNum[i][j] == ChessNum[x][y]){
                count3++;
            }else{
                break;
            }
        }
        for (i = x+1, j = y+1; i < ChessNum.length && j< ChessNum.length; i++,j++) {   //斜左上判断
            if(ChessNum[i][j] == ChessNum[x][y]){
                count3++;
            }else{
                break;
            }
        }
        for (i = x, j = y; i < ChessNum.length && j< ChessNum.length; i--,j++) {   //斜右上判断
            if(ChessNum[i][j] == ChessNum[x][y]){
                count4++;
            }else{
                break;
            }
        }
        for (i = x+1, j = y-1; i < ChessNum.length && j< ChessNum.length; i++,j--) {   //斜左下判断
            if(ChessNum[i][j] == ChessNum[x][y]){
                count4++;
//                System.out.println(count4);
            }else{
                break;
            }
        }
        if(count1==5 || count2==5 || count3==5 || count4==5){
            count =5;
        }
        return count;
    }

    /**
     * 重置棋盘棋子
     * */
    public void resetChess(){
        //遍历存储棋子信息的数组,重置为0
        for(int i=0; i<ChessNum.length ;i++){
            for(int j=0; j<ChessNum.length; j++){
                ChessNum[i][j]=0;
            }
        }
        countClick=0;   //将棋子黑白标志置为零
    }
}

  public void actionPerformed(ActionEvent e)方法详情,通过instanceof判断发生发生Event的对象是否是按键类型,经由getActionCommand()获取内容后赋值给com,比较按键文字内容与com信息,进行不同操作。

@Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() instanceof JButton) {
            com = e.getActionCommand();
            if ("开始".equals(com)) {
                startFlag = 1;
            } else if ("重新开始".equals(com)) {
                this.resetChess();  //清空棋子,重新开始
                renju.repaint();
                startFlag = 0;
            } else if ("认输".equals(com)) {
                if (countClick == 1) {
                    JOptionPane.showMessageDialog(renju, "白子认输,黑子胜利");
                    this.resetChess();  //清空棋子,重新开始
                    renju.repaint();
                    startFlag = 0;
                } else if (countClick == 0) {
                    JOptionPane.showMessageDialog(renju, "黑子认输,白子胜利");
                    this.resetChess();  //清空棋子,重新开始
                    renju.repaint();
                    startFlag = 0;
                }
            } else if ("悔棋".equals(com)) {
                this.regret(list);
            }
        }
    }

   public void regret(ArrayList list)方法详情如下,在list列表中存储着Chess类型的数据,是每一步棋对应的坐标,通过list.get(list.size()-1)获取列表末尾元素信息,将其行列信息赋给chess_row,chess_column,将其对应位置的ChessNum信息置为零(即消去最后一步下棋的信息)后重绘棋子,达成悔棋目的。

    public void regret(ArrayList list) {
        int chess_row, chess_column; //获取行列
        Chess temp = (Chess) list.get(list.size() - 1);
        chess_row = temp.getRow();
        chess_column = temp.getColumn();
        if (list.size() != 0) {
            list.remove(list.size() - 1);     //移除集合末尾元素(即最后一步的数据)
        }
        ChessNum[chess_row][chess_column] = 0;
        renju.repaint();
        this.draw(g);
    }

   public void man_VS_man()方法详情如下,Graphics2D类提供平面图形绘制,设置为抗锯齿后对棋盘信息进行遍历,当鼠标点击位置的坐标符合一定要求(确保棋子准确落子)后,通过判断countClick的奇偶性,来确定落子颜色,将对应信息存入ChessNum数组中(1为黑子,-1为白子),

    public void man_VS_man() {
        Graphics2D g2d = (Graphics2D) g;

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        //遍历整个棋盘的所有位置
        for (int i = 0; i < Line_Num; i++) {
            for (int j = 0; j < Line_Num; j++) {
                int x1 = Start_X + Size * i;    //计算棋盘上每个位置的x坐标
                int y1 = Start_Y + Size * j;    //计算棋盘上每个位置的y坐标

                //判断点击位置在棋盘的哪个点的范围
                if ((x > x1 - Chess_Size / 3 && x < x1 + Chess_Size / 3) && (y > y1 - Chess_Size / 3 && y < y1 + Chess_Size)) {

                    //判断点击次数的奇偶
                    if (ChessNum[i][j] == 0) {
                        countClick++;
                        if (countClick == 1) {
                            g2d.setColor(Color.BLACK);
                            ChessNum[i][j] = 1;   //存储黑子
                            list.add(new Chess(i, j));   //将黑子坐标存入集合

                            g2d.fillOval(Start_X + i * Size - Chess_Size / 2, Start_Y + j * Size - Chess_Size / 2, Chess_Size, Chess_Size);    //绘制棋子
                            stepFlag++;
                            if (this.CheckRow(i, j) == 5) {
                                JOptionPane.showMessageDialog(renju, "黑子胜利");
                                this.resetChess();  //清空棋子,重新开始
                                renju.repaint();
                                startFlag = 0;
                            }
                        } else if (countClick == 2) {
                            g2d.setColor(Color.WHITE);
                            ChessNum[i][j] = -1;  //存储白子
                            list.add(new Chess(i, j));   //将白子坐标存入集合
                            g2d.fillOval(Start_X + i * Size - Chess_Size / 2, Start_Y + j * Size - Chess_Size / 2, Chess_Size, Chess_Size);    //绘制棋子
                            stepFlag++;
                            if (this.CheckRow(i, j) == 5) {
                                JOptionPane.showMessageDialog(renju, "白子胜利");
                                this.resetChess();  //清空棋子,重新开始
                                renju.repaint();
                                startFlag = 0;
                            }
                        }
                    }
                }
                countClick = countClick % 2;
            }
        }
    }

  在Renju.java类中完成了对组件的创建与布局,代码详情如下:

import javax.swing.*;
import java.awt.*;

public class Renju extends JPanel implements Config {
    private static final long serialVersionUID =1L;
    private int[][] chessarray; //存储棋子数据的数组
    private RenjuListener listener = new RenjuListener();   //创建监听器

    public void init(){
        JFrame frame = new JFrame();    //实例化窗体对象
        frame.setSize(800,700); //设置窗体大小
        frame.setLocationRelativeTo(null); //设置窗体居中
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);  //设置关闭时类型为退出程序
        frame.setTitle("五子棋");

        BorderLayout layout = new BorderLayout();   //设置布局样式
        frame.setLayout(layout);

        this.centerPanel(frame);    //设置棋盘面板
        this.eastPanel(frame);  //创建功能面板

        this.addMouseListener(listener);//设置鼠标监听事件

        frame.setVisible(true); //设置为显示窗体,可见
        Graphics g = this.getGraphics();//获取画图对象
        listener.getGraphics(g);    //将画笔传输至监听器

        chessarray = listener.getChessNum(); //获取棋子信息——颜色,坐标
        listener.getRenju(this);
    }

    /**
     * 创建棋盘面板,居中
     * */
    public void centerPanel(JFrame jf){
        this.setBackground(Color.yellow);   //设置面板背景色
        jf.add(this,BorderLayout.CENTER);   //设置窗体为边框布局,将主面板加入窗体展示,居中
    }
    /**
     * 创建功能面板,居右
     * */
    public void eastPanel(JFrame jf){
        JPanel eastPanel = new JPanel(); //创建窗体
        eastPanel.setBackground(Color.blue); //设置背景色
        eastPanel.setPreferredSize(new Dimension(160,100));//设置面板大小

        jf.add(eastPanel,BorderLayout.EAST);//将面板加入窗体,居右(位东)

        String[] ButtonArray={"开始","重新开始","认输","悔棋"};
        Dimension buttonsize = new Dimension(100,100);
        for(int i=0; i<ButtonArray.length; i++){ //循坏添加按键
            JButton button = new JButton(ButtonArray[i]);   //设定按键信息
            button.setPreferredSize(buttonsize);    //设置按键大小
            eastPanel.add(button);  //将按键添加至面板
            button.addActionListener(listener); //添加监听器
        }
    }


    public void paint(Graphics g){
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;    //类型转化为Graphic2D,
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        //绘制棋盘
        for(int i=0; i<Line_Num; i++){
            g2d.drawLine(Start_X, Start_Y+i *Size, Start_X+ (Line_Num - 1) * Size, Start_Y + i * Size);  //绘制行
            g2d.drawLine(Start_X + i * Size, Start_Y, Start_X + i * Size, Start_Y + (Line_Num-1) * Size); //绘制列
        }
        //重绘棋子
        for(int r=0; r< Line_Num; r++){
            for(int c=0; c<Line_Num; c++){
                if(chessarray[r][c]!=0){
                    if(chessarray[r][c]==1){  //落黑子
                        g2d.setColor(Color.BLACK);
                        //绘制圆
                        g2d.fillOval(Start_X + r * Size - Chess_Size/2, Start_Y + c * Size - Chess_Size/2, Chess_Size, Chess_Size);
                    }
                    if(chessarray[r][c]==-1){  //落白子
                        g2d.setColor(Color.WHITE);
                        g2d.fillOval(Start_X + r * Size - Chess_Size/2, Start_Y + c * Size - Chess_Size/2, Chess_Size, Chess_Size);
                    }
                }
            }
        }
    }
}

  上述代码段中运用了基础GUI知识,将组件添加至窗体进行展示,不在过多阐述。

  主类代码段如下:

public class Show {
    public static void main(String[] args){
        Renju r =new Renju();
        r.init();
    }
}

  以上就是本次五子棋制作的整体方式,感谢大家的浏览。(我承认很多东西我是懒得说了,这篇文章写出来就是来玩的,溜了溜了,各位,有缘江湖再见)

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个简单的 Java 五子棋游戏示例,供参考: ```java import java.util.Scanner; public class Gomoku { private static final int ROWS = 15; private static final int COLS = 15; private static final int EMPTY = 0; private static final int BLACK = 1; private static final int WHITE = 2; private int[][] board = new int[ROWS][COLS]; private int player = BLACK; public void start() { Scanner scanner = new Scanner(System.in); while (true) { // 打印棋盘 printBoard(); // 获取玩家输入的坐标 System.out.print("请玩家 " + player + " 输入坐标,格式为 行 列:"); int row = scanner.nextInt(); int col = scanner.nextInt(); // 判断是否落子成功 if (placePiece(row, col)) { // 判断是否获胜 if (checkWin(row, col)) { System.out.println("玩家 " + player + " 获胜!"); printBoard(); break; } // 切换玩家 player = (player == BLACK) ? WHITE : BLACK; } else { System.out.println("该位置已经有子,请重新输入!"); } } } // 打印棋盘 private void printBoard() { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { System.out.print(board[i][j] + " "); } System.out.println(); } } // 落子 private boolean placePiece(int row, int col) { if (board[row][col] == EMPTY) { board[row][col] = player; return true; } else { return false; } } // 判断是否获胜 private boolean checkWin(int row, int col) { int count = 1; // 横向 for (int i = col - 1; i >= 0; i--) { if (board[row][i] == player) { count++; } else { break; } } for (int i = col + 1; i < COLS; i++) { if (board[row][i] == player) { count++; } else { break; } } if (count >= 5) { return true; } // 纵向 count = 1; for (int i = row - 1; i >= 0; i--) { if (board[i][col] == player) { count++; } else { break; } } for (int i = row + 1; i < ROWS; i++) { if (board[i][col] == player) { count++; } else { break; } } if (count >= 5) { return true; } // 左上右下斜线 count = 1; for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { if (board[i][j] == player) { count++; } else { break; } } for (int i = row + 1, j = col + 1; i < ROWS && j < COLS; i++, j++) { if (board[i][j] == player) { count++; } else { break; } } if (count >= 5) { return true; } // 右上左下斜线 count = 1; for (int i = row - 1, j = col + 1; i >= 0 && j < COLS; i--, j++) { if (board[i][j] == player) { count++; } else { break; } } for (int i = row + 1, j = col - 1; i < ROWS && j >= 0; i++, j--) { if (board[i][j] == player) { count++; } else { break; } } if (count >= 5) { return true; } // 没有获胜 return false; } public static void main(String[] args) { Gomoku game = new Gomoku(); game.start(); } } ``` 这个示例使用了一个二维数组来表示棋盘,玩家输入坐标后,通过 `placePiece` 方法把棋子放到相应的位置上,然后判断是否获胜,如果获胜就结束游戏,否则切换玩家。`checkWin` 方法实现了判断是否获胜的逻辑,通过遍历棋盘上的位置,计算横向、纵向和斜线方向上是否有连续的五个相同颜色的棋子。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿飞不想学习

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

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

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

打赏作者

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

抵扣说明:

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

余额充值