JavaScript Hangman演示

1 html javascript dom

我需要输入每个div的id然后如果我输入或者你有另外的想法如何输入一个字母,例如,secret_word是emir所以如果我输入E的短划线(___)删除并替换为E .

不幸的是,这就是我学习javascript的方式我是绝对的初学者,所以我会感谢任何帮助或建议我不知道它是否会在将来制作一些包但这是一张div如何在控制台中的照片我可能需要硬编码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;
}
Run Code Online (Sandbox Code Playgroud)
<!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>
Run Code Online (Sandbox Code Playgroud)

lea*_*eaf 6

在这篇文章的底部你会发现一个工作的刽子手游戏.以下是尝试解释它是如何工作的.虽然听起来很令人惊讶,但对于这个小程序还有很多话要说,因此我决定将我的解释分为三个部分:

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

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]
Run Code Online (Sandbox Code Playgroud)

虽然大多数这些功能都是不言自明的,但我想提出几点:

  • 其中一些函数可以应用于数组和字符串.indexOf例如也可以这样使用:"123".indexOf(2).
  • join是反向的功能split.它通常用于准备存储和输出数据.例如,console.log("[" + [1, 2, 3].join(", ") + "]").
  • map获取一个数组,将给定的函数应用于每个项目,并返回一个新数组.易于理解,比for循环更易读,非常有用.
  • split,mapjoin通常一起使用.这里有愚蠢的用法示例,但很高兴得到这个想法:"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);
}
Run Code Online (Sandbox Code Playgroud)

这就是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.
Run Code Online (Sandbox Code Playgroud)

函数的主体非常简短易读,所以我不会逐行描述源代码,我把这个工作留给你.但是,我建议您先阅读整个部分.

游戏的状态由两个变量组成,一个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", "_"]
  | }
Run Code Online (Sandbox Code Playgroud)

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

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

由于13是关键代码ENTER,上面的代码可以这样表达:"当ENTER按下时,如果游戏没有结束,则判断玩家的猜测是对还是错."

有点画画

可以在此处找到改进: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.
Run Code Online (Sandbox Code Playgroud)

HANGMAN除了它应被视为xy坐标平面之外,没什么可说的:

x = 0, y = 0
HANGMAN[y] // "+----+"
HANGMAN[y][x] // "+"
Run Code Online (Sandbox Code Playgroud)

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] -> |
Run Code Online (Sandbox Code Playgroud)

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

DRAWING_STEPS[3] -> 6 -> +
                         |
                         |
                         |
                         |
                         |
Run Code Online (Sandbox Code Playgroud)

DRAWING_STEPS.length - 1失败,图纸已经完成,游戏就结束了.因此,错误猜测的最大数量取决于DRAWING_STEPS.length :

var MAX_FAILS = (
  DRAWING_STEPS.length - 1
);
Run Code Online (Sandbox Code Playgroud)

3.2.画绞刑架

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

> | // 3 fails -> 6 strokes
  | drawGallows(3)
< | [
  |   ["+", " ", " ", " ", " ", " ", " "],
  |   ["|", " ", " ", " ", " ", " ", " "],
  |   ["|", " ", " ", " ", " ", " ", " "],
  |   ["|", " ", " ", " ", " ", " ", " "],
  |   ["|", " ", " ", " ", " ", " ", " "],
  |   ["|", " ", " ", " ", " ", " ", " "]
  | ]
Run Code Online (Sandbox Code Playgroud)

要构建正在进行的绘图,请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
< | [
  |   ["+", " ", " ", " ", " ", " ", " "],
  |   ["|", " ", " ", " ", " ", " ", " "],
  |   ["|", " ", " ", " ", " ", " ", " "],
  |   ["|", " ", " ", " ", " ", " ", " "],
  |   ["|", " ", " ", " ", " ", " ", " "],
  |   ["|", " ", " ", " ", " ", " ", " "]
  | ]
Run Code Online (Sandbox Code Playgroud)

3.3.一滴胶水

正如您在玩游戏时所看到的,该程序比打印ASCII艺术更多.我们可以看到一条信息,信件和占位符,绞刑架下的地板以及失败的柜台.这些新增outputState功能来自于将所有内容组合在一起并将结果转发到output打印功能的功能.

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

> | drawGallows(3).map(
  |   x => " ".repeat(3) + x.join("")
  | )
< | [
  |   "   +      ",
  |   "   |      ",
  |   "   |      ",
  |   "   |      ",
  |   "   |      ",
  |   "   |      "
  | ]
Run Code Online (Sandbox Code Playgroud)

就这样.

我们完了 !

恭喜并感谢阅读:-)这个答案看起来更像是一篇博文,但我希望你能够欣赏.如果您需要进一步说明,请发表评论.

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  ");
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)