颜色逻辑
正如文章开头所述,颜色是 Wordle 的主要焦点,因此也是 Numble。如果您还没有玩过 Numble 或 Wordle ,强烈建议您这样做,以便正确理解颜色的工作方式。
这是 Numble 使用的着色系统示例:

用户猜测后,颜色会在两个位置更新:实际猜测和键盘上。两者的逻辑完全相同,因此我们可以创建一个名为的箭头函数 getColors ,将猜测和实际数字作为参数。
const getColors = (guess,number) => guess.map((digit,index) => number.includes(digit) ? digit.toString() === number[index] ? "green" : "yellow": "black")
我们映射 ‘guess’ 数组并使用 ‘String.includes(item)’ 方法,我们首先检查答案是否包含猜测的数字。如果是,那么我们检查数字是否在正确的位置。如果是,则颜色被指定为“绿色”。如果不是,则颜色为“黄色”。否则,该数字根本不在答案中,因此颜色为“黑色”。
然后,此箭头函数应返回一个数组,其中包含“绿色”、“黄色”或“黑色”三个项目,对应于“猜测”中的每个数字。
例如,如果我们使用函数调用函数, getColors([1,2,3], “327”) 那么我们应该返回的数组是 [“black”, “green”, “yellow”]
您可能会注意到我们必须将数字更改为字符串。这是因为我们需要将它与存储为字符串的答案进行比较,如果两个元素的类型不同,则无法比较它们。好吧,您可以尝试,但要准备好进入整个 JavaScript 类型强制痛苦的世界。
注意:Wordle 以不同的方式处理重复,所以如果你想让这更难一点,你可以尝试模仿 Wordle 的方法。
对于下一部分,我们不必对 进行任何更改或添加任何内容 State,但 View 确实会变得更复杂一些。正如第一篇文章中简要提到的,我们将使用 CSS 类来更改颜色。
const View = state => html`
<h1>Numble</h1>
${state.started ?
html`<div id="guesses">
${state.guesses.map((guess, i) => html`<div class="row">${guess.map((number,j)=> html`<div class=${state.guessCount > i ? getColors(guess,state.number)[j] : "grey"}">${number}</div>`)}</div>`)}
</div>
<p id="feedback">${state.feedback}</p>
<div id="keyboard">
${state.digits.map((digit,index) => html`<button class=${digit} onclick=${state.appear(index)}>${index}</button>`)}
<button onclick=${state.remove}>DELETE</button>
<button onclick=${state.check}>ENTER</button>
</div>
<button onclick=${state.finish}>END</button>`
:
html`<button onclick=${state.start}>START</button>`
}`
如您所见,唯一改变的两件事是键盘按钮和每行的各个部分的 CSS 类。
从“guesses” div 开始,我们有以下逻辑:
state.guessCount > i ? getColors(guess,state.number)[j] : "grey"
首先检查是否 guessCount 高于索引,这是为了确保每次重新呈现页面时,任何先前的猜测都会重新着色。如果需要颜色,我们 getColors 以用户的猜测和答案作为参数调用该函数,并在每个数字的索引处获取项目, j.
以下是用户猜测后您的屏幕应该是什么样子:

该 getColors 函数的数组是:
["yellow", "black", "black"]
因此,用户现在将知道 3 在数字中但在错误的位置,而 4 和 5 根本不在数字中。
键盘逻辑要简单得多,但它仍然使用 getColor 我们之前编写的相同功能。还记得之前我们是如何 digits 用“灰色”填充数组的吗?这就是我们这样做的原因。
当键盘在屏幕上绘制时,类就是 digits 数组中键索引处的值。稍后我们将介绍如何更改颜色,但是在第一次猜测之后使用上面的示例, digits 数组应该如下所示:
["grey", "grey", "grey", "yellow", "black", "black", "grey", "grey", "grey", "grey"]
我们快到了!我们最后的工作是改变 check 功能。
const check = event => {
Update(state => {
const guess = state.guesses[state.guessCount]
const numble = guess.join`` === state.number
const colors = getColors(guess,state.number)
return {
feedback: numble ? "NUMBLE!" : state.guessCount < 3 ? "Keep going..." : `Nope! It was ${state.number}`,
digits: state.digits.map((colour,digit) => guess.includes(digit) ? colors[guess.indexOf(digit)] : colour),
guessCount: state.guessCount + 1,
count: 0
}
})
}
在 Update 函数中,还有两个常量。这只是使返回对象中的逻辑变得容易。
我们有 guess which 是用户刚刚猜到的三位数数组(因此使用 state.guessCount)。我们 numble 之前也有,但这次使用的是 guess 我们刚刚创建的常量。这只是有助于拥有更清晰的代码并避免重复。最后,我们有 colors 哪个是 getColors 函数运行时返回的数组,用户当前的猜测和答案。
这将更新数字数组并确保键盘上的数字在每次猜测后正确着色。
现在,返回对象与上面的对象相同,但我们也在更新 digits 属性。
state.digits.map((color,digit) => guess.includes(digit) ? colors[guess.indexOf(digit)] : color)
这是我们最终的映射功能!它本质上检查键盘上的数字(即 digit)是否在猜测中。如果是当前颜色,则应替换为 getColors 函数生成的颜色,否则颜色应保持不变。
使用与上面相同的猜测,我们可以看到键盘应该是什么样子:

就是这样!Numble 的全功能版本!
在 Numble 的实际版本中,我添加了许多功能,只是为了让游戏更加动态。如果你想挑战自己并添加一些额外的功能,这里有一些来自我的 Numble 最终版本的建议:
- 再玩一次——让用户想玩多少次就玩多少次,这样每天只有一个挑战
- Streak - 记录你连续有多少正确答案
- 最佳连胜——用户保持的最长连胜
- 暗模式——更像是一个 CSS 挑战,但仍然很有趣
- 显示统计数据——细分用户对每场比赛的猜测次数
- 分享功能——让用户分享他们最好的连胜记录
我真的希望你和我一样在制作 Numble 时玩得开心!