在昨天的基础上,对五子棋进行了调整
1、增加了背景颜色
2、增加了修改棋盘大小功能
3、增加了重新开始功能
仍未进行代码优化,同时对vue的data内的数据修改、读取,未发现好的方式,既可以直接读取带来的方便,但感觉也会带来随意修改数据产生的意外,会影响健壮性。
完整代码Game.vue
<script>
export default {
data() {
return {
board: [],
player: 1,//1--白棋;2--黑棋
winner: null,
restart: false,
boardDetail: {
width: 0,//棋盘大小
lineNumber: 0,//棋盘线数
space: 0,//间隙
}
};
},
// 实例刚创建,但未挂载dom
created() {
document.title = "五子棋";
},
// 实例创建完成,仅在首次加载时完成
mounted() {
this.boardDetail = {
width: document.getElementById("board").clientWidth,
lineNumber: 20,//棋盘线数
space: 30,//间隙
}
this.drawBoard(this.boardDetail.width,
this.boardDetail.lineNumber,
this.boardDetail.space);
},
methods: {
/**
* 画整体棋盘
* @param width 所需棋盘整体大小,上下左右预留一半space空间
* @param lineNumber 线条数,线条数*间距=width
* @param space 间距
*/
drawBoard(width, lineNumber, space) {
const halfSpace = space / 2;
const canvas = document.getElementById("board");
const ctx = canvas.getContext("2d");
// 设置线条颜色
ctx.strokeStyle = "black";
for (let i = 0; i < lineNumber; i++) {
// 绘制横线
ctx.beginPath();
ctx.moveTo(halfSpace, i * space + halfSpace);
ctx.lineTo(width - halfSpace, i * space + halfSpace);
ctx.stroke();
// 绘制竖线
ctx.beginPath();
ctx.moveTo(i * space + halfSpace, halfSpace);
ctx.lineTo(i * space + halfSpace, width - halfSpace);
ctx.stroke();
//填充数组,重置为0
this.board.push(new Array(lineNumber).fill(0))
}
},
/**
* 监听每步棋子,需要传入棋盘信息
* @param event
* @param detail 棋盘信息
*/
handleClickAndDraw(event, detail) {
//存在输赢以后,不允许在落子
if (this.winner != null) {
return;
}
const lineNumber = detail.lineNumber
const space = detail.space
const halfSpace = space / 2;
// let x = event.offsetX;
// let y = event.offsetY;
// console.log(x + ' ' + y)
// 计算棋子落在哪个方格中
const cellX = Math.floor((event.offsetX) / space);
const cellY = Math.floor((event.offsetY) / space);
// console.log(cellX, cellY)
// 判断该位置是否有棋子
if (this.board[cellX][cellY] !== 0) {
alert("该位置已有棋子")
return;
}
const canvas = document.getElementById("board");
const ctx = canvas.getContext("2d");
//画带渐变色的棋子,同心圆形式
//考虑起点为2,因半径为space一半,避免太大,截止1/3大小
let grd = ctx.createRadialGradient(
cellX * space + halfSpace,
cellY * space + halfSpace,
2,
cellX * space + halfSpace,
cellY * space + halfSpace,
space / 3
)
grd.addColorStop(0, this.player === 1 ? '#FFFFFF' : '#4C4C4C')
grd.addColorStop(1, this.player === 1 ? '#DADADA' : '#000000')
ctx.beginPath()
ctx.fillStyle = grd
//画圆,半径设置为space/3,同上r1参数一致
ctx.arc(
cellX * space + halfSpace,
cellY * space + halfSpace,
space / 3,
0,
2 * Math.PI,
false
);
ctx.fill();
ctx.closePath();
this.board[cellX][cellY] = this.player; //将黑白棋信息存储
this.winner = this.checkWinner(this.board, lineNumber) //判断输赢
if (this.winner != null) {
alert(this.winner)
}
this.player = this.player === 1 ? 2 : 1//交换
},
/**
* 胜负检查
* @param board X*X 二维数组
* @param lineNumber 线条数
* @returns {number|null}
*/
checkWinner(board, lineNumber) {
// 检查横向是否有五子连线
for (let i = 0; i < lineNumber; i++) {
let count = 0;
for (let j = 0; j < lineNumber; j++) {
if (board[i][j] === this.player) {
count++;
} else {
count = 0;
}
if (count >= 5) return this.player;
}
}
// 检查纵向是否有五子连线
for (let j = 0; j < lineNumber; j++) {
let count = 0;
for (let i = 0; i < lineNumber; i++) {
if (board[i][j] === this.player) {
count++;
} else {
count = 0;
}
if (count >= 5) return this.player;
}
}
// 检查右斜线是否有五子连线
for (let i = 0; i < lineNumber - 5; i++) {
for (let j = 0; j < lineNumber - 5; j++) {
let count = 0;
for (let k = 0; k < 5; k++) {
if (board[i + k][j + k] === this.player) {
count++;
} else {
count = 0;
}
if (count >= 5) return this.player;
}
}
}
// 检查左斜线是否有五子连线
for (let i = 0; i < lineNumber - 5; i++) {
for (let j = 4; j < lineNumber; j++) {
let count = 0;
for (let k = 0; k < 5; k++) {
if (board[i + k][j - k] === this.player) {
count++;
} else {
count = 0;
}
if (count >= 5) return this.player;
}
}
}
// 如果没有五子连线,则游戏继续
return null;
},
/**
* 重置游戏
*/
restartGame() {
//清空基础数据
this.board = []
this.player = 1
this.winner = null
this.restart = false
//清空画布
const canvas = document.getElementById("board");
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height)
//重新绘制
this.drawBoard(this.boardDetail.width,
this.boardDetail.lineNumber,
this.boardDetail.space);
},
updateDetail(square, lineNumber) {
//重新设置board大小
let canvas = document.getElementById("board")
canvas.width = square
canvas.height = square
//重新设置棋盘大小
this.boardDetail = {
width: square,
lineNumber: lineNumber,
space: square / lineNumber
}
//重新绘制游戏
this.restartGame()
}
}
};
</script>
<template>
<div class="board">
<canvas id="board" width="600" height="600" class="board-chess"
@click="handleClickAndDraw($event,this.boardDetail)"></canvas>
<div class="board-detail">
<div>
<span>棋盘信息:</span><br>
<span>棋盘长宽:<input v-model="this.boardDetail.width"/></span><br>
<span>棋盘线条数:<input v-model="this.boardDetail.lineNumber"/></span><br>
<span>棋盘间距:<input v-model="this.boardDetail.space" disabled/></span><br>
<button @click="updateDetail(this.boardDetail.width,this.boardDetail.lineNumber)">修改</button>
</div>
<button @click="restartGame">重新开始</button>
<div>当前落子:{{ this.player === 1 ? "白" : "黑" }}</div>
<div>胜利方:{{ this.winner === 1 ? "白棋" : this.winner === 2 ? "黑棋" : "" }}</div>
</div>
</div>
</template>
<style scoped>
.board {
padding: 0 0;
margin: 10px;
display: flex;
align-items: center;
justify-content: center;
}
.board-chess {
border: 3px solid black;
padding: 0 0;
margin: 0 0;
}
.board-detail {
margin: 0 20px;
}
.board-detail > div input {
width: 50px;
}
</style>
效果图,测试中发现了一个bug,斜线的胜负检验逻辑有问题
1 条评论
《夺爱之夏》日本剧高清在线免费观看:https://www.jgz518.com/xingkong/140456.html