javascript - 关于必须行驶 100 公里距离的汽车的游戏
问题描述
这是我的任务:
有一辆30升汽油的汽车。
它需要从 0 到 100 公里行驶。
小车分步移动,每一步小车可以在 0 KM 到 6 KM 之间移动(生成一个随机数)。
该车的行驶里程为 1 KM/L。
您可以在道路上放置 5 个随机加油泵。
每次汽车准确地到达汽油泵时,汽车就会补充 20 升油。
编写一个 JavaScript 代码来运行这个游戏并打印汽车的每一步以及当前位置,剩余汽油。
在“开始”页面上添加一个应该开始游戏的按钮。在文档窗口中打印游戏结果。
如果再次单击开始按钮,它应该清除窗口并重新开始游戏。
我想检查汽车是否通过了汽油泵,如果是,则添加 20l,如果没有,则继续,但代码不会超出 switch 语句。我的代码如下:
document.addEventListener('DOMContentLoaded', function () {
const btn = document.getElementById('butt');
btn.addEventListener('click', startTheGame);
const rootbody = document.querySelector('.rootbody');
const start = document.querySelector('.start');
function startTheGame() {
if (rootbody.innerHTML === '') {
const header = document.createTextNode('Game Started!');
start.appendChild(header);
const p = {
PP1: 15,
PP2: 30,
PP3: 45,
PP4: 60,
PP5: 75,
};
const pps = document.createTextNode(
`Petrol Pumps generated at ${p.PP1}, ${p.PP2}, ${p.PP3}, ${p.PP4}, ${p.PP5} `
);
rootbody.appendChild(pps);
let posi = 0;
let rem = 30;
while (posi < 100) {
// Generate a random number
const random = Math.floor(Math.random() * 6 + 1);
// For every random number you generate, add it to posi to get the position
// till that point
posi = posi + random;
rem = parseInt(rem - random);
switch (posi) {
case 15:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 16:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 17:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 18:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 19:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 20:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
default:
break;
}
switch (posi) {
case 30:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 31:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 32:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 33:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 34:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 35:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
default:
break;
}
switch (posi.value) {
case 45:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 46:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 47:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 48:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 49:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 50:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
default:
break;
}
switch (posi) {
case 60:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 61:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 62:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 63:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 64:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 65:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 66:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
default:
break;
}
switch (posi) {
case 75:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 76:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 77:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 78:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 79:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
case 80:
rem += 20;
console.log(`petrol rem ${rem}`);
break;
default:
break;
}
// check whether you have reached the destination or not
// if reached break out of the loop and display destination
// reached!!!!
if (posi >= 100) {
document.body.querySelector(
'.rootbody'
).innerHTML += ` - ${random}Kms travelled, Destination reached`;
break;
}
// append the posi and the step
document.body.querySelector(
'.rootbody'
).innerHTML += `<br />Step - ${random}Kms travelled, position ${posi},
petrol remaining ${rem}L
<br/>`;
}
}
}
});
解决方案
switch
当您有一组要测试的固定值并希望基于它们执行不同的事情时,语句很好。在这种情况下,泵的位置是随机的,如果你以后想跑 500 公里而不是 100 公里,你的代码将会增长并且无法维护。
更好的方法是生成一个位置数组,例如[10, 20, 25...]
泵位置,每次迈出一步时,检查是否:
// Since we can only refill if there is a pump at the exact location we're at
pumpLocations.includes(position)
然后,您的代码中有很多重复。始终认为DRY (不要重复自己)。如果你发现自己用小的改动重写了相同的代码,试着想出一种方法来编写一次并重用它(例如,创建小的可重用函数)。
这也适用于常量。如果说明告诉您补充应该是20
升,请始终想一想“如果要更改此值,我如何才能在 2 天内快速轻松地编辑我的代码?” . 这意味着您不应将数字20
放在代码中的任何位置。将其存储在变量中一次,然后重复使用。也不要写PP1
,,, PP2
...。PP5
使用数组,并假设计数将来会发生变化。
以下是一千种方法之一。
不要复制粘贴!看起来您的老师/讲师为您提供了代码模板,本示例未遵循该模板。所以他们会知道你是否这样做,而你不会学到任何东西。相反,请尝试查看使用的模式,并在调整您的练习版本之前获得一些灵感。
const rootBody = document.querySelector('.rootbody'),
btn = document.getElementById('butt');
btn.addEventListener('click', () => {
rootBody.innerHTML = '';
runGame();
});
function runGame() {
// These values are constant during the game,
// declare them here once and for all
const consumptionPerKm = 1,
minStep = 0,
maxStep = 6,
initialPetrol = 30,
pumpsCount = 5,
refillAmount = 20,
startLocation = 0,
endLocation = 100,
petrolPumpLocations = getRandomIntegers(
pumpsCount,
startLocation,
endLocation
).sort();
// These represent the state at any given time
let position = startLocation,
petrol = initialPetrol;
logStr(`You will find petrol pumps at these positions:\n${
petrolPumpLocations}\nGood luck!\n`);
if (isAtPump()) {
petrol += refillAmount; // If there's a pump at the start
}
logState();
// While we've not reached our destination and still have petrol
while(position < endLocation && petrol > 0) {
// Calculate some metrics for this step
const autonomy = petrol / consumptionPerKm,
remainingDistance = endLocation - position,
maxDistance = Math.min(autonomy, remainingDistance, maxStep),
stepDistance = getRandomInteger(minStep, maxDistance),
stepConsumption = stepDistance * consumptionPerKm;
// Adjust the state accordingly
position += stepDistance;
petrol -= stepConsumption;
if (isAtPump()) {
petrol += refillAmount;
}
logState();
}
if (position === endLocation) {
logStr("You've reached your destination!");
} else {
logStr("Out of petrol :'(");
}
function isAtPump() {
return petrolPumpLocations.includes(position);
}
function logState() {
let str = `Position: ${position}km\tPetrol: ${petrol}L`;
if (isAtPump()) {
str += ` Found a pump! Refilled ${refillAmount}L`;
}
logStr(str);
}
}
function getRandomInteger(min, max) {
return Math.round(Math.random() * (max - min) + min);
}
function getRandomIntegers(n, min, max) {
const res = [];
while (res.length !== n) {
const value = getRandomInteger(min, max);
if (!res.includes(value)) {
res.push(value);
}
}
return res;
}
function logStr(str) {
rootBody.innerHTML += '\n' + str;
}
<button id="butt">Start the game</button>
<pre class="rootbody"></pre>
推荐阅读
- c# - 如何更新数据库中的二进制数据
- java - 如何使用改造和 mvvm 加载多个页面
- twitter-bootstrap - 动态设置容器宽度
- javascript - 角度拖放图标到画布
- laravel - laravel echo server 客户端无法认证,得到 HTTP 状态 302
- java - 在“普通”类中声明通用方法及其返回
- wpf - 选项卡不在视图中时未初始化 WPF ChromiumWebBrowser
- python - 无法将 1.0 转换为 dtype int32 的 EagerTensor
- angular - 如何修复无限加载的 Angular 9 网站?
- oracle - 在数据库启动时,它拒绝错误 ORA-01078:处理系统参数失败 | LRM-00109:无法打开参数文件?