连连看
close_llk();
// toast("开始运行");
// while (true) {
// sleep(200);
// let img = images.captureScreen();
// let color = images.pixel(img, 410, 615);
// // let color = images.pixel(img, 390, 615);
// if (colors.isSimilar(color, color_target, 5, "rgb+")) break;
// }
// // sleep(4000)
// let img = images.captureScreen();
// let img = images.read("/sdcard/Samsung Flow/llk2.png");
// llk();
var w = floaty.rawWindow(
<frame gravity="center" w="226" h="70" alpha="0.6">
<horizontal>
<button id="b_run" w="113" h="70" text="准备中"></button>
<button id="b_auto" w="113" h="70" text="准备中"></button>
</horizontal>
</frame >
);
w.setPosition(330, 2590);
auto.waitFor();
images.requestScreenCapture();
events.on("exit", function () {
img.recycle();
icon_block.recycle();
for (let k = 1; k <= 28; ++k) {
imgIcons[k].recycle();
imgIcons_ice[k].recycle();
}
log("recycle imgs done!")
});
let icon_block = images.read("/sdcard/Samsung Flow/icon_block.png");
let imgIcons = new Array(29);
let imgIcons_ice = new Array(29);
for (let k = 1; k <= 28; ++k) {
imgIcons[k] = images.read("/sdcard/Samsung Flow/llk1/" + k + ".png");
imgIcons_ice[k] = images.read("/sdcard/Samsung Flow/llkice1/" + k + ".png");
}
let color_target = colors.parseColor("#F6A85E");
let llk_running = false;
let manual_run = false;
let llk_auto_run = true;
// llk_auto_run = false;
let llk_no_dfs = true;
w.b_run.click(() => {
if (!llk_running) {
manual_run = true;
w.b_run.setText("队列中");
}
});
w.b_auto.click(() => {
if (llk_auto_run) {
llk_auto_run = false;
w.b_auto.setText("已关闭自动运行");
} else {
llk_auto_run = true;
w.b_auto.setText("已开启自动运行");
}
});
w.b_run.setText("手动启动");
w.b_auto.setText("已开启自动运行");
log("init done!");
while (true) {
if (llk_auto_run) {
img = images.captureScreen();
let color = images.pixel(img, 410, 615);
// let color = images.pixel(img, 390, 615);
if (colors.isSimilar(color, color_target, 5, "rgb+")) {
sleep(20);
img = images.captureScreen();
llk_running = true;
// llk_auto_run = false;
manual_run = false;
// w.b_auto.setText("已关闭自动运行");
w.b_run.setText("自动运行中");
llk();
llk_running = false;
w.b_run.setText("手动启动");
// sleep(300);
}
} else if (manual_run) {
llk_running = true;
manual_run = false;
w.b_run.setText("手动运行中");
img = images.captureScreen();
llk();
llk_running = false;
w.b_run.setText("手动启动");
}
sleep(100);
}
function llk() {
const map = {
r: 8, //地图行数
c: 7, //地图列数
start_x: 0, //方块起始点x坐标
start_y: 808 //方块起始点y坐标
}
map.start_x = map.c == 8 ? 48 : 132;
const arrLen = { r: (map.r + 2), c: (map.c + 2) };//数组大小
const _region = [map.start_x, map.start_y, map.c * 168, map.r * 168]; //找图区间
const _threshold = 0.85; //找图精确度
const log_icons = ["⬛", "⬜", "🟥", "🟪", "🟨", "🟧", "🟦", "🟩", "🟫", "⚪", "🔴", "🟣", "🟡", "🟠", "🔵", "🟢", "🟤", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘", "🌑", "❤", "🧡", "💛", "💚", "💙", "💜", "🤎", "⛔", "🧊"]; //打印图形用图标
const d = [[-1, 0], [1, 0], [0, -1], [0, 1]]; //遍历四个方向
const path = [{ y1: -1, x1: -1, y2: -1, x2: -1 }]; //存储路径搜索结果:表示 (y1, x1) 与 (y2, x2) 可消除
const mp_bw = initArr(arrLen.r, arrLen.c, 0); //地图预处理结果,取值0/1表示是否存在方块
const mp = initArr(arrLen.r, arrLen.c, 0); //地图最终处理结果,0为空,相同的数字代表是同一种方块
const v = new Array(); //二维数组,以方块类型编号为下标,存储该类型方块的坐标
for (let k = 1; k <= 28; ++k) v[k] = new Array();
getMap(); //获取地图,将会写入 mp_bw, mp, v 数组, 其中 mp 数组是为了可视化展示路径用
if (check_map_clean()) return;
// logMap(mp_bw);
logMap(mp);
check_edge(); //检查是否存在某种类型的方块个数是奇数个(多为提取地图出错导致)
// mp_bw[1][1] = mp_bw[2][2] = mp_bw[2][4] = mp_bw[4][2] = 0;
// logMap(mp_bw);
// log(check_connection({ y: 1, x: 5 }, { y: 6, x: 3 }));
// log(check_connection(v[2][0], v[2][1]));
// exit();
let flag_success = false; //标记搜索路径是否成功
let date1 = new Date().getTime();
if (llk_no_dfs)
no_backtrace_search();
else
dfs();
let date2 = new Date().getTime();
log("搜索路径用时:" + (date2 - date1) + "ms");
/* ⛔⛔⛔⛔ no_backtrace_search()无回溯暴力遍历所有点组合,只要遇到能连的点就连,
⛔🟩🟩⛔ 适用于地图只有部分解(只能消除一部分)的情况,
⛔ ⛔ 可能无法解决如左图的情况。
⛔🟪🟩⛔ bfs()同样是遍历所有点的组合,但遇到无解情况会回溯,直到成功为止,
⛔🟩🟪⛔ 适用于当前地图有完全解(能清空)的情况,否则会返回空解集
⛔⛔⛔⛔ 左图情况可以找到正确路径。 */
// log(path);
// exit();
click_path(30);
// draw_path();
return;
function click_path(speed) {
// return;
if (llk_no_dfs) {
for (let k = 1; k < path.length; ++k) {
press(getX(path[k].x1) + 50, getY(path[k].y1) + 50, 1);
sleep(speed);
// sleep(270);
press(getX(path[k].x2) + 50, getY(path[k].y2) + 50, 1);
sleep(speed);
// sleep(470);
}
} else {
for (let k = path.length - 1; k >= 1; --k) {
press(getX(path[k].x1) + 50, getY(path[k].y1) + 50, 1);
sleep(speed);
// sleep(270);
press(getX(path[k].x2) + 50, getY(path[k].y2) + 50, 1);
sleep(speed);
// sleep(470);
}
}
}
function draw_path() {
logMap(mp);
sleep(10);
// for (let k = 1; k < path.length; ++k) {
for (let k = path.length - 1; k >= 1; --k) {
let logStr = "\n";
for (let i = 0; i < arrLen.r; ++i) {
for (let j = 0; j < arrLen.c - 1; ++j) {
if ((i == path[k].y1 && j == path[k].x1) || (i == path[k].y2 && j == path[k].x2))
logStr += "💎";//log_icons_c[mp[i][j]];
else
logStr += log_icons[mp[i][j]];
}
if ((i == path[k].y1 && (arrLen.c - 1) == path[k].x1) || (i == path[k].y2 && (arrLen.c - 1) == path[k].x2))
logStr += "💎"//log_icons_c[mp[i][arrLen.c - 1]];
else
logStr += log_icons[mp[i][arrLen.c - 1]];
if (i != arrLen.r - 1)
logStr += "\n";
}
log(logStr);
mp[path[k].y1][path[k].x1] = mp[path[k].y2][path[k].x2] = 0;
sleep(10);
}
}
function no_backtrace_search() {
while (true) {
// log("--------");
let flag_no_op = 1;
for (let i = 1; i <= 28; ++i) {
// log("dfs 第 " + i + " 种方块", difItem);
for (let j = 0; j < v[i].length; ++j) {
for (let k = j + 1; k < v[i].length; ++k) {
if (v[i][j].vis || v[i][k].vis || check_ice(v[i][j]) || check_ice(v[i][k])) continue;
if (check_connection(v[i][j], v[i][k])) {
flag_no_op = 0;
// click_block(v[i][j].x, v[i][j].y, v[i][k].x, v[i][k].y, 30);
// log(" succ (" + v[i][j].y + ", " + v[i][j].x + ") - (" + v[i][k].y + ", " + v[i][k].x + ")");
path.push({ y1: v[i][j].y, x1: v[i][j].x, y2: v[i][k].y, x2: v[i][k].x });
mp_bw[v[i][j].y][v[i][j].x] = mp_bw[v[i][k].y][v[i][k].x] = 0;
v[i][j].vis = v[i][k].vis = 1;
let tx, ty;
for (let m = 0; m < 4; ++m) {
tx = v[i][j].x + d[m][0]; ty = v[i][j].y + d[m][1];
if (mp_bw[ty][tx] == 33) mp_bw[ty][tx] = 1;
tx = v[i][k].x + d[m][0]; ty = v[i][k].y + d[m][1];
if (mp_bw[ty][tx] == 33) mp_bw[ty][tx] = 1;
}
} else {
// logMap(mp_bw);
// log(" **** [" + i + "][" + j + "] - [" + i + "][" + k + "] - " + check_connection(v[i][j], v[i][k]));
// log(" fail (" + v[i][j].y + ", " + v[i][j].x + ") - (" + v[i][k].y + ", " + v[i][k].x + ")");
}
}
}
}
// log("--------");
if (flag_no_op) return;
}
}
function check_ice(u) {
return mp_bw[u.y][u.x] == 33;
}
function dfs() {
if (check_map_clean()) {
// logMap(mp_bw);
log("dfs successed!");
flag_success = true;
return;
}
// log("dfs check fail");
// 最坏情况 O()
for (let i = 1; i <= 28; ++i) {
// log("dfs 第 " + i + " 种方块,共", v[i].length);
for (let j = 0; j < v[i].length; ++j) {
for (let k = j + 1; k < v[i].length; ++k) {
if (v[i][j].vis || v[i][k].vis || check_ice(v[i][j]) || check_ice(v[i][k])) continue;
if (check_connection(v[i][j], v[i][k])) {
// log(" ***suc (" + v[i][j].y + ", " + v[i][j].x + ") - (" + v[i][k].y + ", " + v[i][k].x + ") ***");
mp_bw[v[i][j].y][v[i][j].x] = mp_bw[v[i][k].y][v[i][k].x] = 0;
v[i][j].vis = v[i][k].vis = 1;
let bt = new Array(); // backtrace数组记录解冻操作
let tx, ty;
for (let m = 0; m < 4; ++m) {
tx = v[i][j].x + d[m][0]; ty = v[i][j].y + d[m][1];
if (mp_bw[ty][tx] == 33) { mp_bw[ty][tx] = 1; bt.push({ y: ty, x: tx }); }
tx = v[i][k].x + d[m][0]; ty = v[i][k].y + d[m][1];
if (mp_bw[ty][tx] == 33) { mp_bw[ty][tx] = 1; bt.push({ y: ty, x: tx }); }
}
dfs();
if (flag_success) {
path.push({ y1: v[i][j].y, x1: v[i][j].x, y2: v[i][k].y, x2: v[i][k].x });
return;
}
// log(" **回溯 👆")
mp_bw[v[i][j].y][v[i][j].x] = mp_bw[v[i][k].y][v[i][k].x] = 1;
for (let m = 0; m < bt.length; ++m)
mp_bw[bt[m].y][bt[m].x] = 33;
} else {
// logMap(mp_bw);
// log(" **** [" + i + "][" + j + "] - [" + i + "][" + k + "] - " + check_connection(v[i][j], v[i][k]));
// log(" fail (" + v[i][j].y + ", " + v[i][j].x + ") - (" + v[i][k].y + ", " + v[i][k].x + ")");
}
}
}
}
// flag_success = true;
// throw new Error("No solution");
}
function check_connection(a, b) {
// if (a.vis || b.vis) return false;
let t = { x: 0, y: 0, dir: -1, turn: -1 };
let x, y, dir, turn;
const q = [{ x: a.x, y: a.y, dir: -1, turn: -1 }];
const vis = new Array(arrLen.r);
for (let k = 0; k < arrLen.r; k++) {
vis[k] = new Array(arrLen.c);
for (let j = 0; j < arrLen.c; j++) {
vis[k][j] = new Array(4);
vis[k][j][0] = vis[k][j][1] = vis[k][j][2] = vis[k][j][3] = 0x3f3f3f3f;
}
}
// const vis = initArr(arrLen.r, arrLen.c, { 0: 0x3f3f3f3f, 1: 0x3f3f3f3f, 2: 0x3f3f3f3f, 3: 0x3f3f3f3f });
vis[a.y][a.x] = 1;
while (q.length) {
t = q.shift();
// log("****: " + t.y, t.x, t.dir, t.turn);
for (let i = 0; i < 4; ++i) {
x = t.x + d[i][0];
y = t.y + d[i][1];
dir = i;
turn = t.turn + (t.dir != i);
if (turn <= 2 && x >= 0 && y >= 0 && x < arrLen.c && y < arrLen.r) {
// log(" **: " + y, x, dir, turn, "mp:", mp_bw[y][x], "vis:", vis[y][x]);
if (y == b.y && x == b.x) return true;
if (mp_bw[y][x] == 0 && vis[y][x][dir] > turn) {
// log("push (" + y + ", " + x + ") d:" + dir + " turn:" + turn);
vis[y][x][dir] = turn;
q.push({ x: x, y: y, dir: dir, turn: turn });
}
}
}
}
return false;
}
function check_map_clean() {
for (let i = 1; i <= map.r; ++i)
for (let j = 1; j <= map.c; ++j)
if (mp_bw[i][j] == 1 || mp_bw[i][j] == 33)
return false;
return true;
}
function getMap() {
let date1 = new Date().getTime();
// let colorCorner = colors.parseColor("#f7f7f5");
let colorCorner2 = colors.parseColor("#f7f7f7");
let colorIce = colors.parseColor("#e5fcff");
// log(colorCorner, colorCorner2);
// var file_catalog = "/sdcard/Samsung Flow/llkice1/";
// var recv = files.listDir(file_catalog, function (name) {
// return name.endsWith(".png") && files.isFile(files.join(file_catalog, name));
// });
// let cnt = recv.length;
// log("cnt1: ", cnt);
// log("mp_bw start");
for (let i = 1; i <= map.r; ++i) {
for (let j = 1; j <= map.c; ++j) {
let color = images.pixel(img, getX(j) + 10, getY(i) + 10);
// log("(" + i + ", " + j + ") :" + colors.toString(color).replace("#ff", "#"));
if (colors.isSimilar(color, colorCorner2, 10, "rgb+")) {
mp_bw[i][j] = 1;
}
}
}
if (check_map_clean()) return;
// log("mp_bw done");
// log("cnt1: **", cnt);
//线程1:寻找冰块 + 识别冰块类型
let find_img_thread1 = threads.start(function () {
// log("ice start");
for (let i = 1; i <= map.r; ++i) {
for (let j = 1; j <= map.c; ++j) {
let color = images.pixel(img, getX(j) + 10, getY(i) + 10);
if (colors.isSimilar(color, colorIce, 10, "rgb+")) {
mp_bw[i][j] = 33;
// let flag = true;
// let imgIcon = images.clip(img, getX(j) + 10, getY(i) + 10, 148, 148);
for (let k = 1; k <= 28; ++k) {
if (images.findImage(img, imgIcons_ice[k], {
region: [getX(j) + 10, getY(i) + 10, 148, 148],
threshold: 0.95,
level: 1
})) {
v[k].push({ y: i, x: j, vis: 0 });
mp[i][j] = k;
break;
}
}
// if (flag)
// images.save(imgIcon, "/sdcard/Samsung Flow/llkice1/" + (++cnt) + ".png", "png", 100);
// imgIcon.recycle();
}
}
}
log("ice done");
logMap(mp_bw);
});
// let file_catalog2 = "/sdcard/Samsung Flow/llk1/";
// let recv2 = files.listDir(file_catalog2, function (name) {
// return name.endsWith(".png") && files.isFile(files.join(file_catalog2, name));
// });
// let cnt2 = recv2.length;
// log("cnt2: ", cnt2);
// let imgMap = images.clip(img, map.start_x, map.start_y, map.c * 168, map.r * 168);
// let idx = 1;
function check_block_type(start, end) {
for (let k = start; k <= end; ++k) {
let points = images.matchTemplate(img, imgIcons[k], {
region: _region,
threshold: _threshold,
max: 6
}).points;
points.forEach(point => {
let ii, jj;
for (ii = map.c; ii > 0; --ii)
if (point.x >= getX(ii))
break;
for (jj = map.r; jj > 0; --jj)
if (point.y >= getY(jj))
break;
// log("(" + (ii + 1) + ", " + (jj + 1) + ") :" + k);
if (mp_bw[jj][ii] == 1) {
mp[jj][ii] = k;
v[k].push({ y: jj, x: ii, vis: 0 });
}
});
}
}
//线程2,3:和主线程分摊全图找图任务
let find_img_thread2 = threads.start(function () {
// log("thread 2 start");
check_block_type(10, 19)
log("thread 2 done");
find_img_thread2.interrupt();
});
let find_img_thread3 = threads.start(function () {
// log("thread 3 start");
check_block_type(20, 28)
log("thread 3 done");
find_img_thread3.interrupt();
});
// log("thread main start");
check_block_type(1, 9);
log("thread main done");
while (find_img_thread2 && find_img_thread2.isAlive()) { sleep(30); }
while (find_img_thread3 && find_img_thread3.isAlive()) { sleep(30); }
log("**** all done!")
//********* 旧版方法:遇到未识别的方块剪切处理后进行全图识别,难以并行处理 *********
// for (let i = 1; i <= map.r; ++i) {
// for (let j = 1; j <= map.c; ++j) {
// if (mp_bw[i][j] == 1 && 0 == mp[i][j]) {
// // log("(" + (i + 1) + ", " + (j + 1) + ") :", 310 + 168 * j, 1154 + 168 * i, 148, 148);
// let imgIcon = images.clip(img, getX(j) + 10, getY(i) + 10, 148, 148);
// // images.save(imgIcon, "/sdcard/Samsung Flow/llk1/" + idx + ".png", "png", 100);
// let points = images.matchTemplate(img, imgIcon, {
// region: _region,
// threshold: _threshold,
// max: 6
// }).points;
// // let flag = true;
// // for (let k = 1; k <= cnt2; ++k) {
// // imga = images.read("/sdcard/Samsung Flow/llk1/" + k + ".png");
// // if (images.findImage(imga, imgIcon)) { flag = false; break; }
// // imga.recycle();
// // }
// // if (flag)
// // log("save ", cnt2);
// // if (flag)
// // images.save(imgIcon, "/sdcard/Samsung Flow/llk1/" + (++cnt2) + ".png", "png", 100);
// imgIcon.recycle();
// // log(points);
// v[idx] = new Array();
// points.forEach(point => {
// let ii, jj;
// for (ii = map.c; ii > 0; --ii) if (point.x >= getX(ii)) break;
// for (jj = map.r; jj > 0; --jj) if (point.y >= getY(jj)) break;
// // log("(" + (ii + 1) + ", " + (jj + 1) + ") :" + idx);
// mp[jj][ii] = idx;
// v[idx].push({ y: jj, x: ii, vis: 0 });
// });
// ++idx;
// }
// }
// }
// difItem = idx;
difItem = 28;
// imgMap.recycle();
// log("cnt2: **", cnt2);
let points = images.matchTemplate(img, icon_block, {
region: [map.start_x, map.start_y, map.c * 168, map.r * 168],
threshold: 0.8
}).points;
points.forEach(point => {
let ii, jj;
for (ii = map.c; ii > 0; --ii) if (point.x >= getX(ii)) break;
for (jj = map.r; jj > 0; --jj) if (point.y >= getY(jj)) break;
mp_bw[jj][ii] = mp[jj][ii] = 32;
});
while (find_img_thread1 && find_img_thread1.isAlive()) { sleep(30); }
let date2 = new Date().getTime();
log("地图处理用时:" + (date2 - date1) + "ms");
}
function check_edge() {
return;
for (let i = 1; i <= 28; ++i) {
log(v[i]);
// if (v[i].length % 2)
// throw new Error("number of points is odd at " + log_icons[i] + "(color " + i + " )");
}
}
function logMap(arr) {
let logStr = "\n";
for (let i = 0; i < arrLen.r; ++i) {
for (let j = 0; j < arrLen.c - 1; ++j) {
// log(String(mp_bw[i][j]));
logStr += log_icons[arr[i][j]];
}
logStr += log_icons[arr[i][arrLen.c - 1]];
if (i != arrLen.r - 1) logStr += "\n";
}
log(logStr);
}
function initArr(r, c, init) {
let tArr = new Array(r);
for (let k = 0; k < r; k++) {
tArr[k] = new Array(c);
for (let j = 0; j < c; j++) {
tArr[k][j] = init;
}
}
return tArr;
}
function getX(c) {
return map.start_x + 168 * (c - 1);
}
function getY(r) {
return map.start_y + 168 * (r - 1);
}
}
function llk_old() {
const mapSize = { r: 8, c: 8 }; //地图边长
// const mapSize = { r: 7, c: 5 }; //地图边长
// const mapStart = { x: 132, y: 808 }; //地图开始坐标
const mapStart = { x: mapSize.c == 8 ? 48 : 132, y: 808 }; //地图开始坐标
const arrLen = { r: (mapSize.r + 2), c: (mapSize.c + 2) };//数组大小
const _region = [mapStart.x, mapStart.y, mapSize.c * 168, mapSize.r * 168];
let difItem; // 方块种类数
const _threshold = 0.85; //找图精确度
const log_icons = ["⬛", "⬜", "🟥", "🟪", "🟨", "🟧", "🟦", "🟩", "🟫", "⚪", "🔴", "🟣", "🟡", "🟠", "🔵", "🟢", "🟤", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘", "🌑", "⛔", "🧊"]; //打印图形用图标
const log_icons_c = ["⚫", "⚪", "🔴", "🟣", "🟡", "🟠", "🔵", "🟢", "🟤", "⬜", "🟥", "🟪", "🟨", "🟧", "🟦", "🟩", "🟫", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘", "🌑", "⛔", "🧊"]; //打印图形用图标
let flag_success = false; //标记搜索路径是否成功
let icon_block = images.read("/sdcard/Samsung Flow/icon_block.png");
const mp_bw = initArr(arrLen.r, arrLen.c, 0); //地图预处理结果,取值0/1表示是否存在方块
const mp = initArr(arrLen.r, arrLen.c, 0); //地图最终处理结果,0为空,相同的数字代表是同一种方块
const v = new Array(); //二维数组,以方块类型编号为下标,存储该类型方块的坐标
const path = [{ y1: -1, x1: -1, y2: -1, x2: -1 }]; //存储运算结果:表示 (y1, x1) 与 (y2, x2) 可消除
getMap(); //获取地图,将会写入 mp_bw, mp, v 数组
if (check_map_clean()) return;
// logMap(mp_bw);
logMap(mp);
// check_edge(); //检查是否存在某种类型的方块个数是奇数个(多为提取地图出错导致)
// mp_bw[1][1] = mp_bw[2][2] = mp_bw[2][4] = mp_bw[4][2] = 0;
// logMap(mp_bw);
// log(judge_connection({ y: 1, x: 5 }, { y: 6, x: 3 }));
// log(judge_connection(v[2][0], v[2][1]));
// exit();
let date1 = new Date().getTime();
if (llk_no_dfs)
no_backtrace_search();
else
dfs();
let date2 = new Date().getTime();
toastLog("搜索路径用时:" + (date2 - date1) + "ms");
// log(path);
// exit();
for (let k = 1; k < path.length; ++k)
click_block(path[k].x1, path[k].y1, path[k].x2, path[k].y2, 30);
// draw_path();
icon_block.recycle();
return;
function click_block(x1, y1, x2, y2, speed) {
// for (let k = 1; k < path.length; ++k) {
// for (let k = path.length - 1; k >= 1; --k) {
press(getX(x1) + 50, getY(y1) + 50, 1);
sleep(speed);
// sleep(270);
press(getX(x2) + 50, getY(y2) + 50, 1);
sleep(speed);
// sleep(470);
// }
}
function draw_path() {
logMap(mp);
sleep(10);
for (let k = 1; k < path.length; ++k) {
// for (let k = path.length - 1; k >= 1; --k) {
let logStr = "\n";
for (let i = 0; i < arrLen.r; ++i) {
for (let j = 0; j < arrLen.c - 1; ++j) {
if ((i == path[k].y1 && j == path[k].x1) || (i == path[k].y2 && j == path[k].x2))
logStr += "💎";//log_icons_c[mp[i][j]];
else
logStr += log_icons[mp[i][j]];
}
if ((i == path[k].y1 && (arrLen.c - 1) == path[k].x1) || (i == path[k].y2 && (arrLen.c - 1) == path[k].x2))
logStr += "💎"//log_icons_c[mp[i][arrLen.c - 1]];
else
logStr += log_icons[mp[i][arrLen.c - 1]];
if (i != arrLen.r - 1)
logStr += "\n";
}
log(logStr);
mp[path[k].y1][path[k].x1] = mp[path[k].y2][path[k].x2] = 0;
sleep(10);
}
}
function no_backtrace_search() {
while (true) {
let flag_no_op = 1;
for (let i = 1; i < difItem; ++i) {
// log("dfs 第 " + i + " 种方块", difItem);
for (let j = 0; j < v[i].length; ++j) {
for (let k = j + 1; k < v[i].length; ++k) {
if (v[i][j].vis || v[i][k].vis) continue;
if (judge_connection(v[i][j], v[i][k])) {
flag_no_op = 0;
// click_block(v[i][j].x, v[i][j].y, v[i][k].x, v[i][k].y, 30);
// log(" succ (" + v[i][j].y + ", " + v[i][j].x + ") - (" + v[i][k].y + ", " + v[i][k].x + ")");
path.push({ y1: v[i][j].y, x1: v[i][j].x, y2: v[i][k].y, x2: v[i][k].x });
mp_bw[v[i][j].y][v[i][j].x] = mp_bw[v[i][k].y][v[i][k].x] = 0;
v[i][j].vis = v[i][k].vis = 1;
} else {
// logMap(mp_bw);
// log(" **** [" + i + "][" + j + "] - [" + i + "][" + k + "] - " + judge_connection(v[i][j], v[i][k]));
// log(" fail (" + v[i][j].y + ", " + v[i][j].x + ") - (" + v[i][k].y + ", " + v[i][k].x + ")");
}
}
}
}
if (flag_no_op) return;
}
}
function dfs() {
if (check_map_clean()) {
// logMap(mp_bw);
log("dfs successed!");
flag_success = true;
return;
}
// log("dfs check fail");
for (let i = 1; i < difItem; ++i) {
// log("dfs 第 " + i + " 种方块", difItem);
for (let j = 0; j < v[i].length; ++j) {
for (let k = j + 1; k < v[i].length; ++k) {
if (v[i][j].vis || v[i][k].vis) continue;
if (judge_connection(v[i][j], v[i][k])) {
log(" succ (" + v[i][j].y + ", " + v[i][j].x + ") - (" + v[i][k].y + ", " + v[i][k].x + ")");
mp_bw[v[i][j].y][v[i][j].x] = mp_bw[v[i][k].y][v[i][k].x] = 0;
v[i][j].vis = v[i][k].vis = 1;
// return;
dfs();
if (flag_success) {
path.push({ y1: v[i][j].y, x1: v[i][j].x, y2: v[i][k].y, x2: v[i][k].x });
return;
}
log(" **回溯 👆")
mp_bw[v[i][j].y][v[i][j].x] = mp_bw[v[i][k].y][v[i][k].x] = 1;
} else {
// logMap(mp_bw);
// log(" **** [" + i + "][" + j + "] - [" + i + "][" + k + "] - " + judge_connection(v[i][j], v[i][k]));
log(" fail (" + v[i][j].y + ", " + v[i][j].x + ") - (" + v[i][k].y + ", " + v[i][k].x + ")");
}
}
}
}
// throw new Error("No solution");
}
function judge_connection(a, b) {
// if (a.vis || b.vis) return false;
let t = { x: 0, y: 0, dir: -1, turn: -1 };
let x, y, dir, turn;
const q = [{ x: a.x, y: a.y, dir: -1, turn: -1 }];
const vis = new Array(arrLen.r);
for (let k = 0; k < arrLen.r; k++) {
vis[k] = new Array(arrLen.c);
for (let j = 0; j < arrLen.c; j++) {
vis[k][j] = new Array(4);
vis[k][j][0] = vis[k][j][1] = vis[k][j][2] = vis[k][j][3] = 0x3f3f3f3f;
}
}
// const vis = initArr(arrLen.r, arrLen.c, { 0: 0x3f3f3f3f, 1: 0x3f3f3f3f, 2: 0x3f3f3f3f, 3: 0x3f3f3f3f });
const d = [[-1, 0], [1, 0], [0, -1], [0, 1]];
vis[a.y][a.x] = 1;
while (q.length) {
t = q.shift();
// log("****: " + t.y, t.x, t.dir, t.turn);
for (let i = 0; i < 4; ++i) {
x = t.x + d[i][0];
y = t.y + d[i][1];
dir = i;
turn = t.turn + (t.dir != i);
if (turn <= 2 && x >= 0 && y >= 0 && x < arrLen.c && y < arrLen.r) {
// log(" **: " + y, x, dir, turn, "mp:", mp_bw[y][x], "vis:", vis[y][x]);
if (y == b.y && x == b.x) return true;
if (mp_bw[y][x] == 0 && vis[y][x][dir] > turn) {
// log("push (" + y + ", " + x + ") d:" + dir + " turn:" + turn);
vis[y][x][dir] = turn;
q.push({ x: x, y: y, dir: dir, turn: turn });
}
}
}
}
return false;
}
function check_map_clean() {
for (let i = 1; i <= mapSize.r; ++i)
for (let j = 1; j <= mapSize.c; ++j)
if (mp_bw[i][j] == 1)
return false;
return true;
}
function getMap() {
let date1 = new Date().getTime();
// let colorCorner = colors.parseColor("#f7f7f5");
let colorCorner2 = colors.parseColor("#f7f7f7");
let colorIce = colors.parseColor("#e5fcff");
// log(colorCorner, colorCorner2);
for (let i = 1; i <= mapSize.r; ++i) {
for (let j = 1; j <= mapSize.c; ++j) {
let color = images.pixel(img, getX(j) + 10, getY(i) + 10);
// log("(" + i + ", " + j + ") :" + colors.toString(color).replace("#ff", "#"));
if (colors.isSimilar(color, colorCorner2, 10, "rgb+")) {
mp_bw[i][j] = 1;
} else if (colors.isSimilar(color, colorIce, 10, "rgb+")) {
mp_bw[i][j] = mp[i][j] = 26;
}
}
}
// let imgMap = images.clip(img, mapStart.x, mapStart.y, mapSize.c * 168, mapSize.r * 168);
let idx = 1;
for (let i = 1; i <= mapSize.r; ++i) {
for (let j = 1; j <= mapSize.c; ++j) {
if (mp_bw[i][j] == 1 && 0 == mp[i][j]) {
// log("(" + (i + 1) + ", " + (j + 1) + ") :", 310 + 168 * j, 1154 + 168 * i, 148, 148);
let imgIcon = images.clip(img, getX(j) + 10, getY(i) + 10, 148, 148);
// images.save(imgIcon, "/sdcard/Samsung Flow/llk2.png", "png", 100);
let points = images.matchTemplate(img, imgIcon, {
region: _region,
threshold: _threshold,
max: 6
}).points;
imgIcon.recycle();
// log(points);
v[idx] = new Array();
points.forEach(point => {
let ii, jj;
for (ii = mapSize.c; ii > 0; --ii) if (point.x >= getX(ii)) break;
for (jj = mapSize.r; jj > 0; --jj) if (point.y >= getY(jj)) break;
// log("(" + (ii + 1) + ", " + (jj + 1) + ") :" + idx);
mp[jj][ii] = idx;
v[idx].push({ y: jj, x: ii, vis: 0 });
});
++idx;
}
}
}
difItem = idx;
// imgMap.recycle();
let points = images.matchTemplate(img, icon_block, {
region: [mapStart.x, mapStart.y, mapSize.c * 168, mapSize.r * 168],
threshold: 0.8
}).points;
points.forEach(point => {
let ii, jj;
for (ii = mapSize.c; ii > 0; --ii) if (point.x >= getX(ii)) break;
for (jj = mapSize.r; jj > 0; --jj) if (point.y >= getY(jj)) break;
mp_bw[jj][ii] = mp[jj][ii] = 25;
});
let date2 = new Date().getTime();
log("地图处理用时:" + (date2 - date1) + "ms");
}
function check_edge() {
return;
for (let i = 1; i < difItem; ++i) {
// log(v[i]);
if (v[i].length % 2)
throw new Error("number of points is odd at " + log_icons[i] + "(color " + i + " )");
}
}
function logMap(arr) {
// 🟥🟧🟨🟩🟦🟪🟫⬛⬜ 🔴🟠🟡🟢🔵🟣🟤⚫⚪
let logStr = "\n";
for (let i = 0; i < arrLen.r; ++i) {
for (let j = 0; j < arrLen.c - 1; ++j) {
// log(String(mp_bw[i][j]));
logStr += log_icons[arr[i][j]];
}
logStr += log_icons[arr[i][arrLen.c - 1]];
if (i != arrLen.r - 1) logStr += "\n";
}
log(logStr);
}
function initArr(r, c, init) {
let tArr = new Array(r);
for (let k = 0; k < r; k++) {
tArr[k] = new Array(c);
for (let j = 0; j < c; j++) {
tArr[k][j] = init;
}
}
return tArr;
}
function getX(c) {
return mapStart.x + 168 * (c - 1);
}
function getY(r) {
return mapStart.y + 168 * (r - 1);
}
}
function close_llk() {
var ThisEngine = engines.myEngine();
var RunningNow = engines.all();
if (RunningNow.length > 1) {
for (var i = 0; i < RunningNow.length; i++) {
if (RunningNow[i].toString() != ThisEngine.toString() && RunningNow[i].toString().indexOf("连连看") != -1) {
log("停止脚本", RunningNow[i].toString());
RunningNow[i].forceStop();
}
}
}
// toast("已关闭所有脚本");
}
东北日出西边雨 道是无情却有情

浙公网安备 33010602011771号