Autojs 利用OpenCV识别棋子之天天象棋你马没了

本例子通过代码像你介绍利用OpenCV实现霍尔找圆的方法定位棋子位置
通过autojs脚本实现自动点击棋子 开源地址

https://github.com/Liberations/TtxqYourHorseIsGone/blob/master/main.js
AutoXJs
https://github.com/kkevsekk1/AutoX/releases
auto()
//安卓版本高于Android 9
if (device.sdkInt > 28) {
    //等待截屏权限申请并同意
    threads.start(function () {
        packageName('com.android.systemui').text('立即开始').waitFor()
        text('立即开始').click()
    });
}
//申请截屏权限
if (!requestScreenCapture()) {
    toast("请求截图失败")
    exit()
}
http.__okhttp__.setTimeout(40 * 1000)//低版本需要加这个
// 创建空的棋盘
// 创建空的棋盘
function createEmptyChessboard() {
    var temp = [];
    // 创建一个大小为 10x9 的二维数组,并用空字符串初始化
    for (var i = 0; i < 10; i++) {
        temp[i] = Array(9).fill("O");
    }

    return temp;
}


// 打印二维数组
function printChessboard(chessboard) {
    for (var i = 0; i < chessboard.length; i++) {
        var row = chessboard[i].join(" ");
        log(row);
    }
}


//复制一份新的数组
function copyArray(array) {
    var newArray = [];

    for (var i = 0; i < array.length; i++) {
        var innerArray = array[i];
        var newInnerArray = innerArray.slice(); // 复制内部数组
        newArray.push(newInnerArray);
    }

    return newArray;
}

//将[row,col] 转成字母
function coordinatesToAlgebraic(coordinates) {
    var row = coordinates[0]
    var col = coordinates[1]
    if (isRed) {
        row = 9 - row;
        col = col + 'a'.charCodeAt(0);
        return String.fromCharCode(col) + row.toString();
    } else {
        col = 8 - col + 'a'.charCodeAt(0);
        return String.fromCharCode(col) + row.toString();
    }


}


//将字母转成 [row,col]
function algebraicToCoordinates(algebraic) {
    var col = algebraic.charCodeAt(0) - 'a'.charCodeAt(0);
    var row = 9 - parseInt(algebraic.substring(1));
    if (isRed) {
        //b9 c7 (0,1) (2,2)
        return [row, col];
    } else {
        //b9 c7  (9,7) (7,6)
        row = 9 - row
        col = 8 - col
        return [row, col];
    }
}


//二维数组旋转180度
function rotateArray180(array) {
    var rotated = [];
    for (var i = array.length - 1; i >= 0; i--) {
        var row = array[i];
        var rotatedRow = row.slice().reverse();
        rotated.push(rotatedRow);
    }
    return rotated;
}

//大小写翻转
function transformString(str) {
    let transformedString = "";

    for (let i = 0; i < str.length; i++) {
        let char = str.charAt(i);
        if (char === char.toUpperCase()) {
            transformedString += char.toLowerCase();
        } else {
            transformedString += char.toUpperCase();
        }
    }

    return transformedString;
}



//释放图片资源
function releaseSouce() {
    // if (img != null) {
    //     img.recycle()
    //     img = null
    // }
    if (board_img != null) {
        board_img.recycle()
        img = null
    }
}


//通过row col去点击相应的坐标
function clickChess(row, col) {
    var clickStartX = (2 * col + 1) * chess_piece_radius + boardLeft;
    var clickStartY = (2 * row + 1) * chess_piece_radius + boardTop;
    //log("点击位置clickStartX " + clickStartX + " clickStartY " + clickStartY)
    click(clickStartX, clickStartY);
}




//所有的操作都用这个控制
//初始的象棋布局
var defaultChessBoard = [
    ['r', 'n', 'b', 'a', 'k', 'a', 'b', 'n', 'r'],
    ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
    ['O', 'c', 'O', 'O', 'O', 'O', 'O', 'c', 'O'],
    ['p', 'O', 'p', 'O', 'p', 'O', 'p', 'O', 'p'],
    ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
    ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
    ['P', 'O', 'P', 'O', 'P', 'O', 'P', 'O', 'P'],
    ['O', 'C', 'O', 'O', 'O', 'O', 'O', 'C', 'O'],
    ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
    ['R', 'N', 'B', 'A', 'K', 'A', 'B', 'N', 'R']
]

//初始化圆的位置
var defaultCircleBoard = [
    ['B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'],
    ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
    ['O', 'B', 'O', 'O', 'O', 'O', 'O', 'B', 'O'],
    ['B', 'O', 'B', 'O', 'B', 'O', 'B', 'O', 'B'],
    ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
    ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
    ['R', 'O', 'R', 'O', 'R', 'O', 'R', 'O', 'R'],
    ['O', 'R', 'O', 'O', 'O', 'O', 'O', 'R', 'O'],
    ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
    ['R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R']
]

var defaultBlackCircleBoard = [
    ['R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R'],
    ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
    ['O', 'R', 'O', 'O', 'O', 'O', 'O', 'R', 'O'],
    ['R', 'O', 'R', 'O', 'R', 'O', 'R', 'O', 'R'],
    ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
    ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
    ['B', 'O', 'B', 'O', 'B', 'O', 'B', 'O', 'B'],
    ['O', 'B', 'O', 'O', 'O', 'O', 'O', 'B', 'O'],
    ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'],
    ['B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B']
]

var isRed = null
var isSart = true
var isMyStep = false //标志是否我方下棋
var stepCount = 0 //累计步数
var fen = ""
var img = null //每次的截图
var board_img = null //裁剪出来的棋盘
var storage = storages.create("chessStorage");
var boardWidth = 1010 //棋 盘宽度
var boardHeight = 1140  //棋盘高度
var boardTop = 626 //棋盘上边距
var boardLeft = 34 //棋盘左边距
var speekOn = false //棋盘左边距
var chess_piece_radius = 0 //棋子半径
var chess_piece_width = 0 //棋子宽度
var moves = [] //当前移动的fen码
var chessBoard = null
var circleBoard = []
var intervalId = 0
var 开始 = images.read("开始.png")
var 关闭 = images.read("关闭.png")
var 确定 = images.read("确定.png")
var 叉叉 = images.read("叉叉.jpg")
var 对战助手 = images.read("对战助手.jpg")
var 确定退出 = images.read("确定退出.jpg")

//删除截图
var imgDir = "img";
files.removeDir(imgDir)
files.create(imgDir + "/")

function main() {
    initStart()
    isSart = true
    log('开始新的对局')
    while (isSart) {
        try {
            sleep(2000)
            findChess()
        } catch (e) {
            log("发生异常" + e)
        }
        //isSart = false
    }

}

function initStart() {
    chessBoard = copyArray(defaultChessBoard)
    circleBoard = copyArray(defaultCircleBoard)
    isRed = null
    isSart = true
    isMyStep = false //标志是否我方下棋
    stepCount = 0 //累计步数
    fen = ""
    moves = []
    lastMove = ""
    if (intervalId != 0) {
        clearInterval(intervalId)
        intervalId = 0
    }
}


function findChess() {
    img = images.captureScreen()
    if (!img) {
        toastLog('截图失败')
        return
    }
    var pos4 = images.findImage(img, 对战助手)
    if (pos4) {
        speek("发现对战助手按钮")
        click(pos4.x, pos4.y)
        //重新初始化
        initStart()
        return
    }
    //log("开始findChess")
    var pos = images.findImage(img, 关闭)
    if (pos) {
        speek("发现关闭对局结束")
        click(pos.x, pos.y)
        sleep(1000)
        click(device.width / 2, device.height / 2)
        //重新初始化
        initStart()
        return
    }

    var pos1 = images.findImage(img, 开始)
    if (pos1) {
        speek("发现开始按钮")
        click(pos1.x, pos1.y)
        //重新初始化
        initStart()
        return
    }

    var pos2 = images.findImage(img, 确定)
    if (pos2) {
        speek("发现确定按钮")
        click(pos2.x, pos2.y)
        //重新初始化
        initStart()
        return
    }

    var pos3 = images.findImage(img, 叉叉)
    if (pos3) {
        speek("发现叉叉按钮")
        click(pos3.x, pos3.y)
        //重新初始化
        initStart()
        return
    }

    chess_piece_width = boardWidth / 9
    chess_piece_radius = chess_piece_width / 2
    board_img = images.clip(img, boardLeft, boardTop, boardWidth, boardHeight)

    if (isRed == null) {
        var col = 4
        var row = 0
        var centerX = (2 * col + 1) * chess_piece_radius;
        var centerY = (2 * row + 1) * chess_piece_radius;
        var left = centerX - chess_piece_radius
        var top = centerY - chess_piece_radius
        let cutImg = images.clip(board_img, left, top, chess_piece_radius * 2, chess_piece_radius * 2)

        let containRed = images.findColor(cutImg, "#953c28", {
            threshold: 4
        })
        let containBlack = images.findColor(cutImg, "#3a3938", {
            threshold: 4
        })

        if (containRed) {
            circleBoard = null
            circleBoard = copyArray(defaultBlackCircleBoard)
            isRed = false
        } else if (containBlack) {
            circleBoard = null
            circleBoard = copyArray(defaultCircleBoard)
            isRed = true
        } else {
            log("没找到帅啥也没有")
        }
        speek("我方为" + (isRed ? "红方" : "黑方"))


    }

    var tempchessboard = createEmptyChessboard()
    var count = 0;
    // 找圆
    min_radius = chess_piece_width / 4
    max_radius = chess_piece_width / 3
    // 灰度化图片
    let gray = images.grayscale(board_img);
    // 找圆
    let arr = images.findCircles(gray, {
        dp: 1,
        minDst: 30,
        param1: 50,
        param2: 30,
        minRadius: parseInt(min_radius),
        maxRadius: parseInt(max_radius),
    });
    gray.recycle()
    for (let i = 0; i < arr.length; i++) {
        let circle = arr[i];
        let x = circle.x; // 圆心 x 坐标
        let y = circle.y; // 圆心 y 坐标
        let radius = circle.radius; // 圆的半径
        // 裁剪图像
        let row = parseInt(y / chess_piece_width)
        let col = parseInt(x / chess_piece_width)
        var left = x - radius;
        var top = y - radius;
        let cutImg = images.clip(board_img, left, top, radius * 2, radius * 2)
        let containRed = images.findColor(cutImg, "#953c28", {
            threshold: 4
        })
        let containBlack = images.findColor(cutImg, "#3a3938", {
            threshold: 4
        })
        if (containRed) {
            count++
            tempchessboard[row][col] = "R"
        } else if (containBlack) {
            count++
            tempchessboard[row][col] = "B"
        } else {
            tempchessboard[row][col] = "O"
        }
        cutImg.recycle()

    }

    //log('总共找到圆' + count)
    if (stepCount == 0 && count != 32) {
        log(arr.length + '数量不够' + count)
        initStart()
        printChessboard(tempchessboard)
        releaseSouce()
        return
    }

    if (stepCount < 999) {
        var pao1start = tempchessboard[7][1]
        var pao1Mid = tempchessboard[2][1]
        var pao1end = tempchessboard[0][1]

        var pao2start = tempchessboard[7][7]
        var pao2Mid = tempchessboard[2][7]
        var pao2end = tempchessboard[0][7]
        if (pao1start != "O" && pao1end != "O" && pao1Mid != "O") {
            speek("发现炮1")
            clickChess(7, 1)
            sleep(50)
            clickChess(0, 1)
            speek("你马没了")
            sleep(2000)
            stepCount++
            return
        }
        if (pao2start != "O" && pao2end != "O" && pao2Mid != "O") {
            speek("发现炮2")
            clickChess(7, 7)
            sleep(50)
            clickChess(0, 7)
            speek("你马没了")
            sleep(2000)
            stepCount++
            return
        }
        return
    }
}

function speek(str) {
    if (true) {
        TTS.speak(str, TextToSpeech.QUEUE_ADD, null);//自定义语音合成内容
    } else {
        log(str)
    }

}

//调用系统语音合成
importPackage(android.speech.tts);
importClass(java.util.Locale);
if (TTS != undefined) { TTS.stop(); TTS.shutdown(); }
var TTS = new TextToSpeech(context, function (status) {
    if (status != TextToSpeech.SUCCESS) {
        toast("初始化TTS失败");
    }
    var r = TTS.setLanguage(Locale.CHINA);
    if (r < 0) {
        toast("不支持该语言: " + r);
        exit();
    }
    log("TTS初始化成功");
});
sleep(500);
speek("开始辅助")
// 创建悬浮窗
var window = floaty.window(
    <vertical>
        <text text="在棋力评测或者积分场快速按钮界面点击开始运行,需要辅助功能模拟点击" textColor="red" w="auto" ></text>
        <button id="toggleButton" text="展开" w="auto" h="auto" />
        <vertical id="menu" visibility="gone">
            <button id="startButton" text="开始" w="auto" h="auto" />
            <button id="stopButton" text="结束" w="auto" h="auto" />
        </vertical>
    </vertical>
);
var isOpen = false
// 设置悬浮窗位置
window.setPosition(0, device.height / 20);

log("我的引擎" + engines.myEngine())
engines.all().forEach(item => {
    if (item.id != engines.myEngine().id) {
        log("停止引擎" + item)
        item.forceStop()
    }

})
function hideMenu() {
    isOpen = false
    window.menu.setVisibility(8);
    window.toggleButton.setText("展开");
}
function expandOrHideMenu() {
    isOpen = !isOpen
    if (isOpen) {
        window.menu.setVisibility(0);
        window.toggleButton.setText("收起");
    } else {
        window.menu.setVisibility(8);
        window.toggleButton.setText("展开");
    }
}
// 切换按钮点击事件
window.toggleButton.click(() => {
    expandOrHideMenu()

});

// 开始按钮点击事件
window.startButton.click(() => {
    hideMenu()
    threads.start(function () {
        isSart = false
        speek("开始")
        main()
    });

});

// 结束按钮点击事件
window.stopButton.click(() => {
    isSart = false
    threads.shutDownAll()
    toastLog("已停止");
    hideMenu()
});

//保持脚本运行
setInterval(() => { }, 1000);

主要函数利用autojs提供的 findCircles函数

images.findCircles(gray, options)
gray {Image} 灰度图片
options {Object} 选项包括:
region {Array} 找圆区域。是一个两个或四个元素的数组。(region[0], region[1])表示找圆区域的左上角;region[2]*region[3]表示找圆区域的宽高。如果只有region只有两个元素,则找圆区域为(region[0], region[1])到图片右下角。如果不指定region选项,则找圆区域为整张图片。
dp {number} dp是累加面与原始图像相比的分辨率的反比参数,dp=2时累计面分辨率是元素图像的一半,宽高都缩减为原来的一半,dp=1时,两者相同。默认为1。
minDst {number} minDist定义了两个圆心之间的最小距离。默认为图片高度的八分之一。
param1 {number} param1是Canny边缘检测的高阈值,低阈值被自动置为高阈值的一半。默认为100,范围为0-255。
param2 {number} param2是累加平面对是否是圆的判定阈值,默认为100。
minRadius {number} 定义了检测到的圆的半径的最小值,默认为0。
maxRadius {number} 定义了检测到的圆的半径的最大值,0为不限制最大值,默认为0。
return {Array}

在图片中寻找圆(做霍夫圆变换)。找到时返回找到的所有圆{x,y,radius}的数组,找不到时返回null。

一个寻找圆的例子:

// 请求截图
requestScreenCapture();
// 截图
let img = captureScreen();
// 灰度化图片
let gray = images.grayscale(img);
// 找圆
let arr = findCircles(gray, {
    dp: 1,
    minDst: 80,
    param1: 100,
    param2: 100,
    minRadius: 50,
    maxRadius: 80,
});
// 回收图片
gray.recycle();

具体看代码 可以在这个基础上实现手机版自动连线功能!
在这里插入图片描述

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

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

相关文章

Elasticsearch(十五)搜索---搜索匹配功能⑥--基于地理位置查询

一、前言 随着互联网的热门&#xff0c;越来越多的传统行业将全部或者部分业务转移到互联网上&#xff0c;其中不乏一些和地理位置强相关的行业。基于地理位置的搜索功能&#xff0c;大大提升了人们的生活和工作效率。例如&#xff0c;外出旅行时&#xff0c;只需要用手机打开…

NineData:高效、安全、可靠的DB2数据管理平台

Db2 是老牌厂商 IBM 研发和维护的关系型数据库管理系统。作为一个拥有悠久历史的数据库系统&#xff0c;Db2 凭借它的高可靠、可扩展和高安全性等诸多优点&#xff0c;在如今的数据库市场依然占据相当大的份额。 对于诸多金融行业的企业而言&#xff0c; Db2 作为承载其核心业务…

R语言的物种气候生态位动态量化与分布特征模拟实践技术

在全球气候快速变化的背景下&#xff0c;理解并预测生物种群如何应对气候变化&#xff0c;特别是它们的地理分布如何变化&#xff0c;已经变得至关重要。利用R语言进行物种气候生态位动态量化与分布特征模拟&#xff0c;不仅可以量化描述物种对环境的需求和适应性&#xff0c;预…

【开源】基于SpringBoot的农村物流配送系统的设计和实现

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统登录、注册界面2.2 系统功能2.2.1 快递信息管理&#xff1a;2.2.2 位置信息管理&#xff1a;2.2.3 配送人员分配&#xff1a;2.2.4 路线规划&#xff1a;2.2.5 个人中心&#xff1a;2.2.6 退换快递处理&#xff1a;…

Windows server部署filebeat到kafka

需求&#xff1a;Windows dhcp日志需要实时传输到elk或者其他告警平台。 1、filebeat下载地址&#xff1a;https://www.elastic.co/cn/downloads/beats/filebeat 2、下载后解压后配置filebeat.yml文件&#xff0c; 3、README.md文件中有运行的操作方法&#xff1a;cmd上进入f…

手写效果流式响应(langchain+fastapi+js)

这是一个前后端完整可用的小项目 后端是 Python 的 FastAPI 框架&#xff0c;调用 langchain 进行 openai 的模型对话。前端是纯html css javascript&#xff0c;没调用任何第三方库&#xff0c;方便集成到 Vue React 等现有前端项目。 聊天界面&#xff1a; 效果就是提问之…

【开源】基于SpringBoot的高校学院网站的设计和实现

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学院院系模块2.2 竞赛报名模块2.3 教育教学模块2.4 招生就业模块2.5 实时信息模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 学院院系表3.2.2 竞赛报名表3.2.3 教育教学表3.2.4 招生就业表3.2.5 实时信息表 四、系…

ERP管理系统的运作流程是怎样的?

ERP管理系统的运作流程是怎样的&#xff1f; 下文中用到的图片和系统&#xff0c;都来自于我们公司正在用的软件——简道云进销存软件 这是我们团队搭建的模板&#xff0c;需要的可以自取&#xff0c;可以直接使用&#xff0c;也可以在模板的基础上自行搭建 ERP管理系统模板&…

分布式日志和链路追踪

分布式日志 实现思路 分布式日志框架服务的实现思路基本是一致的&#xff0c;如下&#xff1a; 日志收集器&#xff1a;微服务中引入日志客户端&#xff0c;将记录的日志发送到日志服务端的收集器&#xff0c;然后以某种方式存储数据存储&#xff1a;一般使用ElasticSearch分…

【QT开发笔记-基础篇】| 第四章 事件QEvent | 4.10 总结QT中的事件传递流程

本节对应的视频讲解&#xff1a;B_站_链_接 【QT开发笔记-基础篇】 第4章 事件 4.10 总结事件传递流程(1) 事件处理函数接受还是忽略 本章要实现的整体效果如下&#xff1a; 事件传递总流程图&#xff0c;如下&#xff1a; 这张图是不是还不太明白&#xff1f;&#xff1f; 别…

RabbitMQ基础篇 笔记

RabbitMQ 余额支付 同步调用 一步一步的来&#xff0c;支付业务写完后&#xff0c;如果之后加需求&#xff0c;还需要增加代码&#xff0c;不符合开闭原则。 性能上也有问题&#xff0c;openfeign是同步调用&#xff0c;性能太差。 同步调用耦合太多。 同步的优势是可以立…

matlab中narginchk函数用法及其举例

matlab中narginchk函数用法及其举例 narginchk在编写子函数程序时候&#xff0c;在验证输入参数数目方面具有重要作用&#xff0c;本博文讲一讲该函数的用法。 一、narginchk功能 narginchk的作用是验证输入参数数目。 二、语法 narginchk(minArgs,maxArgs)narginchk(minA…

windows服务器环境下使用php调用com组件

Office设置 安装 office2013 且通过正版激活码激活 在组件服务 计算机 我的电脑 DOM 中找到 Microsoft Word 97 - 2003 文档 服务&#xff0c;右键属性 身份验证调整为 无 在 标识中 调整为 交互式用户 php环境设置 开启com组件扩展 在php.ini中设置 extensionphp_com_dotn…

同范围中的嵌入式和单片机区别是什么?

今日话题&#xff0c;同范围中的嵌入式和单片机区别是什么&#xff1f;嵌入式系统和单片机不仅仅是软硬件的区别&#xff0c;更涉及到应用领域和功能特性的不同。嵌入式系统通常包括一个完整的计算机系统&#xff0c;其中包括处理器、内存、输入输出接口以及一个操作系统&#…

2023年中国消防报警设备市场规模现状及行业竞争趋势分析[图]

消防安全行业主要分为消防产品和消防工程两个子行业。消防产品又可细分成消防装备、消防报警、自动灭火、防火与疏散、通用与防烟排烟、消防供水等 6 大类&#xff0c;其中消防装备主要用于消防部队&#xff0c;其他 5 大类主要用于建筑物消防。 消防行业内容 资料来源&#x…

21款奔驰GLE450升级23P驾驶辅助 缓解开车疲劳

驾驶辅助和自动驾驶的区别就是需要人为去接管&#xff0c;虽然车辆会根据道路自己行驶&#xff0c;弯道上也能居中自动修正行驶&#xff0c;长时间不接管方向盘&#xff0c;系统会提示人为接管&#xff0c;这就是奔驰的23P驾驶辅助系统&#xff0c; 很多车友升级23P驾驶辅助系…

苍穹外卖-01

苍穹外卖-01 课程内容 软件开发整体介绍苍穹外卖项目介绍开发环境搭建导入接口文档Swagger 项目整体效果展示&#xff1a; ​ 管理端-外卖商家使用 ​ 用户端-点餐用户使用 当我们完成该项目的学习&#xff0c;可以培养以下能力&#xff1a; 1. 软件开发整体介绍 作为一名…

用Visual Studio(VS)开发UNIX/Linux项目

目录 FTP是免不了的 正确设置头文件 组织项目结构 创建何种项目类型 FTP自动上传 大部分具有Windows开发经验的程序员会比较喜欢使用Visual Studio&#xff0c;而大部分Unix/Linux程序员则喜欢使用UltraEdit直接在主机上写代码。 为什么直接在主机上写代码呢&#xff0c;因…

Leo赠书活动-03期 【ChatGPT 驱动软件开发:AI 在软件研发全流程中的革新与实践 】

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

【JAVA学习笔记】45 - (35 - 43)第十章作业

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter10/src/com/yinhai/homework10 1.静态属性的共享性质 判断下列输出什么 public class HomeWork01 {public static void main(String[] args) {Car c new Car();//无参构造时改变color为red…