gpt4 book ai didi

javascript - JavaScript Hangman演示

转载 作者:行者123 更新时间:2023-11-30 07:52:51 26 4
gpt4 key购买 nike

我需要为每个div输入一个id,然后如果我键入或者如果您有另一个输入字母的想法,例如secret_word是emir,那么如果我输入E,则将破折号(___)删除并替换为E 。

不幸的是,这是我学习JavaScript的方式,我是绝对的初学者,所以我将不胜感激任何帮助或建议,我不知道它将来是否会带来麻烦,但this is a photo of how the divs are in the console并且我可能需要对数字1进行硬编码,而不是var sw ='';我真的不确定。

另外,我认为以某种方式提示是个让老师成为我朋友的单词的好方法,他们将任务分为几部分,我可以问他们或使用StackOverflow。另外,如果您可以将我引至某些链接,在哪里可以找到一些有用的建议,我们将不胜感激。



function getTheWord(){
//var secret_word = document.getElementById("secret").value;
secret_word = "emir";
var sw = '';

for(i=1; i <= secret_word.length;i++){
console.log(i);
console.log(sw);
sw += '<div style="display:inline-block;"> ___ </div>';
}
document.getElementById('secret').innerHTML = sw;
}
function GetValue()
{
var my_array= new Array("head","hand1","hand2","body","leg1","leg2");
var random_array = my_array[Math.floor(Math.random() * my_array.length)];
console.log(random_array);
document.getElementById("message").innerHTML=random_array;
}

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="style.css" rel="stylesheet" type="text/css">
<title>Document</title>
</head>
<body onload="getTheWord();">


<input type="button" id="btnSearch" value="Search" onclick="GetValue();" />
<p id="message" ></p>

<div id="secret"></div>
<br>
<input type="text" id="secret" />

</body>
</html>

最佳答案

在这篇文章的底部,您将找到一个有效的子手游戏。接下来是尝试解释其工作原理。听起来很令人惊讶,关于这个小程序还有很多话要说,因此我决定将我的解释分为三个部分:


JavaScript内置函数:快速查看此程序涉及的本机功能。
游戏的状态和循环:程序结构和逻辑的概述。
一点点绘画:专注于与程序输出相关的源代码。


1. JavaScript内置函数

本节旨在在我们自己的功能与该程序涉及的本机功能之间划清界限。我将重点介绍关键功能,如何使用它们以及它们如何相互作用。牢记这些基本知识,您应该能够更快地了解该程序。这是一个汇总表:

 Name    | Array   | String  | Usage -> Output
---------|---------|---------|-------------------------------------------
repeat | | X | "123".repeat(3) -> "123123123"
split | | X | "1|2|3".split("|") -> [1, 2, 3]
join | X | | [1, 2, 3].join("|") -> "1|2|3"
map | X | | [1, 2, 3].map(x => 2 * x) -> [2, 4, 6]
reduce | X | | [1, 2, 3].reduce((a, x) => a + x, 0) -> 6
indexOf | X | X | [1, 2, 3].indexOf(2) -> 1
concat | X | X | [1].concat([2, 3]) -> [1, 2, 3]


尽管这些功能大多数都是不言自明的,但我想指出几点:


其中一些功能可以同时应用于数组和字符串。例如 indexOf也可以这样使用: "123".indexOf(2)
joinsplit的反向功能。它通常用于准备要存储和输出的数据。例如, console.log("[" + [1, 2, 3].join(", ") + "]")
map接受一个数组,将给定的函数应用于每个项目,然后返回一个新数组。易于理解,比 for循环更具可读性,并且非常有用。
splitmapjoin通常一起使用。这里有一个愚蠢的用法示例,但很容易理解: "123".split("").map(x => 2 * x).join("")给出 "246"


reduce可能是最棘手的功能。由于对此功能只有一个调用,因此我不再赘述。您需要知道的是,它获得了“ ASCII艺术”中最长的一行。顺便说一句,我们可以用一个很好的 for循环替换它:

var CANVAS_WIDTH = 0;
for (var i = 0; i < HANGMAN.length; i++) {
CANVAS_WIDTH = Math.max(HANGMAN[i].length, CANVAS_WIDTH);
}


JavaScript内置程序就是这样。如果您需要更多详细信息,我可以建议您使用Google“ mdn [功能名称]”。 MDN适用于 Mozilla Developer Network,可将其视为Web开发人员的手册。

2.游戏的状态和循环

子手游戏是典型的互动程序。当播放器键入内容时,程序会根据输入更新其状态,向播放器提供反馈,并等待下一个输入。这种模式不断重复直到游戏结束:等待,输入,更新,输出,等待,输入,更新,输出等...三个功能在此机制中起着关键作用:

 Name        | Short description
-------------|------------------------------------------------------
main | Entry point of the program. Starts the game's loop.
isGameOver | Returns true or false depending on the game's state.
updateState | Contains the logic related to the player's input.


该函数的主体很短且易于阅读,因此我不会逐行描述源代码,我将这份工作留给您。但是,让我建议您先阅读整个部分。

游戏的状态由两个变量组成,一个 fails计数器和一个 progress数组。 main函数负责初始化它们。首先,将 fails设置为 0,并用占位符( progress)填充 _。然后, updateState负责使变量保持最新。错误的猜测会增加 fails计数器,而好的猜测将给定字母替换为占位符。让我给你演示 :

> | secret = "secret",
| progress = ["_", "_", "_", "_", "_", "_"],
| state = { fails: 0, progress: progress }
< | {
| fails: 0,
| progress: ["_", "_", "_", "_", "_", "_"]
| }
> | updateState("e", secret, state),
| state
< | {
| fails: 0,
| progress: ["_", "e", "_", "_", "e", "_"]
| }
> | updateState("a", secret, state),
| state
< | {
| fails: 1,
| progress: ["_", "e", "_", "_", "e", "_"]
| }


main函数还会初始化游戏的循环。然后,每个新输入触发一次迭代。在每次迭代中, isGameOver都会检查游戏的状态,以便确定程序是否应继续与玩家对话。当秘密被发现( progress数组中没有剩余的占位符)或绘图完成( fails计数器达到最大值)时,对话框停止。这是相应的代码片段:

input.onkeyup = function (ev) {
if (ev.which === 13) {
var value = this.value;
...
} else if (!isGameOver(state)) {
updateState(value, secret, state);
}
}
};


由于 13是ENTER的键代码,因此上面的代码可以这样表示:``当按下ENTER键时,如果游戏还没有结束,请确定玩家的猜测是对还是错。''

3.一点绘画


  可以在此处找到改进: https://stackoverflow.com/a/50085635/1636522。但是,最好的实现是在这里: https://stackoverflow.com/a/50090320/1636522。它代替了3.1和3.2节,但3.3节仍然适用。


到目前为止,我们已经涵盖了大约50%的源代码。我们能够区分本机和用户定义的函数,并且对程序的结构和逻辑有很好的了解。现在是时候讨论剩余的50%的代码,这与程序的输出有关。

等等,困难的部分尚未到来+0+'

3.1。数据结构

我将要描述的三个数据结构涉及绘制绞架。请注意,如果您想要另一种ASCII艺术,只需更改这些结构,程序就可以正常工作。另外,它们应该是``只读的'',这就是为什么我使用大写字母命名它们的原因,大写字母是常量的普遍约定:

 Name           | Type       | Short description
----------------|------------|--------------------------------
HANGMAN | [String] | The ASCII art.
STROKES_COORDS | [[Int]] | Coordinates of the strokes.
DRAWING_STEPS | [Int] | Steps to complete the drawing.


关于 HANGMAN没什么多说的,只是它应该被视为xy坐标平面:

x = 0, y = 0
HANGMAN[y] // "+----+"
HANGMAN[y][x] // "+"


STROKES_COORDS包含可以在 HANGMAN平面中找到的笔触坐标。例如, STROKES_COORDS[5]给出 [0,0],它指向第一个“ +”。此外,数组按时间顺序排序。因此,如果您打印前六个笔画,则会获得绞架极的快照(从下至上读取):

STROKES_COORDS[5] -> [0,0] -> +
STROKES_COORDS[4] -> [0,1] -> |
STROKES_COORDS[3] -> [0,2] -> |
STROKES_COORDS[2] -> [0,3] -> |
STROKES_COORDS[1] -> [0,4] -> |
STROKES_COORDS[0] -> [0,5] -> |


DRAWING_STEPS可以看作是 STROKES_COORDS之上的另一个间接级别。此数组也按时间顺序排序,并包含每次错误猜测后要绘制的笔划数。下图说明了三个失败导致打印六个笔划:

DRAWING_STEPS[3] -> 6 -> +
|
|
|
|
|


DRAWING_STEPS.length - 1失败后,绘制完成,游戏结束。因此,错误猜测的最大数量取决于 DRAWING_STEPS.length

var MAX_FAILS = (
DRAWING_STEPS.length - 1
);


3.2。绘制绞架

drawGallows函数在游戏的某个时刻获取错误的猜测数量,并以二维数组( [[String]])的形式返回正在进行的绘图:

> | // 3 fails -> 6 strokes
| drawGallows(3)
< | [
| ["+", " ", " ", " ", " ", " ", " "],
| ["|", " ", " ", " ", " ", " ", " "],
| ["|", " ", " ", " ", " ", " ", " "],
| ["|", " ", " ", " ", " ", " ", " "],
| ["|", " ", " ", " ", " ", " ", " "],
| ["|", " ", " ", " ", " ", " ", " "]
| ]


要构建进行中的图形, drawGallows依赖于前面描述的数据结构。该函数首先创建一个空画布,然后循环遍历 STROKES_COORDS数组,并用在 n中找到的第一个 HANGMAN笔划的副本填充空白。在下一个代码段中,您可以看到正在使用的副本:

> | canvas = HANGMAN.map(
| () => BLANK_ROW.split("")
| );
< | [
| [" ", " ", " ", " ", " ", " ", " "],
| [" ", " ", " ", " ", " ", " ", " "],
| [" ", " ", " ", " ", " ", " ", " "],
| [" ", " ", " ", " ", " ", " ", " "],
| [" ", " ", " ", " ", " ", " ", " "],
| [" ", " ", " ", " ", " ", " ", " "]
| ]
> | fails = 3;
| n = DRAWING_STEPS[fails]; // 6
| for (i = 0; i < n; i++) {
| x = STROKES_COORDS[i][0];
| y = STROKES_COORDS[i][1];
| canvas[y][x] = HANGMAN[y][x]; // <- copy
| }
| canvas
< | [
| ["+", " ", " ", " ", " ", " ", " "],
| ["|", " ", " ", " ", " ", " ", " "],
| ["|", " ", " ", " ", " ", " ", " "],
| ["|", " ", " ", " ", " ", " ", " "],
| ["|", " ", " ", " ", " ", " ", " "],
| ["|", " ", " ", " ", " ", " ", " "]
| ]


3.3。一滴胶水

正如您在玩游戏时所看到的那样,该程序比打印ASCII艺术字有更多作用。我们可以看到一条消息,字母和占位符,绞架下面的地板以及失败计数器。这些添加项来自 outputState函数,该函数组合了所有内容并将结果转发到 output函数进行打印。

请注意, output将字符串数组作为参数,因此有必要将 drawGallows返回的画布列连接在一起。同时,线向右移动以使绞架水平居中:

> | drawGallows(3).map(
| x => " ".repeat(3) + x.join("")
| )
< | [
| " + ",
| " | ",
| " | ",
| " | ",
| " | ",
| " | "
| ]


就这样。

我们完了 !

祝贺您,并感谢您的阅读:-)这个答案看起来更像是一篇博文,但无论如何,我希望您对此表示赞赏。如果您需要进一步的说明,请发表评论。



var HANGMAN = [
"+----+"
, "| |"
, "| o"
, "| /M\\"
, "| / \\"
, "|"
];

var STROKES_COORDS = [
[0,5], [0,4], [0,3], [0,2],
[0,1], [0,0], [1,0], [2,0],
[3,0], [4,0], [5,0], [5,1], [5,2],
[5,3], [4,3], [6,3], [4,4], [6,4]
];

var DRAWING_STEPS = [
0, 2, 4, 6, 8,
11, 13, 16, 18
];

var CANVAS_WIDTH = HANGMAN.reduce(
(a, x) => Math.max(x.length, a), 0
);

var BLANK_ROW = (
" ".repeat(CANVAS_WIDTH)
);

var MAX_FAILS = (
DRAWING_STEPS.length - 1
);

onload = function () {
main("save earth");
};

function main (secret) {
var placeholders = "_".repeat(secret.length);
var state = { fails: 0, progress: placeholders.split("") };
var input = document.getElementById("input");
outputState(state, "Let's try!");
input.onkeyup = function (ev) {
if (ev.which === 13) {
var value = this.value;
this.value = ""; // reset input box
if (value === "reset") {
state.fails = 0;
state.progress = placeholders.split("");
outputState(state, "Let's try again!");
} else if (!isGameOver(state)) {
updateState(value, secret, state);
}
}
};
}

function isGameOver (state) {
return state.fails >= MAX_FAILS || (
state.progress.indexOf("_") === -1
);
}

function updateState (input, secret, state) {
if (fillIn(input, state.progress, secret)) {
if (state.progress.indexOf("_") === -1) {
outputState(state, "Good job :-)");
} else {
outputState(state, "Yes! Keep it up :-D");
}
} else {
if (++state.fails === MAX_FAILS) {
outputState(state, "Bad job :-(");
} else {
outputState(state, "No... Hang on :-P");
}
}
}

function fillIn (letter, progress, secret) {
var found = false;
for (var i = 0; i < secret.length; i++) {
if (secret[i] === letter) {
found = true, progress[i] = secret[i];
}
}
return found;
}

function drawGallows (fails) {
var canvas = HANGMAN.map(
() => BLANK_ROW.split("")
);
var n = DRAWING_STEPS[fails];
for (var i = 0; i < n; i++) {
var x = STROKES_COORDS[i][0];
var y = STROKES_COORDS[i][1];
canvas[y][x] = HANGMAN[y][x];
}
return canvas;
}

function outputState (state, message) {
output([
message, "",
state.progress.join(" "), ""
].concat(
drawGallows(state.fails).map(
x => " ".repeat(3) + x.join("")
)
).concat((
"-".repeat(CANVAS_WIDTH + 6)
) + " fails = " + (
state.fails + " / " + MAX_FAILS
)));
}

function output (lines) {
var p = document.getElementById("pre");
p.textContent = " " + lines.join("\n ");
}

<table width="100%" cellspacing="0">
<tr>
<td width="40%" valign="top" style="text-align: center;">
<p style="font-size: 14px;">
Type a character or "reset"<br>
(white spaces matter),<br>
then press ENTER.
</p>
<input id="input" type="text">
</td>
<td valign="top" style="border-left: 1px solid #999;">
<pre id="pre" style="
font-size: 12px;
font-family: monospace, monospace;
"></pre>
</td>
</tr>
</table>

关于javascript - JavaScript Hangman演示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48532419/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com