主要分几个步骤:
- 首先先画棋盘
- 保存所有赢法
- 监听点击, 每次点击画出棋子, 并遍历赢法,查看游戏是否结束
- 画棋盘
<canvas id="chessboard" width="460" height="460">
您的浏览器不支持canvas,请升级到最新的浏览器
</canvas>
<script>
//绘制棋盘
let chessboard = document.getElementById("chessboard")
let ctx = chessboard.getContext('2d')
ctx.lineWidth = '1'
ctx.beginPath()
for (let i = 0; i < 15; i++) {
//绘制横线
ctx.moveTo(20, 20 + i * 30)
ctx.lineTo(440, 20 + i * 30)
//绘制竖线
ctx.moveTo(20 + i * 30, 20)
ctx.lineTo(20 + i * 30, 440)
}
ctx.stroke()
<script>
- 保存所有赢法
/*
赢法格式 wins[i][j][k]
如wins[0][0][0]
wins[1][0][0]
wins[2][0][0]
wins[3][0][0]
wins[4][0][0] 为第一种赢法 第一个为x坐标,第二个为y坐标 第三个为赢法序号
*/
let wins = []
for (let i = 0; i < 15; i++) {
wins[i] = []
for (let j = 0; j < 15; j++) {
wins[i][j] = []
}
}
// 赢法个数
let count = 0
// 横线赢法
for (let i = 0; i < 15; i++) {
for (let j = 0; j < 11; j++) {
wins[j + 0][i][count] = true
wins[j + 1][i][count] = true
wins[j + 2][i][count] = true
wins[j + 3][i][count] = true
wins[j + 4][i][count] = true
count++
}
}
// 竖线赢法
for (let i = 0; i < 15; i++) {
for (let j = 0; j < 11; j++) {
wins[i][j + 0][count] = true
wins[i][j + 1][count] = true
wins[i][j + 2][count] = true
wins[i][j + 3][count] = true
wins[i][j + 4][count] = true
count++
}
}
// 斜线赢法 左上到右下
for (let i = 0; i < 11; i++) {
for (let j = 0; j < 11; j++) {
wins[j + 0][i + 0][count] = true
wins[j + 1][i + 1][count] = true
wins[j + 2][i + 2][count] = true
wins[j + 3][i + 3][count] = true
wins[j + 4][i + 4][count] = true
count++
}
}
// 斜线赢法 左下到右上
for (let i = 0; i < 11; i++) {
for (let j = 14; j > 3; j--) {
wins[i + 0][j - 0][count] = true
wins[i + 1][j - 1][count] = true
wins[i + 2][j - 2][count] = true
wins[i + 3][j - 3][count] = true
wins[i + 4][j - 4][count] = true
count++
}
}
这里需要使用一个二维数组保存所有落子,默认为0没有棋子, 1为黑子 2为白子
使用一个变量over保存游戏是否结束
使用一个变量isblackchess 保存落子颜色
新建数组记录当前黑白棋子 赢法完成度
// 保存所有落子
let chessmen = []
for (let i = 0; i < 15; i++) {
chessmen[i] = []
for (let j = 0; j < 15; j++) {
chessmen[i][j] = 0
}
}
// 使用变量保存是否结束
let over = false
//保存当前落子的颜色
let isblackchess = true
// 新建数组记录当前黑白棋子 赢法完成度
let blackWinArr = Array(count)
let whiteWinArr = Array(count)
blackWinArr.fill(0)
whiteWinArr.fill(0)
- 监听棋盘的点击
chessboard.onclick = function (e) {
if (over) {
return
}
let i = ((e.offsetX - 20) / 30).toFixed(0)
let j = ((e.offsetY - 20) / 30).toFixed(0)
//如果当前位置没有棋子 则
if (chessmen[i][j] == 0) {
//step接收三个参数: x坐标, y坐标, 是否是黑子, 然后画出黑子/白字
step(i, j, isblackchess)
if (isblackchess) {
chessmen[i][j] = 1
//addBlack 将落下的黑子放入黑子的赢法数组中
addBlack(i, j)
} else {
chessmen[i][j] = 2
//addBlack 将落下的白子放入黑子的赢法数组中
AddWhite(i, j)
}
}
isblackchess = !isblackchess
}
函数
//单击后画棋子
function step(i, j, me) {
let x = 20 + i * 30
let y = 20 + j * 30
ctx.beginPath()
ctx.arc(x, y, 13, 0, 2 * Math.PI)
ctx.closePath()
let gradient = ctx.createRadialGradient(x, y, 0, x, y, 8)
if (me) {
gradient.addColorStop(0, '#636766')
gradient.addColorStop(1, '#0a0a0a')
} else {
gradient.addColorStop(0, "#f9f9f9");
gradient.addColorStop(1, "#d1d1d1");
}
ctx.fillStyle = gradient
ctx.fill()
}
// 记录黑棋赢法的完成度, 某个赢法达到 5则游戏结束
function addBlack(i, j) {
for (let k = 0; k < count; k++) {
if (wins[i][j][k]) {
blackWinArr[k]++
if (blackWinArr[k] == 5) {
setTimeout(() => {alert("黑棋赢了")}) //这里添加个定时器, 不然第五个棋子会后面显示
over = true
}
}
}
}
//记录白棋所在赢法 的完成度
function AddWhite(i, j) {
for (let k = 0; k < count; k++) {
if (wins[i][j][k]) {
whiteWinArr[k]++
if (whiteWinArr[k] == 5) {
setTimeout(() => {alert("白棋赢了")})
over = true
}
}
}
}
注意点:
- 使用canvas画图在script标签里加上一下代码, 不然没有提示
/** @type {HTMLCanvasElement} */
- alert会先于棋子显示, 要加个setTimeout
-
关于赢法
Snipaste_2020-07-14_10-23-54.png
以左上角为(0, 0) 那么:
//横线第1个赢法
wins[0][0][0]
wins[1][0][0]
wins[2][0][0]
wins[3][0][0]
wins[4][0][0]
//横线第2个赢法
wins[1][0][1]
wins[2][0][1]
wins[3][0][1]
wins[4][0][1]
wins[5][0][1]
可以看出第一个数一次循环+1 ,第二个不变,第三个为次数,每次循环+1
所以第一个为内层循环, 第二个外层循环, 内层循环一次count+1
而当x坐标>=11时,是不能凑成一个赢法的,那么第一个数小于11,也就是内层循环小于11
所以有:
for (let i = 0; i < 15; i++) {
for (let j = 0; j < 11; j++) {
wins[j + 0][i][count] = true
wins[j + 1][i][count] = true
wins[j + 2][i][count] = true
wins[j + 3][i][count] = true
wins[j + 4][i][count] = true
count++
}
}