首页  >  文章  >  web前端  >  JavaScript 要点:Javascript 的部分策划者)

JavaScript 要点:Javascript 的部分策划者)

Barbara Streisand
Barbara Streisand原创
2024-10-30 17:09:02867浏览

JavaScript Essentials: Part Mastermind in Javascript)

在本节中,我们将用 JavaScript 实现一个名为 Mastermind 的游戏。这个游戏开发将涵盖我们迄今为止讨论过的许多概念。我们将定义函数、向它们传递参数、使用变量以及使用循环和 if 语句。我们将简要介绍一下函数的另一个概念,即 IIFE,即立即调用函数表达式。我们还将了解如何通过命令行获取用户输入。此时,它只是控制台应用程序。

您可以在这里参考类似的实现,Master mind in python

Mastermind 是一款简单的棋盘游戏,使用颜色,但我们会使用数字。

摘要:条形后面是一名玩家放置的四种颜色。其他玩家看不到第一个玩家的颜色。第一个玩家的颜色称为代码制作者,另一个玩家的颜色称为代码破坏者。密码破译者尝试猜测密码编写者的密码(包括 2 到 12 次)。尝试次数必须是偶数。

执行

  • 在您的电脑(或放置项目的位置)上创建一个名为 mastermind 的文件夹,并在 mastermind 中,使用 npm init -y (在命令行上)初始化节点项目。我在 Linux 机器上,所以这就是我设置项目的方式。

    • 打开我的终端,运行,cd 将我移动到用户文件夹。
    • 然后,cd ~/projects。项目是我保存项目的地方。
    • 然后 mkdir mastermind 和 cd mastermind 创建 mastermind 文件夹并切换到该文件夹​​。
    • 使用 npm init -y 初始化节点项目。将创建 package.json 文件。
    • 使用触摸 app.js 创建 app.js
    • 将 console.log("Mastermind") 写入 app.js 并使用 Node app.js 运行它。我希望见到Mastermind,否则我的设置有问题。
  • 这个游戏的起点(入口)将在App中,一个函数。让我们创建一个名为 App 的函数并添加 console.log("App")。然后我们可以调用 App() 并使用 Node app.js 执行代码。我不会告诉您运行代码,但这是您在编写代码时应该做的事情。这是我的 app.js 文件的当前内容。

console.log("Mastermind");

function App() {
  console.log("App");
}

App();
  • 比赛开始时

    • 用户输入他们想要玩的回合数,并且输入的值必须经过验证
    • 用户选择是否允许重复
    • 代码生成器是随机生成的
    • 用户已输入密码破解器
    • 破码器与破码器进行比较,如果不匹配就会给出提示
    • 在这个过程中,我们进行了轮数
    • 为了让这个更像游戏,我们将整个应用程序放入无限循环
  • 让我们实现一个为代码生成器生成随机数的函数,从而为代码生成器设置随机值。

  • 首先,我们需要一种生成随机数的方法。为了不干扰

    app.js 中的代码,让我们创建另一个名为 scratch_pad.js 的文件,并在这个文件中进行实验。

  • JavaScript 有一种简单的方法来调用 Math.random() 生成随机数。在便签本中,让我们使用循环构造记录 4 个随机数。



console.log("Mastermind");

function App() {
  console.log("App");
}

App();
  • 我们想要的是整数(如数字)0、1、2、...、9,而不是小数。我们可以将 Math.random() 返回的值乘以 10,得到 x.something,其中 x 现在为 1,2,3,...,9。请记住,这些实验都是在草稿本上完成的。尝试一下。

  • 我们想要的是点之前的数字,即整数部分。我们可以编写代码将数字转换为字符串,然后用“.”分隔它。并获取第一个元素。然而,我们可以使用一个名为“地板”的功能。


for (let i = 0; i < 4; i++) {
  console.log(Math.random());
}
// 0.10037268097853191
// 0.20981624777230534
// 0.47828165742292583
// 0.8160883929470153
    其工作原理是,如果我们想获得某个数字 min 和 max 之间的随机数,其中 max 大于 min,那么我们可以这样做, min Math.floor(Math.random() * (max -分钟 1))。 min 是最小期望值,max 是最大期望值。在我们的例子中,最小值为 0,最大值为 9。
  • 这是我用于生成随机数的片段。我向函数添加了参数,因为我不希望函数具有内部状态。
for (let i = 0; i < 4; i++) {
  console.log(Math.floor(Math.random() * 10));
}
// 4
// 7
// 3
// 4
  • 此时,我们现在可以返回到

    app.js 并添加上面的函数来为代码生成器生成随机数。将其放在 App 函数上方。

  • 从摘要来看,使用的颜色数量是 4。因此我们需要为代码生成器生成 4 个数字。我们还必须处理是否允许重复。回到草稿本。

  • 我们有函数、if 和 else 语句、for 和 while 循环等。这些构造都有一个块或一个主体。在这些块中初始化的变量可以在块内使用,而不能在块外使用。这称为变量的范围。因此,变量可以存在于全局范围内,这意味着该变量可以在任何地方使用或评估。当我们在块中声明变量时。该变量成为内部变量或限制在该范围内。在暂存器中运行它。

console.log("Mastermind");

function App() {
  console.log("App");
}

App();
  • 现在通过在 if 语句中初始化变量 x 来更新它,console.log(x) 在 if 块之外并运行便签本。您应该会收到与此类似的错误。
for (let i = 0; i < 4; i++) {
  console.log(Math.random());
}
// 0.10037268097853191
// 0.20981624777230534
// 0.47828165742292583
// 0.8160883929470153

此时我想提请您注意有关作用域的想法。

  • 生成代码生成器时,我们想知道是否允许重复,此时,我们知道代码生成器是一个数字(或数字字符串)数组。让我们从便签本开始。我们想要实现一个函数,它接受一个布尔参数来指示是否允许重复。该函数会将四个数​​字添加(推送)到代码生成器中,但在此之前,我们必须检查是否允许重复,并在不允许时进行处理。
for (let i = 0; i < 4; i++) {
  console.log(Math.floor(Math.random() * 10));
}
// 4
// 7
// 3
// 4
  • 我们还以这样的方式编写代码,即代码生成器不能在代码生成器函数中全局访问。因此将返回代码生成器。
function generateRandomNumbersBetween(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

for (let i = 0; i < 4; i++) {
  console.log(generateRandomNumbersBetween(0, 9));
}
  • app.js 中,我们现在可以添加代码生成器函数和用于代码生成的变量。
  • 现在回到草稿本。我们希望从终端获取用户的输入。 JavaScript 也有办法做到这一点。试试这个片段。
const HP = 100;

if (true) {
  console.log("IF BLOCK::", HP);
}

console.log("End::", HP);

// IF BLOCK:: 100
// End:: 100
  • 这种获取用户输入的方法没有问题。只是我们必须使用回调函数,并且无法将输入的输入传递到 readlineOInstance.question 回调函数的外部范围。

  • 你在想什么?在“便笺簿”中尝试一下。如果您正在考虑在 readlineOInstance.question 的外部范围中声明一个变量并将输入的输入分配给它,那么这是一个很好的方法,但是......仍然尝试一下。

  • 你还记得 Promise 的概念吗?我们可以在这里使用 Promise 并解析输入。然而,我们必须将整个过程包装在函数中。 readlineOInstance.question 有几个部分有一个类似于 Question(query: string, callback: (answer: string) => void 的 header。query 是对用户的查询(或提示),callback 是如何我们处理输入集合。由于稍后可能会在某个地方重用相同的函数,因此我们会将查询作为参数传递。

console.log("Mastermind");

function App() {
  console.log("App");
}

App();
  • 现在我们可以将 getInput 函数添加到 app.js 中。不要忘记导入,const readline = require("readline")。 app.js 的内容应类似于下面的代码片段。
for (let i = 0; i < 4; i++) {
  console.log(Math.random());
}
// 0.10037268097853191
// 0.20981624777230534
// 0.47828165742292583
// 0.8160883929470153
  • 现在我们要求用户输入轮数以及是否允许重复。我们知道轮数必须是偶数并且在 2 到 12 之间。我们将实现一个函数来验证值(数字)是否为偶数并且在 2 到 12 之间。它将返回一个布尔值。当数模 2 为零时,该数为偶数。 (即数字 % 2 == 0)。
for (let i = 0; i < 4; i++) {
  console.log(Math.floor(Math.random() * 10));
}
// 4
// 7
// 3
// 4
  • 在App函数的主体中,我们可以请求输入并验证它们。我们将不断要求输入正确的轮数。对于代码中的重复值,当用户输入预期之外的任何内容时,我们会假设用户不想要重复值。我们将使用 while 循环并将条件设置为 true,并且仅在回合有效时才中断,但是使用 try 和 catch(用于错误处理),当用户输入无效值时,我们会记录一条消息,指示输入的值无效。尝试一下。
function generateRandomNumbersBetween(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

for (let i = 0; i < 4; i++) {
  console.log(generateRandomNumbersBetween(0, 9));
}

运行 app.js 并与其交互。这是交互过程中的类似输出。

const HP = 100;

if (true) {
  console.log("IF BLOCK::", HP);
}

console.log("End::", HP);

// IF BLOCK:: 100
// End:: 100
  • 我们已经计算了轮数和重复值。现在我们可以生成代码生成器了。为此,我们可以调用generateCodeMaker函数并将复制选项值传递给它(或者保留它,因为它默认为false)。
 IF BLOCK:: 100
 /home/Projects/mastermind/scratch_pad.js:8
 console.log(x)
    ^

 ReferenceError: x is not defined
    at Object.<anonymous> (/home/Projects/mastermind/scratch_pad.js:8:13)
    at Module._compile (node:internal/modules/cjs/loader:1469:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1548:10)
    at Module.load (node:internal/modules/cjs/loader:1288:32)
    at Module._load (node:internal/modules/cjs/loader:1104:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:174:12)
    at node:internal/main/run_main_module:28:49

 Node.js v20.17.0
  • 现在我们可以向用户询问代码破译器并将其与代码生成器进行比较。破码器也是一个数字数组。我们还将添加一个提示,让用户知道他们距离特定代码有多远。因此,如果破码者的代码大于破码者的代码,我们就说得更多。当它们相等时我们说相等,而当来自破码器的代码小于破码器的代码时我们说更少。让我们进入草稿本。
  • 我们将创建一个函数,该函数将采用 4 个元素的数字数组,然后比较用户的输入(代码断路器)。
// a global code maker that is accessible inside any other scope
let CODE_MAKER = [];

function generateRandomNumbersBetween(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

function generateCodeMaker(isDuplicatesAllowed = false) {
  let counter = 0;

  while (counter < 4) {
    let code = generateRandomNumbersBetween(0, 9);

    if (isDuplicatesAllowed) {
      CODE_MAKER.push(code);
      counter += 1;
    } else if (!CODE_MAKER.includes(code)) {
      CODE_MAKER.push(code);
      counter += 1;
    }
  }
}

console.log(CODE_MAKER);
generateCodeMaker(true);
console.log(CODE_MAKER);

// reset the code maker
CODE_MAKER = [];
generateCodeMaker(false);
console.log(CODE_MAKER);
// []
// [ 6, 6, 0, 9 ]
// [ 2, 5, 0, 8 ]
  • 我们有一个变量来处理提示,以及与代码创建者和破坏者相关的每个代码的值。
  • 我们将代码生成器传递给函数,以将其与用户的输入进行比较。
  • 我们更新了提示,让用户知道如何更新代码断路器中的值
  • 现在我们可以将 HINTS 和 CompareCode 函数添加到 app.js 中。现在是在 App 功能之上运行 app.js 的好时机。

  • 现在我们实现了一个比较代码生成器和代码破解器的函数,现在我们可以将其放入循环中以计算轮数(轮数 = 玩游戏的次数)。因此,如果轮数为 6,那么游戏将进行 6 次,但当用户正确猜出所有代码时,即 HINTS 中的值全为 0 时,我们必须终止游戏。因此,当我们数出 HINTS 中 0 的数量并且为 4 时,我们就可以终止游戏并说用户获胜。

console.log("Mastermind");

function App() {
  console.log("App");
}

App();
  • 回合数减少,如果回合数不为0,我们就知道用户是否获胜。
for (let i = 0; i < 4; i++) {
  console.log(Math.random());
}
// 0.10037268097853191
// 0.20981624777230534
// 0.47828165742292583
// 0.8160883929470153
  • 运行程序时的一些输出
for (let i = 0; i < 4; i++) {
  console.log(Math.floor(Math.random() * 10));
}
// 4
// 7
// 3
// 4
  • 当我按下回车键时
function generateRandomNumbersBetween(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

for (let i = 0; i < 4; i++) {
  console.log(generateRandomNumbersBetween(0, 9));
}
  • 我想我们可以享受到目前为止的辛苦工作了。我有大约130行。你有多少个?

  • 这是完整代码

const HP = 100;

if (true) {
  console.log("IF BLOCK::", HP);
}

console.log("End::", HP);

// IF BLOCK:: 100
// End:: 100

还有改进的空间吗?

尽管这是一个简单的控制台/终端/基于文本的应用程序,但我们可以做更多的事情。

  • 我们可以替换所有常量,例如字符串和数字。
  • 我们可以从比较代码中提取(重构)代码断路器输入并将其拆分,然后将代码断路器和代码生成器作为参数传递。我们甚至可以让函数返回提示,而不是全局访问提示。我们将创建一个新的提示变量并返回它。因此,compareCode 将返回分配给hints 变量的提示。
 IF BLOCK:: 100
 /home/Projects/mastermind/scratch_pad.js:8
 console.log(x)
    ^

 ReferenceError: x is not defined
    at Object.<anonymous> (/home/Projects/mastermind/scratch_pad.js:8:13)
    at Module._compile (node:internal/modules/cjs/loader:1469:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1548:10)
    at Module.load (node:internal/modules/cjs/loader:1288:32)
    at Module._load (node:internal/modules/cjs/loader:1104:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:174:12)
    at node:internal/main/run_main_module:28:49

 Node.js v20.17.0
  • 我们还可以将 console.clear() 包装到一个函数中。
  • 我们可以在下一场比赛之前让程序放慢速度
  • 我们可以将 HINTS.filter((value) => 0 === value).length === 4 作为函数取出。其目的是检查密码破译者是否正确猜出密码制作者。
  • 我们也可以用同样的方法来宣布谁赢得了比赛
// a global code maker that is accessible inside any other scope
let CODE_MAKER = [];

function generateRandomNumbersBetween(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

function generateCodeMaker(isDuplicatesAllowed = false) {
  let counter = 0;

  while (counter < 4) {
    let code = generateRandomNumbersBetween(0, 9);

    if (isDuplicatesAllowed) {
      CODE_MAKER.push(code);
      counter += 1;
    } else if (!CODE_MAKER.includes(code)) {
      CODE_MAKER.push(code);
      counter += 1;
    }
  }
}

console.log(CODE_MAKER);
generateCodeMaker(true);
console.log(CODE_MAKER);

// reset the code maker
CODE_MAKER = [];
generateCodeMaker(false);
console.log(CODE_MAKER);
// []
// [ 6, 6, 0, 9 ]
// [ 2, 5, 0, 8 ]
  • 将所有可以独立的函数放入自己的文件functions.js中并导出它们。然后,我们可以重构依赖于全局变量的独立函数,然后使用参数将该数据作为参数传递给函数。
  • 我们甚至可以有一个单独的文件
// a global code maker that is accessible inside any other scope
let CODE_MAKER = [];

function generateRandomNumbersBetween(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

function generateCodeMaker(isDuplicatesAllowed = false) {
  let counter = 0;
  let codeMaker = [];

  while (counter < 4) {
    let code = generateRandomNumbersBetween(0, 9);

    if (isDuplicatesAllowed) {
      codeMaker.push(code);
      counter += 1;
    } else if (!codeMaker.includes(code)) {
      codeMaker.push(code);
      counter += 1;
    }
  }

  return codeMaker;
}

console.log(CODE_MAKER);
CODE_MAKER = generateCodeMaker(true);
console.log(CODE_MAKER);

CODE_MAKER = generateCodeMaker(false);
console.log(CODE_MAKER);

// []
// [ 6, 6, 0, 9 ]
// [ 2, 5, 0, 8 ]

结论

我们已经使用了在这个项目中学到的所有知识,而且还有更多。我提到我们可以对一些函数进行分组并导出它们。为此,我们将讨论如何在 Javascript 中导入和导出。我将提供另一个我认为对您有用的项目。智者游戏到此结束,希望大家也进行一些重构,因为还有很多需要重构的地方。祝你好运...

const readline = require("readline");

const readlineOInstance = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

readlineOInstance.question("Enter code maker: ", (userInput) => {
  console.clear();
  console.log(`INPUT: ${userInput}`);
  readlineOInstance.close();
});

来源

  • wiki-play-mastermind
  • 维基百科-mastermind
  • Python 大师思想

以上是JavaScript 要点:Javascript 的部分策划者)的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn