【前言】
离公司近的好处,就在于每天都能利用自己的下班时间,更好地查漏补缺,充实技能。
最近小编做的项目需要写js偏多,而我不擅长写前端js,利用工作之余,开始学习,下面通过一个成型的js小游戏,开始我的js再次学习之旅。
【需求】
创建一个可以猜数字的游戏,它会在1~100以内随机选择一个数, 然后让玩家挑战在10轮以内猜出这个数字,每一轮都要告诉玩家正确或者错误, 如果出错了,则告诉他数字是低了还是高了,并且还要告诉玩家之前猜的数字是什么。 一旦玩家猜测正确,或者他们用完了回合,游戏将结束。 游戏结束后,可以让玩家选择再次开始。
界面基本如上所示。
【思路】
因为我是在MDN论坛里学习到的这个小游戏,他给出了很好的设计思路:
1.生成1到100之间的随机数。
2.记录玩家在第几轮。从1开始。
3.为玩家提供一种猜测数字的方法。
4.一旦提交了猜测,首先将它记录在某处,以便用户可以看到他们先前的猜测。
5.接下来检查它是否是正确的数字。
6.如果是正确的:
1.显示祝贺消息。
2.阻止玩家输入更多的猜测(这会使游戏混乱)。
3.显示控制允许玩家重新开始游戏。
7.如果它错了,并且玩家有剩余轮次:
1.告诉玩家他们错了。
2.允许他们输入另一个猜测。
3.将圈数增加1。
8.如果它是错误的,并且玩家没有剩余轮次:
1.告诉玩家游戏结束。
2.阻止玩家输入更多的猜测(这会使游戏混乱)。
3.显示控制允许玩家重新开始游戏。
9.一旦游戏重新启动,请确保游戏逻辑和用户界面完全重置,然后返回步骤1。
因为是为了学习js,就按照MDN给出的思路来写。
【实现】
1.静态网页:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Number guessing game</title>
<style>
html {
font-family: sans-serif;
}
body {
width: 50%;
max-width: 800px;
min-width: 480px;
margin: 0 auto;
}
.lastResult {
color: white;
padding: 3px;
}
</style>
</head>
<body>
<h1>Number guessing game</h1>
<p>We have selected a random number between 1 and 100. See if you can guess it in 10 turns or fewer. We'll tell you if your guess was too high or too low.</p>
<div class="form">
<label for="guessField">Enter a guess: </label><input type="text" id="guessField" class="guessField">
<input type="submit" value="Submit guess" class="guessSubmit">
</div>
<div class="resultParas">
<p class="guesses"></p>
<p class="lastResult"></p>
<p class="lowOrHi"></p>
</div>
<script>
// Your JavaScript goes here
</script>
</body>
</html>
如上代码新建一个.htm文件,用浏览器打开之后,则显示了上述截图的静态部分。页面分2大块:
1)form,用于用户输入guess的数字,以及submit按钮;
2)resultParas,用于响应用户的输出结果,显示成功、失败状态(以及guess的历史记录,便于用户做新的判断)
2.动态代码
这里我先放代码:
<script>
//1.定义变量:随机数、
var randomNumber = Math.floor(Math.random() * 100) + 1;
var guesses = document.querySelector('.guesses');
var lastResult = document.querySelector('.lastResult');
var lowOrHi = document.querySelector('.lowOrHi');
var guessSubmit = document.querySelector('.guessSubmit');
var guessField = document.querySelector('.guessField');
var guessCount = 1;
var resetButton;
guessField.focus();
function checkGuess() {
var userGuess = Number(guessField.value);
if(guessCount === 1) {
guesses.textContent = 'Previous guesses: ';
}
guesses.textContent += userGuess + ' ';
if(userGuess === randomNumber) {
lastResult.textContent = 'Congratulations! You got it right!';
lastResult.style.backgroundColor = 'green';
lowOrHi.textContent = '';
setGameOver();
} else if(guessCount === 10) {
lastResult.textContent = '!!!GAME OVER!!!';
lowOrHi.textContent = '';
setGameOver();
} else {
lastResult.textContent = 'Wrong!';
lastResult.style.backgroundColor = 'red';
if(userGuess < randomNumber) {
lowOrHi.textContent = 'Last guess was too low!';
} else if(userGuess > randomNumber) {
lowOrHi.textContent = 'Last guess was too high!';
}
}
guessCount++;
guessField.value = '';
guessField.focus();
}
guessSubmit.addEventListener('click', checkGuess);
function setGameOver() {
guessField.disabled = true;
guessSubmit.disabled = true;
resetButton = document.createElement('button');
resetButton.textContent = 'Start new game';
document.body.appendChild(resetButton);
resetButton.addEventListener('click', resetGame);
}
function resetGame() {
guessCount = 1;
var resetParas = document.querySelectorAll('.resultParas p');
for(var i = 0 ; i < resetParas.length ; i++) {
resetParas[i].textContent = '';
}
resetButton.parentNode.removeChild(resetButton);
guessField.disabled = false;
guessSubmit.disabled = false;
guessField.value = '';
guessField.focus();
lastResult.style.backgroundColor = 'white';
randomNumber = Math.floor(Math.random() * 100) + 1;
}
</script>
如上所述,同样对js感兴趣的你,可以将这两段代码粘到一个html文件中跑一跑,玩几次这个猜数字游戏之后,了解了它的一些功能设计,再往下来一起探讨。
【探讨】
一、静态部分
核心输入<div class="form">是静态部分的重心,<div class="resultParas">其实用于存储变量时,起了很大作用。“guess”,“lastResult”,“loworhi”分别用于:
二、动态部分
这块主要3个function实现游戏过程,checkGuess(),setGameOver(),resetGame(),分别递进地实现游戏逻辑。
1.checkGuess()
玩过几把游戏之后,发现每次单击这里:
<input type="submit" value="Submit guess" class="guessSubmit">
就会触发checkGuess()中的内容,如上所示,并没有onclick()来触发,那究竟是怎么回事?
在<script>标签中有这么一句:
guessSubmit.addEventListener('click', checkGuess);
看方法名大致能猜道,这是一个Listener监听,用js的术语,这叫“事件”。 事件(Event)是浏览器中发生的动作,例如点击按钮,加载页面或播放视频,我们可以调用代码来响应。 侦听事件发生的构造方法称为事件监听器,响应事件触发而运行的代码块被称为事件处理器。
为guessSubmit按钮添加了一个监听事件。这个方法包含两个可输入值(参数),监听事件的类型(在本例中为“点击”),和当事件发生时我们想要执行的代码(在本例中为checkGuess()函数)——注意,当函数作为事件监听方法的参数时,函数名后不应带括号。
这样子,checkGuess()函数,就被submit类型的input标签通过单击触发到了。
参考checkGuess()函数
function checkGuess() {
var userGuess = Number(guessField.value); //Number()为内置函数
if(guessCount === 1) {
guesses.textContent = 'Previous guesses: ';
}
guesses.textContent += userGuess + ' ';
if(userGuess === randomNumber) {
lastResult.textContent = 'Congratulations! You got it right!';
lastResult.style.backgroundColor = 'green';
lowOrHi.textContent = '';
setGameOver();
} else if(guessCount === 10) {
lastResult.textContent = '!!!GAME OVER!!!';
lowOrHi.textContent = '';
setGameOver();
} else {
lastResult.textContent = 'Wrong!';
lastResult.style.backgroundColor = 'red';
if(userGuess < randomNumber) {
lowOrHi.textContent = 'Last guess was too low!';
} else if(userGuess > randomNumber) {
lowOrHi.textContent = 'Last guess was too high!';
}
}
guessCount++;
guessField.value = '';
guessField.focus();
}
如果玩了几次游戏,你就知道了<resultParam>中的guesses标签用于存储每次输入的数字,如果是第一次,还会匹配上“Preview guess”字段,而userGuess则用于存储用户每次输入的值。
接下来验证输入值是否和随机数相等,如果等于,lastResult显示“Congruation!”并且背景色变绿,可知lastResult则用于显示每次输入后对用户的反馈,loworhi置为“”,调用setGameOver()方法,很像是面向对象的java后台代码写法;
之后,如果不等于随机数验证guessCount,每次调用checkGuess(),都将此变量加一,一旦等于10次,则对应Over文案,setGameOver;
如果都不满足,显示文案:“Wrong”,并且根据当前值与随机数对比,“loworhigh”标签做提示,指引用户下次输入。最后人性化的设计理念,guessField清空,获得焦点。
2.setGameOver()
function setGameOver() {
guessField.disabled = true;
guessSubmit.disabled = true;
resetButton = document.createElement('button');
resetButton.textContent = 'Start new game';
document.body.appendChild(resetButton);
resetButton.addEventListener('click', resetGame);
}
由上所述,该函数在猜中或者超过10次,被调用,2个标签被禁用,通过DOM创建一个新按钮,新建Event时间,一旦点击,触发resetGame()重新开始游戏。
3.resetGame()
function resetGame() {
guessCount = 1;
var resetParas = document.querySelectorAll('.resultParas p');
for(var i = 0 ; i < resetParas.length ; i++) {
resetParas[i].textContent = '';
}
resetButton.parentNode.removeChild(resetButton);
guessField.disabled = false;
guessSubmit.disabled = false;
guessField.value = '';
guessField.focus();
lastResult.style.backgroundColor = 'white';
randomNumber = Math.floor(Math.random() * 100) + 1;
}
这个函数,有点垃圾回收的感觉,注意:
resetButton.parentNode.removeChild(resetButton);
将上一步新建的button删掉了!重置了初始状态。
在这里注意js中的for循环,<div class="resultParas">,把这个div中三个元素的textContent清空,guessField获得焦点。
写在最后:
1.通过实例去敲、去思考、去学习,效率远高于直接W3CSchool.
2.收获:class选择、事件、函数、动静布局、CSS样式以及属性的运用。