VUE3+Canvas绘制五子棋(一)

趁着休息,花了1小时参考网上各类简单的写了个五子棋,主要实现功能,未进行任何优化

修改画布大小及棋子布局

1
2
3
4
5
<template>
<div class="board">
<canvas id="board" width="600" height="600"></canvas>
</div>
</template>

CSS相应如下

1
2
3
4
5
6
7
8
9
10
.board {
border: 1px solid red;
width: 630px;
height: 630px;
padding: 0 0;
margin: 0 0;
display: flex;
align-items: center;
justify-content: center;
}

1、绘制棋盘,以30为一格,考虑棋子落在交叉点,故在绘制时右移和下移了15,并将数组进行重置(600的棋盘,30一个,共20个)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
drawBoard() {
const canvas = document.getElementById("board");
const ctx = canvas.getContext("2d");

// 设置线条颜色
ctx.strokeStyle = "black";
// 绘制横线
for (let i = 0; i <= 19; i++) {
ctx.beginPath();
ctx.moveTo(15, i * 30 + 15);
ctx.lineTo(570 + 15, i * 30 + 15);
ctx.stroke();
}

// 绘制竖线
for (let i = 0; i <= 19; i++) {
ctx.beginPath();
ctx.moveTo(i * 30 + 15, 0 + 15);
ctx.lineTo(i * 30 + 15, 570 + 15);
ctx.stroke();
}
// 重置为0
for (let i = 0; i <= 19; i++) {
this.board.push(new Array(20).fill(0))
}
// console.log(this.board)
},

2、绘制棋子,考虑正负15的距离,此处在绘制完成后,进行了正负判断,选手交换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
drawCell() {
let container = document.getElementById("board");
container.addEventListener("click", this.handleClickAndDraw)
},
handleClickAndDraw(event) {
let x = event.offsetX;
let y = event.offsetY;
console.log(x + ' ' + y)
// 计算棋子落在哪个方格中
const cellX = Math.floor((event.offsetX) / 30);
const cellY = Math.floor((event.offsetY) / 30);
console.log(cellX, cellY)
// 判断该位置是否有棋子
if (this.board[cellX][cellY] !== 0) {
alert("该位置已有棋子")
return;
}
const canvas = document.getElementById("board");
const ctx = canvas.getContext("2d");
//画带渐变色的棋子,同心圆形式
let grd = ctx.createRadialGradient(
cellX * 30 + 15,
cellY * 30 + 15,
2,
cellX * 30 + 15,
cellY * 30 + 15,
10
)
grd.addColorStop(0, this.player === 1 ? '#FFFFFF' : '#4C4C4C')
grd.addColorStop(1, this.player === 1 ? '#DADADA' : '#000000')
ctx.beginPath()
ctx.fillStyle = grd
ctx.arc(
cellX * 30 + 15,
cellY * 30 + 15,
10,
0,
2 * Math.PI,
false
);
ctx.fill();
ctx.closePath();
this.board[cellX][cellY] = this.player; //将黑白棋信息存储
this.winner = this.checkWinner(this.board)
if (this.winner != null) {
alert(this.winner)
}
this.player = this.player === 1 ? 2 : 1
},

3、正负判断,这个主要采取网上CSDN,并未进行过多加工

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
checkWinner(board) {
// 检查横向是否有五子连线
for (let i = 0; i < 19; i++) {
let count = 0;
for (let j = 0; j < 19; j++) {
if (board[i][j] === this.player) {
count++;
} else {
count = 0;
}

if (count >= 5) {
return this.player;
}
}
}

// 检查纵向是否有五子连线
for (let j = 0; j < 19; j++) {
let count = 0;
for (let i = 0; i < 19; i++) {
if (board[i][j] === this.player) {
count++;
} else {
count = 0;
}

if (count >= 5) {
return this.player;
}
}
}

// 检查右斜线是否有五子连线
for (let i = 0; i < 14; i++) {
for (let j = 0; j < 14; 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 < 14; i++) {
for (let j = 4; j < 19; 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;
}

最后,完整代码如下App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
<script>
export default {
data() {
return {
board: [],
player: 1,//1--白棋;2--黑棋
winner: null
};
},
mounted() {
this.drawBoard();
this.drawCell();
},
methods: {
drawBoard() {
const canvas = document.getElementById("board");
const ctx = canvas.getContext("2d");

// 设置线条颜色
ctx.strokeStyle = "black";

// 绘制横线
for (let i = 0; i <= 19; i++) {
ctx.beginPath();
ctx.moveTo(15, i * 30 + 15);
ctx.lineTo(570 + 15, i * 30 + 15);
ctx.stroke();
}

// 绘制竖线
for (let i = 0; i <= 19; i++) {
ctx.beginPath();
ctx.moveTo(i * 30 + 15, 0 + 15);
ctx.lineTo(i * 30 + 15, 570 + 15);
ctx.stroke();
}
// 重置为0
for (let i = 0; i <= 19; i++) {
this.board.push(new Array(20).fill(0))
}
// console.log(this.board)
},
drawCell() {
let container = document.getElementById("board");
container.addEventListener("click", this.handleClickAndDraw)
},
handleClickAndDraw(event) {
let x = event.offsetX;
let y = event.offsetY;
console.log(x + ' ' + y)
// 计算棋子落在哪个方格中
const cellX = Math.floor((event.offsetX) / 30);
const cellY = Math.floor((event.offsetY) / 30);
console.log(cellX, cellY)
// 判断该位置是否有棋子
if (this.board[cellX][cellY] !== 0) {
alert("该位置已有棋子")
return;
}
const canvas = document.getElementById("board");
const ctx = canvas.getContext("2d");
//画带渐变色的棋子,同心圆形式
let grd = ctx.createRadialGradient(
cellX * 30 + 15,
cellY * 30 + 15,
2,
cellX * 30 + 15,
cellY * 30 + 15,
10
)
grd.addColorStop(0, this.player === 1 ? '#FFFFFF' : '#4C4C4C')
grd.addColorStop(1, this.player === 1 ? '#DADADA' : '#000000')
ctx.beginPath()
ctx.fillStyle = grd
ctx.arc(
cellX * 30 + 15,
cellY * 30 + 15,
10,
0,
2 * Math.PI,
false
);
ctx.fill();
ctx.closePath();
this.board[cellX][cellY] = this.player; //将黑白棋信息存储
this.winner = this.checkWinner(this.board)
if (this.winner != null) {
alert(this.winner)
}
this.player = this.player === 1 ? 2 : 1
},
checkWinner(board) {
// 检查横向是否有五子连线
for (let i = 0; i < 19; i++) {
let count = 0;
for (let j = 0; j < 19; j++) {
if (board[i][j] === this.player) {
count++;
} else {
count = 0;
}

if (count >= 5) {
return this.player;
}
}
}

// 检查纵向是否有五子连线
for (let j = 0; j < 19; j++) {
let count = 0;
for (let i = 0; i < 19; i++) {
if (board[i][j] === this.player) {
count++;
} else {
count = 0;
}

if (count >= 5) {
return this.player;
}
}
}

// 检查右斜线是否有五子连线
for (let i = 0; i < 14; i++) {
for (let j = 0; j < 14; 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 < 14; i++) {
for (let j = 4; j < 19; 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;
}
}
};
</script>

<template>
<div class="board">
<canvas id="board" width="600" height="600"></canvas>
</div>
</template>

<style scoped>
.board {
border: 1px solid red;
width: 630px;
height: 630px;
padding: 0 0;
margin: 0 0;
display: flex;
align-items: center;
justify-content: center;
}
</style>

效果图
效果图


VUE3+Canvas绘制五子棋(一)
http://060800.xyz/2024/11/28/VUE3-Canvas绘制五子棋(一)/
作者
砖头
发布于
2024年11月28日
许可协议