五子棋

  • 功能分析
    • 界面绘制
    • 下棋策略
    • 胜负判定
    • 棋局录制与回放
    • 悔棋
  • 功能实现
    • 界面绘制与更新
    • 胜负判定策略
    • 回放
    • 悔棋
  • 项目优化
    • 界面重构时棋盘闪烁问题解决方案
  • 整体展示
    • 界面展示
    • 代码

功能分析

界面绘制

界面分为棋盘区域按键面板

  • 整体界面为1500×1000
  • 棋盘区域背景色为浅灰色,棋盘为21×21大小间隔45个像素点,放置在左侧
  • 按键面板背景色为白色,大小为500×1000,共放置5个按键“开始游戏悔棋认输回放退出游戏

下棋策略

  • 棋子放置在棋盘线的交汇点上
  • 黑白交替下棋

胜负判定

  • 每下颗棋子后进行胜负判定
  • 输出胜负信息

棋局录制与回放

  • 回放下棋过程的每一步,并间隔一段时间

悔棋

  • 撤销最新下的棋子

功能实现

界面绘制与更新

  • 继承JFrame类,重写paint方法。在paint方法中绘制棋盘
    棋盘从(50,50)到(950,950)像素坐标;间隔45个像素坐标;一共21根线
@Overridepublic void paint(Graphics g) {super.paint(g);g.setColor(Color.black);for (int i = 0; i <= 20; i++) {//画横线g.drawLine(50, 50 + i*45, 950, 50 + i*45);//画竖线g.drawLine(50 + i*45, 50, 50 + i*45, 950);}}
  • 棋子绘制与更新
    棋子分为白色和黑色两种,如何使其看起来立体,需要控制同心圆颜色的变化
    黑色棋子RGB值变化:0~200;
    白色棋子RGB值变化:205~255;
public static void drawpiece (int x, int y, int color){for (int i = 0; i < 40; i++) {if (color == 1){//黑色g.setColor(new Color(i*5, i*5, i*5));}else if (color == 2){//白色g.setColor(new Color(205+i,205+i ,205+i));}g.fillOval(x + i/2, y + i/2, 40-i, 40-i);}}

棋子更新使用update方法绘制棋子,在画面更新或者回放时调用
本案例使用列表储存坐标点使其包含时间顺序
回放模式加入500ms的停顿,回放会更加清晰每一子的情况

@Overridepublic void update(Graphics g) {super.update(g);for (int i = 0; i < Pieces.num; i++) {if (Gobang_Listerner.name.equals("回放")){try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}Gobang_Listerner.drawpiece(Gobang_Listerner.pieces[i].x - 20, Gobang_Listerner.pieces[i].y - 20, Gobang_Listerner.pieces[i].color);}}

胜负判定策略

每下一个棋子都应该进行胜负判定。策略如图所示,寻找一条直线上的五个棋子
实现的过程需要一个二维数组,将其初始化为全0;黑色棋子存为1;白色棋子存为2;

回放

回放的功能主要是把棋子的时间顺序记录下来,然后按照时间先后重新绘制在棋盘上

悔棋

删除最新下的一颗棋子;需要注意的问题是,除了在棋子列表,还需要修改二维数组以及棋子颜色

if (Pieces.num > 0) {color_flag = !color_flag;Piece_x.remove(Pieces.num - 1);Piece_y.remove(Pieces.num - 1);piece_coordinates[x/45 - 1][y/45 - 1] = 0;Pieces.num--;jf.update(g);
}
else {System.err.println("不能撤销");
}

项目优化

界面重构时棋盘闪烁问题解决方案

在更新界面的时候我们通常会使用repaint方法,但是repaint方法会把paint方法重新调用,这使得棋盘和棋子都重新绘制了一遍,因此造成了画面闪烁。
解决办法如下:将棋盘绘制与棋子绘制进行分开,当程序需要对界面上的棋子进行重绘的时候调用update方法而并非使用repaint。

整体展示

界面展示


代码

  • GobangUI
package Gobang;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;public class GobangUI extends JFrame{public static void main(String[] args) {GobangUI go = new GobangUI();go.initUI();}public void initUI() {JFrame jf = this;jf.setTitle("五子棋");jf.setSize(1500, 1000);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setBackground(Color.LIGHT_GRAY);Gobang_Listerner gl = new Gobang_Listerner();JPanel bt_panel = new JPanel();bt_panel.setBackground(Color.WHITE);init_bt_panel(bt_panel, gl);jf.add(bt_panel, BorderLayout.EAST);jf.setVisible(true);gl.setJf(jf);jf.addMouseListener(gl);jf.addMouseMotionListener(gl);Gobang_Listerner.g = jf.getGraphics();}public void init_bt_panel(JPanel bt_panel, ActionListener actionListener) {Dimension dimension = new Dimension(500, 1000);bt_panel.setPreferredSize(dimension);bt_panel.setLayout(new FlowLayout());String[] strs = {"开始游戏","悔棋","认输","回放","退出游戏"};Dimension bt_dimension = new Dimension(250, 45);for (String str : strs) {JButton btn = new JButton(str);btn.setBackground(Color.WHITE);btn.setPreferredSize(bt_dimension);btn.addActionListener(actionListener);bt_panel.add(btn, BorderLayout.CENTER);}}@Overridepublic void paint(Graphics g) {super.paint(g);g.setColor(Color.black);for (int i = 0; i <= 20; i++) {//画横线g.drawLine(50, 50 + i*45, 950, 50 + i*45);//画竖线g.drawLine(50 + i*45, 50, 50 + i*45, 950);}}@Overridepublic void update(Graphics g) {super.update(g);for (int i = 0; i < Pieces.num; i++) {if (Gobang_Listerner.name.equals("回放")){try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}Gobang_Listener.drawpiece(Gobang_Listener.pieces[i].x - 20, Gobang_Listener.pieces[i].y - 20, Gobang_Listener.pieces[i].color);}}
}
  • Gobang_Listener
package Gobang;import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;public class Gobang_Listener implements MouseListener, ActionListener, MouseMotionListener {JFrame jf;static Graphics g;boolean repetition_flag = false;boolean color_flag = false;int color = 0;static String name = "a";int x, y;ArrayList<Integer> Piece_x = new ArrayList<>();ArrayList<Integer> Piece_y = new ArrayList<>();int[][] piece_coordinates = new int[21][21];static Pieces[] pieces = new Pieces[441];public Gobang_Listener(){for (int i = 0; i < 441; i++) {pieces[i] = new Pieces();}}public void setJf(JFrame jf) {this.jf = jf;}public boolean Victory(int x, int y, int color){boolean victory = false;int index_x = x/45 - 1;int index_y = y/45 - 1;int i = 1;int num = 1;boolean disconnect_L = false;boolean disconnect_R = false;boolean disconnect_U = false;boolean disconnect_D = false;//左-右while (i < 5) {if (index_x - i >= 0 && disconnect_L == false) {if (piece_coordinates[index_x - i][index_y] == color) {num++;}else {disconnect_L = true;}}if (index_x + i <= 20 && disconnect_R == false) {if (piece_coordinates[index_x + i][index_y] == color) {num++;}else {disconnect_R = true;}}if (num == 5) {victory = true;break;} else {i++;}}//上-下if (!victory) {i  = 1;num = 1;while (i < 5) {if (index_y - i >= 0 && !disconnect_U) {if (piece_coordinates[index_x][index_y - i] == color) {num++;}else {disconnect_U = true;}}if (index_y + i <= 20 && !disconnect_D) {if (piece_coordinates[index_x][index_y + i] == color) {num++;}else {disconnect_D = true;}}if (num == 5) {victory = true;break;} else {i++;}}}//左下-右上if (!victory) {i  = 1;num = 1;disconnect_L = false;disconnect_R = false;while (i < 5) {if (index_x - i >= 0 && index_y + i <= 20 && !disconnect_L) {if (piece_coordinates[index_x - i][index_y + i] == color) {num++;}else {disconnect_L = true;}}if (index_x + i <= 20 && index_y - i >= 0 && !disconnect_R) {if (piece_coordinates[index_x + i][index_y - i] == color) {num++;}else{disconnect_R = true;}}if (num == 5) {victory = true;break;} else {i++;}}}//左上-右下if (!victory) {i  = 1;num = 1;disconnect_L = false;disconnect_R = false;while (i < 5) {if (index_x - i >= 0 && index_y - i >= 0 && !disconnect_L) {if (piece_coordinates[index_x - i][index_y - i] == color) {num++;}else {disconnect_L = true;}}if (index_x + i <= 20 && index_y + i <= 20 && !disconnect_R) {if (piece_coordinates[index_x + i][index_y + i] == color) {num++;}else{disconnect_R = true;}}if (num == 5) {victory = true;break;} else {i++;}}}return victory;}@Overridepublic void mouseClicked(MouseEvent e) {x = e.getX();y = e.getY();if (x >= 50 && x <= 950 && y >= 50 && y <= 950){for (int i = 50; i < 950; i = i+45) {if (x >= i && x <= i + 45){if (x - i > i + 45 - x){x = i + 45;}else {x = i;}}if (y > i && y < i + 45){if (y - i > i + 45 - y){y = i + 45;}else {y = i;}}}if (Piece_x.isEmpty()) {repetition_flag = false;}else{for (int i = 0; i < Piece_x.size(); i++) {if (Piece_x.get(i) == x/45 && Piece_y.get(i) == y/45){repetition_flag = true;break;}if (Piece_x.get(i) != x/45 && Piece_y.get(i) != y/45){repetition_flag = false;}}}if (repetition_flag){System.err.println("重复下子");}else {color_flag = !color_flag;if (color_flag){color = 1;}else {color = 2;}Piece_x.add(x/45);Piece_y.add(y/45);piece_coordinates[x/45 - 1][y/45 - 1] = color;drawpiece(x-20, y-20, color);boolean victor = Victory(x, y, color);System.out.println(victor);if (victor){if (color == 1){JOptionPane.showMessageDialog(null, "恭喜黑子胜利");}else if (color == 2){JOptionPane.showMessageDialog(null, "恭喜白子胜利");}}pieces[Pieces.num].x = x;pieces[Pieces.num].y = y;pieces[Pieces.num].color = color;Pieces.num++;}}else {System.err.println("请在棋盘内下棋子!");}}@Overridepublic void mousePressed(MouseEvent e) {}@Overridepublic void mouseReleased(MouseEvent e) {}@Overridepublic void mouseEntered(MouseEvent e) {jf.update(g);}@Overridepublic void mouseExited(MouseEvent e) {}public static void drawpiece (int x, int y, int color){for (int i = 0; i < 40; i++) {if (color == 1){//黑色g.setColor(new Color(i*5, i*5, i*5));}else if (color == 2){//白色g.setColor(new Color(205+i,205+i ,205+i));}g.fillOval(x + i/2, y + i/2, 40-i, 40-i);}}@Overridepublic void actionPerformed(ActionEvent e) {name = e.getActionCommand();switch (name) {case ("开始游戏") -> {color_flag = false;Piece_x.clear();Piece_y.clear();Pieces.num = 0;for (int i = 0; i < 21; i++) {for (int j = 0; j < 21; j++){piece_coordinates[i][j] = 0;}}jf.update(g);}case ("退出游戏") -> {System.out.println("退出游戏");color_flag = false;Piece_x.clear();Piece_y.clear();Pieces.num = 0;for (int i = 0; i < 21; i++) {for (int j = 0; j < 21; j++){piece_coordinates[i][j] = 0;}}jf.setVisible(false);}case ("悔棋") -> {if (Pieces.num > 0) {color_flag = !color_flag;Piece_x.remove(Pieces.num - 1);Piece_y.remove(Pieces.num - 1);piece_coordinates[x/45 - 1][y/45 - 1] = 0;Pieces.num--;jf.update(g);}else {System.err.println("不能撤销");}}case ("回放") -> {jf.update(g);name = "a";}case ("认输") -> {if (color == 1) {JOptionPane.showMessageDialog(null, "恭喜黑子胜利");} else if (color == 2) {JOptionPane.showMessageDialog(null, "恭喜白子胜利");}}}}@Overridepublic void mouseDragged(MouseEvent e) {}@Overridepublic void mouseMoved(MouseEvent e) {}
}
  • Pieces
package Gobang;public class Pieces {int x;int y;int color;static int num = 0;
}

Java项目(五子棋)相关推荐

  1. Java Swing五子棋项目

    一.项目简介 本项目为Java Swing五子棋项目,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者. 包含:项目源码.数据库脚本等,该项目附带全部源码可作为毕设使用. 项 ...

  2. java技术分享主题_Java开发入门:适合新手练手的Java项目(附源码下载)

    Java作为一门古老的语言,已有20年左右的历史,这在发展日新月异的技术圈可以说是一个神话.虽然不少人曾抱怨Java语言就像老太太的裹脚布,又臭又长,有时写了500行都不能表达程序员的意图. 但从市场 ...

  3. 献给java初学者,非常适合新手练习的Java项目

    Java作为一门古老的语言,已有20年左右的历史,这在发展日新月异的技术圈可以说是一个神话.虽然不少人曾抱怨Java语言就像老太太的裹脚布,又臭又长,有时写了500行都不能表达程序员的意图. 但从市场 ...

  4. java 适合练手的java项目

    Java作为一门古老的语言,已有20年左右的历史,这在发展日新月异的技术圈可以说是一个神话. 虽然不少人曾抱怨Java语言就像老太太的裹脚布,又臭又长,有时写了500行都不能表达程序员的意图. 但从市 ...

  5. Java——一些适合新手练手的Java项目

    转载自 https://blog.csdn.net/luolianxi/article/details/77924728 Java作为一门古老的语言,已有20年左右的历史,这在发展日新月异的技术圈可以 ...

  6. Java【有哪些适合新手练手的Java项目?】

    Java作为一门古老的语言,已有20年左右的历史,这在发展日新月异的技术圈可以说是一个神话. 虽然不少人曾抱怨Java语言就像老太太的裹脚布,又臭又长,有时写了500行都不能表达程序员的意图. 但从市 ...

  7. java设计五子棋_JAVA 五子棋设计

    学习JAVA以来,这也算做的第一个小项目吧.下面来讲解具体的使用JAVA实现五子棋的过程.(所有功能实现之后我重新写了一个开始界面,这里就只介绍主要的实现步骤了) 1.游戏界面的实现 思路是:定义一个 ...

  8. 实战突击JAVA开发项目_《实战突击Java项目开发案列整合》随书资料(视频+源码)_源雷技术空间...

    资源名称:<实战突击Java项目开发案列整合>随书资料(视频+源码) 资源目录: [IT教程网]第1-9_11-15_18_20_21章 [IT教程网]第10章BBS论坛 [IT教程网]第 ...

  9. Java实现五子棋(附详细源码)

    这篇文章主要为大家详细介绍了Java实现五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 五子棋是一种两人对弈的纯策略型棋类游戏,棋具与围棋通用,是起源于中国古 ...

  10. github javaguide_GitHub上收获Star数排名前10的Java项目

    1. CS-Notes star:92.1k 介绍:技术面试必备基础知识.Leetcode.计算机操作系统.计算机网络.系统设计.Java.Python.C++ :地址:https://cyc2018 ...

最新文章

  1. provide和inject,Vue父组件直接给孙子组件传值
  2. 博客堂也遇DotText经典Exception
  3. iphone objective-c内存管理
  4. matlab 寻找二进制图像边缘
  5. 从SOURCE_BUFFER单元开始存放了20个字母A, 编程将这20个字母A的字符串传送到DEST_BUFFER开始的单元中.
  6. Android 4.4(KitKat)表格管理子系统 - 骨架
  7. 用户画像_什么是“用户画像”?如何利用用户画像进行精准营销?
  8. Halcon—Tuple中符号的含义
  9. linux的vim多选择,真的有(很多)linux大牛用vim写项目吗?
  10. cad vba编程从入门到精通_【CAD教程】CAD2020零基础入门到精通全套视频教程
  11. 现货!《PHP7实践指南:o2o网站与App后台开发》京东天猫有售
  12. pd虚拟机镜像:懒人一键安装win10、11
  13. supervisord的安装
  14. java环境变量的设置方法_Java环境变量配置方法详解
  15. 翻译:Towards Lingua Franca Named Entity Recognition with BERT(基于BERT的通用语命名实体识别)
  16. 异速联服务器配置系统管理员,异速联V6.2.4.0正式版全新发布
  17. 富人们赚到的人生第一桶金
  18. 台式计算机麦说不了话,耳机有声音麦克风没声音怎么办?解决电脑耳机有声音麦不能说话...
  19. java 163邮箱发邮件_java用163邮箱发邮件的方式,步骤有哪些?
  20. Java mybatis-plus详解

热门文章

  1. 简单计算器代码(含加减乘除取余5个操作)
  2. QT ——添加多国语言
  3. VMware centos7镜像安装详细步骤
  4. C语言的输出对齐应用
  5. 页面中文乱码,tomcat服务器,jsp乱码
  6. fanuc换刀宏程序详解_FANUC宏程序入门到精通,新手必看
  7. 一个PHP的QRcode类,与大家分享
  8. JAVA入门教程-专题视频课程
  9. Java高并发编程实战1,那些年学过的锁
  10. Nanohttpd 异常 Explicit termination medthod 'end' not called 解决方法