数字华容道小游戏http://kiss-rebounds.gitee.io/huarong-road-game/
相信大家都知道数字华容道玩法吧。
放上完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数字华容道小游戏</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
width: 100vw;
height: 100vh;
display: grid;
place-content: center;
}
.Huarong-Road {
background-color: #575757;
user-select: none;
}
.Huarong-Road tr td {
width: 100px;
height: 100px;
background-color: #FFA042;
text-align: center;
font-size: 60px;
line-height: 100px;
color: #842B00;
margin: 2px;
display: inline-block;
box-sizing: border-box;
}
.Huarong-Road tr td.notAllowed {
animation: notAllowed .3s;
}
@keyframes notAllowed {
0% {}
100% {
opacity: 0.3;
}
}
.selectLevel {
width: 10vw;
min-width: 100px;
height: 5vh;
position: fixed;
top: 10px;
right: 10px;
background-color: #FFA042;
color: #531c01;
border: none;
padding: 3px;
}
</style>
</head>
<body>
<table class="Huarong-Road"></table>
<select class="selectLevel">
<option value="3">3×3</option>
<option value="4">4×4</option>
<option value="5">5×5</option>
<option value="6">6×6</option>
</select>
<script>
const HuarongRoad = document.querySelector('.Huarong-Road');
const selectLevel = document.querySelector('.selectLevel');
let numArray = [];
let playFlag = false;
let allTd;
let difficultyNum;
// 判断用户是否处于电脑端、移动端
function selectAndResize() {
let userAgentInfo = navigator.userAgent;
const Agents = ["Android", "iPhone", "symbianOS", "Windows Phone", "iPad", "iPod"]
for (let i = 0; i < Agents.length; i++) {
if (userAgentInfo.indexOf(Agents[i]) > 0) {
// 是移动端
mobile();
break;
} else {
// 电脑端
difficulty(selectLevel.value);
updata();
}
}
}
selectAndResize();
// 窗口大小改变时触发selectAndResize函数
window.addEventListener("resize", selectAndResize);
function mobile() {
difficulty(selectLevel.value);
let windowWidth = window.innerWidth;
let num = Math.floor(windowWidth / selectLevel.value) - 20;
allTd = document.querySelectorAll('td');
allTd.forEach(item => {
item.style.width = num + 'px';
item.style.height = num + 'px';
item.style.fontSize = num / 2 + 'px';
item.style.lineHeight = num + 'px';
});
updata();
}
selectLevel.addEventListener('change', function () {
// difficulty(selectLevel.value);
// updata();
selectAndResize();
// 禁止选择难度
selectLevel.disabled = true;
// 等更新完DOM后才能再次切换难度
setTimeout(() => selectLevel.disabled = false, selectLevel.value * 400);
});
function difficulty(num) {
difficultyNum = num;
let createTd = '';
let createTr = '';
// 重置为空数组
numArray = [];
// 创建td
for (let i = 0; i < num; i++) {
const td = '<td></td>'
createTd += td;
}
// 创建tr
for (let i = 0; i < num; i++) {
// 把创建好的td放入tr
const tr = '<tr>' + createTd + '</tr>';
createTr += tr;
}
// 把创建好的tr和td放到table里面
HuarongRoad.innerHTML = createTr;
// 获取num的平方
let square = num ** 2;
// 为numArray数组添加1-num的数字
for (let i = 1; i < square; i++) {
numArray.push(i);
}
// 并补上一个空null
numArray.push(null);
// 重新获取所有的td
allTd = document.querySelectorAll('.Huarong-Road tr td');
// 将数组中的数字放入td中,并设置data-number和data-victory-number属性
numArray.forEach((item, index) => {
allTd[index].setAttribute('data-number', item);
allTd[index].setAttribute('data-victory-number', item)
allTd[index].innerHTML = item;
});
}
// 默认为3×3
difficulty(3);
// 重新更新页面
function updata() {
// 重置playFlag
playFlag = false;
// 为每个td绑定点击事件
allTd.forEach(item => {
item.addEventListener('click', function () {
// 判断是否点击空格子上左下右的四个相邻td元素,若否,则返回
if (!item.attributes['allowClick']) {
// 添加样式,提醒玩家不允许点击
item.classList.add('notAllowed');
setTimeout(() => item.classList.remove('notAllowed'), 300);
return;
};
// 获取当前点击的元素的number值
const number = item.getAttribute('data-number');
const myNull = document.querySelector('.Huarong-Road tr td[data-number="null"]');
// 替换空格子与当前点击元素的值
item.innerHTML = '';
item.setAttribute('data-number', 'null');
myNull.innerHTML = number;
myNull.setAttribute('data-number', number);
// 判断是否胜利
victoryOrNot();
// 重置空格子旁边元素的样式
setAllowClick();
});
});
// 只允许点击空格子旁边的元素
setAllowClick();
// 打乱顺序
upset(difficultyNum * 400);
}
updata();
// 只允许点击空格子旁边的元素
function setAllowClick() {
// 移除所有allowClick属性
allTd.forEach(item => item.removeAttribute('allowClick'));
const myNullBeside = getNullBeside();
myNullBeside.forEach(item => {
// 如果为空则直接返回
if (!item) return;
item.setAttribute('allowClick', '');
});
}
setAllowClick();
// 获得随机整数
function randomNum(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
};
// 打乱顺序
function upset(duration) {
// 开始打乱顺序
let timerUpset = setInterval(() => {
// 过滤出能点击的td元素
const myNullBeside = getNullBeside().filter(item => item != null);
// 获得随机数字
const num = randomNum(0, myNullBeside.length - 1);
// 点击
myNullBeside[num].click();
}, 5);
// 结束打乱顺序
setTimeout(() => {
clearInterval(timerUpset);
playFlag = true;
}, duration)
}
upset(1000);
// 获取空格子旁边上左下右的四个相邻td元素
function getNullBeside() {
const myNull = document.querySelector('.Huarong-Road tr td[data-number="null"]');
// 获取空格子左边的元素
const Left = myNull.previousElementSibling || null;
// 获取空格子右边的元素
const Right = myNull.nextElementSibling || null;
// 获取空格子上边的元素
const Up = myNull.parentElement.previousElementSibling ? myNull.parentElement.previousElementSibling.children[myNull.cellIndex] : null;
// 获取空格子下边的元素
const Down = myNull.parentElement.nextElementSibling ? myNull.parentElement.nextElementSibling.children[myNull.cellIndex] : null;
// 返回空格子旁边上左下右的四个相邻td元素
return [
Left,
Right,
Up,
Down
];
}
// 判断是否胜利
function victoryOrNot() {
if (!playFlag) return;
let victoryNum = 0;
// 若一个元素的data-number属性值与其data-victory-number属性值相等,则victoryNum加1
allTd.forEach(item => item.getAttribute('data-number') == item.getAttribute('data-victory-number') && victoryNum++);
// 若九个td元素都符合上述条件,则victoryNum==allTd.length, 所以胜利
victoryNum >= allTd.length && setTimeout(() => alert('恭喜你,胜利了!'), 100); //延迟100ms,先更新DOM元素
}
</script>
</body>
</html>