Java图形化界面编程——五子棋游戏 笔记

2.8.5 五子棋

接下来,我们使用之前学习的绘图技术,做一个五子棋的游戏。
在这里插入图片描述
注意,这个代码只实现了五子棋的落子、删除棋子和动画等逻辑实现,并没有把五子棋的游戏逻辑编写完整,比较简单易上手。

图片素材
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述


package Draw;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.io.File;

public class Gobang {
    //定义五子棋游戏窗口
    private JFrame jframe = new JFrame("五子棋游戏"); //改动一,使用swing中的JFrame解决画面闪烁

    //声明四个BufferedImage对象,分别记录四张图片

    BufferedImage table;
    BufferedImage black;
    BufferedImage white;
    BufferedImage selected;

    //声明棋盘的宽和高(与棋盘图片的宽和高一致)
    private final int TABLE_WIDTH = 535;
    private final int TABLE_HEIGHT = 536;

    //声明棋盘横向和纵向分别可以下多少子,它们的值都为十五(多少行多少列)
    final int BOARD_SIZE =15;

    //声明每个棋子占用棋盘的比率
    final int RATE = TABLE_WIDTH/BOARD_SIZE;

    //声明变量记录棋子对于x方向和y方向的偏移量,在像素中量出来的
    final int X_OFFSET = 5;
    final int Y_OFFSET = 6;

    //声明一个二维数组,记录当前位置棋子的状态,如果索引[i][j]的值为 0-没有棋子, 1-白棋, 2-黑棋
    int[][] board = new int[BOARD_SIZE][BOARD_SIZE];

    //声明红色选择框的坐标,也是二维数组中的索引
    int selected_X = -1;
    int selected_Y = -1;

    //自定义类继承Canvas,充当画布
    private class ChessBoard extends JPanel{   //改动二,继承swing中JPanel而不是Canvas,解决画面闪烁
        @Override
        public void paint(Graphics g) {
            //绘图
            //绘制棋盘
            g.drawImage(table,0,0,null);

            //绘制选择框
            if(selected_X>0 && selected_Y>0) //判断有移动时再开始绘制
                //注意索引与真实位置的转换
                g.drawImage(selected,selected_X*RATE+X_OFFSET,selected_Y*RATE+Y_OFFSET,null);

            //绘制棋子
            for (int i = 0; i < BOARD_SIZE; i++) {
                for (int j = 0; j < BOARD_SIZE; j++) {
                    //绘制黑棋
                    if(board[i][j] == 2) g.drawImage(black,i*RATE+X_OFFSET,j*RATE+Y_OFFSET,null);
                    //绘制白棋
                    if(board[i][j] == 1) g.drawImage(white,i*RATE+X_OFFSET,j*RATE+Y_OFFSET,null);
                }
            }
        }
    }
    ChessBoard chessBoard = new ChessBoard();

    //声明变量,记录当前下棋的颜色,1-白棋, 2-黑棋
    int board_type = 2;

    //声明底部需要用的组件
    Panel p = new Panel();
    Button whiteBtn = new Button("白棋");
    Button blackBtn = new Button("黑棋");
    Button deleteBtn = new Button("删除");

    public void refreshBtnColor(Color whitBtnColor, Color blackBtnColor, Color deleteBtnColor) {         //用来刷新按钮的颜色
        whiteBtn.setBackground(whitBtnColor); //setBackground来设置按钮(背景)颜色
        blackBtn.setBackground(blackBtnColor);
        deleteBtn.setBackground(deleteBtnColor);
    }

    public void init() throws Exception{

        //组装视图,编写逻辑
        //编写白棋按钮的逻辑
        whiteBtn.addActionListener(e->{
            //修改当前要下的棋子的标志为1,对应下白棋。
            board_type = 1;

            //刷新按钮的颜色
            refreshBtnColor(Color.GREEN,Color.GRAY,Color.GRAY);
        });
        //黑棋和清除按钮的逻辑
        blackBtn.addActionListener(e->{
            //修改当前要下的棋子的标志为2,对应下黑棋。
            board_type = 2;

            //刷新按钮的颜色
            refreshBtnColor(Color.GRAY,Color.GREEN,Color.GRAY);
        });
        deleteBtn.addActionListener(e->{
            //修改当前要下的棋子的标志为0,对应着删除
            board_type = 0;

            //刷新按钮的颜色
            refreshBtnColor(Color.GRAY,Color.GRAY,Color.GREEN);
        });
        //将按钮添加到面板中
        p.add(whiteBtn);
        p.add(blackBtn);
        p.add(deleteBtn);
        //将面板添加到frame的南部区域
        jframe.add(p,BorderLayout.SOUTH);

        //组装棋盘
        //初始化图片
        //这里保存图片时需要在项目里建立一个文件夹,来存放图片,不然放在其他地方好像都读不到。。
        table = ImageIO.read(new File("E:\\java_untitled\\calculatoe\\img\\table.jpg"));
        black = ImageIO.read(new File("E:\\java_untitled\\calculatoe\\img\\black.gif"));
        white = ImageIO.read(new File("E:\\java_untitled\\calculatoe\\img\\white.gif"));
        selected = ImageIO.read(new File("E:\\java_untitled\\calculatoe\\img\\selected.gif"));

        //处理棋盘的游戏逻辑,如红色选择框随鼠标移动,鼠标点击便下子
        //处理鼠标移动
        chessBoard.addMouseMotionListener(new MouseMotionAdapter() {
            //当鼠标移动时会调用该方法
            @Override
            public void mouseMoved(MouseEvent e) {
                selected_X = (e.getX()-X_OFFSET)/RATE;//获取此时鼠标的坐标-偏移量/比率,就能得到下棋子的坐标
                selected_Y = (e.getY()-Y_OFFSET)/RATE;
                chessBoard.repaint();
            }
        });

        //处理鼠标点击
        chessBoard.addMouseListener(new MouseAdapter() {
            //当鼠标被点击后会调用该方法
            @Override
            public void mouseClicked(MouseEvent e) {
                int xPos = (e.getX()-X_OFFSET)/RATE;//跟上面一样得到真实坐标
                int yPos = (e.getY()-Y_OFFSET)/RATE;

                board[xPos][yPos] = board_type;//更新坐标中的标记意味已经下子了
                chessBoard.repaint();
            }
            //当鼠标退出区域时,重置界面,使selected_X和selected_Y为-1
            @Override
            public void mouseExited(MouseEvent e) {
                selected_X = -1;
                selected_Y = -1;
                chessBoard.repaint();
            }
        });

        chessBoard.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));//设置画布
        jframe.add(chessBoard);

        //设置frame最佳大小并可见
        jframe.pack();
        jframe.setVisible(true);
    }

    public static void main(String[] args) throws Exception {
        new Gobang().init();
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习与计算机视觉 | 实用CV开源项目汇总(有github代码链接,建议收藏!)

本文来源公众号“深度学习与计算机视觉”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;【建议收藏】实用CV开源项目汇总&#xff08;文末有彩蛋~&#xff09; 01 Trace.moe 图像反向搜索动漫场景&#xff0c;使用动漫截图搜索该…

数据库实验报告

用SQL语句和企业管理器建立如下的表结构并输入数据 给定表结构如下&#xff1a; 创建数据库 创建数据库 create table student(Sno int auto_increment primary key,Sname varchar(45),Ssex varchar(45),Sage int,Sdept varchar(45) )engine InnoDB default charsetutf8; …

java之VO,BO,PO,DO,DTO

概念 VO&#xff08;View Object&#xff09;&#xff1a;视图对象&#xff0c;用于展示层&#xff0c;它的作用是把某个指定页面&#xff08;或组件&#xff09;的所有数据封装起来。DTO&#xff08;Data Transfer Object&#xff09;&#xff1a;数据传输对象&#xff0c;这…

代码随想录刷题笔记-Day19

1. 二叉搜索树的最小绝对差 530. 二叉搜索树的最小绝对差https://leetcode.cn/problems/minimum-absolute-difference-in-bst/ 给你一个二叉搜索树的根节点 root &#xff0c;返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数&#xff0c;其数值等于两值之差的绝…

windows安装Mysql解压版

windows安装Mysql解压版 一、下载mysql-8.0.36-winx64.zip二、解压三、配置3.1. 添加环境变量&#xff1a;新建MYSQL_HOME3.2.如何验证是否添加成功&#xff1a;必须以管理员身份启动3.3. 初始化MySQL&#xff1a;必须以管理员身份启动3.4. 注册MySQL服务&#xff1a;必须以管理…

算法练习-01背包问题【含递推公式推导】(思路+流程图+代码)

难度参考 难度&#xff1a;困难 分类&#xff1a;动态规划 难度与分类由我所参与的培训课程提供&#xff0c;但需 要注意的是&#xff0c;难度与分类仅供参考。且所在课程未提供测试平台&#xff0c;故实现代码主要为自行测试的那种&#xff0c;以下内容均为个人笔记&#xff0…

PCL库学习及ROS使用

PCL库学习 c_cpp_properties.json {"configurations": [{"name": "Linux","includePath": ["${workspaceFolder}/**","/usr/include","/usr/local/include"],"defines": [],"compiler…

Linux第60步_“buildroot”构建根文件系统第2步_配置“buildroot下的busybox”并测试“buildroot”生成的根文件系统

1、查看“buildroot下的busybox”安装路径 打开终端 输入“ls回车” 输入“cd linux回车/”&#xff0c;切换到到“linux”目录 输入“ls回车”&#xff0c;查看“linux”目录下的文件和文件夹 输入“cd buildroot/回车”&#xff0c;切换到到“buildroot”目录 输入“ls…

ClickHouse迎战十亿行数据的挑战

本文字数&#xff1a;6782&#xff1b;估计阅读时间&#xff1a;17 分钟 作者&#xff1a;Dale McDiarmid 审校&#xff1a;庄晓东&#xff08;魏庄&#xff09; 本文在公众号【ClickHouseInc】首发 本月初&#xff0c;Decodable 公司的 Gunnar Morling 提出了一项为期一月挑战…

接口测试怎么进行,如何做好接口测试

一、什么是接口&#xff1f; 接口测试主要用于外部系统与系统之间以及内部各个子系统之间的交互点&#xff0c;定义特定的交互点&#xff0c;然后通过这些交互点来&#xff0c;通过一些特殊的规则也就是协议&#xff0c;来进行数据之间的交互。 二、 常用接口采用方式&#x…

API自动化测试你以为很难?看完这篇文章直接打开你的任督二脉

API测试已成为日常的测试任务之一&#xff0c;为了提高测试效率&#xff0c;减少重复的手工操作&#xff0c;API自动化测试也逐渐变得愈加重要&#xff0c;本文是自己在API自动化测试方面的一些经验积累和心得、汇总成文&#xff0c;以飨读者 我相信自动化技能已经成为高级测试…

单调栈题目总结

单调栈 496. 下一个更大元素 I 503. 下一个更大元素 II 739. 每日温度 6227. 下一个更大元素 IV 模版归纳 「单调栈」顾名思义就是具有单调性的栈结构&#xff0c;一般常用于找到下一个更大的元素&#xff0c;即当前元素右侧第一个更大的元素 看下面一个例子&#xff1a…

消毒柜行业分析:市场渗透率不足20%

目前消毒柜仍然属于“小众”品类&#xff0c;疫情前期市场渗透率也不足20%。有业内人士表示&#xff0c;多年来消毒柜零售量规模基本在400万台左右徘徊&#xff0c;这个角度看&#xff0c;消毒柜是具有自身的产品消费人群的&#xff0c;其市场相对稳定&#xff0c;而且消毒柜的…

DoRA(权重分解低秩适应):一种新颖的模型微调方法

来自&#xff1a;小互 DoRA&#xff08;权重分解低秩适应&#xff09;&#xff1a;一种新颖的模型微调方法 DoRA在LoRA的基础上进一步发展&#xff0c;通过将预训练权重分解为“幅度”和“方向”两个部分进行微调。 这种权重分解方法允许DoRA更精细地控制模型的学习过程&…

error: ‘QWidget‘ file not found

说明你没有加载 widgets模块 缺少widgets&#xff0c;就报错

mysql 2-17

UNION关键字和UNION ALL 自然连接 USING使用 函数 单行函数 基本函数 三角函数 指数和对数 进制间的转换 字符串函数 时间和日期函数 计算日期和时间的函数 日期的格式化和解析 流程控制函数

这样用TVS管

对于工程师来说&#xff0c;浪涌保护不仅仅是选择合适的电源板或者拔下几根电缆&#xff0c;主要涉及在 PCB 布局中放置瞬态保护组件并应用明确的接地策略。 TVS 二极管是用于保护PCB布局中组件的常用组件&#xff0c;这些组件放置在数据线上&#xff0c;一旦电路中接收到ESD脉…

激活函数30年回顾总结,全paper第一份详尽研究来了!

B站&#xff1a;啥都会一点的研究生公众号&#xff1a;啥都会一点的研究生 新年好&#xff0c;离退休又近了一年 假期躺平未更新&#xff0c;但该保存的素材及热点还是拿小本本记了下来&#xff0c;如这篇今年2月14号arXiv上发表的长达100页神经网络中激活函数大总结文章就进…

综合练习

目录 查询每个员工的编号、姓名、职位、基本工资、部门名称、部门位置 确定要使用的数据表 确定已知的关联字段 查询每个员工的编号、姓名、职位、基本工资、工资等级 确定要使用的数据表 确定已知的关联字段 查询每个员工的编号、姓名、职位、基本工资、部门名称、工资…

string的用法

概念 可代替字符数组来存储字符串 访问 string name[i];//下标访问 string::iterator it;//迭代器访问常用函数 1.begin():获得字符串首地址 2.end():获得字符串末地址 3.&#xff1a;字符串的加法&#xff0c;可将两个字符串拼接起来 4.比较符&#xff1a;&#xff0c;>…