使用原生JS快速寫出一個(gè)五子棋小游戲
1.棋盤和棋子的繪制。
let arr = [
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},],
]
//封裝渲染函數(shù)
const render = () => {
document.querySelector('table').innerHTML = ''
arr.forEach((item, index) => {
let tr = document.createElement('tr')
item.forEach((item2, index2) => {
let td = document.createElement('td')//遍歷數(shù)組,繪制棋盤
//給td標(biāo)簽設(shè)置自定義屬性,用來(lái)作為坐標(biāo)使用
td.dataset.y = index
td.dataset.x = index2
tr.appendChild(td)
//給數(shù)組里面的對(duì)象做條件判斷,這樣就能渲染出顏色
if (item2.num === 1) {
td.classList.add('bgc1')
}
else if (item2.num === 2) {
td.classList.add('bgc2')
}
})
document.querySelector('table').appendChild(tr)
})
}
render()
先創(chuàng)建一個(gè)15 * 15的二維數(shù)組,通過(guò)對(duì)數(shù)組的兩層遍歷,創(chuàng)建出一個(gè)15*15的表格,這樣棋盤就有了。用數(shù)組來(lái)繪制棋盤的好處是便于查找和篩選。 每一個(gè)td都對(duì)應(yīng)著一個(gè)空對(duì)象,下棋的時(shí)候通過(guò)給這個(gè)對(duì)象添加一個(gè)num的屬性,num為1時(shí),就渲染成黑色,2就渲染成白色,再稍微調(diào)整一下css樣式,這樣棋盤和棋子就繪制好了。每一個(gè)td都有自己的自定義屬性x和y,類似于坐標(biāo),這樣就可以很方便的把td標(biāo)簽和數(shù)組里對(duì)應(yīng)的值聯(lián)系起來(lái)。 下面是css代碼
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
list-style: none;
}
table {
position: relative;
width: 730px;
height: 730px;
margin: 0 auto;
border: 5px solid black;
background: url(./src=http___pic45.nipic.com_20140804_2372131_155038114014_2.jpg&refer=http___pic45.nipic.webp) no-repeat;
background-size: 100%;
background-position: center;
padding: 24px 12px;
}
td {
width: 35px;
height: 35px;
border-radius: 50%;
margin-right: 13px;
margin-bottom: 11px;
cursor: pointer;
}
.bgc1 {
background-color: black;
}
.bgc2 {
background-color: white;
}
button {
position: absolute;
width: 200px;
height: 100px;
bottom: 100px;
right: 200px;
text-align: center;
line-height: 100px;
font-size: 25px;
}
</style>
<table></table> <button>悔棋</button>

2.輪流下棋的點(diǎn)擊事件
下棋的邏輯很簡(jiǎn)單,就是點(diǎn)擊棋盤的時(shí)候,給點(diǎn)擊的td對(duì)應(yīng)的那個(gè)對(duì)象添加一個(gè)num屬性,黑棋就是1,白棋就是2,然后渲染出來(lái)就可以了。下棋順序可以通過(guò)一個(gè)全局變量flag來(lái)控制,同時(shí)聲明兩個(gè)全局?jǐn)?shù)組,用來(lái)存放所有的黑棋和白棋。后面判斷勝負(fù)時(shí),要對(duì)這兩個(gè)數(shù)組先進(jìn)行遍歷。
//判斷下棋順序的全局變量
let flag = true
//所有黑棋數(shù)組
let blackArr = []
//所有白棋數(shù)組
let whiteArr = []
//輪流下棋邏輯
document.querySelector('table').addEventListener('click', function (e) {
if (e.target.dataset.x) {
let td = e.target
//判斷黑白棋子的順序
if (flag) {
//判斷點(diǎn)擊的地方是否已經(jīng)有棋子了,避免棋子覆蓋
if (!arr[td.dataset.y][td.dataset.x].num) {
flag = !flag
arr[td.dataset.y][td.dataset.x].num = 1
//每走一步,就將其添加至對(duì)應(yīng)的數(shù)組當(dāng)中
blackArr.push([td.dataset.y, td.dataset.x])
}
} else {
if (!arr[td.dataset.y][td.dataset.x].num) {
flag = !flag
arr[td.dataset.y][td.dataset.x].num = 2
whiteArr.push([td.dataset.y, td.dataset.x])
}
}
//調(diào)用判斷勝負(fù)的函數(shù)
XWin(td)
YWin(td)
X_YWin(td)
Y_XWin(td)
}
render()
})

3.獲勝條件判斷
接下來(lái)就是寫獲勝條件了。我分成了4種情況,橫軸,數(shù)軸,正斜軸和反斜軸。這4種情況邏輯和方法大致都是相同的,就是里面的數(shù)據(jù)有些細(xì)微差別。
3.1橫軸獲勝
以橫軸為例,如何判斷獲勝,先判斷是黑棋還是白棋,然后遍歷對(duì)應(yīng)的數(shù)組。已黑棋為例,遍歷之后把y值相同的黑棋篩選出來(lái)都放入一個(gè)數(shù)組中,也就是同一行的黑棋。接著比較這一行的這些黑棋的x值,如果有5個(gè)連續(xù)的x值,則說(shuō)明橫軸上有5個(gè)連續(xù)的黑棋,就可以判斷獲勝了。怎么比較這些x值呢,我的做法是先將他們用sort()方法排序,接著從小到大依次比較。建一個(gè)新數(shù)組,第二個(gè)值等于第一個(gè)值加1,就把他們?nèi)拥竭@個(gè)新數(shù)組中,如果出現(xiàn)某個(gè)值不連續(xù)了,就將這個(gè)數(shù)組清空,這樣通過(guò)判斷這個(gè)數(shù)組的長(zhǎng)度,就能判斷勝負(fù)了。
//橫軸獲勝邏輯
function XWin(td) {
//當(dāng)前X軸的所有棋子集合
let xAllArr = []
//判斷橫軸勝負(fù)邏輯的X軸棋子
let xWinArr = []
//判斷下的是黑棋還是白棋
if (!flag) {
blackArr.map(item => {
if (item[0] == td.dataset.y) {
//將當(dāng)前排的所有棋子加入對(duì)應(yīng)數(shù)組
xAllArr.push(item[1])
}
})
} else {
whiteArr.map(item => {
if (item[0] == td.dataset.y) {
xAllArr.push(item[1])
}
})
}
//把橫排總數(shù)組排序,方便比較
xAllArr.sort((a, b) => a - b)
for (let i = 1; i < xAllArr.length; i++) {
// console.log(xAllArr[i]);
if (xAllArr[i] == (+xAllArr[i - 1] + 1)) {
//如果相鄰的兩個(gè)棋子數(shù)量相差1,就將其添加至勝負(fù)邏輯數(shù)組
xWinArr.push(xAllArr[i])
} else {
//否則得清空
xWinArr = []
}
}
//獲勝條件
if (xWinArr.length == 4) {
//這里要用定時(shí)器將彈框變成異步任務(wù),否則第五顆棋子渲染不出來(lái)就提示獲勝了
if (!flag) {
setTimeout(function () {
alert('黑棋獲勝!')
location.reload()
}, 100)
} else {
setTimeout(function () {
alert('白棋獲勝!')
location.reload()
}, 100)
}
}
}

3.2數(shù)軸獲勝
豎軸和橫軸代碼基本上也相同
只是換了個(gè)條件,把if (item[0] == td.dataset.y) 換成了if (item[1] == td.dataset.x),意思就是選出這一列所有的棋子。后面的邏輯和代碼就和橫軸一樣了。
//豎軸獲勝邏輯
function YWin(td) {
//當(dāng)前Y軸的所有棋子集合
let yAllArr = []
//判斷豎軸勝負(fù)邏輯的X軸棋子
let yWinArr = []
if (!flag) {
blackArr.map(item => {
if (item[1] == td.dataset.x) {
yAllArr.push(item[0])
}
})
} else {
whiteArr.map(item => {
if (item[1] == td.dataset.x) {
yAllArr.push(item[0])
}
})
}
//豎排總數(shù)組排序
yAllArr.sort((a, b) => a - b)
for (let i = 1; i < yAllArr.length; i++) {
// console.log(xAllArr[i]);
if (yAllArr[i] == (+yAllArr[i - 1] + 1)) {
yWinArr.push(yAllArr[i])
} else {
yWinArr = []
}
}
if (yWinArr.length == 4) {
if (!flag) {
setTimeout(function () {
alert('黑棋獲勝!')
location.reload()
}, 100)
} else {
setTimeout(function () {
alert('白棋獲勝!')
location.reload()
}, 100)
}
}
}

3.3正斜軸獲勝
斜軸困難一點(diǎn)的地方就是,怎么篩選出這一條斜線上的所有棋子。
只要能把這條斜線上的棋子給找出來(lái),后面的邏輯判斷就都一樣了。所有的斜線都是45度角,也就是說(shuō)斜線上的任意兩個(gè)棋子,他們的x值之差于y值之差是相等的。這樣的話,判斷起來(lái)就簡(jiǎn)單了。 if ((item[0] - td.dataset.y) == (item[1] - td.dataset.x))這樣就可以了。斜線上的棋子找出來(lái)后,后面的步驟就都一樣了,復(fù)制粘貼即可。
//正斜軸獲勝邏輯
function X_YWin(td) {
//當(dāng)前X軸的所有棋子集合
let x_yAllArr = []
//判斷橫軸勝負(fù)邏輯的X軸棋子
let x_yWinArr = []
if (!flag) {
blackArr.map(item => {
//判斷斜軸棋子,斜軸棋子的x和y之差都是相同的
if ((item[0] - td.dataset.y) == (item[1] - td.dataset.x)) {
x_yAllArr.push(item[1])
}
})
} else {
whiteArr.map(item => {
if ((item[0] - td.dataset.y) == (item[1] - td.dataset.x)) {
x_yAllArr.push(item[1])
}
})
}
x_yAllArr.sort((a, b) => a - b)
for (let i = 1; i < x_yAllArr.length; i++) {
if (x_yAllArr[i] == (+x_yAllArr[i - 1] + 1)) {
//如果相鄰的兩個(gè)棋子數(shù)量相差1,就將其添加至勝負(fù)邏輯數(shù)組
x_yWinArr.push(x_yAllArr[i])
} else {
//否則得清空
x_yWinArr = []
}
}
//獲勝條件
if (x_yWinArr.length == 4) {
if (!flag) {
setTimeout(function () {
alert('黑棋獲勝!')
location.reload()
}, 100)
} else {
setTimeout(function () {
alert('白棋獲勝!')
location.reload()
}, 100)
}
}
}

3.4反斜軸獲勝
反斜軸同理,條件改成 if (0 - (item[0] - td.dataset.y) == (item[1] - td.dataset.x)),其余的復(fù)制粘貼。
//反斜軸獲勝邏輯
function Y_XWin(td) {
//當(dāng)前X軸的所有棋子集合
let y_xAllArr = []
//判斷橫軸勝負(fù)邏輯的X軸棋子
let y_xWinArr = []
if (!flag) {
blackArr.map(item => {
//判斷斜軸棋子
if (0 - (item[0] - td.dataset.y) == (item[1] - td.dataset.x)) {
y_xAllArr.push(item[1])
}
})
} else {
whiteArr.map(item => {
if (0 - (item[0] - td.dataset.y) == (item[1] - td.dataset.x)) {
y_xAllArr.push(item[1])
}
})
}
y_xAllArr.sort((a, b) => a - b)
for (let i = 1; i < y_xAllArr.length; i++) {
if (y_xAllArr[i] == (+y_xAllArr[i - 1] + 1)) {
//如果相鄰的兩個(gè)棋子數(shù)量相差1,就將其添加至勝負(fù)邏輯數(shù)組
y_xWinArr.push(y_xAllArr[i])
} else {
//否則得清空
y_xWinArr = []
}
}
//獲勝條件
if (y_xWinArr.length == 4) {
if (!flag) {
setTimeout(function () {
alert('黑棋獲勝!')
location.reload()
}, 100)
} else {
setTimeout(function () {
alert('白棋獲勝!')
location.reload()
}, 100)
}
}
}

把這些函數(shù)放到下棋事件里面調(diào)用,整個(gè)功能就完成了。
4.悔棋功能
最后寫一下悔棋功能,點(diǎn)擊悔棋,把對(duì)應(yīng)數(shù)組里面的數(shù)據(jù)刪除,然后重新渲染棋盤就完事了。
//悔棋
document.querySelector('button').addEventListener('click', function () {
//判斷前面一步是黑棋還是白棋
if (!flag) {
//黑棋
//獲取對(duì)應(yīng)棋子總數(shù)組的最后一個(gè)數(shù)據(jù)的值
const y = blackArr[blackArr.length - 1][0]
const x = blackArr[blackArr.length - 1][1]
//將對(duì)應(yīng)的對(duì)象里的num值刪除,這樣渲染出來(lái)對(duì)應(yīng)棋子就消失了
delete arr[y][x].num
//刪除總數(shù)組里的最后一個(gè)數(shù)據(jù),否則勝負(fù)邏輯會(huì)有問(wèn)題
blackArr.splice(blackArr.length - 1, 1)
//重置下棋順序
flag = !flag
} else {
//白棋
const y = whiteArr[whiteArr.length - 1][0]
const x = whiteArr[whiteArr.length - 1][1]
delete arr[y][x].num
whiteArr.splice(whiteArr.length - 1, 1)
flag = !flag
}
render()
})
總結(jié)
整個(gè)代碼寫下來(lái),都是些js的基本語(yǔ)法,幾個(gè)數(shù)組的方法來(lái)回用,希望能給js初學(xué)者一些幫助。

到此這篇關(guān)于使用原生JS快速寫出一個(gè)五子棋小游戲的文章就介紹到這了,更多相關(guān)原生JS寫五子棋小游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript前端UI框架Kit使用指南之kitjs的對(duì)話框組件
本文以kitjs對(duì)話框組件為例,給我們?cè)敿?xì)介紹了kitjs的組件目錄、默認(rèn)代碼模板、構(gòu)造器及初始方法、以及Kitjs繼承。講解的非常細(xì)致,對(duì)我們熟練掌握kitjs組件很有幫助。2014-11-11
ES6中l(wèi)et、const的區(qū)別及變量的解構(gòu)賦值操作方法實(shí)例分析
這篇文章主要介紹了ES6中l(wèi)et、const的區(qū)別及變量的解構(gòu)賦值操作方法,結(jié)合實(shí)例形式分析了ES6中l(wèi)et、const的功能、原理、使用方法及數(shù)組、字符串、函數(shù)參數(shù)等解構(gòu)賦值相關(guān)操作技巧,需要的朋友可以參考下2019-10-10
解讀TypeScript與JavaScript的區(qū)別
這篇文章主要介紹了TypeScript與JavaScript的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
layui頁(yè)面級(jí)彈出框的實(shí)現(xiàn)
本文主要介紹了layui頁(yè)面級(jí)彈出框的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02

