Java Swing五子棋项目

简介: Java Swing五子棋项目

一、项目简介

本项目为Java Swing五子棋项目,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。

包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。

项目都经过严格调试,eclipse 确保可以运行!

该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值

二、技术实现

后端:java,面向对象,swing编程和ImageIO类。

运行环境及开发工具:jdk,idea或者eclipse

三、功能描述

Java五子棋项目

该项目主要使用到了swing编程和ImageIO类。

  • 游戏开始:清空棋盘,重新绘图
  • 游戏设置:设置倒计时
  • 游戏说明:说明游戏规则
  • 认输:某一方放弃游戏,另一方直接获胜
  • 引入背景音乐功能:可以引入音频文件
  • 关于:显示程序的作者、版本等
  • 退出:结束程序

##五子棋游戏的功能##

  1. 用户点击鼠标时,将棋子渲染到相应的位置;
  2. 自动判断游戏是否结束。
  3. 对游戏时间进行设置,判断是否超出规定时间。

实现步骤

  1. 渲染游戏界面(swing)。新建一个类FiveCheeseFrame继承JFrame并实现MouseListener接口。在构造方法中初始化界面(大小、位置等)。
  2. 在鼠标事件的mouseClick()方法中响应相关事件。
  3. 为了实现倒计时,需要单独引入一个线程。

该游戏的难点:

1.如何让游戏界面居中显示?

获取屏幕的宽高和游戏的宽高。设置显示位置为屏幕的宽高减去游戏的宽高除以2就行了。

// 取得屏幕的宽高
int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
System.out.println("屏幕的尺寸是:" + screenWidth + "*" + screenHeight);
// 设置游戏界面居中显示,jf是自定义的窗体类,继承自JFrame
jf.setLocation((screenWidth - WIDTH) / 2, (screenHeight - HEIGHT) / 2);

2.在鼠标点击的位置显示棋子?

MouseEvent的getX()getY()方法可以获得点击的位置。黑子可以用实心的黑圆表示,白字可以用空心黑圆+实心白圆表示。Graphics类的drawOval()fillOval()方法。

3.之前下过的棋子的位置如何保存?

通过19*19的二维数组allChess保存每个交叉点的状态(黑子(填充1)、白子(填充2)、无子(填充0))。

4.在窗口中绘制网格和图像

Graphics类,类似画笔,可以在窗口中绘制文字和图像。通过覆写JFrame中的paint()方法来使用,通过repaint()方法(表示重新执行一次paint方法)来调用。

Graphics g;
BufferedImage image;
try {
  image = ImageIO.read(new File("images/title.jpg")); //解决窗体透明问题只需要在窗体中绘制一张图片,在此基础上绘制其他
  g.drawImage(image, 20, 40,this);
} catch (IOException e) {
  e.printStackTrace();
}

5.如何让棋子对齐到十字线?

棋盘绘制完成后,实际上就建立了如下的一个坐标轴为0~18的坐标系坐标系。

对于每一个鼠标点击的点,我们可以取离鼠标点击位置最近的点。关键就是得到0~18的整数。将大坐标转换为小坐标。

思考

每个单元格是25*25像素,我们惠子棋盘的时候采用的是for循环。

for (int i = 0; i < 19; i++) {
  g.drawLine(15, 70 + 25 * i, 465, 70 + 25 * i); // 绘制横线
  g.drawLine(15 + 25 * i, 70, 15 + 25 * i, 520);// 绘制竖线
}

我们通过鼠标监听器得到点击位置的坐标,然后分别减去起始位置,再除以25,就可以得到一个0~18的数,然后通过这个数字,就可以让其精确对准棋盘。

x = e.getX(); // 得到鼠标的点击位置
y = e.getY();
x = (x - 15) / 25; // 得到最近的十字点,可以先得到0~18的整数,然后通过这个整数乘以每行的间距完成
y = (y - 70) / 25;

6.如何判断游戏胜负?

依据:五子棋的游戏规则:是否有同一种颜色的棋子连成5个。判断当前棋子周围是否有5个连续一样棋子——一共需要判断4种情况:水平方向、垂直方向和两条对角线的方向。其中每一种情况又需要判断两次,例如水平方向需要从左向右和从右向左进行判断。

首先得到当前的棋子的颜色color即二维数组allCheese[x][y]

水平方向:y坐标不变,x坐标每次增加1或者减去1.

// 横向判断
int i = 1;
while (color==allChess[x+i][y]) { // 向右判断
  count++;
  i++;
}
i = 1; // i归位,特别注意这里
while (color == allChess[x-i][y]) { // 向左判断
  count++;
  i++;
}
if (count >= 5) {
  flag = true; // flag表示是否有5子相连
}

同理,垂直方向仅仅是x坐标不变,y的坐标每次加1,减1。和上面的算法几乎一样

左上-右下方向:如果判断方向是“左上—>右下”,则x和y的坐标每次都加1;如果从右下判断到左上,则x和y的坐标每次加1,这里同样要注意变量i要复位。

// 左下-右上判断
int i3 = 1;
int count3 = 1;
while (color==allChess[x+i3][y-i3]) { // 左下--->右上---> allChess[x+i3][y-i3]
  count3++;
  i3++;
}
i3 = 1; // i3归位
while (color == allChess[x-i3][y+i3]) { // 右上--->左下---> allChess[x-i3][y+i3]
  count3++;
  i3++;
}
if (count3 >= 5) {
  flag = true;
}

右上-左下方向的判断和左上-右下的判断类似,只是x,y的变化是异号的。

思考

上面的4个方向的算法大体类似,我们可以将其抽象为一个方法。观察到以上4方向上的算法的不同之处就是x坐标和y轴的变化率,同时它们都需要判断当前棋子的颜色color,得到当前相同棋子相连的最大数count,将算法加以抽象得到如下的方法:

/**
 * 得到相同的棋子连接的数量,由上面的4次判断抽象出来的
 * @param xChange:x的变化
 * @param yChange:y的变化
 * @param color:当前棋子状态(黑?白)
 * @return
 */
private int checkCount(int xChange,int yChange,int color){
  int count = 1;
  int tempX = xChange, tempY = yChange; // 保存传过来的xChange和yChange,复位的时候需要用到
  // 首先要检查数组下标是否越界
  while (x + xChange >= 0 && x + xChange <= 18 && y + yChange >= 0 && y + yChange <= 18 && color == allChess[x + xChange][y + yChange]) {
    count++;
    if (xChange != 0) {
      xChange++;
    }
    if (yChange != 0) {
      if (yChange > 0) {
        yChange++;
      }else {
        yChange--;
      }
    }
  }
  xChange = tempX; // 复位
  yChange = tempY;
  // 首先要检查数组下标是否越界
  while (x - xChange >= 0 && x - xChange <= 18 && y - yChange >= 0 && y - yChange <= 18 && color == allChess[x - xChange][y - yChange]) {
    count++;
    if (xChange != 0) {
      xChange++;
    }
    if (yChange != 0) {
      if (yChange > 0) {
        yChange++;
      }else {
        yChange--;
      }
    }
  }
  return count;
}

得到棋子数只需要这样调用以上的方法:

/* 判断4个方向上的棋子数,判断的顺序不重要 */
count = checkCount(1, 0, color); // 横向的棋子数
if (count >= 5) {
  flag = true;
}else {
  count = checkCount(0, 1, color); // 纵向的棋子数
  if (count >= 5) {
    flag = true;
  }else {
    count = checkCount(1, -1, color); // 左下-右上的棋子数
    if (count >= 5) {
      flag = true;
    }else{
      count = checkCount(1, 1, color); // 左上-右下的棋子数
      if (count >= 5) {
        flag = true;
      }
    }
  }
}

7. 如何设置倒计时##

让窗体类实现Runnable接口,在构造方法中启动线程,并将其挂起。因为游戏刚刚启动的时候并不需要倒计时,只需要用户点击设置游戏时间之后倒计时才开始生效。声明两个全局变量blackTimewhiteTime分别保存黑方和白方额度剩余时间(初始值为0)。用户点击”游戏设置“按钮后,将时间赋值给这两个变量,重新开始游戏(清空棋盘),并将挂起的线程恢复(resume()方法)。在run()方法中首先判断是否有时间的限制,再进一步判断,当前棋子的状态,给对应的时间每隔1秒减去1,当时间变为0的时候,给用户提示,显示输赢信息,并设置不能够再次下棋。需要将时间同步显示到界面。

8.背景音乐的控制

新引入一个背景音乐的线程,在主界面渲染(窗体的构造方法中)的时候启动线程。引入一个全局变量布尔控制背景音乐的开关,当用户点击音乐的时候改变状态,并将背景音乐挂起或者恢复。

四、界面截图

五、源码地址

https://download.csdn.net/download/weixin_43860634/87364581


相关文章
|
1月前
|
JavaScript NoSQL Java
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
186 96
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
|
6天前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
58 23
|
1月前
|
前端开发 JavaScript Java
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
131 13
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
|
1月前
|
人工智能 JavaScript 关系型数据库
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
99 14
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
|
1月前
|
SQL JavaScript 安全
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
87 11
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
|
1月前
|
人工智能 JavaScript 安全
【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
108 13
【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
|
1月前
|
网络协议 Java Shell
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
73 7
|
Java
编写Java程序,模拟五子棋博弈过程中的异常声明和异常抛出
编写Java程序,模拟五子棋博弈过程中的异常声明和异常抛出
245 0
编写Java程序,模拟五子棋博弈过程中的异常声明和异常抛出
|
17天前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
142 60
【Java并发】【线程池】带你从0-1入门线程池
|
13天前
|
Java 调度
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
当我们创建一个`ThreadPoolExecutor`的时候,你是否会好奇🤔,它到底发生了什么?比如:我传的拒绝策略、线程工厂是啥时候被使用的? 核心线程数是个啥?最大线程数和它又有什么关系?线程池,它是怎么调度,我们传入的线程?...不要着急,小手手点上关注、点赞、收藏。主播马上从源码的角度带你们探索神秘线程池的世界...
81 0
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码

热门文章

最新文章