本文實例為大家分享了canvas實現(xiàn)五子棋小游戲的具體代碼,供大家參考,具體內(nèi)容如下
效果
思路
- canvans 繪制棋盤,繪制時候邊緣預(yù)留棋子位置
- 監(jiān)聽點擊事件繪制落子并記錄到字典中
- 獲勝判定,在四個方向上檢測是否有足夠數(shù)量的連貫棋子
代碼
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
|
<!DOCTYPE html> < html lang = "en" > < head > < meta charset = "UTF-8" > < title >ym</ title > < style > canvas { display: block; margin: 0 auto; border: 0 } .result { text-align: center; } button{ display: block; margin: 0 auto; padding: 4px 20px; border:0; color: #fff; outline: none; border-radius: 3px; background: #43a6ff } button:hover{ font-weight: bold; cursor: pointer; } </ style > </ head > < body > < canvas id = "cv" width = "200px" height = "200px" ></ canvas > < p class = "result" ></ p > < button onclick = "loadPanel(400, 400,30,13)" >刷新</ button > < script > loadPanel(400, 400,30,13); /** * 1) 點擊落子并切換執(zhí)子者 * 2)以當(dāng)前落子位置為基準(zhǔn),以‘米'字型判定,是否能構(gòu)成五連及以上 * @param w 棋盤寬度 * @param h 棋盤高度 * @param cs 格子尺寸 * @param ps 棋子半徑 */ function loadPanel(w, h, cs, ps) { let i, j, k; let chks = [[1, 0], [0, 1], [1, 1], [1, -1]];//水平,縱向,斜下,斜上 四個方向 let successNum = 5;//贏棋標(biāo)準(zhǔn) let resultEl = document.querySelector('.result'); //1)繪制棋盤,邊緣應(yīng)隔開棋子半徑的距離 cs = cs || 16;//默認(rèn)格子寬高 ps = ps || 4;//棋子半徑 h = h || w;//高度默認(rèn)等于寬度 let el = document.getElementById('cv'); el.setAttribute('width', w + 'px'); el.setAttribute('height', h + 'px'); let context = el.getContext("2d"); //計算棋盤分割,向下取整 let splitX = ~~((w - 2 * ps) / cs), splitY = ~~((h - 2 * ps) / cs); //初始化落子位置使用字典存儲,相較于數(shù)組簡單且減少內(nèi)存占用 let pieces = {}; //循環(huán)劃線 context.translate(ps, ps); context.beginPath(); context.strokeStyle = '#000'; //垂直線 for (i = 0; i < splitX + 1; i++) { context.moveTo(cs * i, 0); context.lineTo(cs * i, splitY * cs); context.stroke(); } //水平線 for ( j = 0 ; j < splitY + 1; j++) { context.moveTo(0, cs * j); context.lineTo(splitX * cs, cs * j); context.stroke(); } context.closePath(); let user = 0 , colors = ['#000', '#fefefe']; el.addEventListener('click', function (e) { let x = e .offsetX, y = e .offsetY, //計算落子范圍 rx = ~~((x - ps) / cs) + (((x - ps) % cs <= cs / 2) ? 0 : 1), ry = ~~((y - ps) / cs) + (((y - ps) % cs <= cs / 2) ? 0 : 1); //繪制棋子 context.beginPath(); context.arc(cs * rx, cs * ry, ps, 2 * Math.PI, false); context.fillStyle = colors [user]; context.strokeStyle = '#000' ; user ? user = 0 : user = 1 ;//切換執(zhí)子者 context.fill(); context.stroke(); context.closePath(); //記錄棋子位置 let piece = pieces [rx + '-' + ry] = user; //米字型計算結(jié)果,以當(dāng)前落子位置計算是否存在某個方向上具有連續(xù)的五個相同棋子 for ( j = 0 ; j < chks.length; j++) { let num = 1 , chk = chks [j]; for ( i = 1 ; i <= 4; i++) { if (pieces[(rx + chk[0] * i) + '-' + (ry + chk[1] * i)] == piece) { num++ } else { for (i = -1; i >= -4; i--) { if (pieces[(rx + chk[0] * i) + '-' + (ry + chk[1] * i)] == piece) { num++ } } break } } if (num == successNum) { resultEl.innerHTML = ['白', '黑'][user] + '方贏'; break; } } }) } </ script > </ body > </ html > |
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。原文鏈接:https://blog.csdn.net/weixin_43954962/article/details/112863298