![Complete Intro to Web Development, v3](https://static.frontendmasters.com/assets/courses/2022-09-05-web-development-v3/thumb.webp)
Check out a free preview of the full Complete Intro to Web Development, v3 course
The "Project JavaScript: Commit Word" Lesson is part of the full, Complete Intro to Web Development, v3 course featured in this preview video. Here's what you'd learn in this lesson:
Brian walks through a possible solution for keeping track of the current number of correct, out-of-place, and incorrect letters in a guess.
Transcript from the "Project JavaScript: Commit Word" Lesson
[00:00:00]
>> We are gonna do all of the marking as correct, close, or wrong. Now, I'm just gonna forewarn you here that I've already thought about this a lot. And so we're just gonna go straight to my best solution, but it took me a couple of iterations of trying it once, trying it twice, trying it a different way, trying it again.
[00:00:20]
And I have found that eventually, the easiest way to do this was to go over the list or the word once mark, everything is correct, that's correct. Then go back over it again and mark everything that else as close or wrong. And I'll explain to you why. So again, remember the correct word here is ivory, right?
[00:00:43]
If I put pools here, notice that this first o is marked as incorrect, right? Now if I was just doing like a really naïve implementation, there is an o in this, right? There's this o, so if I was just being naïve about it, this would be marked as close, right?
[00:01:03]
It'd be marked as yellow. But we don't want that, that's actually not correct. So we actually have to keep track of how many of each letter is in the word. Does that make sense? Okay, so let me show you how I did that. There's definitely other ways of doing that.
[00:01:23]
So the first thing I'm gonna do is I'm gonna split our guess into pieces. Easy way to do that, Is we're gonna say, const guessParts or whatever you wanna call it, equals currentGuess.split. And if you split on an empty string, it'll rip it apart and make each character one entry in an array.
[00:01:56]
Let me show you what I mean here. So if I go over here to the console, and I say POOLS. Sorry, I have to make it a string. POOLS.split and I give it an empty string. Notice I get back an array of P-O-O-L-S, right? That's what split does.
[00:02:24]
Okay, so now I have this array of letters. The next thing I'm gonna do is, I wanna go count how many of each letter. Well, before I even do that, I have this word here. So I'm actually going to go up here, again, this word doesn't change, so I can actually just do it up here.
[00:02:45]
I'm gonna say const wordParts, = word.split, again, same way. So now I have two different part arrays, right? This one is gonna be the correct answer, and this is going to be what the user is guessing at the moment. So even before we go and do all the counting, let's just go ahead and, We're gonna say for, Let i = 0.
[00:03:29]
i is less than, you could say parts or .length or you can even just say ANSWER LENGTH, they should all be the same thing. I ++, and we're gonna go through, all we're gonna do right now is just mark things that are correct. So we're gonna say here this is the mark as correct.
[00:03:55]
And we're just gonna say, if, guessParts at I triple equals wordParts at i, Then it's right, right, they got the right thing in the right spot, right? So again, if we're over here at POOLS, and we're on the this one here, the word is IVORY. On this one, the O is going to triple equal to the O, they got something correct.
[00:04:28]
So what we're gonna do there is we're gonna say, letters, currentRow times ANSWER_LENGTH plus what? Plus i, right? So if we're on, the second one has to be plus two, if we're on the zero with one that it's plus zero, so plus i there, wherever this i is correct.
[00:05:02]
We're just gonna say .classList cuz they're all dom nodes, .add and they are correct, right? So we'll mark it is green. Cool, good so far? So let's actually try that see if it works. We know what are word is it's IVORY. If I type in here POOLS, I would expect this O to be green.
[00:05:40]
Very cool. If I type in here IVORY, we haven't done this yet but now all of them are correct. So far pretty good. PEARS, that one's right. Awesome. Okay, let's go do a second loop through. And we're gonna do on the second loop everything's gonna be marked as incorrect or correct.
[00:06:10]
Now, again, you might be looking me like Brian, why can I just mark it as incorrect or close in here? You could, but I promise you, you're gonna run into an issue that you're gonna have to refactor later. We're gonna go for a second loop. Let i = 0.
[00:06:28]
i is less than ANSWER_LENGTH i++. So we're gonna basically take this first one. Since we already took care of this one, we're just gonna do nothing here, we don't need to do anything again. Do nothing we already did it. Else if, We have to do something here, so I'm just gonna put like a little comment here to say that we're gonna come back and get this right.
[00:07:21]
TODO make this more accurate. For now, what we're gonna say if a guest parts, sorry, wordParts.includes, so wordParts is an array, right? And, Includes is a function that you can call to say, hey, does this array contain this other thing anywhere? So let me give you an example of that.
[00:08:01]
If I have, 1, 2, 3, 4, 5, and I say .includes(3), that's true, right? Because three is somewhere in this array. If I do 10, that's false because there's no 10 in that array. So I'm gonna say does workParts.include anywhere guessParts(i), if it does, Then mark it is close, right?
[00:08:36]
So we're gonna say, we're gonna just take this exact same thing here. But instead of adding correct we're gonna add close. And if it's not close or correct, what is it? It's wrong. Okay, refresh the page. So how about POOLS? PEARS, or something like that, right? So, this is doing exactly what we told it to do, or how about TOILS?
[00:09:28]
So this one's actually right, this would be correct. There is an O but it's in the wrong place, there is an I but it's in the wrong place, this is exactly what it should be showing, right? T is incorrect, it's not an IVORY at all. L is incorrect it's not an IVORY and S is not in IVORY at all.
[00:09:46]
Where we have a problem now is we have this one. This O is being marked as close and it's not, right? Because there is an O it's in the correct place, this is informing the user there's an O in here somewhere and we lied. It's a lie, everything's a lie.
[00:10:06]
So that means we kind of have to keep track of how many letters are in there? And I'll show you how I did it. First of all, any questions here before we dive into making it even more correct? So we have to count for every letter how many of them are in here, right?
[00:10:27]
So we have to know that there's exactly one O, and there's not two O's. So the way that I chose to do this is before I even get started, I have a function here, just down at the bottom it's kind of just like a little utility function and I call it makeMap.
[00:10:41]
And it takes in an array. It makes an object. And all it's gonna do is it's just going to say, there's one P in here, there's one O, there's one I, there's two. And it's just gonna make an object of that, right? So it's gonna say 4, let i = 0, i is less than array.length, i + +.
[00:11:08]
And it's gonna say, if you already have that object, so object, Of array i. So this might be a little bit more clear, let's do it this way. const, letter, Equals array of i. So we talked a little about this when we're doing objects. So this will be like P or O or L and this will be setting either P or O or I or something like that, on the object.
[00:11:56]
So if I just say, if object of letter, if I just say like that, if it exists, it'll return true, if it doesn't exist, it will not return true. And if it does exist, then we're just gonna say ++ or otherwise we're gonna say object of letter equals 1 and we will return the object.
[00:12:26]
So let me show you an example of using this and then we'll go back and dissect it again. So const map equals make map, that function that we just wrote together, of guess, not just guessParts but wordParts. And then just to show you what it is we'll say console.log map, map now.
[00:12:52]
Refresh the page and I say POOLS here and I hit Enter. It's giving me IVORY which has one of each letter, right? Which in this general case is probably gonna be okay, but let's take a look at, makeMap of something like POOLS, and we'll split that on empty string.
[00:13:18]
Right, POOLS has two O's, right, so it comes out back with two. And that's what we're looking for, cuz then I can keep track of how many, of each letter I've marked as close or correct. And then therefore at the end of this I can make sure that I have exactly the correct amount of things marked as correct and close.
[00:13:36]
There are other ways you could have done this for sure. You could have checked the string every time of like, okay how many O's are in here? This is the way that made sense to me. Because now at the end of this, if I go down to my commit, this part, if they get a correct thing I can just say, map, Of the letter, right, the letter is gonna be whatever the guess part was, right?
[00:14:07]
So I can put that here and I can just say --, right? So that means after I guess the O correctly here it'll minus minus this, so that later I can check to say like, hey, is there an O left for me to mark as close, right? You can use this technique to kind of do that.
[00:14:34]
So again, guess parts here, this will be like O, right? And inside of that map, if you remember here, it'll just make this, O go minus minus, right? So if I do that again, I will just say x equals, right, and when I say x.o, right, and I say --, Then x.o here now is 1.
[00:14:57]
If I do it again, x.o --, then x.o oops. X.o is 0, right? And then now once it's 0, then I can say, cool, there are no more O's left in this string. Does that follow make sense? Cool. All right. Why map? That's probably a good question you could ask me.
[00:15:26]
That kind of data structure that I showed you where you were just making like a mapping basically, it's just called a map, that's what you would call it. A map is, loosely an object. Now every time we mark something as correct we're doing minus minus and this is why I split it apart, is I can go mark all the correct things first cuz that's more important than being close as being correct.
[00:15:51]
Then on here, now we can make this more correct, right, we can say, If this is true, if it includes it, and then we can do what's called the compound condition. So if I put a double ampersand here, now both of these things have to be true. So if I say and, Map, guessParts of i, right, that thing that we've been decrementing up here.
[00:16:30]
If that's greater than 0, Okay, then we can mark it as close. Right, so with this one now it's gonna go find this first O on the first pass. It'll decrement that so that there's no O's left for it to mark on the second pass through. And so this mapGuess parts of O here is going to be what?
[00:17:01]
0, right, because there's no O's left here, so it's not gonna mark it as close, it's gonna mark it as wrong. Okay, and then important here you have to also do decrement here as well. All right, because now we've marked that many right. You can imagine a case where there's three of one letter, right?
[00:17:26]
In which case it would become important here, or two if you just got them both close, or one, doesn't matter. Anyway, important for you to say that I've, you're basically counting how many of these you're keeping track of. And now if we save this and come back over here and refresh, if we say POOLS, Now this is not being counted which is exactly what we wanted.
[00:17:58]
Right, and now it'll only mark the first one, not the other three.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops