<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#myCanvas {
background-color: cadetblue;
}
</style>
</head>
<body>
<canvas id="myCanvas"></canvas>
<script>
class Gomoku {
constructor(canvas, context) {
this.canvas = canvas;
this.context = context;
this.canvas.width = 750;
this.canvas.height = 750;
this.canvas.addEventListener('click', this.handleClick.bind(this));
this.canvas.addEventListener('mousemove', this.handleMouseMove.bind(this));
this.init();
}
//初始化
init() {
this.isBlack = true;
this.chessGame = new Array(15).fill(null).map(() => new Array(15).fill(null));
this.chessboard()
}
handleClick(event) {
let x = Math.round((event.offsetX - 25) / 50)
let y = Math.round((event.offsetY - 25) / 50)
//如果该位置有棋子,则无法落子
if (this.chessGame[x][y]) {
return;
}
this.chessGame[x][y] = { isBlack: this.isBlack }
this.drawChess(x, y, this.isBlack)
this.x = x;
this.y = y;
//四条线的两端分别判断是否五子连线
for (let i = 0; i < 4; i++) {
if (this.line(i, 'left') + this.line(i, 'right') == 4) {
return setTimeout(() => {
alert(this.isBlack ? '黑棋获胜' : '白棋获胜')
this.init()
}, 1)
}
}
this.isBlack = !this.isBlack
}
handleMouseMove(event) {
let x = Math.round((event.offsetX - 25) / 50)
let y = Math.round((event.offsetY - 25) / 50)
//如果该位置有棋子,则无法落子
if (!this.chessGame[x][y] && (x != this.willX || y != this.willY)) {
this.canvas.style.cursor = 'pointer'
this.context.clearRect(0, 0, 750, 750)
this.chessboard()
this.drawChess(x, y, this.isBlack, 0.8)
this.willX = x;
this.willY = y;
}
else if (this.chessGame[x][y] && (x != this.willX || y != this.willY)) {
this.canvas.style.cursor = 'default'
this.context.clearRect(0, 0, 750, 750)
this.chessboard()
this.willX = x;
this.willY = y;
}
else if (!this.chessGame[x][y] && !(x != this.willX || y != this.willY)) {
this.canvas.style.cursor = 'pointer'
}
else {
this.canvas.style.cursor = 'default'
}
}
//创建棋盘
chessboard() {
this.context.clearRect(0, 0, 750, 750)
let chessboard = new Path2D();
for (let i = 0; i < 15; i++) {
chessboard.moveTo(50 * i + 25, 25)
chessboard.lineTo(50 * i + 25, 725)
this.context.stroke(chessboard)
}
for (let i = 0; i < 15; i++) {
chessboard.moveTo(25, 50 * i + 25)
chessboard.lineTo(725, 50 * i + 25)
this.context.stroke(chessboard)
}
this.chessGame.map((item1, x) => {
item1.map((item2, y) => {
if (item2) {
this.drawChess(x, y, item2.isBlack)
}
})
})
}
//画棋子
drawChess(x, y, isBlack, a = 1) {
let chess = new Path2D();
chess.arc(x * 50 + 25, y * 50 + 25, 20, 0, 2 * Math.PI)
let cx = isBlack ? x * 50 + 15 : x * 50 + 35
let cy = isBlack ? y * 50 + 15 : y * 50 + 35
let grd = this.context.createRadialGradient(cx, cy, 0, cx, cy, 20)
grd.addColorStop(0, isBlack ? ("rgba(204,204,204," + a + ")") : ("rgba(102,102,102," + a + ")"));
grd.addColorStop(1, isBlack ? ("rgba(0,0,0," + a + ")") : ("rgba(255,255,255," + a + ")"));
this.context.fillStyle = grd;
this.context.fill(chess)
// 边框虚线
// this.context.save()
// context.setLineDash([20, 5]); // [实线长度, 间隙长度]
// context.lineDashOffset = -0;
// this.context.strokeStyle = this.isBlack ? 'black' : 'white';
// this.context.stroke(chess)
// this.context.restore()
}
//判断五子连线
line(times, direction) {
let count = 0;
let x;
let y;
for (let i = 1; i < 5; i++) {
switch (times) {
case 0:
x = direction == 'left' ? this.x + i : this.x - i;
y = this.y;
break;
case 1:
x = this.x;
y = direction == 'left' ? this.y + i : this.y - i;
break;
case 2:
x = direction == 'left' ? this.x + i : this.x - i;
y = direction == 'left' ? this.y + i : this.y - i;
break;
case 3:
x = direction == 'left' ? this.x + i : this.x - i;
y = direction == 'left' ? this.y - i : this.y + i;
break;
}
if (this.chessGame[x] && this.chessGame[x][y] && this.chessGame[x][y].isBlack == this.isBlack) {
count++
}
else {
break;
}
}
return count
}
}
let canvas = document.getElementById('myCanvas')
let context = canvas.getContext('2d')
let gomuku = new Gomoku(canvas, context);
</script>
</body>
</html>
canvas实现简易五子棋
于 2023-11-05 23:32:05 首次发布