我建立了一個利用遞回輔助函式的boggle解算器演算法。 它使用一個 trie 資料結構來快速檢查現有的前綴在字典中是否有任何單詞。 我希望對演算法的每一步進行影片處理,以顯示HTML表格中每個單詞的發現情況,但無法使其正常作業。
以下是該演算法:
const trie = '' //instantiated trie class(為簡潔起見省略)
const list = '' //匯入字典(為簡略起見省略)
//inputs是指表格內所有容納字母的單元格。
const inputs = document.getElementsByClassName("input") 。
//size是表格的大小(例如,4x4,8x8,等等...)。
const size = document.getElementById("size"/span>).valueAsNumber;
//用字典中的每個詞來填充 trie。
for (let item of list) {
trie.insert(item)。
}
const movements = (i, j) => [
{ row: i, column: j 1, move: "RIGHT" }。
{ row: i 1, column: j 1, move: "BOTTOM_RIGHT" }。
{ row: i 1, column: j, move: "BOTTOM"/span> }。
{ row: i 1, column: j - 1, move: "BOTTOM_LEFT" }。
{ row: i, column: j - 1, move: "LEFT" },
{ row: i - 1, column: j - 1, move: "TOP_LEFT" },
{ row: i - 1, column: j, move: "TOP"/span> }。
{ row: i - 1, column: j 1, move: "TOP_RIGHT" }。
];
//將一個二維陣列作為輸入(例如:['a', 'b', 'c', 'd'], ['e', 'f', 'g', 'h']])/span>
export const findWords = (matrix)=> {
const words = [] 。
const iterate = (i, j, word, visited) => {
if (matrix[i] && matrix[i] [j]) {
if (!visited[`${i}_${j}`]) {
visited[`${i}_${j}`] = true。
word = matrix[i][j];
if (trie.find(word).length) {
if (trie.contains(word)) {
words.push(word)。
}
const moves = movements(i, j)。
for (let move of moves) {
const { row, column } = move;
iterate(row, column, word, { ... visited });
}
}
}
}
};
for (let i = 0; i < matrix.length; i ) {
for (let j = 0; j < matrix[i].length; j ) {
iterate(i, j, ""/span>, {})。
}
}
return words;
};
在這里可以找到一個作業的應用實體。https://jsfiddle.net/Msiric/24x765bn/
這是使用生成器時的代碼:
export const findWords = (matrix)=> {
const words = [] 。
const iterate = function* (i, j, word, visited, color) {
if (matrix[i] && matrix[i] [j]) {
if (!visited[`${i}_${j}`]) {
visited[`${i}_${j}`] = true。
word = matrix[i][j];
//在這里突出顯示當前單元格; word = matrix[i][j]; //在這里突出顯示當前單元格
inputs[j size * i].classList.add(color)。
if (Trie.find(word).length) {
if (trie.contains(word)) {
words.push(word)。
}
const moves = movements(i, j)。
for (let move of moves) {
const { row, column } = move;
yield* iterate(
行。
列。
字。
{ ...visited },
column % 2 === 0 ? "blue" : "red" ?
);
//該單元格一旦完成,就應該取消高亮顯示。
inputs[j size * i].classList.remove(color)。
}
}
}
}
};
for (let i = 0; i < matrix.length; i ) {
for (let j = 0; j < matrix[i].length; j ) {
iterate(i, j, "", {}, j % 2 == 0 ? "blue" : "red").next()。
}
}
return words;
};
這樣做只是顯示演算法的最終狀態,這不是我想要的。 我希望在執行每一個步驟和找到每一個單詞時,顯示每一個單元格被高亮或不被高亮。 我也試過用setTimeout函式來延遲輔助函式的執行,但這也不起作用。 它只是導致了隨機的閃爍,因為單元格被高亮/不高亮的順序不對。
希望得到任何幫助
uj5u.com熱心網友回復:
在javascript中,你不能在一個同步函式的程序中渲染東西。任何試圖對DOM進行修改的代碼都只能排隊,而在運行時執行同步函式時,這些修改是不能被繪制的。
因此,你必須使你的函式成為異步函式,就像在這個例子中一樣 https://jsfiddle.net/ep783cgw/2/
雖然我不確定你想如何將其可視化,但我做了一個renderState函式,你可以根據自己的喜好進行定義。
//根據你的喜好修改它。
const renderState = (anim,i,j,move) => {
const {row,column} = move.
影片。 innerText = `${i} _${j}-${row}_${column}-${move. move}`
}
//顯示影片的明顯延遲。
const delay = (ms) => new Promise(res => setTimeout(res, ms)
//make findWords async[/span]。
const findWords = async ( matrix) => {
const words = [] 。
const anim = document.querySelector('#result') 。
const iterate = async (i, j, word, visited)=> {
if (matrix[i] && matrix[i] [j]) {
if (!visited[`${i}_${j}`]) {
visited[`${i}_${j}`] = true。
word = matrix[i][j];
if (trie.find(word).length) {
if (trie.contains(word)) {
words.push(word)。
}
const moves = movements(i, j)。
for (let move of moves) {
const { row, column } = move;
//render the DOMrenderState(anim,i,j, move);
//使用 await 等待200ms。瀏覽器將在這段時間內繪制DOM。
await delay(200)。
//再次使用await進行迭代。
await iterate(row, column, word, { ... visited })。
}
}
}
}
};
for (let i = 0; i < matrix.length; i ) {
for (let j = 0; j < matrix[i].length; j ) {
await iterate(i, j, "", {})。
}
}
return words;
};
//make handleSubmit async
const handleSubmit = async(e)=> {
e.preventDefault()。
const inputs = document.querySelectorAll(".input") 。
const result = document.getElementById("result") 。
const size = document.getElementById("size"/span>).valueAsNumber;
const matrix = [] 。
for (let i = 0; i < size; i ) {
const row = [];
for (let j = 0; j < size; j ) {
row.push(inputs[j size * i].value.toLowerCase() 。)
}
matrix.push(row)。
}
//使用 await 獲得 findWords 的輸出。
const words = await findWords(矩陣)。
result.innerHTML = words;
};
要了解更多資訊,請關注這些鏈接
。編輯:我剛剛注意到,你沒有正確使用生成器函式。
為了更好地利用生成器函式,你應該創建一個單一的生成器實體并對其呼叫next()以產生所有的值。但是在你的代碼中,你寫了
iterate(i, j, ", {}, j % 2 ==0 ? "blue" : "red").next()。
在這里你要在每次.next()呼叫之前創建一個新的實體。因此,iterate生成器將不會產生所有的值。
因此,上面這一行應該是
const instance = iterate(i, j, "", {}, j % 2== 0 ? "blue"/span> : "red"/span>)
while(!instance.next().done)
你可以閱讀一個生成器函式的例子這里
uj5u.com熱心網友回復:
這里的代碼有點多,我現在無法接受。 但是一個一般性的建議是,你不要試圖將演算法和顯示混合在一起。
在演算法中,保持對你所測驗的動作及其結果的跟蹤。 在這里,請不要擔心你將如何顯示這些內容。
在你完成之后,進行測驗,一次一個,突出網格。 在這里,使用setInterval或連鎖的setTimeouts是很容易的,因為你只是在一個嘗試的串列上進行迭代。 每次你只需要取消當前的高亮顯示,然后對路徑上的單元格進行設定,也許對路徑上的第一個和最后一個單元格有不同的顯示,也許當你碰到一個合法的單詞時有不同的顯示(將添加到串列中的影片?
讓我們想象一下,我們有一個部分看起來像這樣的網格:
我們有一個部分看起來像這樣的網格。
x
y 0 1 2 3
0 | - | - O | - |
1 | - | O | F | - | |
2 | Z | L | - | H | |
3 | - | I | S | - | |
也許每個測驗都會產生類似于
的結果{
path: [{x: 2, y: 1, c: 'F'}, {x: 2, y: 0, c: 'O'}, {x: 1, y: 1, 'c'/span>: 'O'}]。
stuck: false,
isWord: false
(假設 "FOO "不在你的字典里。)
當,因為你沒有被卡住,你最終添加了{x: 1, y: 2, c: 'L'},你將有isWord: true ("FOOL") 和stuck: false (因為 trie 說在F-O-O-L下有節點)。
{
path: [{x: 2, y: 1, c: 'F'}, {x: 2, y: 0, c: 'O'}, {x: 1, y: 1, 'c'/span>: 'O'}。
{x: 1, y: 2, c: 'L'}]。
stuck: false,
isWord: true, isWord.
但是當你嘗試添加{x: 0, y: 2, c: 'Z'},而三角形告訴你沒有以F-O-O-Z開頭的詞,你可以記錄下這不是一個詞,你被卡住了。
{
path: [{x: 2, y: 1, c: 'F'}, {x: 2, y: 0, c: 'O'}, {x: 1, y: 1, 'c'/span>: 'O'}。
{x: 0, y: 2, c: 'Z'}]。
stuck: true,
isWord: false
最終,你將嘗試這個七個字母的詞:
{
path: [{x: 2, y: 1, c: 'F'}, {x: 2, y: 0, c: 'O'}, {x: 1, y: 1, c: 'O'}。
{x: 1, y: 2, c: 'L'}, {x: 1, y: 3, c: 'I'}, {x: 2, y: 3, c: 'S'}。
{x: 3, y: 2, c: 'H'}]。
stuck: false,
isWord: true, isWord.
注意,這些可以是你的演算法的唯一輸出,因為從這些測驗中生成單詞串列是微不足道的:
.filter (t => t .isWord)
.map (({path}) => path 。 map (n => n 。 c) .join (''/span>)
const uniqueWords = [... new Set(words)]
uj5u.com熱心網友回復:
這是我想出的辦法。https://jsfiddle.net/Msiric/jwag86o2/3/
該解決方案的部分靈感來自于 Scott 的建議,但由于我無法讓它發揮作用,我找到了另一種方法來指定影片運行時應執行的每一步。
演算法的主要變化:
const movements = (i, j) => [
{ row: i, column: j 1, move: "RIGHT" }。
{ row: i 1, column: j 1, move: "BOTTOM_RIGHT" }。
{ row: i 1, column: j, move: "BOTTOM"/span> }。
{ row: i 1, column: j - 1, move: "BOTTOM_LEFT" }。
{ row: i, column: j - 1, move: "LEFT" },
{ row: i - 1, column: j - 1, move: "TOP_LEFT" },
{ row: i - 1, column: j, move: "TOP"/span> }。
{ row: i - 1, column: j 1, move: "TOP_RIGHT" }。
];
const addStep = (() => {
let counter = 1;
return (i, j, matrix, isWord, action, steps) => {
steps.push({
x: i,
y: j,
c: matrix[i][j],
isWord。
行動。
計數器。
});
action === "remove" ? counter-- : counter ;
};
})();
const findWords = (matrix) => {
const words = [] 。
const map = {};
const steps = [] 。
const iterate = (i, j, word, visited) => {
if (matrix[i] && matrix[i] [j]) {
if (!visited[`${i}_${j}`]) {
visited[`${i}_${j}`] = true。
word = matrix[i][j];
addStep(i, j, matrix, false, "add", steps)。
if (trie.find(word).length) {
if (trie.contains(word) && !map[word] ) {
words.push(word)。
map[word] = true;
steps[stips.length - 1] = {
...step[step.length - 1] 。
isWord: true,
};
}
const moves = movements(i, j)。
for (let move of moves) {
const { row, column } = move;
iterate(row, column, word, { ... visited });
}
addStep(i, j, matrix, false, "remove", steps);
} else {
addStep(i, j, matrix, false, "remove", steps) 。
}
}
}
};
for (let i = 0; i < matrix.length; i ) {
for (let j = 0; j < matrix[i].length; j ) {
iterate(i, j, ""/span>, {})。
}
}
return { words, steps };
};
而這里是可視化函式:
const visualizeSteps = async(step, inputs, spans, size)=> {
for (let step of steps) {
const { x, y } = step;
const selection = y size * x;
await delay(0)。
if (spans[selection].innerHTML === ""/span>) {
spans[selection].innerHTML = step.counter。
}
inputs[selection].classList.add("highlight") 。
if (step.isWord) {
const highlights = document.getElementsByClassName("highlight")。
for (let highlight of highlights) {
highlight.classList.add("success") 。
}
await delay(500)。
for (let highlight of highlights) {
highlight.classList.remove("success") 。
}
} else {
if (step.action == "remove") {
await delay(0)。
inputs[selection].classList.remove("highlight"/span>)。
spans[selection].innerHTML = ""。
}
}
}
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/326066.html
標籤:
