2017-07-05 50 views
1

在連接4中檢查4行的最佳方法是什麼?在javascript中連接4個算法

我不會複製代碼的陣列,但它基本上是長度42的陣列,每個陣列元件將X,Y位置圖和彩色

var board_array = [{x:60, y:55, c:"Red"}, // ... and so on 

和看起來像這樣:

enter image description here

起初,我採取這種方式。這裏有所有不同的可能的方式有人可以贏得比賽。這還不是全部在一排位置的可能4,但所有的不同的方式的人可以贏得垂直,水平和垂直方向 - 你仍然需要使用某種形式的嵌套的循環

// Winning vertically 
wins[0] = new Array(0, 7, 14, 21, 28, 35); 
wins[1] = new Array(1, 8, 15, 22, 29, 36); 
wins[2] = new Array(2, 9, 16, 23, 30, 37); 
wins[3] = new Array(3, 10, 17, 24, 31, 38); 
wins[4] = new Array(4, 11, 18, 25, 32, 39); 
wins[5] = new Array(5, 12, 19, 26, 33, 40); 
wins[6] = new Array(6, 13, 20, 27, 34, 41); 
// Winning horizontally 
wins[7] = new Array(0, 1, 2, 3, 4, 5, 6); 
wins[8] = new Array(7, 8, 9, 10, 11, 12, 13); 
wins[9] = new Array(14, 15, 16, 17, 18, 19, 20); 
wins[10] = new Array(21, 22, 23, 24, 25, 26, 27); 
wins[11] = new Array(28, 29, 30, 31, 32, 33, 34); 
wins[12] = new Array(35, 36, 37, 38, 39, 40, 41); 
// Winning diagonally, left to right 
wins[13] = new Array(14, 22, 30, 38); 
wins[14] = new Array(7, 15, 23, 31, 39); 
wins[15] = new Array(0, 8, 16, 24, 32, 40); 
wins[16] = new Array(1, 9, 17, 25, 33, 41); 
wins[17] = new Array(2, 10, 18, 26, 34); 
wins[18] = new Array(3, 11, 19, 27); 
//Winning diagonally, right to left 
wins[19] = new Array(20, 26, 32, 38); 
wins[20] = new Array(13, 19, 25, 31, 37); 
wins[21] = new Array(6, 12, 18, 24, 30, 36); 
wins[22] = new Array(5, 11, 17, 23, 29, 35); 
wins[23] = new Array(4, 10, 16, 22, 28); 
wins[24] = new Array(3, 9, 15, 21); 

檢查如果你覺得board_array作爲這個:

//0 1 2 3 4 5 6 
//7 8 9 10 11 12 13 
//14 15 16 17 18 19 20 
//21 22 23 24 25 26 27 
//28 29 30 31 32 33 34 
//35 36 37 38 39 40 41 

我用了3層for循環和一個計數器來檢查wins陣列反對board_array但無濟於事。我只是想知道是否有更簡單的方法。

+0

我的方法是通過放置令牌循環。對於每一個令牌,我都向左邊3,右邊3,上邊3,下邊3以及每個方向的對角線3看。我會檢查它們是否都是相同的顏色。 –

+0

如果你得到的數組超出界限類型的錯誤 – jimbo123

+0

你將不得不檢查出界。從簡單的事情開始,例如只檢查是否有垂直勝利。然後將該邏輯應用於水平。然後對角線。 –

回答

0

有很多方法可以這樣做。如果你想擺脫循環,你可以使用動態編程算法,並在每次添加硬幣時計算結果。

要做到這一點,你必須保存每場4個值:水平 - ,的在垂直,對角左斜,右值

class Field { 
     int horiz; 
     int vert; 
     int diagLeft; 
     int diagRight; 
} 

在開始的時候,所有字段都初始化爲0(全該字段的值)。 如果添加硬幣字段,就可以計算出值那樣:

fields[i][j].horiz = fields[i][j+1].horiz + fields[i][j-1].horiz + 1; 
fields[i][j].vert = fields[i+1][j].vert + fields[i-1][j].vert + 1; 
fields[i][j].diagLeft = fields[i+1][j+1].diagLeft + fields[i-1][j-1].diagLeft +1; 
fields[i][j].diagRight = fields[i-1][j-1].diagRight + fields[i+1][j+1] 

如果這四個計算值中的一個是> = 4,則有一個贏家。

處理兩個球員,你可以做一個場陣爲每個玩家,或者如果你想避免檢查的範圍(i和j)所有的時間,你可以使用正負值

,你可以添加一個邊界到你的領域(所以你有左和右一個額外的列,在頂部和底部一個額外的行)

+1

收回移動可能難以維持,除非您爲每次移動都保存整個狀態。 – trincot

+0

謝謝。沒有這樣想過 –

1

「什麼是最好的方式來檢查連接4行4 ?」

我不會說這是「最好的方式」,但它是一種方式。

晴忽略UI格賓斯,該方法是(有點)簡單地每個計數器在其中可能包含的四個連接帶的動態創建的搜索模式下降時間來讀取網格。

每一行,列和向前和向後傾斜的對角條都是一個字符串,它是從沿着它的每個點處找到的顏色值連接而來的。
所述條帶抵靠簡單正則表達式進行測試,以查看是否相同的四個計數器的顏色(紅色或黃色)被連續地提及。

雖然它非常惡劣,但對象非常簡短,並且check4Winner()(它讀取網格)中的第一個嵌套循環會整理完成檢查所需的所有數據,同時檢查獲勝連接的行。
以下循環循環僅在沒有找到贏家時才檢查柱狀和斜條。

優化不包括(幾乎沒有值得額外的代碼說實話)可能是刪除十二個對角線條(每個角落三個),沒有必要檢查,因爲它們太短。

如果需要導出或導入遊戲數據,則可以很容易地使用字符串數組的臨時對象(用於演示的console.log ged)。

UI gubbins雖然對於找到贏家的算法並不嚴格重要,但是設計時考慮了該算法,因此DOM的狀態是正在讀取的數據的來源。
我有意關閉片段中的console輸出,但您可以在瀏覽器的控制檯中看到通過讀取DOM(以此特定方式)生成的數據。

var player = "red"; 
 
const players = { "red": "yellow", "yellow": "red" }, 
 
    output = document.querySelector("output"), 
 
    tbody = document.querySelector("tbody"), 
 
    rows = tbody.querySelectorAll("tr"), 
 
    prepArray = (n) => { 
 
    return Array(n).fill(""); 
 
    }, 
 
    connect4 = (strip) => { 
 
    const rslt = /(?:(red){4}|(yellow){4})/.exec(strip); 
 
    if (!!rslt) { 
 
     output.classList.add(rslt[ 1 ] || rslt[ 2 ]); 
 
     return true; 
 
    } 
 
    return false; 
 
    }, 
 
    check4Winner =() => { 
 
    var strips = { 
 
      h: [], 
 
      v: prepArray(7), 
 
      f: prepArray(12), 
 
      b: prepArray(12) 
 
     }, 
 
     strip, color, winner, dir; 
 
    rows.forEach((row, ri) => { 
 
     strip = ""; 
 
     row.querySelectorAll("td").forEach((cell, ci) => { 
 
     color = cell.getAttribute("class") || " "; 
 
     strips.b[ ci - ri + rows.length - 1 ] += color; 
 
     strips.f[ ci + ri ] += color; 
 
     strips.v[ ci ] += color; 
 
     strip += color; 
 
     }); 
 
     strips.h.push(strip); 
 
     winner = winner || connect4(strip); 
 
    }); 
 
    
 
    console.log(strips); // game data object 
 
    
 
    for (dir in strips) { 
 
     if (!winner && strips.hasOwnProperty(dir)) { 
 
     strips[ dir ].forEach((s) => { 
 
      winner = winner || connect4(s); 
 
     }); 
 
     } 
 
    } 
 
    }, 
 
    dropCounter = (ci) => { 
 
    var cell, pc; 
 
    rows.forEach((row) => { 
 
     if (!(pc = row.childNodes[ ci ]).getAttribute("class")) { 
 
     cell = pc; 
 
     } 
 
    }); 
 
    if (cell) { 
 
     cell.classList.add(player = players[ player ]); 
 
     check4Winner(); 
 
    } 
 
    }; 
 
output.addEventListener("click",() => { 
 
    output.removeAttribute("class"); 
 
    tbody.querySelectorAll("td").forEach((c) => { 
 
    c.removeAttribute("class"); 
 
    }); 
 
}, false); 
 
tbody.addEventListener("click", (evt) => { 
 
    const trg = evt.target; 
 
    if (!output.getAttribute("class") && trg.tagName.toLowerCase() === "td") { 
 
    dropCounter(trg.cellIndex); 
 
    } 
 
}, false);
table, 
 
output { 
 
    box-shadow: .5vh .5vh 2vh .5vh rgba(0, 0, 0, .5); 
 
} 
 
table { 
 
    width: 90vh; 
 
    border-collapse: collapse; 
 
    border: 2vh solid royalblue; 
 
} 
 
td { 
 
    width: calc(90vh/7); 
 
    background: royalblue; 
 
    cursor: default; 
 
    user-select: none; 
 
} 
 
td:before { 
 
    content: ""; 
 
    display: block; 
 
    width: calc(90vh/7); 
 
    height: calc(90vh/7); 
 
    border-radius: 50%; 
 
    box-shadow: inset .5vh .5vh 2vh .5vh rgba(0, 0, 0, .5); 
 
    background: white; 
 
} 
 
td.red:before { 
 
    background: red; 
 
} 
 
td.yellow:before { 
 
    background: yellow; 
 
} 
 
output { 
 
    position: fixed; 
 
    display: none; 
 
    width: 90vh; 
 
    height: 10vh; 
 
    top: 10vh; 
 
    left: 5vh; 
 
    background: white; 
 
    text-align: center; 
 
    font: 5vh sans-serif; 
 
    line-height: 10vh; 
 
    cursor: pointer; 
 
} 
 
output:before { 
 
    content: attr(class); 
 
} 
 
output.red, 
 
output.yellow { 
 
    display: block; 
 
}
<table><tbody> 
 
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> 
 
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> 
 
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> 
 
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> 
 
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> 
 
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> 
 
</tbody></table> 
 
<output> wins!</output>

附:我很喜歡建立這個,所以謝謝你問:-)