“狼人杀”是一款多人参与的策略类桌面游戏。本题我们一起完成一个简易的狼人杀游戏,让我们找到其中的狼人。
开始答题前,需要先打开本题的项目代码文件夹,目录结构如下:
├── css
│ └── style.css
├── images
│ └── card.svg
├── index.html
└── js
└── myarray.js
其中:
css/style.css
是样式文件。index.html
是主页面。images
是图片文件夹。js/myarray.js
是需要补充的 js 文件。注意:打开环境后发现缺少项目代码,请手动键入下述命令进行下载:
cd /home/project
wget https://labfile.oss.aliyuncs.com/courses/9791/09.zip && unzip 09.zip && rm 09.zip
在浏览器中预览 index.html
页面效果如下:
在本题
index.html
已经给出的数组中,我们可以通过数组的filter
方法:cardList.filter((item) => item.category == "werewolf")
返回一个都是狼人的新数组。但是技术主管为了考验大家的技术,规定了在代码中任何地方都不能出现filter
关键字。所以我们需要封装一个myarray
方法来实现类似数组filter
的功能。
item.name
,请实现一个通用的方法。effect.gif
(请使用 VS Code 或者浏览器打开 gif 图片)。filter
关键字。id
、class
、函数名等名称,以免造成无法判题通过。// 返回条件为真的新数组
Array.prototype.myarray = function (cb) {
// TODO:待补充代码
let newArr = []
this.forEach((item)=>{
if(cb(item)){newArr.push(item)}
})
return newArr
};
<!DOCTYPE html>
<html>
<head>
<title>寻找小狼人</title>
<meta charset="utf-8" />
<link href="css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="content">
<p id="gameText"></p>
<ul></ul>
<div class="btnbox">
<button class="btn">寻找狼人</button>
</div>
</div>
<script src="./js/myarray.js"></script>
<script>
// JavaScript 代码部分
</script>
</body>
</html>
<!DOCTYPE html>
:声明文档类型为 HTML5。<head>
部分: <meta charset="utf-8" />
:设置字符编码为 UTF - 8。<title>传送门</title>
:设置网页标题为 “传送门”。<link rel="stylesheet" type="text/css" href="./css/index.css" />
:引入外部 CSS 文件 index.css
来设置页面样式。<body>
部分: <div id="top"></div>
、<div id="middle"></div>
、<div id="foot"></div>
:分别表示页面的顶部、中间和底部区域。<div id="lift">
:侧边栏容器,包含三个链接和分隔线。 <a>
标签:三个链接,分别绑定了 toFunction
函数,点击时会调用该函数并传入不同的滚动高度参数。<span class="line"></span>
:分隔线。<script>
标签:引入 jQuery 库和自定义的 JavaScript 文件 index.js
。/* 重置默认样式 */
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
font,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend {
margin: 0;
padding: 0;
font-size: 100%;
border: 0;
outline: 0;
background: transparent;
}
ol,
ul {
list-style: none;
}
:focus {
outline: 0;
}
/* 页面内容样式 */
#content {
padding-top: 40px;
}
#content ul {
width: 1200px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.btnbox {
width: 1200px;
margin: 0 auto;
text-align: center;
}
#content ul li {
margin: 20px;
width: 200px;
height: 180px;
}
#content ul li:last-child {
margin-right: 0;
}
#content ul li a {
position: relative;
display: block;
width: 100%;
height: 100%;
perspective: 800px;
}
#content ul li a > div {
position: absolute;
left: 0;
height: 0;
width: 100%;
height: 100%;
color: #fff;
overflow: hidden;
transform-style: preserve-3d;
transition: 0.8s ease-in-out;
backface-visibility: hidden;
}
#content ul li a div:first-child {
display: flex;
justify-content: center;
transform: rotateY(0);
z-index: 2;
border: 1px solid #2e7eee;
}
#content ul li a div:last-child {
background: rgb(0, 188, 212);
transform: rotateY(180deg);
z-index: 1;
}
#content ul li a div h1 {
text-align: center;
line-height: 180px;
font-size: 26px;
}
#content ul li a div img {
max-width: 100%;
}
/* 卡片翻转动画类 */
.rotatey180 {
transform: rotateY(-180deg) !important;
}
.rotateyzero {
transform: rotateY(0) !important;
}
/* 按钮样式 */
.btn,
.btn-all {
margin-top: 60px;
display: inline-block;
color: #0099cc;
background: #2e7eee;
border-radius: 10px;
text-decoration: none;
text-transform: uppercase;
border: none;
color: white;
padding: 8px 16px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
transition-duration: 0.4s;
cursor: pointer;
}
/* 卡片编号样式 */
.cardnum {
position: absolute;
font-size: 20px;
left: 10px;
top: 10px;
}
/* 游戏提示信息样式 */
#gameText {
text-align: center;
}
#content
:设置页面主要内容区域的顶部内边距。#content ul
:设置卡片列表的宽度、居中显示,并使用 Flexbox 布局实现卡片的多行排列。.btnbox
:设置按钮容器的宽度和居中显示。#content ul li
:设置每个卡片项的外边距、宽度和高度。#content ul li a
:设置卡片链接的定位和透视效果,为卡片翻转动画做准备。#content ul li a > div
:设置卡片正反两面的公共样式,包括绝对定位、颜色、溢出隐藏、3D 变换和过渡效果。#content ul li a div:first-child
:设置卡片正面的样式,初始状态为不旋转。#content ul li a div:last-child
:设置卡片背面的样式,初始状态为旋转 180 度。.rotatey180
:将元素绕 Y 轴旋转 -180 度。.rotateyzero
:将元素绕 Y 轴旋转 0 度。// 获取页面元素
let content = document.querySelector("#content ul");
let cardList = [
{
id: 1,
category: "werewolf",
name: "小狼人",
},
{
id: 2,
category: "werewolf",
name: "小狼人",
},
{
id: 3,
category: "hunter",
name: "猎人",
},
{
id: 4,
category: "poor",
name: "平民",
},
{
id: 5,
category: "witch",
name: "女巫",
},
{
id: 6,
category: "prophet",
name: "预言家",
},
{
id: 7,
category: "poor",
name: "平民",
},
{
id: 8,
category: "werewolf",
name: "黑狼王",
},
{
id: 9,
category: "poor",
name: "平民",
},
];
// 初始渲染所有卡片
for (let index = 0; index < cardList.length; index++) {
const element = cardList[index];
content.innerHTML += `<li>
<a href="javascript:void(0)">
<div class="z">
<img src="./images/card.svg" alt="">
</div>
<div class="b">
<h1>${element.name}</h1>
</div>
</a>
</li>`;
}
// 获取游戏提示信息元素
let gameText = document.querySelector("#gameText");
let color = ["♠", "❤", "♣", "♦"];
// 筛选并渲染狼人卡片的函数
function newHtml() {
content.innerHTML = "";
let newcardList = cardList.myarray((item) => item.category == "werewolf");
for (let index = 0; index < newcardList.length; index++) {
let randomColor = color[Math.floor(Math.random() * color.length)];
const element = newcardList[index];
content.innerHTML += `<li>
<a href="javascript:void(0)">
<div class="z">
<img src="./images/card.svg" alt="">
</div>
<div class="b">
<span class='cardnum'>${randomColor} ${element.id} </span>
<h1>
${element.name}
</h1>
</div>
</a>
</li>`;
}
gameText.innerHTML = `恭喜你,成功找出${newcardList.length}个狼人!`;
}
// 获取按钮元素并添加点击事件监听器
let btnbox = document.querySelector(".btn");
btnbox.addEventListener("click", function () {
newHtml();
let domb = document.querySelectorAll(".b");
let domz = document.querySelectorAll(".z");
setTimeout(() => {
for (let index = 0; index < domb.length; index++) {
const dombelement = domb[index];
const domzelement = domz[index];
dombelement.classList.add("rotateyzero");
domzelement.classList.add("rotatey180");
}
}, 200);
});
// 自定义数组过滤方法
Array.prototype.myarray = function (cb) {
let newArr = [];
this.forEach((item) => {
if (cb(item)) {
newArr.push(item);
}
});
return newArr;
};
content
:通过 document.querySelector
方法获取卡片列表元素。cardList
:定义一个包含多个角色对象的数组,每个对象包含角色的 id
、category
和 name
。for
循环遍历 cardList
数组,将每个角色的 HTML 结构添加到 content
元素中。newHtml
: content
元素的内容。myarray
方法筛选出 category
为 werewolf
的角色。content
元素中。gameText
元素的内容,显示找到的狼人的数量。newHtml
函数筛选并渲染狼人卡片。setTimeout
函数延迟 200 毫秒后,为每个卡片的正反两面添加翻转动画类。myarray
: Array.prototype
添加一个自定义方法 myarray
,用于过滤数组元素。四、工作流程▶️ 1. 页面加载:
2. 卡片翻转动画:
newHtml
函数清空原有卡片内容。myarray
方法筛选出所有狼人角色。3. 筛选并渲染狼人卡片:
newHtml
函数。4. 点击按钮: