【Java GUI】人机对弈五子棋

在学校的Java课程中,我们被分配了一项有趣的任务:开发一款能够实现人机对弈的五子棋游戏。为了更好地理解Java GUI的运用,并与大家分享学习心得,我将整个开发过程记录在这篇博客中。欢迎大家阅读并提供宝贵的意见和建议!"

python版五子棋(讲解的更详细) 

1.绘制棋盘

1.定义myPanel类。

myPanel相当于画板。

myPanel要继承 JPanel类,并要覆盖父类的paint方法,在paint方法里面写负责绘画的代码


public class myPanel extends JPanel {static final int start = 6;@Overridepublic void paint(Graphics g){//调用父类的paint初始化画笔super.paint(g);//绘制背景DrawBackground(g);//绘制外边框DrawBorder(g);//绘制棋盘DrawChessBoard(g);}public void DrawBackground(Graphics g){    //绘制背景g.setColor(new Color(211, 152, 91));g.fillRect(0, 0, 620,620);}public void DrawBorder(Graphics g){//绘制外边框g.setColor(Color.BLACK);g.fillRect(5,5,610,5);g.fillRect(610,5,5,610);g.fillRect(5,610,610,5);g.fillRect(5,5,5,610);}public void DrawChessBoard(Graphics g){g.setColor(Color.BLACK);//画横线for (int i = 0; i < 19; i++) {g.drawLine(6+i*32,6,6+i*32,614);}//画竖线for (int i = 0; i < 19; i++) {g.drawLine(6,6+i*32,614,6+i*32);}}//画棋子public void DrawChess(Graphics g,int x,int y,int  type){switch (type){case 1:g.setColor(Color.BLACK);break;case 2:g.setColor(Color.WHITE);}g.fillOval(x*32+start,y*32+start,30,30);}}
2.定义myFrame类。

myFrame相当于窗口,画板要放在窗口里。

myFram要继承 JFram类,在初始化函数设置窗口参数


public class MyFrame extends JFrame {myPanel mp  = null;public MyFrame() {mp = new myPanel();this.setTitle("五子棋");this.setSize(620, 620);//添加画板this.add(mp);//点击窗口叉叉退出程序this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);}static public void main(String[] args) {MyFrame mf = new MyFrame();}
}

2.核心功能

1.实现下棋功能

 1.定义相关变量

    //偏移量static final int IndexOffset = -10;static final int ChessOffset = -10;//黑子下棋标记static boolean black = true;boolean gameIsOver = false;int chess[][]=new int[19][19];

2.添加事件监听

myPanel实现 MouseListener接口

重写mouseClicked方法

    @Overridepublic void mouseClicked(MouseEvent e) {//计算棋子坐标//# 0表示空棋//# 1表示黑棋//# 2表示白棋int x = (e.getX() - IndexOffset) / 32;int y = (e.getY() - 32 - IndexOffset) / 32;System.out.println(y);chess[x][y] = 1;this.repaint();}

myFrame添加事件监听

    public MyFrame() {mp = new myPanel();this.setTitle("五子棋");this.setSize(620, 620);//添加画板this.add(mp);//点击窗口叉叉退出程序this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.addMouseListener(mp);this.setVisible(true);}
2.实现自动下棋

1.按照优先级从高到低枚举出所有情况


//# 0表示空棋
//# 1表示黑棋
//# 2表示白棋
//# 3表示下棋的位置private static final int[][] cdata = {{3, 1, 1, 1, 1}, {1, 3, 1, 1, 1}, {1, 1, 3, 1, 1}, {1, 1, 1, 3, 1}, {1, 1, 1, 1, 3},{2, 2, 3, 2, 2}, {2, 2, 2, 3, 2}, {2, 3, 2, 2, 2}, {3, 2, 2, 2, 2}, {2, 2, 2, 2, 3},{3, 1, 1, 1, 0}, {1, 1, 1, 3, 0}, {1, 1, 3, 1, 0}, {1, 3, 1, 1, 0},{3, 2, 2, 2, 0}, {2, 3, 2, 2, 0}, {2, 2, 3, 2, 0}, {2, 2, 2, 3, 0},{1, 1, 3, 3, 0}, {3, 1, 1, 0, 0}, {0, 1, 3, 1, 0},{3, 2, 2, 0, 0}, {2, 2, 3, 0, 0}, {1, 3, 1, 0, 0},{3, 1, 0, 0, 0}, {1, 3, 0, 0, 0}};

2.选出最佳下棋位置 

    public Point getBestPoint() {//记录最低分(分值越低,优先级越高)int score = 100;//最佳位置Point point = new Point(0, 0);//每次都要遍历四个方向 左下 下 右下 右int[] dx = {-1, 0, 1, 1};int[] dy = {1, 1, 1, 0};for (int i = 0; i < 19; i++) {for (int j = 0; j < 19; j++) {for (int k = 0; k < 4; k++) {int cnt = 0;for (int[] e : cdata) {int m;int x = i;int y = j;int bestX = 0;int bestY = 0;for (m = 0; m < 5; m++) {if (e[m] == 3 && chess[x][y] == 0) {bestX = x;bestY = y;} else {if (chess[x][y] != e[m]) {break;}}x += dx[k];y += dy[k];if (x < 0 || x >= 19 || y < 0 || y >= 19) {break;}}if (m == 5) {if (cnt < score) {score = cnt;point.x = bestX;point.y = bestY;}break;}cnt++;}}}}if (score < 100) {return point;} else {int x = (int) (Math.random() * 19);int y = (int) (Math.random() * 19);while (chess[x][y] != 0) {x = (int) (Math.random() * 19);y = (int) (Math.random() * 19);}return new Point(x, y);}}
3.判断游戏是否结束

遍历棋盘

   public boolean check() {//每次都要遍历四个方向 左下 下 右下 右int[] dx = {-1, 0, 1, 1};int[] dy = {1, 1, 1, 0};for (int i = 0; i < 19; i++) {for (int j = 0; j < 19; j++) {for (int k = 0; k < 4; k++) {int x = i;int y = j;int m;boolean flag = true;for (m = 0; m < 4; m++) {int tx = x + dx[k];int ty = y + dy[k];if (tx < 0 || tx > 19 || ty < 0 || ty > 19) {flag = false;break;}if (chess[x][y] != chess[x + dx[k]][y + dy[k]]) {flag = false;break;} else if (chess[x][y] == 0) {flag = false;break;}x = tx;y = ty;}if (flag) {gameIsOver = true;return true;}}}}return false;}
4.事件循环
   @Overridepublic void paint(Graphics g) {//调用父类的paint初始化画笔super.paint(g);//绘制背景DrawBackground(g);//绘制外边框DrawBorder(g);//绘制棋盘DrawChessBoard(g);DrawChess(g);//开始游戏if (!gameIsOver)game();//游戏结束if (check()) {gameOver(g);}}

完整代码 

myPanel

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;/*** ** @author yuwei* @date 23:29 2024/4/23*/
public class myPanel extends JPanel implements MouseListener {//偏移量static final int IndexOffset = -10;static final int ChessOffset = -10;//黑子下棋标记static boolean black = true;boolean gameIsOver = false;//# 0表示空棋
//# 1表示黑棋
//# 2表示白棋
//# 3表示下棋的位置private static final int[][] cdata = {{3, 1, 1, 1, 1}, {1, 3, 1, 1, 1}, {1, 1, 3, 1, 1}, {1, 1, 1, 3, 1}, {1, 1, 1, 1, 3},{2, 2, 3, 2, 2}, {2, 2, 2, 3, 2}, {2, 3, 2, 2, 2}, {3, 2, 2, 2, 2}, {2, 2, 2, 2, 3},{3, 1, 1, 1, 0}, {1, 1, 1, 3, 0}, {1, 1, 3, 1, 0}, {1, 3, 1, 1, 0},{3, 2, 2, 2, 0}, {2, 3, 2, 2, 0}, {2, 2, 3, 2, 0}, {2, 2, 2, 3, 0},{1, 1, 3, 3, 0}, {3, 1, 1, 0, 0}, {0, 1, 3, 1, 0},{3, 2, 2, 0, 0}, {2, 2, 3, 0, 0}, {1, 3, 1, 0, 0},{3, 1, 0, 0, 0}, {1, 3, 0, 0, 0}};int chess[][] = new int[20][20];@Overridepublic void paint(Graphics g) {//调用父类的paint初始化画笔super.paint(g);//绘制背景DrawBackground(g);//绘制外边框DrawBorder(g);//绘制棋盘DrawChessBoard(g);DrawChess(g);//开始游戏if (!gameIsOver)game();//游戏结束if (check()) {gameOver(g);}}public void gameOver(Graphics g) {Font font = new Font("Arial", Font.BOLD, 24);g.setColor(Color.red);g.setFont(font);g.drawString("游戏结束", 270, 270);}public void DrawBackground(Graphics g) {    //绘制背景g.setColor(new Color(211, 152, 91));g.fillRect(0, 0, 620, 620);}public void DrawBorder(Graphics g) {//绘制外边框g.setColor(Color.BLACK);g.fillRect(5, 5, 610, 5);g.fillRect(610, 5, 5, 610);g.fillRect(5, 610, 610, 5);g.fillRect(5, 5, 5, 610);}public void DrawChessBoard(Graphics g) {g.setColor(Color.BLACK);//画横线for (int i = 0; i < 19; i++) {g.drawLine(6 + i * 32, 6, 6 + i * 32, 614);}//画竖线for (int i = 0; i < 19; i++) {g.drawLine(6, 6 + i * 32, 614, 6 + i * 32);}}//画棋子public void DrawChess(Graphics g) {for (int i = 0; i < 19; i++) {for (int j = 0; j < 19; j++) {if (chess[i][j] == 1) {g.setColor(Color.BLACK);} else if (chess[i][j] == 2) {g.setColor(Color.WHITE);} else {continue;}g.fillOval(i * 32 + ChessOffset, j * 32 + ChessOffset, 30, 30);}}}public Point getBestPoint() {//记录最低分(分值越低,优先级越高)int score = 100;//最佳位置Point point = new Point(0, 0);//每次都要遍历四个方向 左下 下 右下 右int[] dx = {-1, 0, 1, 1};int[] dy = {1, 1, 1, 0};for (int i = 0; i < 19; i++) {for (int j = 0; j < 19; j++) {for (int k = 0; k < 4; k++) {int cnt = 0;for (int[] e : cdata) {int m;int x = i;int y = j;int bestX = 0;int bestY = 0;for (m = 0; m < 5; m++) {if (e[m] == 3 && chess[x][y] == 0) {bestX = x;bestY = y;} else {if (chess[x][y] != e[m]) {break;}}x += dx[k];y += dy[k];if (x < 0 || x >= 19 || y < 0 || y >= 19) {break;}}if (m == 5) {if (cnt < score) {score = cnt;point.x = bestX;point.y = bestY;}break;}cnt++;}}}}if (score < 100) {return point;} else {int x = (int) (Math.random() * 19);int y = (int) (Math.random() * 19);while (chess[x][y] != 0) {x = (int) (Math.random() * 19);y = (int) (Math.random() * 19);}return new Point(x, y);}}public boolean check() {//每次都要遍历四个方向 左下 下 右下 右int[] dx = {-1, 0, 1, 1};int[] dy = {1, 1, 1, 0};for (int i = 0; i < 19; i++) {for (int j = 0; j < 19; j++) {for (int k = 0; k < 4; k++) {int x = i;int y = j;int m;boolean flag = true;for (m = 0; m < 4; m++) {int tx = x + dx[k];int ty = y + dy[k];if (tx < 0 || tx > 19 || ty < 0 || ty > 19) {flag = false;break;}if (chess[x][y] != chess[x + dx[k]][y + dy[k]]) {flag = false;break;} else if (chess[x][y] == 0) {flag = false;break;}x = tx;y = ty;}if (flag) {gameIsOver = true;return true;}}}}return false;}public void game()  {if (check()) {return;}if (black) {Point point = getBestPoint();chess[point.x][point.y] = 1;black = false;this.repaint();}}@Overridepublic void mouseClicked(MouseEvent e) {//计算棋子坐标//# 0表示空棋//# 1表示黑棋//# 2表示白棋if (!black&&!gameIsOver) {int x = (e.getX() - IndexOffset) / 32;int y = (e.getY() - 32 - IndexOffset) / 32;chess[x][y] = 2;black = true;this.repaint();}}@Overridepublic void mousePressed(MouseEvent e) {}@Overridepublic void mouseReleased(MouseEvent e) {}@Overridepublic void mouseEntered(MouseEvent e) {}@Overridepublic void mouseExited(MouseEvent e) {}
}

myFrame

import javax.swing.*;/*** 用户服务** @author yuwei* @date 23:42 2024/4/23*/
public class MyFrame extends JFrame {myPanel mp  = null;public MyFrame() {mp = new myPanel();this.setTitle("五子棋");this.setSize(620, 620);//添加画板this.add(mp);//点击窗口叉叉退出程序this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.addMouseListener(mp);this.setVisible(true);}static public void main(String[] args) {MyFrame mf = new MyFrame();}
}

感谢阅读,希望本文对你有所帮助 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/3710.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序-------模板与配置

能够使用 WXML 模板语法渲染页面结构能够使用 WXSS 样式美化页面结构能够使用 app.json 对小程序进行全局性配置能够使用 page.json 对小程序页面进行个性化配置能够知道如何发起网络数据请求 一.WXML 模板语法 数据绑定 1. 数据绑定的基本原则 ① 在 data 中定义数据 ② 在…

[leetcode] 58. 最后一个单词的长度

文章目录 题目描述解题方法倒序遍历java代码复杂度分析 题目描述 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 示例 1&#xff1a…

未来已来:解锁AGI的无限潜能与挑战

未来已来&#xff1a;解锁AGI的无限潜能与挑战 引言 假设你有一天醒来&#xff0c;发现你的智能手机不仅提醒你今天的日程&#xff0c;还把你昨晚做的那个奇怪的梦解释了一番&#xff0c;并建议你可能需要减少咖啡摄入量——这不是科幻电影的情节&#xff0c;而是人工通用智能…

maldev tricks在注册表中存储 payload

简介 注册表是 Windows 操作系统中一个重要的数据库&#xff0c;它包含 Windows 操作系统和应用程序的重要设置和选项。由于注册表的功能非常强大&#xff0c;因此注册表对于恶意程序来说是非常有利用价值的。 在 windows 注册表中存储二进制数据&#xff0c;这是一种常见的技…

十七、Java网络编程(一)

1、Java网络编程的基本概念 1)网络编程的概念 Java作为一种与平台无关的语言,从一出现就与网络有关及其密切的关系,因为Java写的程序可以在网络上直接运行,使用Java,只需编写简单的代码就能实现强大的网络功能。下面将介绍几个与Java网络编程有关的概念。 2)TCP/IP协议概…

MVP+敏捷开发

MVP敏捷开发 1. 什么是敏捷开发&#xff1f; 敏捷开发是一种软件开发方法论&#xff0c;旨在通过迭代、自组织的团队和持续反馈&#xff0c;快速响应需求变化并交付高质量的软件。相较于传统的瀑布模型&#xff0c;敏捷开发强调灵活性、适应性和与客户的紧密合作。敏捷开发方…

qml和c++结合使用

目录 文章简介1. 创建qml工程2. 创建一个类和qml文件&#xff0c;修改main函数3. 函数说明&#xff1a;4. qml 文件间的调用5. 界面布局6. 代码举例 文章简介 初学qml用来记录qml的学习过程&#xff0c;方便后面归纳总结整理。 1. 创建qml工程 如下图&#xff0c;我使用的是…

【北京迅为】《iTOP龙芯2K1000开发指南》-第四部分 ubuntu开发环境搭建

龙芯2K1000处理器集成2个64位GS264处理器核&#xff0c;主频1GHz&#xff0c;以及各种系统IO接口&#xff0c;集高性能与高配置于一身。支持4G模块、GPS模块、千兆以太网、16GB固态硬盘、双路UART、四路USB、WIFI蓝牙二合一模块、MiniPCIE等接口、双路CAN总线、RS485总线&#…

光伏无人机:巡检无人机解决巡检难题

随着科技的飞速发展&#xff0c;无人机技术已经广泛应用于各个领域&#xff0c;其中光伏无人机在解决光伏电站巡检难题方面发挥了重要作用。光伏无人机以其高效、精准、安全的特点&#xff0c;为光伏电站的巡检工作带来了革命性的变革。 光伏电站通常位于广阔的户外场地&#x…

webpack热更新原理详解

文章目录 前言基础配置创建项目HMR配置 HMR交互概览HMR流程概述HMR实现细节初始化注册监听编译完成事件启动服务监听文件代码变化服务端发送消息客户端收到消息热更新文件请求热更新代码替换 问题思考 前言 刷新分为两种&#xff1a;一种是页面刷新&#xff0c;不保留页面状态…

GPU深度学习环境搭建:Win10+CUDA 11.7+Pytorch1.13.1+Anaconda3+python3.10.9

1. 查看显卡驱动及对应cuda版本关系 1.1 显卡驱动和cuda版本信息查看方法 在命令行中输入【nvidia-smi】可以当前显卡驱动版本和cuda版本。 根据显示,显卡驱动版本为:Driver Version: 516.59,CUDA 的版本为:CUDA Version 11.7。 此处我们可以根据下面的表1 显卡驱动和c…

大模型咨询培训老师叶梓:利用知识图谱和Llama-Index增强大模型应用

大模型&#xff08;LLMs&#xff09;在自然语言处理领域取得了显著成就&#xff0c;但它们有时会产生不准确或不一致的信息&#xff0c;这种现象被称为“幻觉”。为了提高LLMs的准确性和可靠性&#xff0c;可以借助外部知识源&#xff0c;如知识图谱。那么我们如何通过Llama-In…

将阿里云中数据传输到其他超算服务器

目录 方法一&#xff1a;在阿里云中连接超算&#xff0c;然后使用rsync&#xff08;速度慢&#xff09; 方法2&#xff1a;rclone(速度很快&#xff0c;100G只花了大约20min) 方法一&#xff1a;在阿里云中连接超算&#xff0c;然后使用rsync/scp&#xff08;速度慢&#xff0…

网贷大数据黑名单要多久才能变正常?

网贷大数据黑名单是指个人在网贷平台申请贷款时&#xff0c;因为信用记录较差而被列入黑名单&#xff0c;无法获得贷款或者贷款额度受到限制的情况。网贷大数据黑名单的具体时间因个人信用状况、所属平台政策以及银行审核标准不同而异&#xff0c;一般来说&#xff0c;需要一定…

mac: docker安装及其Command not found: docker

已经安装了docker desktop&#xff0c;没安装的 点击安装 傻瓜式安装即可 接着打开终端&#xff1a;好一个 Comand not found:docker 看我不把你整顿&#xff0c;解决如下&#xff1a; 如果你在 macOS 上安装了 Docker Desktop&#xff0c;但是终端无法识别 docker 命令&…

微信搜一搜优化:今天你“搜一搜”了吗?

微信“搜一搜”功能的排名规则和机制是微信生态系统中非常重要的一部分&#xff0c;它决定了小程序、公众号、文章、直播等内容在搜索结果中的展示顺序。小柚给大家整理了一份对其排名规则和机制的详细解析&#xff1a; 首先&#xff0c;关键词匹配度是影响搜索结果排名的重要…

HashMap底层实现条分缕析

目录 题外话 正题 哈希表 哈希碰撞 HashMap底层实现 小结 题外话 又水了两天,怪我,在宿舍确实没什么状态,是时候调整调整了 正题 今天直接讲解HashMap底层实现 哈希表 哈希表又称散列表 是数组和单向链表的结合体 如下图 而哈希表存放元素机制是靠哈希函数解析关键…

Jira搭建过程

看到很多小伙伴对jira有兴趣,我们今天就来分享一下jira的搭建吧 首先要明白jira是什么? 看来搭建jira也是我们测试人员需要具备的技能之一了.下面是详细的大家步骤: 1.系统环境准备 Centos 7.5 Mysql 5.6 Java1.8 2.软件安装包 atlassian-jira-software-7.13.0-x64.bin …

Linux_环境变量

目录 1、查询所有环境变量 2、常见的环境变量 2.1 PATH 2.2 HOME 2.3 PWD 3、增加新的环境变量 4、删除环境变量 5、main函数的三个形参 5.1 argv字符串数组 5.2 env字符串数组 6、系统调用接口 6.1 getenv 6.2 putenv 7、全局变量environ 结语 前言&…

SpringBoot + kotlin 协程小记

前言&#xff1a; Kotlin 协程是基于 Coroutine 实现的&#xff0c;其设计目的是简化异步编程。协程提供了一种方式&#xff0c;可以在一个线程上写起来像是在多个线程中执行。 协程的基本概念&#xff1a; 协程是轻量级的&#xff0c;不会创建新的线程。 协程会挂起当前的协…