<!DOCTYPE html>
<html lang="en">
<head>
<style>
canvas {
background-color: #0a0;
display:block;
margin:0 auto;
}
.tip {
text-align: center;
padding: 20px;
}
</style>
</head>
<body>
<div class="tip">请黑棋落子</div>
<script>
//创建canvas标签
const canvas = document.createElement("canvas")
canvas.width = 800;
canvas.height = 800; document.body.append(canvas)
// 获取 tip 元素
const tip = document.getElementsByClassName("tip")[0];
//得到 context 对象
const context = canvas.getContext("2d");
const maxRow = 16;
const maxCol = 16;
// 画棋盘
for(let i=1;i< maxCol;i++) {
context.moveTo(50,50*i);
context.lineTo(750,50*i);
context.stroke();
}
for (let i = 1; i < maxRow; i++) {
context.moveTo(50 * i,50);
context.lineTo(50 * i,750);
context.stroke();
}
// 使用变量保存当前棋子颜色
let isBlack = true;
// 使用二维数组存储棋子
let circles = []
for(let i=1;i< maxCol;i++) {
circles[i] = []
}
// 设置一个变量确定是否可以结束游戏
let endGame = false;
// 当点击在棋盘里面时,绘制一个圆
canvas.addEventListener("click",e =>{
// 判断是否可以继续游戏
if (endGame) {
return
}
let {offsetX,offsetY} = e;
// 确定点击位置边界
if(offsetX < 25 || offsetY < 25 || offsetX > 775 || offsetY > 775) {
return
}
// 确定棋子最终位置
let i = Math.floor((offsetX + 25) / 50)
let j = Math.floor((offsetY + 25) / 50)
// 判断当前位置是否已经存在棋子
if(circles[i][j]) {
// 也可以提醒用户当前位置已经有棋子了
tip.innerText =`这里不能重复落子,当前是${isBlack?"黑" :"白"}棋的回合`
return
}
let x = i * 50;
let y = j * 50;
context.beginPath();
context.arc(x,y,20,0,2*Math.PI)
// 把对应棋子存放在二维数组中
circles[i][j] = isBlack?'black' : 'white';
// 判断当前棋子使用什么颜色
let tx = isBlack? x-10 : x+10
let ty = isBlack ? y - 10 : y + 10
let gradient = context.createRadialGradient(tx, ty,0, tx, ty,30);
gradient.addColorStop(0,isBlack ? "#ccc" : "#666");
gradient.addColorStop(1, isBlack ? "#000" : "#fff");
context.fillStyle= gradient;
// 设置阴影美化棋子,增加立体感
context.shadowBlur = 4;
context.shadowColor = "#333";
context.shadowOffsetX = 4;
context.fill()
context.closePath()
// 判断当前棋子是否已经连成
endGame = checkVertical(i,j) || checkHorizontal(i,j) || checkLurd(i,j) || checkRuld(i,j)
if(endGame) {
tip.innerText = `${isBlack ? '黑' : '白'}棋已获胜,请刷新重新开始`
return
}
// 提醒用户 换人了
isBlack = !isBlack
tip.innerText = isBlack ? "请黑棋落子" : "请白棋落子"
})
// 纵向查找五子棋
function checkVertical(row,col) {
// 定义一个变量,记录向上的次数
let up = 0;
// 定义一个变量,记录向下的次数
let down = 0;
// 定义当前共有几个连接在一起
let count = 1;
let times = 0
// 避免出现死循环
while(times < 100) {
times++;
let target = isBlack? "black" : "white";
// 以 row,col 为起点,在二维数组上,向上查找
up++;
if(col - up > 0 && circles[row][col-up] && circles[row][col-up] == target) {
count++;
}
down++;
// 以 row,col 为起点,在二维数组上,向下查找
if (col + down < maxCol && circles[row][col + down] && circles[row][col + down] == target) {
count++;
}
// 判断是否结束循环
if (count >= 5 || col + down < maxCol && col -up> 0 && circles[row][col-up] !== target && circles[row][col+down] !== target) {
break;
}
}
return count >=5
}
// 横向查找五子棋
function checkHorizontal (row, col) {
// 定义一个变量,记录向左的次数
let left = 0;
// 定义一个变量,记录向右的次数
let right = 0;
// 定义当前共有几个连接在一起
let count = 1;
let times = 0
// 避免出现死循环
while (times < 100) {
times++;
let target = isBlack ? "black" : "white";
// 以 row,col 为起点,在二维数组上,向左查找
left++;
if (row - left > 0 && circles[row - left][col] && circles[row - left][col] == target) {
count++;
}
right++;
// 以 row,col 为起点,在二维数组上,向右查找
if ( row + right<maxRow && circles[row + right][col] && circles[row + right][col] == target) {
count++;
}
// 判断是否结束循环
if (count >= 5 || row + right < maxRow && row - left > 0 && circles[row - left][col] !== target && circles[row + right][col] !== target) {
break;
}
}
return count >= 5
}
// 左上到右下查找五子棋
function checkLurd (row, col) {
// 定义一个变量,记录向左上的次数
let lu = 0;
// 定义一个变量,记录向右下的次数
let rd = 0;
// 定义当前共有几个连接在一起
let count = 1;
let times = 0
// 避免出现死循环
while (times < 100) {
times++;
let target = isBlack ? "black" : "white";
// 以 row,col 为起点,在二维数组上,向左上查找
lu++;
if (row - lu > 0 && col - lu > 0 && circles[row - lu][col - lu] && circles[row - lu][col - lu] == target) {
count++;
}
rd++;
// 以 row,col 为起点,在二维数组上,向右下查找
if (row + rd < maxRow && col + rd<maxCol && [row + rd][col + rd] && circles[row + rd][col + rd] == target) {
count++;
}
// 判断是否结束循环
if (count >= 5 || row + rd < maxRow && col + rd < maxCol && row - lu > 0 && col - lu > 0 && circles[row - lu][col - lu] !== target && circles[row + rd][col + rd] !== target) {
break;
}
}
return count >= 5
}
// 右上到左下查找五子棋
function checkRuld (row, col) {
// 定义一个变量,记录向右上的次数
let ru = 0;
// 定义一个变量,记录向左下的次数
let ld = 0;
// 定义当前共有几个连接在一起
let count = 1;
let times = 0
// 避免出现死循环
while (times < 100) {
times++;
let target = isBlack ? "black" : "white";
// 以 row,col 为起点,在二维数组上,向右上查找
ru++;
if ( row + ru <maxRow && col - ru >0 && [row + ru][col - ru] && circles[row + ru][col - ru] == target) {
count++;
}
ld++;
// 以 row,col 为起点,在二维数组上,向左下查找
if (row - ld>0 && col + ld <maxCol && [row - ld][col + ld] && circles[row - ld][col + ld] == target) {
count++;
}
// 判断是否结束循环
if (count >= 5 || row - ld > 0 && col + ld < maxCol && row + ru < maxRow && col - ru > 0 && circles[row + ru][col - ru] !== target && circles[row - ld][col + ld] !== target) {
break;
}
}
return count >= 5
}
</script>
</body>
</html>
01-02
133
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
07-23
855
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
05-02