吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 13131|回复: 67
上一主题 下一主题
收起左侧

[其他原创] 拼多多斗地主记牌器 - Autojs

[复制链接]
跳转到指定楼层
楼主
spawn_fly 发表于 2021-4-9 14:44 回帖奖励
本帖最后由 spawn_fly 于 2021-4-15 11:31 编辑

拼多多在“多多果园”里上线了“多多斗地主”游戏,找了一圈也没找到能用的记牌器,索性用Autojs自己写了一个。
测试环境是MIUI11,安卓9,分辨率为1920x1080,Autojs4.1.1
思路就是将截图灰度并阈值化处理,然后找图(每次找图输出的时机是轮到本方出牌时)

使用过程中的几张截图,见下(最上面的记牌器是拼多多需使用道具购买的记牌器,下方的是我的记牌器,我的记牌器没记录大小王,因为灰度处理截图后大小王是一样的,而且这两张牌也没多大必要记录,一般人都能记得住

2021年4月15日更新:
不少人不知道怎么用,因为没有适配不同分辨率,所以不是1920x1080的,需要自行修改。
将找图文件(见附件)放入/sdcard/360/文件夹下。
特意做了个说明图(见下),看看这个脚本的获取区域是怎样的。
添加了打开拼多多的代码。
每次启动记牌器的时机是等叫地主环节结束后,一局游戏结束后,停止记牌器(按音量键),新游戏开始时再运行一次即可。
为了方便多次运行记牌器,在Autojs的“示例代码”文件夹下有个叫“悬浮窗”的文件夹,在里面有个“悬浮运行脚本按钮”的脚本,编辑它,将第一行的路径设置为记牌器脚本的完整路径,保存,运行“悬浮运行脚本按钮”。这时在手机左上角会有个“开始运行”按钮,通过这个按钮就能启动和停止记牌器了。为了方便大家操作,我也将这个“悬浮运行脚本按钮”的脚本发到最下面。



---------------------------------------------更新分隔线---------------------------------------------










[JavaScript] 纯文本查看 复制代码
//请求截图
if(!requestScreenCapture()){
    toast("请求截图失败");
    exit();
}
//测试环境:MIUI11,安卓9,分辨率为1920x1080,Autojs4.1.1
//找图思路:截图→灰度自适应阈值化处理→找图→每当本方回合→输出已出牌到记牌器
//使用前准备:将所有牌的灰度自适应阀值化处理后的小图存到basePath下
//使用方法:游戏开始时,点悬浮窗的“开始运行”即可。
var basePath = "/sdcard/360/"; //找图文件所在路径
var cardList = [2,"A","K","Q","J",10,9,8,7,6,5,4,3]; //显示在记牌器中的牌组(不含大小王)
var numList = [2,1,13,12,11,10,9,8,7,6,5,4,3]; //找图用,牌组文件名(不含扩展名)
var numCount = [4,4,4,4,4,4,4,4,4,4,4,4,4]; //初始时各牌的最大数量
var curCount = []; //已出牌的数组
var switchMode = 0; //记录上一次已出牌的数组,为了防止重复匹配
var myTurn = 0; //判断是否为本方回合
var window;

main();

//主函数
function main() {
    launchApp("拼多多");
    sleep(2000);
    initCard(); //检索本方手牌
    initWindow(); //初始化记牌器
    checkCard(); //循环检索打出的牌
}

//初始化记牌器
function initWindow() {
    window = floaty.window(
        <frame gravity="center" bg="#f4f5f6">
            <text id="card" textSize="14sp" textColor="#62220f" padding="13 4 0 0"/>
            <text id="num" textSize="14sp" textColor="#ca3331" padding="13 5 0 3"/>
        </frame>
    );
    window.exitOnClose();
    window.setSize(880, 185); //记牌器的尺寸
    window.setPosition(135, 145); //记牌器的位置
    window.num.click(()=>{
        window.setAdjustEnabled(!window.isAdjustEnabled());
    });
    //将本方手牌输出到记牌器
    ui.run(function(){
        window.card.setText(cardList.join('    '));
        window.num.setText("\n"+curCount.join("    "));
    });
}
// 循环检索打出的牌并输出到记牌器
function checkCard() {
    setInterval(()=>{
        switchMode = myTurn;
        myTurn = isMyTurn();
        // print("myTurn:"+myTurn);
        // print("switchMode:"+switchMode);
        if (myTurn == 1 && switchMode!=myTurn) {
            // print("又轮到我了!!");
            sleep(500); //炸弹、飞机、连对时有特效,延迟一会等特效消失才能更好的判断是否为本方回合
            ui.run(function(){
                window.card.setText(cardList.join('    ')); //输出本方手牌到记牌器
                window.num.setText(dynamicNum()); //输出打出的牌到记牌器
            });
        }
    }, 1000);
}

//检索打出的牌
function dynamicNum() {
    getCard();
    str = "\n"+curCount.join("    ");
    return str;
}
//检索全部牌,返回检索到的手牌数组(按numList数组排序)
//参数mode默认为检索打出的牌,当为'own'时则表示检索本方手牌
//TODO 先判断已出牌的数量,再进行检索
function findAllNum(mode) {
    var img = captureScreen();
    var g = images.grayscale(img);
    var bgImg = images.adaptiveThreshold(g, 200, "MEAN_C", "BINARY", 25, 10);
    var mybg = "/sdcard/360/mybg.png";
    images.saveImage(bgImg, mybg);
    var tempArr = [];
    img = images.read(mybg);
    for (var nl=0;nl<13;nl++) {
        var curTotal = 0;//计数
        if (mode == 'own') {
            var curDes = basePath + numList[nl] + ".png";
            var mydes = images.read(curDes);
            var point = images.matchTemplate(img, mydes,{region:[20,1215,1030,400],threshold:0.9,max:4, level:1}); // 本方的手牌
            if (point!=null) {
                curTotal = curTotal + point.matches.length;
            }
        } else {
            var curDes = basePath + numList[nl] + "s.png";
            var mydes = images.read(curDes);
            var point = images.matchTemplate(img, mydes,{region:[0,592,1030,563],threshold:0.8,max:4, level:1}); // 出牌的部分
            if (point!=null) {
                curTotal = curTotal + point.matches.length;
            }
        }
        mydes.recycle();
        tempArr.push(curTotal);
    }
    img.recycle();
    return tempArr;
}

// 初始化牌(即将自己的手牌排除在剩余牌组外)
function initCard() {
    own = findAllNum('own');
    // print("own    :"+own.join(","))
    curCount = makeDiffArr(numCount, own);
    print("curCoun:"+curCount.join(","));
    curCount[3] = " "+ curCount[3]; //细调位置
    curCount[5] = "  "+ curCount[5]; //细调位置
}

// 获取出牌时的牌,并计算剩余牌组
function getCard() {
    other = findAllNum('other');
    print("other  :"+other.join(","))
    var re = 0;
    while (sum(other) == 0) {
        if (re > 4) {
            break;
        }
        other = findAllNum('other');
        re++;
    }
    curCount = makeDiffArr(curCount, other);
    print("curCoun:"+curCount.join(","));
    curCount[3] = " "+ curCount[3]; //细调位置
    curCount[5] = "  "+ curCount[5]; //细调位置
}

//计算数组内所有数值相加后的结果
function sum(arr) {
    return eval(arr.join("+"));
}
// 看看是不是已经到了我的回合,通过判断小闹钟的上左右 3 个坐标是否是二进制灰度后的黑色来进行的
function isMyTurn() {
    var n = 0;
    var img = captureScreen();
    var g = images.grayscale(img);
    var adaptiveImg = images.adaptiveThreshold(g, 200, "MEAN_C", "BINARY", 25, 10);
    var myTurnBg = "/sdcard/360/myturnbg.png";
    images.saveImage(adaptiveImg, myTurnBg);
    adaImg = images.read(myTurnBg);
    if (adaImg != null) {
        if(images.detectsColor(adaImg, "#000000", 675, 1186)){ //本方能出得起牌时的小闹钟颜色和坐标(通过这个来判断的)
            n++;
        }
        if(images.detectsColor(adaImg, "#000000", 404, 1187)){ //本方出不起牌时的小闹钟颜色和坐标
            n++;
        }
        if (n >= 1) {
            print("轮到我了!");
            adaImg.recycle();
            return 1;
        }
    }
    adaImg.recycle();
    return 0;
}

// 返回两个数组的差所能成的新数组
function makeDiffArr(arr1, arr2) {
    var tempArr = [];
    for (var i=0;i<arr1.length;i++) {
        var t = arr1[i]-arr2[i];
        if (t<0) t = 0;
        tempArr.push(t);
    }
    return tempArr;
}


** 以上文件可以命名为 jpq **
[JavaScript] 纯文本查看 复制代码
var path = "/sdcard/脚本/jqp.js";
if(!files.exists(path)){
    toast("脚本文件不存在: " + path);
    exit();
}
var window = floaty.window(
    <frame>
        <button id="action" text="开始运行" w="90" h="40" bg="#77ffffff"/>
    </frame>
);

setInterval(()=>{}, 1000);

var execution = null;

//记录按键被按下时的触摸坐标
var x = 0, y = 0;
//记录按键被按下时的悬浮窗位置
var windowX, windowY;
//记录按键被按下的时间以便判断长按等动作
var downTime;

window.action.setOnTouchListener(function(view, event){
    switch(event.getAction()){
        case event.ACTION_DOWN:
            x = event.getRawX();
            y = event.getRawY();
            windowX = window.getX();
            windowY = window.getY();
            downTime = new Date().getTime();
            return true;
        case event.ACTION_MOVE:
            //移动手指时调整悬浮窗位置
            window.setPosition(windowX + (event.getRawX() - x),
                windowY + (event.getRawY() - y));
            //如果按下的时间超过1.5秒判断为长按,退出脚本
            if(new Date().getTime() - downTime > 1500){
                exit();
            }
            return true;
        case event.ACTION_UP:
            //手指弹起时如果偏移很小则判断为点击
            if(Math.abs(event.getRawY() - y) < 5 && Math.abs(event.getRawX() - x) < 5){
                onClick();
            }
            return true;
    }
    return true;
});

function onClick(){
    if(window.action.getText() == '开始运行'){
        execution = engines.execScriptFile(path);
        window.action.setText('停止运行');
    }else{
        if(execution){
            execution.getEngine().forceStop();
        }
        window.action.setText('开始运行');
    }
}


**以上为悬浮运行脚本按钮的脚本,第一行就是记牌器脚本的路径,改成你手机上记牌器的路径后,保存,运行

pddRecordImgs.zip

44.63 KB, 下载次数: 383, 下载积分: 吾爱币 -1 CB

找图文件

免费评分

参与人数 7吾爱币 +7 热心值 +6 收起 理由
gannong + 1 热心回复!
bloodsoul + 1 + 1 谢谢@Thanks!
zailzkz + 1 + 1 谢谢@Thanks!
小兴818 + 1 + 1 谢谢@Thanks!优秀到我惊
Cool_Breeze + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
影视专业 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
鸭鸭鸭? + 1 + 1 厉害厉害

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
睿智爱宝 发表于 2021-4-9 15:59
还有这个操作,六了六了
推荐
Amenggwf 发表于 2021-4-16 21:12
spawn_fly 发表于 2021-4-16 14:48
你这autojs是什么版本的?网上有很多版本,我之前用的是酷安上有人反编译的,找图的时候经常出错。后来换 ...

换了个4.1.1的版本,运行不报错了,但还是记牌不准确啊!

//请求截图
if(!requestScreenCapture()){
    toast("请求截图失败");
    exit();
}
//测试环境:MIUI11,安卓9,分辨率为1920x1080,Autojs4.1.1
//找图思路:截图→灰度自适应阈值化处理→找图→每当本方回合→输出已出牌到记牌器
//使用前准备:将所有牌的灰度自适应阀值化处理后的小图存到basePath下
//使用方法:游戏开始时,点悬浮窗的“开始运行”即可。
var basePath = "/sdcard/360/"; //找图文件所在路径
var cardList = [2,"A","K","Q","J",10,9,8,7,6,5,4,3]; //显示在记牌器中的牌组(不含大小王)
var numList = [2,1,13,12,11,10,9,8,7,6,5,4,3]; //找图用,牌组文件名(不含扩展名)
var numCount = [4,4,4,4,4,4,4,4,4,4,4,4,4]; //初始时各牌的最大数量
var curCount = []; //已出牌的数组
var switchMode = 0; //记录上一次已出牌的数组,为了防止重复匹配
var myTurn = 0; //判断是否为本方回合
var window;

main();

//主函数
function main() {
    //launchApp("拼多多");
    //sleep(2000);
    initCard(); //检索本方手牌
    initWindow(); //初始化记牌器
    checkCard(); //循环检索打出的牌
}

//初始化记牌器
function initWindow() {
    window = floaty.window(
        <frame gravity="center" bg="#f4f5f6">
            <text id="card" textSize="14sp" textColor="#62220f" padding="13 4 0 0"/>
            <text id="num" textSize="14sp" textColor="#ca3331" padding="13 5 0 3"/>
        </frame>
    );
    window.exitOnClose();
    window.setSize(1100, 250); //记牌器的尺寸
    window.setPosition(135, 145); //记牌器的位置
    window.num.click(()=>{
        window.setAdjustEnabled(!window.isAdjustEnabled());
    });
    //将本方手牌输出到记牌器
    ui.run(function(){
        window.card.setText(cardList.join('    '));
        window.num.setText("\n"+curCount.join("    "));
    });
}
// 循环检索打出的牌并输出到记牌器
function checkCard() {
    setInterval(()=>{
        switchMode = myTurn;
        myTurn = isMyTurn();
        // print("myTurn:"+myTurn);
        // print("switchMode:"+switchMode);
        if (myTurn == 1 && switchMode!=myTurn) {
            // print("又轮到我了!!");
            sleep(500); //炸弹、飞机、连对时有特效,延迟一会等特效消失才能更好的判断是否为本方回合
            ui.run(function(){
                window.card.setText(cardList.join('    ')); //输出本方手牌到记牌器
                window.num.setText(dynamicNum()); //输出打出的牌到记牌器
            });
        }
    }, 1000);
}

//检索打出的牌
function dynamicNum() {
    getCard();
    str = "\n"+curCount.join("    ");
    return str;
}
//检索全部牌,返回检索到的手牌数组(按numList数组排序)
//参数mode默认为检索打出的牌,当为'own'时则表示检索本方手牌
//TODO 先判断已出牌的数量,再进行检索
function findAllNum(mode) {
    var img = captureScreen();
    var g = images.grayscale(img);
    var bgImg = images.adaptiveThreshold(g, 200, "MEAN_C", "BINARY", 25, 10);
    var mybg = "/sdcard/360/mybg.png";
    images.saveImage(bgImg, mybg);
    var tempArr = [];
    img = images.read(mybg);
    for (var nl=0;nl<13;nl++) {
        var curTotal = 0;//计数
        if (mode == 'own') {
            var curDes = basePath + numList[nl] + ".png";
            var mydes = images.read(curDes);
            var point = images.matchTemplate(img, mydes,{region:[20,1500,1030,400],threshold:0.9,max:4, level:1}); // 本方的手牌
            if (point!=null) {
                curTotal = curTotal + point.matches.length;
            }
        } else {
            var curDes = basePath + numList[nl] + "s.png";
            var mydes = images.read(curDes);
            var point = images.matchTemplate(img, mydes,{region:[0,592,1030,563],threshold:0.8,max:4, level:1}); // 出牌的部分
            if (point!=null) {
                curTotal = curTotal + point.matches.length;
            }
        }
        mydes.recycle();
        tempArr.push(curTotal);
    }
    img.recycle();
    return tempArr;
}

// 初始化牌(即将自己的手牌排除在剩余牌组外)
function initCard() {
    own = findAllNum('own');
    // print("own    :"+own.join(","))
    curCount = makeDiffArr(numCount, own);
    print("curCoun:"+curCount.join(","));
    curCount[3] = " "+ curCount[3]; //细调位置
    curCount[5] = "  "+ curCount[5]; //细调位置
}

// 获取出牌时的牌,并计算剩余牌组
function getCard() {
    other = findAllNum('other');
    print("other  :"+other.join(","))
    var re = 0;
    while (sum(other) == 0) {
        if (re > 4) {
            break;
        }
        other = findAllNum('other');
        re++;
    }
    curCount = makeDiffArr(curCount, other);
    print("curCoun:"+curCount.join(","));
    curCount[3] = " "+ curCount[3]; //细调位置
    curCount[5] = "  "+ curCount[5]; //细调位置
}

//计算数组内所有数值相加后的结果
function sum(arr) {
    return eval(arr.join("+"));
}
// 看看是不是已经到了我的回合,通过判断小闹钟的上左右 3 个坐标是否是二进制灰度后的黑色来进行的
function isMyTurn() {
    var n = 0;
    var img = captureScreen();
    var g = images.grayscale(img);
    var adaptiveImg = images.adaptiveThreshold(g, 200, "MEAN_C", "BINARY", 25, 10);
    var myTurnBg = "/sdcard/360/myturnbg.png";
    images.saveImage(adaptiveImg, myTurnBg);
    adaImg = images.read(myTurnBg);
    if (adaImg != null) {
        if(images.detectsColor(adaImg, "#000000", 672, 1371)){ //本方能出得起牌时的小闹钟颜色和坐标(通过这个来判断的)
            n++;
        }
        if(images.detectsColor(adaImg, "#000000", 401, 1371)){ //本方出不起牌时的小闹钟颜色和坐标
            n++;
        }
        if (n >= 1) {
            print("轮到我了!");
            adaImg.recycle();
            return 1;
        }
    }
    adaImg.recycle();
    return 0;
}

// 返回两个数组的差所能成的新数组
function makeDiffArr(arr1, arr2) {
    var tempArr = [];
    for (var i=0;i<arr1.length;i++) {
        var t = arr1-arr2;
        if (t<0) t = 0;
        tempArr.push(t);
    }
    return tempArr;
}

微信图片_20210416210908.jpg (173.93 KB, 下载次数: 0)

微信图片_20210416210908.jpg

2.jpg (198.42 KB, 下载次数: 0)

2.jpg

3.jpg (201.55 KB, 下载次数: 0)

3.jpg
沙发
小二白 发表于 2021-4-9 15:27
3#
xscbelieve 发表于 2021-4-9 15:28
拼多多已删
4#
梦如星陨 发表于 2021-4-9 15:33
拼多多对我来说就是买五块钱以下东西的,斗地主有JJ即可,不过还是支持大神
5#
muyu110 发表于 2021-4-9 15:33
感觉很厉害的样子,,,
6#
395552895 发表于 2021-4-9 15:38
我先下载去斗两把
7#
血情 发表于 2021-4-9 15:45
没有成品吗,楼主
8#
随意飘荡 发表于 2021-4-9 15:58
厉害呀。。。果然是万能的论坛
10#
li20050730 发表于 2021-4-9 16:03
我想要自己玩的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-6-4 23:06

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表