Practical Problem Solving with Algorithms

Highlighting Diagonal Tiles

Kyle Simpson

Kyle Simpson

You Don't Know JS
Practical Problem Solving with Algorithms

Check out a free preview of the full Practical Problem Solving with Algorithms course

The "Highlighting Diagonal Tiles" Lesson is part of the full, Practical Problem Solving with Algorithms course featured in this preview video. Here's what you'd learn in this lesson:

Kyle uses a series of for loops to search for diagonal tiles to highlight. Each loop traverses tiles in a different diagonal direction until an upper or lower bound is reached.


Transcript from the "Highlighting Diagonal Tiles" Lesson

>> Now the fun stuff. How are we gonna turn that into highlighting our diagonals? But let's look at the relationship of coordinates of the thing that we clicked and the thing that we want to highlight. Here's our starting element that we've clicked on and here are the first four coordinates that we need to highlight.

Got a little bit of spacing off here. But we are highlighting this element at (3,1), (3,1) this one at (3,3). This one at (5,1) and this is at (5,3). Do you see those coordinates how they match up? This is row three column three. This is row three, column one.

This is row five column one and row five column three. What do you notice about the relationship between the coordinates of these four elements that are on the respective diagonals? What's the relationship between those coordinate values and the coordinate value of the thing that we clicked on?
>> Adding, subtracting.

>> It's just different by one, right? Take (4,2) and go to (3,1). That means we subtracted 1 from the row index and we subtracted 1 from the column index. Take (4,2) and go to (3,3) that's subtracting 1 from the row index but adding 1 to the column index.

Same thing going in the downward direction, we add 1 to the row index, subtract 1 from the column index to get (5,1). We add 1 to both the row and column index to get (5,3). The same would be true all the way up and down all four directions along those diagonals.

Each thing along the diagonal is just a + or- of 1 from the previous one. Following that? So that kind of suggests to us an algorithm for highlighting the diagonals does it not? We could start at the selected tile at the clicked tile and run some loops in the four directions Increasing indexes of row and column or decreasing accordingly in the four directions.

And that would give us the indexes of the elements that we need to highlight. Wouldn't give us the elements yet, but at least gives us the indexes that we need to highlight. Make sense? Let's switch back to the code editor. We're gonna do four separate loops, one for each of these directions, okay?

I'm going to highlight in the upper left direction. Okay, you'll see me sometimes just pointing at my computer and making sure my left's and rights are not getting backwards or something like that. So highlighting in the upper left direction for you it's this, for me it's this, the upper left direction, okay?

So what do we know in the upper left? We know that both the row index and the column index decrease in the up left direction. So we're going to set ourselves up with a two variable four loop. Some of you may be aware that this syntax can be done, others may be seeing this for the first time, but we're gonna have an I and a J.

The I starts at the tiles row index and the J starts at the tiles column index. We want to keep going while, And these are gonna be decreasing. How do we know when we've reached the edge of the board?
>> We've reached a minimum or a maximum.
>> And what is the minimum for the row index and column index?

>> 0.
>> 0. So while i, which is our row indexing, while i is greater than or equal to 0 and j is greater than or equal to 0. We wanna keep going in that direction, and we're going to decrement i and decrement j. Single four loop doing both, Decrementing of the row and column indexes.

The i and j in this loop is going to give us the indexes of those elements along that diagonal but it doesn't give us the elements themselves. So to get the element themselves, we're going to need to call a function which I will call find tile, that we pass in the row and column index two and it gives us back the DOM element reference.

And assuming that that function exists, which we'll write in a moment once we get a reference to it we just need to add the highlighted class to it. Does everybody understand how I wrote that four loop? Does that one make sense? It's one of the four loops that we need.

It is the one that is going in the upward and leftward direction. I don't know if leftward is a word, but I'm gonna use it. To save myself some typing, I'm gonna duplicate that loop and I'm gonna go do the up-right direction. What is different about going in the upright direction?

My row indexes still decrease, so I still want to do greater than or equal to 0 for my row indexes. But my column indexes increase when I'm going rightward, right? So I don't want j greater than or equal to 0. What I want j, What should this be?

Not greater than or equal to 0, it should be, Less than 8 or less than or equal to 7 if you prefer that form but I'm gonna use the less than 8. And j is naught- -, what should it be? I suppose. That's the only thing I needed to change was the condition of when it finishes and incrementing that one.

And now I'm really lazy. So to do the other two loops, I'm just gonna duplicate both of those loops. For these loops, what changes? We're changing from up to down, And that's gonna change our i's, right? So our i is no longer greater than or equal to 0.

What's the condition for i when our row index is increasing? Less than or equal to 7 or less than or equal to 8, if you like that, right? So for both of these loops, I'm gonna change the i condition to i less than 8. And for both of these I'm gonna change it from i-- to i + +.

I've taught this workshop a dozen times now, and every workshop, including me, people get these wrong, okay? So even though you're trying very meticulously to get the less than or greater than, this is one of those places where it's easy for us to trip up and get wrong.

Even when you're looking at it and looking at yours and you're like, it looks right, it looks right. I don't see what's wrong. If we try this and yours breaks, don't waste any more time on it. You understand how this works just grab the copy from the repo, right?

I don't want people sitting here frustrated because they missed a-- or something, okay? As long as you understand conceptually how I constructed the four different loops. We're simply either incrementing or decrementing the row and the tile indexes respectively, so that we go in the four respective directions. And the last thing that we're gonna need is just this little old find tile function.

Following? So let's write our find tile function, and then we'll test everything and see how we did, okay? Remember that find tile, Receives a row index and a column index. I'll just call it row and column to keep things short here. How are we, given a numerical index, going to pull out a reference to the respective DOM element?

There are multiple ways to do this. Some of them are better than others. I'm only gonna show you one of them, but this is not certainly the only way. You could loop through all of them until you find an i and j that match row and column. I'm gonna use the CSS engine to do it.

Because we have the nth tile selector, and I have these indexes, and I'm just gonna construct a CSS selector that pulls out the respective element. So that is gonna look like this, we're gonna use our our friend query selector all, I'm sorry query selector not selector all. We got to do it on document and, Oops, we're gonna select the parent element board and then div, this will be our row.

So we're gonna do nth-tile, And remember that CSS deals with indexes in one based so we're gonna take our row + 1. So if our row index was 4, then we want to actually pass the selector 5 because that's how CSS will see it. And then we'll do another direct descendant.

Actually, since this is a template string I'll just do these on separate lines. So it's easier for you to read. So this was selecting the row element. Now we wanna select the tile inside of that. So we've got another direct descendant and we'll do nth tile. And we'll do column + 1.

This offloads to the CSS engine, all of the work of finding the DOM element. And it goes on the assumption that the CSS engine is going to be more efficient at doing that than my four loops would be. If we haven't made a mistake, hopefully we should be able to save this file and switch over to the browser.

Refresh our page, click on an item, and there's our highlighted tiles.
>> First try. No mistakes.
>> Doesn't happen very often.
>> They call them first try tile.
>> Somebody mark this date because we'll wanna remember the date that I wrote code and didn't make a mistake. Turn up very often.

Like I said don't bang your head against too much if it's like, it's missing one of the diagonals or it's throwing an out of bounds are, or something. It's almost certainly, you have missed doing a- -, or you missed doing a less than, or something like that. That happens all the time with this stuff.

This is not the kind of code that I'd like to check into production and say, Hey, please keep this code around forever cause it's hard to read, hard to maintain. But what does it do critically? It gets us to a first step, a working algorithm which is out baseline that we can work from to improve the code, improve the optimization, improve the readability.

This is the code as it sits in the option one branch. So if for some reason yours missed the character somewhere it's not quite working. As long as you feel comfortable with how we did it and what the concept was that approached it, stash your changes, and check out the option one branch so that's the correct starting point for the next work that we'll do.

>> What another way to do this roll call stuff based on arrays without the CSS selector, which approach would you use?
>> Yes, you could have done this with the tile nodes, arrays and use those indexes that way. So you could have said, original board element, dot tile nodes dot tile nodes of call.

It absolutely could have done it that way. My impression, or my guess, is that both of those are gonna perform about the same which is to say that they're quite fast because they're using built in stuff. I don't think that the CSS selector is gonna be any less slow than the array reference because those aren't real arrays.

Those are DOM node lists. If they were real native JavaScript arrays, then it would be much faster to access the real native JavaScript array element. But we don't yet have an array in JavaScript of those, what we have is these DOM element lists. So, I don't think that there's gonna be much of a performance difference between the two, but it's certainly a valid approach if you like that style of code better.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now