HTML5+JavaScript实现连连看游戏
HTML5+JavaScript实现连连看游戏
连连看游戏连接规则:
只能连接相同图案(或图标、字符)的方块。
连线路径必须是由直线段组成的,最多可以有两个拐角。
连线路径必须是空的,不能穿过其他方块。
当两个相同图案的方块被有效连接时,它们会从游戏板上消失。当所有方块都被消除时,玩家获胜。
运行效果:
源码如下(参考https://blog.csdn.net/time1812/article/details/79513508 略有修改):
<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>连连看</title><style>/* 单元格边框样式 */.border {display: inline-block;width: 40px;height: 40px;font-weight: 600;font-size: 36px;margin: 1px;}/* 显示路径时的样式 */.border.showPath {background-color: #99FF00;}/* 单元格样式 */.cell {display: inline-block;width: 40px;height: 40px;border: 1px solid #0099FF;text-align: center;font-weight: 600;font-size: 36px;background-color: #FFFFFF;color: #000000;}/* 选中单元格的样式 */.cell.selected {background-color: #3399FF;color: #FFFFFF;}/* 显示路径的单元格样式 */.cell.showPath {background-color: #99FF00;}/* 行样式 */ .row {display: block;height: 42px;}/* 游戏区域的边框样式 */#game {border: 2px solid #0033FF;width: 600px; /* 设置游戏区域的宽度 */}</style>
</head>
<body onselectstart="return false"><div id="game"></div><script type="text/javascript">let nx = 12, ny = 8; // 游戏网格的宽和高let gameDiv = document.getElementById('game');let selectedCell = null; // 当前选中的方块let empty = ' '; // 空方块let count = nx * ny; // 方块总数let cellArray = []; // 存储方块的数组// 获取特定坐标的方块function fc(x, y) {return (x < 0 || x > nx + 1 || y < 0 || y > ny + 1) ? null : cellArray[y][x];}// 获取方块的邻居function neighbors(c) {return [fc(c.x - 1, c.y),fc(c.x + 1, c.y),fc(c.x, c.y + 1),fc(c.x, c.y - 1)];}// 查找连接路径function findPath(c, target, pathStack, turnCount) {if (!c) return false;let prev = pathStack[pathStack.length - 2];if (prev && prev.x !== c.x && prev.y !== c.y && ++turnCount > 2) return false;if (c === target) {pathStack.push(c);return true;}if (c.innerHTML !== empty || pathStack.includes(c)) return false;pathStack.push(c);let nexts = neighbors(c);for (let next of nexts) {if (findPath(next, target, pathStack, turnCount)) return true;}pathStack.pop();return false;}// 清除路径样式function clearPath(path) {for (let cell of path) {cell.classList.remove('showPath');}}// 绘制路径function drawPath(path) {for (let cell of path) {cell.classList.add('showPath');}setTimeout(clearPath, 150, path);}// 尝试匹配两个方块function tryMatch(ca, cb) {if (ca === cb || ca.innerHTML !== cb.innerHTML) return;let pathStack = [ca];let found = false;let nexts = neighbors(ca);for (let next of nexts) {if (findPath(next, cb, pathStack, 0)) {found = true;break;}}if (!found) return;ca.innerHTML = cb.innerHTML = empty;setTimeout(drawPath, 10, pathStack);count -= 2;if (count < 2) alert('You win!');}// 处理方块点击事件function onCellClicked() {if (this.innerHTML === empty) return;if (selectedCell) {tryMatch(selectedCell, this);selectedCell.className = 'cell';selectedCell = null;} else {selectedCell = this;selectedCell.className = 'cell selected';}}// 初始化游戏网格function init(m, n) {for (let i = 0; i < n + 2; i++) {let row = document.createElement('div');row.className = 'row';let cellArrayRow = [];cellArray.push(cellArrayRow);gameDiv.appendChild(row);for (let j = 0; j < m + 2; j++) {let cell = document.createElement('div');cellArrayRow.push(cell);if (i === 0 || j === 0 || i === n + 1 || j === m + 1) {cell.className = 'border';cell.innerHTML = empty;} else {cell.className = 'cell';cell.addEventListener('click', onCellClicked);}cell.id = j + '_gc_' + i;cell.x = j;cell.y = i;row.appendChild(cell);}}}// 随机重置游戏function reset() {let all = count = nx * ny;let halfAll = all / 2;let tmp = [];for (let i = 0; i < halfAll; i++) {let c = symbols.charAt(Math.floor(Math.random() * 35));tmp.push(c, c);}for (let i = all - 1; i >= 0; i--) {let r = Math.floor(Math.random() * i);let c = tmp.splice(r, 1);let y = Math.floor(i / nx);let x = i - y * nx;fc(x + 1, y + 1).innerHTML = c;}}init(nx, ny);//let symbols = 'ABCDEFGHIGKLMNOPQRSTUVWXYZ123456789'; // 可用符号let symbols = 'πφω▽Ф#*∩+■▲▼◆●★♀∽※⊕☆㐃□◇△◎○Ω⊙Θ☮☯㊣@$θ'; // 可用符号reset(); // 初始化游戏</script>
</body>
</html>