实时路径优化
智能规避死路,成功率提升至 99.9%
支持手势操作:双指缩放查看细节路径
多端同步支持
手机 / Pad / 电脑全平台适配
自动填充输入
点击单元格自动填充,无需手动输入
一键清除输入框内容。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>淘宝一笔画福路径规划工具</title>
<style>
:root {
--cell-size: 60px;
--gap-size: 8px;
--primary-color: #4a90e2;
--danger-color: #ff4757;
--success-color: #2ed573;
}
body {
font-family: 'Segoe UI', sans-serif;
max-width: 1000px;
margin: 20px auto;
padding: 20px;
background-color: #f5f6fa;
}
.container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
}
.control-panel {
background: white;
padding: 25px;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #2f3542;
font-weight: 500;
}
input[type="text"] {
width: 100%;
padding: 10px;
border: 2px solid #dfe4ea;
border-radius: 6px;
font-size: 16px;
transition: border-color 0.3s ease;
}
input:focus {
border-color: var(--primary-color);
outline: none;
}
.button-group {
display: flex;
gap: 10px;
margin-top: 20px;
}
button {
padding: 12px 24px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
transition: transform 0.2s, background-color 0.3s;
}
button[type="submit"] {
background-color: var(--primary-color);
color: white;
}
#clearBtn {
background-color: var(--danger-color);
color: white;
}
button:hover {
transform: translateY(-1px);
}
.grid-container {
position: relative;
background: white;
padding: 20px;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.grid {
display: grid;
gap: var(--gap-size);
position: relative;
grid-template-columns: repeat(5, var(--cell-size));
grid-template-rows: repeat(7, var(--cell-size));
}
.cell {
width: var(--cell-size);
height: var(--cell-size);
border: 2px solid #dfe4ea;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
background: white;
transition: all 0.2s ease;
cursor: pointer;
}
.cell:hover {
transform: scale(1.05);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.start { background: var(--success-color); color: white; }
.end { background: var(--danger-color); color: white; }
.missing { background: #ced6e0; opacity: 0.6; }
canvas {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
.input-active {
box-shadow: 0 0 0 2px var(--primary-color);
}
.error-message {
color: var(--danger-color);
margin-bottom: 15px;
padding: 10px;
background: #ffe5e5;
border-radius: 6px;
}
</style>
</head>
<body>
<?php
// 固定7行5列网格
$rows = 7;
$cols = 5;
$matrix = [];
$path = [];
$errors = [];
// 生成固定矩阵
for ($i = 0; $i < $rows; $i++) {
for ($j = 0; $j < $cols; $j++) {
$matrix[$i][$j] = chr(65 + $j) . ($i + 1);
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$start = strtoupper(trim($_POST['start'] ?? ''));
$end = strtoupper(trim($_POST['end'] ?? ''));
$missing = array_map('trim', explode(',', str_replace([',', ' '], ',', strtoupper(trim($_POST['missing'] ?? '')))));
// 验证坐标是否存在
function validatePoint($matrix, $point, &$errors, $type) {
$exists = false;
foreach ($matrix as $row) {
if (in_array($point, $row)) {
$exists = true;
break;
}
}
if (!$exists) $errors[] = "<span style='color:var(--danger-color)'>⚠️ $type '$point' 不存在</span>";
return $exists;
}
// 输入验证
$validStart = validatePoint($matrix, $start, $errors, '起点');
$validEnd = validatePoint($matrix, $end, $errors, '终点');
if (in_array($start, $missing)) $errors[] = "<span style='color:var(--danger-color)'>⚠️ 起点不能设为空位</span>";
if (in_array($end, $missing)) $errors[] = "<span style='color:var(--danger-color)'>⚠️ 终点不能设为空位</span>";
// 路径查找函数
function findLongestPath($matrix, $start, $end, $missing, $rows, $cols) {
$maxPath = [];
$visited = [];
$dfs = function($x, $y, $path) use (&$dfs, &$maxPath, $matrix, $end, $missing, $rows, $cols, &$visited) {
if ($x < 0 || $x >= $cols || $y < 0 || $y >= $rows) return;
$cell = $matrix[$y][$x];
if (isset($visited["$y-$x"]) || in_array($cell, $missing)) return;
$visited["$y-$x"] = true;
$path[] = ['x' => $x, 'y' => $y];
if ($cell === $end) {
if (count($path) > count($maxPath)) $maxPath = $path;
} else {
$directions = [[-1,0], [1,0], [0,-1], [0,1]];
foreach ($directions as $dir) {
$dfs($x + $dir[0], $y + $dir[1], $path);
}
}
unset($visited["$y-$x"]);
};
if ($startPos = findCoordinates($matrix, $start)) {
$dfs($startPos['x'], $startPos['y'], []);
}
return $maxPath;
}
// 坐标转换函数
function findCoordinates($matrix, $point) {
foreach ($matrix as $y => $row) {
foreach ($row as $x => $cell) {
if ($cell === $point) return ['x' => $x, 'y' => $y];
}
}
return null;
}
if ($validStart && $validEnd && empty($errors)) {
$path = findLongestPath($matrix, $start, $end, $missing, $rows, $cols);
if (empty($path)) $errors[] = "<span style='color:var(--danger-color)'>⚠️ 未找到有效路径!</span>";
}
}
?>
<div class="container">
<div class="control-panel">
<h1>淘宝一笔画福路径工具</h1>
<?php if (!empty($errors)): ?>
<div class="error-message">
<?php foreach ($errors as $error): ?>
<?= $error ?>
<?php endforeach; ?>
</div>
<?php endif; ?>
<form method="post">
<div class="form-group">
<label>起点坐标:</label>
<input type="text" name="start" required class="input-field"
placeholder="点击网格选择"
value="<?= htmlspecialchars($_POST['start'] ?? '') ?>">
</div>
<div class="form-group">
<label>终点坐标:</label>
<input type="text" name="end" required class="input-field"
placeholder="点击网格选择"
value="<?= htmlspecialchars($_POST['end'] ?? '') ?>">
</div>
<div class="form-group">
<label>空位坐标:</label>
<input type="text" name="missing" class="input-field"
placeholder="点击网格选择(多个用逗号分隔)"
value="<?= htmlspecialchars($_POST['missing'] ?? '') ?>">
</div>
<div class="button-group">
<button type="submit">生成路径 ▶</button>
<button type="button" id="clearBtn">彻底清除 ✖</button>
</div>
<h2>绿色方块为起点、红色方块为终点</h2>
</form>
</div>
<div class="grid-container">
<div class="grid">
<canvas id="pathCanvas" width="332" height="468"></canvas>
<?php foreach ($matrix as $y => $row): ?>
<?php foreach ($row as $x => $cell): ?>
<?php
$classes = [];
if (isset($_POST['start']) && $cell === $_POST['start']) $classes[] = 'start';
if (isset($_POST['end']) && $cell === $_POST['end']) $classes[] = 'end';
if (isset($missing) && in_array($cell, $missing)) $classes[] = 'missing';
?>
<div class="cell <?= implode(' ', $classes) ?>" data-value="<?= $cell ?>">
<?= $cell ?>
</div>
<?php endforeach; ?>
<?php endforeach; ?>
</div>
</div>
</div>
<script>
// 初始化默认焦点
let activeInput = document.querySelector('input[name="start"]');
activeInput.classList.add('input-active');
// 输入框聚焦处理
document.querySelectorAll('.input-field').forEach(input => {
input.addEventListener('focus', function() {
document.querySelectorAll('.input-field').forEach(i => i.classList.remove('input-active'));
this.classList.add('input-active');
activeInput = this;
});
});
// 单元格点击处理
document.querySelectorAll('.cell').forEach(cell => {
cell.addEventListener('click', function() {
const value = this.textContent.trim();
if (activeInput.name === 'missing') {
// 处理空位坐标(追加)
const currentValues = activeInput.value.split(',').filter(v => v);
if (!currentValues.includes(value)) {
activeInput.value = currentValues.length > 0
? `${currentValues.join(',')},${value}`
: value;
}
// 保持焦点在空位坐标输入框以便继续添加
activeInput.focus();
} else {
// 处理起点/终点(覆盖模式)
activeInput.value = value;
// 在三个输入框之间循环切换焦点
const inputs = document.querySelectorAll('.input-field');
const currentIndex = Array.from(inputs).indexOf(activeInput);
const nextIndex = (currentIndex + 1) % inputs.length;
// 自动切换到下一个输入框(跳过空位坐标输入框如果是起点/终点)
if (activeInput.name !== 'missing') {
inputs[nextIndex].focus();
}
}
});
});
// 彻底清除功能
document.getElementById('clearBtn').addEventListener('click', () => {
// 重置所有输入框
document.querySelectorAll('.input-field').forEach(input => {
input.value = input.name === 'missing' ? '' : input.value;
});
document.querySelectorAll('.input-field').forEach(input => {
input.value = input.name === 'start' ? '' : input.value;
});
// 清除画布
const canvas = document.getElementById('pathCanvas');
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
// 重置单元格样式
document.querySelectorAll('.cell').forEach(cell => {
cell.className = 'cell';
});
// 重置焦点到起点输入框
activeInput = document.querySelector('input[name="start"]');
activeInput.focus();
activeInput.classList.add('input-active');
// 移除其他输入框高亮
document.querySelectorAll('.input-field').forEach(input => {
if(input !== activeInput) input.classList.remove('input-active');
});
});
// 路径绘制
const path = <?= json_encode($path ?? []) ?>;
const canvas = document.getElementById('pathCanvas');
if (canvas && path.length > 1) {
const ctx = canvas.getContext('2d');
ctx.strokeStyle = '#3742fa';
ctx.lineWidth = 4;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.beginPath();
path.forEach((point, index) => {
const x = point.x * 68 + 34; // 60+8=68, 60/2=30 + 8/2=4 → 34
const y = point.y * 68 + 34;
index === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
});
ctx.stroke();
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>淘宝一笔画福路径规划工具</title>
<style>
:root {
--cell-size: 60px;
--gap-size: 8px;
--primary-color: #4a90e2;
--danger-color: #ff4757;
--success-color: #2ed573;
}
body {
font-family: 'Segoe UI', sans-serif;
max-width: 1000px;
margin: 20px auto;
padding: 20px;
background-color: #f5f6fa;
}
.container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
}
.control-panel {
background: white;
padding: 25px;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #2f3542;
font-weight: 500;
}
input[type="text"] {
width: 100%;
padding: 10px;
border: 2px solid #dfe4ea;
border-radius: 6px;
font-size: 16px;
transition: border-color 0.3s ease;
}
input:focus {
border-color: var(--primary-color);
outline: none;
}
.button-group {
display: flex;
gap: 10px;
margin-top: 20px;
}
button {
padding: 12px 24px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
transition: transform 0.2s, background-color 0.3s;
}
button[type="submit"] {
background-color: var(--primary-color);
color: white;
}
#clearBtn {
background-color: var(--danger-color);
color: white;
}
button:hover {
transform: translateY(-1px);
}
.grid-container {
position: relative;
background: white;
padding: 20px;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.grid {
display: grid;
gap: var(--gap-size);
position: relative;
grid-template-columns: repeat(5, var(--cell-size));
grid-template-rows: repeat(7, var(--cell-size));
}
.cell {
width: var(--cell-size);
height: var(--cell-size);
border: 2px solid #dfe4ea;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
background: white;
transition: all 0.2s ease;
cursor: pointer;
}
.cell:hover {
transform: scale(1.05);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.start { background: var(--success-color); color: white; }
.end { background: var(--danger-color); color: white; }
.missing { background: #ced6e0; opacity: 0.6; }
canvas {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
.input-active {
box-shadow: 0 0 0 2px var(--primary-color);
}
.error-message {
color: var(--danger-color);
margin-bottom: 15px;
padding: 10px;
background: #ffe5e5;
border-radius: 6px;
}
</style>
</head>
<body>
<?php
// 固定7行5列网格
$rows = 7;
$cols = 5;
$matrix = [];
$path = [];
$errors = [];
// 生成固定矩阵
for ($i = 0; $i < $rows; $i++) {
for ($j = 0; $j < $cols; $j++) {
$matrix[$i][$j] = chr(65 + $j) . ($i + 1);
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$start = strtoupper(trim($_POST['start'] ?? ''));
$end = strtoupper(trim($_POST['end'] ?? ''));
$missing = array_map('trim', explode(',', str_replace([',', ' '], ',', strtoupper(trim($_POST['missing'] ?? '')))));
// 验证坐标是否存在
function validatePoint($matrix, $point, &$errors, $type) {
$exists = false;
foreach ($matrix as $row) {
if (in_array($point, $row)) {
$exists = true;
break;
}
}
if (!$exists) $errors[] = "<span style='color:var(--danger-color)'>⚠️ $type '$point' 不存在</span>";
return $exists;
}
// 输入验证
$validStart = validatePoint($matrix, $start, $errors, '起点');
$validEnd = validatePoint($matrix, $end, $errors, '终点');
if (in_array($start, $missing)) $errors[] = "<span style='color:var(--danger-color)'>⚠️ 起点不能设为空位</span>";
if (in_array($end, $missing)) $errors[] = "<span style='color:var(--danger-color)'>⚠️ 终点不能设为空位</span>";
// 路径查找函数
function findLongestPath($matrix, $start, $end, $missing, $rows, $cols) {
$maxPath = [];
$visited = [];
$dfs = function($x, $y, $path) use (&$dfs, &$maxPath, $matrix, $end, $missing, $rows, $cols, &$visited) {
if ($x < 0 || $x >= $cols || $y < 0 || $y >= $rows) return;
$cell = $matrix[$y][$x];
if (isset($visited["$y-$x"]) || in_array($cell, $missing)) return;
$visited["$y-$x"] = true;
$path[] = ['x' => $x, 'y' => $y];
if ($cell === $end) {
if (count($path) > count($maxPath)) $maxPath = $path;
} else {
$directions = [[-1,0], [1,0], [0,-1], [0,1]];
foreach ($directions as $dir) {
$dfs($x + $dir[0], $y + $dir[1], $path);
}
}
unset($visited["$y-$x"]);
};
if ($startPos = findCoordinates($matrix, $start)) {
$dfs($startPos['x'], $startPos['y'], []);
}
return $maxPath;
}
// 坐标转换函数
function findCoordinates($matrix, $point) {
foreach ($matrix as $y => $row) {
foreach ($row as $x => $cell) {
if ($cell === $point) return ['x' => $x, 'y' => $y];
}
}
return null;
}
if ($validStart && $validEnd && empty($errors)) {
$path = findLongestPath($matrix, $start, $end, $missing, $rows, $cols);
if (empty($path)) $errors[] = "<span style='color:var(--danger-color)'>⚠️ 未找到有效路径!</span>";
}
}
?>
<div class="container">
<div class="control-panel">
<h1>淘宝一笔画福路径工具</h1>
<?php if (!empty($errors)): ?>
<div class="error-message">
<?php foreach ($errors as $error): ?>
<?= $error ?>
<?php endforeach; ?>
</div>
<?php endif; ?>
<form method="post">
<div class="form-group">
<label>起点坐标:</label>
<input type="text" name="start" required class="input-field"
placeholder="点击网格选择"
value="<?= htmlspecialchars($_POST['start'] ?? '') ?>">
</div>
<div class="form-group">
<label>终点坐标:</label>
<input type="text" name="end" required class="input-field"
placeholder="点击网格选择"
value="<?= htmlspecialchars($_POST['end'] ?? '') ?>">
</div>
<div class="form-group">
<label>空位坐标:</label>
<input type="text" name="missing" class="input-field"
placeholder="点击网格选择(多个用逗号分隔)"
value="<?= htmlspecialchars($_POST['missing'] ?? '') ?>">
</div>
<div class="button-group">
<button type="submit">生成路径 ▶</button>
<button type="button" id="clearBtn">彻底清除 ✖</button>
</div>
<h2>绿色方块为起点、红色方块为终点</h2>
</form>
</div>
<div class="grid-container">
<div class="grid">
<canvas id="pathCanvas" width="332" height="468"></canvas>
<?php foreach ($matrix as $y => $row): ?>
<?php foreach ($row as $x => $cell): ?>
<?php
$classes = [];
if (isset($_POST['start']) && $cell === $_POST['start']) $classes[] = 'start';
if (isset($_POST['end']) && $cell === $_POST['end']) $classes[] = 'end';
if (isset($missing) && in_array($cell, $missing)) $classes[] = 'missing';
?>
<div class="cell <?= implode(' ', $classes) ?>" data-value="<?= $cell ?>">
<?= $cell ?>
</div>
<?php endforeach; ?>
<?php endforeach; ?>
</div>
</div>
</div>
<script>
// 初始化默认焦点
let activeInput = document.querySelector('input[name="start"]');
activeInput.classList.add('input-active');
// 输入框聚焦处理
document.querySelectorAll('.input-field').forEach(input => {
input.addEventListener('focus', function() {
document.querySelectorAll('.input-field').forEach(i => i.classList.remove('input-active'));
this.classList.add('input-active');
activeInput = this;
});
});
// 单元格点击处理
document.querySelectorAll('.cell').forEach(cell => {
cell.addEventListener('click', function() {
const value = this.textContent.trim();
if (activeInput.name === 'missing') {
// 处理空位坐标(追加)
const currentValues = activeInput.value.split(',').filter(v => v);
if (!currentValues.includes(value)) {
activeInput.value = currentValues.length > 0
? `${currentValues.join(',')},${value}`
: value;
}
// 保持焦点在空位坐标输入框以便继续添加
activeInput.focus();
} else {
// 处理起点/终点(覆盖模式)
activeInput.value = value;
// 在三个输入框之间循环切换焦点
const inputs = document.querySelectorAll('.input-field');
const currentIndex = Array.from(inputs).indexOf(activeInput);
const nextIndex = (currentIndex + 1) % inputs.length;
// 自动切换到下一个输入框(跳过空位坐标输入框如果是起点/终点)
if (activeInput.name !== 'missing') {
inputs[nextIndex].focus();
}
}
});
});
// 彻底清除功能
document.getElementById('clearBtn').addEventListener('click', () => {
// 重置所有输入框
document.querySelectorAll('.input-field').forEach(input => {
input.value = input.name === 'missing' ? '' : input.value;
});
document.querySelectorAll('.input-field').forEach(input => {
input.value = input.name === 'start' ? '' : input.value;
});
// 清除画布
const canvas = document.getElementById('pathCanvas');
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
// 重置单元格样式
document.querySelectorAll('.cell').forEach(cell => {
cell.className = 'cell';
});
// 重置焦点到起点输入框
activeInput = document.querySelector('input[name="start"]');
activeInput.focus();
activeInput.classList.add('input-active');
// 移除其他输入框高亮
document.querySelectorAll('.input-field').forEach(input => {
if(input !== activeInput) input.classList.remove('input-active');
});
});
// 路径绘制
const path = <?= json_encode($path ?? []) ?>;
const canvas = document.getElementById('pathCanvas');
if (canvas && path.length > 1) {
const ctx = canvas.getContext('2d');
ctx.strokeStyle = '#3742fa';
ctx.lineWidth = 4;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.beginPath();
path.forEach((point, index) => {
const x = point.x * 68 + 34; // 60+8=68, 60/2=30 + 8/2=4 → 34
const y = point.y * 68 + 34;
index === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
});
ctx.stroke();
}
</script>
</body>
</html>
![图片[1]|淘宝一笔画福路径路线工具php源码|不死鸟资源网](https://www.busi.net/wp-content/uploads/2025/06/20250610184252699-image.png)
本站资源均为作者提供和网友推荐收集整理而来,仅供学习和研究使用,请在下载后24小时内删除,谢谢合作!
THE END