|
1 |
| -import { emptyFlag, arrayPic } from './config'; |
| 1 | +import { emptyFlag, arrayPic, loading } from './config'; |
2 | 2 | import type { Block } from './type';
|
3 | 3 |
|
4 | 4 | const pictureMap = new Map<string, any>()
|
@@ -27,7 +27,6 @@ async function generateImage(image: any, n: number) {
|
27 | 27 | const ctx = canvas.getContext("2d")!;
|
28 | 28 | const w = image.width / n;
|
29 | 29 | const h = image.height / n;
|
30 |
| - let count = 0 |
31 | 30 | const cacheUrl = new Map<string, string>()
|
32 | 31 | for (let j = 0; j <= 2 * n + 1; j++) {
|
33 | 32 | const col = [];
|
@@ -59,7 +58,9 @@ async function generateImage(image: any, n: number) {
|
59 | 58 | url,
|
60 | 59 | x: i,
|
61 | 60 | y: j,
|
62 |
| - pos: ++count |
| 61 | + pos: j > n |
| 62 | + ? i - 1 + (j - n - 1) * n |
| 63 | + : i - 1 + (j - 1) * n |
63 | 64 | };
|
64 | 65 |
|
65 | 66 | numbers.push(JSON.parse(JSON.stringify(block)))
|
@@ -114,45 +115,178 @@ function randomPic(numbers: any[]) {
|
114 | 115 | return result
|
115 | 116 | }
|
116 | 117 | export async function initData(n: number, src: string) {
|
117 |
| - const { result: arrayPic, numbers } = await splitImage(n, src) as any |
| 118 | + const { result: array, numbers } = await splitImage(n, src) as any |
118 | 119 | const copyNumbers = JSON.parse(JSON.stringify(numbers))
|
119 |
| - const copyArrayPic = JSON.parse(JSON.stringify(arrayPic)) |
| 120 | + const copyArrayPic = JSON.parse(JSON.stringify(array)) |
| 121 | + let targetMap: Record<number, any> | null = {} |
120 | 122 |
|
121 |
| - for (let i = 1; i < arrayPic.length - 1; i++) { |
122 |
| - for (let j = 1; j < arrayPic[i].length - 1; j++) { |
| 123 | + for (let i = 1; i < array.length - 1; i++) { |
| 124 | + for (let j = 1; j < array[i].length - 1; j++) { |
123 | 125 | const { url, pos, } = randomPic(copyNumbers)
|
| 126 | + if (targetMap[pos] === undefined) { |
| 127 | + targetMap[pos] = copyArrayPic[i][j] |
| 128 | + } else { |
| 129 | + copyArrayPic[i][j].target = targetMap[pos] |
| 130 | + } |
124 | 131 | copyArrayPic[i][j].url = url
|
125 | 132 | copyArrayPic[i][j].pos = pos
|
126 | 133 | }
|
127 | 134 | }
|
128 |
| - return copyArrayPic |
| 135 | + targetMap = null |
| 136 | + arrayPic.value = copyArrayPic |
| 137 | + if (noMatching()) { |
| 138 | + reset() |
| 139 | + } |
129 | 140 | }
|
130 | 141 |
|
131 | 142 | export function reset() {
|
| 143 | + loading.value = true |
132 | 144 | const numbers: any[] = []
|
133 | 145 | const copyArrayPic: Array<Block[]> = JSON.parse(JSON.stringify(arrayPic.value))
|
| 146 | + let targetMap: Record<number, any> | null = {} |
134 | 147 |
|
135 |
| - console.log(arrayPic.value) |
136 | 148 | arrayPic.value.forEach(row => {
|
137 | 149 | row.forEach(block => {
|
138 | 150 | if (block.url !== emptyFlag) {
|
139 | 151 | numbers.push(block)
|
140 | 152 | }
|
141 | 153 | })
|
142 | 154 | })
|
143 |
| - copyArrayPic.forEach(row => { |
144 |
| - row.forEach(block => { |
| 155 | + copyArrayPic.forEach((row, i) => { |
| 156 | + row.forEach((block, j) => { |
145 | 157 | if (block.url !== emptyFlag) {
|
146 | 158 | const { url, pos } = randomPic(numbers)
|
| 159 | + delete block.target |
| 160 | + if (targetMap![pos] === undefined) { |
| 161 | + targetMap![pos] = copyArrayPic[i][j] |
| 162 | + } else { |
| 163 | + block.target = targetMap![pos] |
| 164 | + } |
147 | 165 | block.url = url
|
148 | 166 | block.pos = pos
|
149 | 167 | }
|
150 | 168 | })
|
151 | 169 | })
|
152 |
| - console.log(copyArrayPic) |
153 | 170 | arrayPic.value = copyArrayPic
|
| 171 | + if (noMatching()) { |
| 172 | + reset() |
| 173 | + } else { |
| 174 | + loading.value = false |
| 175 | + } |
154 | 176 | }
|
155 | 177 |
|
156 | 178 |
|
| 179 | +export function noMatching() { |
| 180 | + // 判断是否无解了 |
| 181 | + const array: Block[] = [] |
| 182 | + arrayPic.value.forEach((row) => { |
| 183 | + row.forEach((block) => { |
| 184 | + if (block.target && block.url !== emptyFlag) { |
| 185 | + array.push(block) |
| 186 | + } |
| 187 | + }) |
| 188 | + }); |
| 189 | + const result = array.every(block => !bfs(block, block.target!)) |
| 190 | + console.log(result) |
| 191 | + return result |
| 192 | +} |
157 | 193 |
|
158 | 194 |
|
| 195 | +function preReturn(block: Block | null) { |
| 196 | + if (!block) { |
| 197 | + return false |
| 198 | + } |
| 199 | + let count = 0; |
| 200 | + let pre = null, |
| 201 | + cur = null; |
| 202 | + if (block.types!.length < 4) { |
| 203 | + return true; |
| 204 | + } |
| 205 | + |
| 206 | + for (let i = 1; i < block.types!.length; i++) { |
| 207 | + cur = block.types![i]; |
| 208 | + pre = block.types![i - 1]; |
| 209 | + if (pre !== cur) { |
| 210 | + count++; |
| 211 | + } |
| 212 | + if (count > 2) { |
| 213 | + return false; |
| 214 | + } |
| 215 | + } |
| 216 | + return true; |
| 217 | +} |
| 218 | + |
| 219 | + |
| 220 | +function sameBlock(block: Block, target: Block) { |
| 221 | + return block.pos === target.pos && block.x === target.x && block.y === target.y |
| 222 | +} |
| 223 | + |
| 224 | +export function bfs(block: Block, target: Block, map = new Set) { |
| 225 | + const queue = [block]; |
| 226 | + const maxHeight = arrayPic.value[0].length - 1 |
| 227 | + const maxWidth = arrayPic.value.length - 1 |
| 228 | + while (queue.length) { |
| 229 | + const cur: Block = queue.shift()!; |
| 230 | + if (map.has(cur)) { |
| 231 | + continue |
| 232 | + } |
| 233 | + map.add(cur) |
| 234 | + const y = cur.y; |
| 235 | + const x = cur.x; |
| 236 | + const types: string[] = cur.types || [] |
| 237 | + const top = y > 0 ? JSON.parse(JSON.stringify(arrayPic.value[y - 1][x])) : null |
| 238 | + const bottom = y < maxWidth ? JSON.parse(JSON.stringify(arrayPic.value[y + 1][x])) : null |
| 239 | + const left = x > 0 ? JSON.parse(JSON.stringify(arrayPic.value[y][x - 1])) : null |
| 240 | + const right = x < maxHeight ? JSON.parse(JSON.stringify(arrayPic.value[y][x + 1])) : null |
| 241 | + pushTypes(top, types, 'down') |
| 242 | + pushTypes(bottom, types, 'up') |
| 243 | + pushTypes(left, types, 'right') |
| 244 | + pushTypes(right, types, 'left') |
| 245 | + |
| 246 | + // 处理边界 |
| 247 | + if (preReturn(top) && (block.x !== target.x || block.y > target.y)) { |
| 248 | + if (sameBlock(top, target)) { |
| 249 | + console.log("find", top); |
| 250 | + return true; |
| 251 | + } |
| 252 | + if (top.url === emptyFlag) { |
| 253 | + queue.push(top); |
| 254 | + } |
| 255 | + } |
| 256 | + if (preReturn(bottom) && (block.x !== target.x || block.y < target.y)) { |
| 257 | + if (sameBlock(bottom, target)) { |
| 258 | + console.log("find", bottom); |
| 259 | + return true; |
| 260 | + } |
| 261 | + if (bottom.url === emptyFlag) { |
| 262 | + queue.push(bottom); |
| 263 | + } |
| 264 | + } |
| 265 | + if (preReturn(left) && (block.y !== target.y || block.x > target.x)) { |
| 266 | + if (sameBlock(left, target)) { |
| 267 | + console.log("find", left); |
| 268 | + return true; |
| 269 | + } |
| 270 | + if (left.url === emptyFlag) { |
| 271 | + queue.push(left); |
| 272 | + } |
| 273 | + |
| 274 | + } |
| 275 | + if (preReturn(right) && (block.y !== target.y || block.x < target.x)) { |
| 276 | + if (sameBlock(right, target)) { |
| 277 | + console.log("find", right); |
| 278 | + return true; |
| 279 | + } |
| 280 | + if (right.url === emptyFlag) { |
| 281 | + queue.push(right); |
| 282 | + } |
| 283 | + } |
| 284 | + } |
| 285 | + return false; |
| 286 | +} |
| 287 | + |
| 288 | +function pushTypes(block: Block | null, types: string[], type: string) { |
| 289 | + if (!block) |
| 290 | + return |
| 291 | + block.types = types ? [type, ...types] : [type]; |
| 292 | +} |
0 commit comments