JavaScript 要点: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中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。 1)C 用于解析JavaScript源码并生成抽象语法树。 2)C 负责生成和执行字节码。 3)C 实现JIT编译器,在运行时优化和编译热点代码,显着提高JavaScript的执行效率。
