Practical Problem Solving with Algorithms Drawing the Chessboard
Transcript from the "Drawing the Chessboard" Lesson
>> The next exercise that we wanna tackle, it's gonna be a little bit of a change of pace. Hopefully, that'll be a good thing. We're gonna mess around with a few things that you may not be super familiar with messing around with, specifically the DOM API. Most people these days only work with these frameworks that have heavily abstracted away working with things.
[00:00:25] We're actually going to work with the direct DOM API here. So, hopefully that doesn't scare you too much. This exercise is chessboard diagonals. Again, there's the link for the repo. Hopefully, you have that cloned and changed to the start here branch. What we're going to be doing is dealing with a chessboard and specifically highlighting the diagonals when you click on a particular tile.
[00:00:51] So if I were to click on any particular tile here, I want you to know that there are actually. Two diagonals that any square on the chessboard participates in, and some of you are probably chest fans. From the chess world, there's actually a name for these two diagonals.
[00:01:13] So, the diagonal that starts on the top left and works to the bottom right, if it goes in that direction, that's called a major diagonal. And you'll note as I'm kinda doing my mouse cursor here to illustrate as a pointer here, you'll notice that this diagonal is going from top left to top right that there are 15 of them, if you count them out.
[00:01:35] This square right here is a diagonal that only has one square in it. This one has two squares in it. This one has three squares in it and so on. So, those top left to bottom right diagonals are called the major diagonals. And then we have another 15 diagonals going the other direction, which are the minor diagonals going from the top right to the bottom left.
[00:01:56] So this one's a top right, this one's on top right. This one with three white squares in it as a top is a minor. This one's another minor. So we have another 15 of those minor diagonals. So any square that you click on or put a piece on, if you will, in a chessboard, for example, the queen, you put a queen on any square on the board, and there are two diagonals, one major and one minor that that piece can move on.
[00:02:26] In our case, we're gonna just be highlighting these diagonals as you click on them, much like you might do if you were clicking to show all of the places that a bishop or a queen could move on a chessboard. Make sense? All right, so what we're going to do is we're going to think about what is the conceptual basis for how we're going to solve this?
[00:02:53] In other words, what is the mental model that we're going to create for the chessboard that we're then going to translate into code? Can anybody suggest a data structure that might be used to represent a chessboard? This is not a trick question. A two-dimensional array, right? That might be what the people in the chatroom were about to say, Mark.
[00:03:27] A two-dimensional array seems like a fairly reasonable first assumption at a data structure. We have columns going across here and rows going across here and you can have an array of rows, or you could have an array of columns. And the columns could have elements in them, but either way you could represent a two-dimensional grid as a matrix, as a two-dimensional array.
[00:03:53] Since that's the most natural thing and also since we need to ask ourselves how are we going to draw a chess board on our webpage, and there's a heavy emphasis on child elements being inside of parent elements, there's a hierarchical grid structure just implied by the way the DOM elements are gonna sit on our page.
[00:04:21] So that seems like a place to start. Everybody agree with that? We're gonna see that may be is not the best data structure for our problem but we're gonna start there and then work our way forward. So, at any given point on this chessboard, we'll come back to the diagram.
[00:04:38] So let's go ahead and take a look at some of the code and orient ourselves to that and then we'll look at some of these diagrams here. You're gonna have an index.html and you'll notice that we have a div id for the board, but there's nothing in it yet and it has a little to-do that says remove the text, so you should go ahead and remove the text just like I did just there.
[00:04:59] But the reason that to-do comment was there is because it reminds us that we need to write code to fill in those elements. Whatever elements are going to be used to represent the board, we need to fill in those elements and that will be part of what we need to implement.
[00:05:16] If we look at the chessboard module, which is where we're gonna be doing all of our coding, we won't be making changes. Other than that little change to index.html, we won't change the CSS or the app.js. But we do have a draw function here and indeed that's where we're going to write the code that creates eight rows of eight tiles each.
[00:05:40] We're gonna use divs inside of divs. Nothing fancy, no, there's not a chessboard element and we're not gonna make a custom element here. So we're just gonna make divs inside of divs. Now, what are we gonna do to make it colored in the way that a chessboard is colored?
[00:05:58] If I come back to this diagram, you'll note that we have an alternating pattern on the first row that just goes white, black, white, black, white, black. So you might think, well, if I just create it and it's an eight by eight chessboard so there's 64 elements, you might just think what if I just created 64 divs and have them alternating odd, even, odd, even, white, black, white, black.
[00:06:25] Does anybody spot a problem with that approach?
>> That's going to be some gnarly CSS to keep them alive.
>> Potentially, but the biggest problem Is that when we get to the eighth element, and then we get to the ninth element, they are both black. And then this element and this element are both white.
[00:06:53] So what we have is an alternation not only across a row, but across columns. We have an odd even relationship in the columns and an odd even relationship in the rows. It turns out there is actually a pretty straightforward trick to doing this in CSS and you don't have to write any CSS, I've already written the CSS for you.
[00:07:14] But it turns out that if we simply do eight rows of eight elements each rather than doing all 64 and letting them just sort of float into the grid or whatever. If we did eight rows of eight divs each, we can target the row individually with a CSS index selector, and then target each tile inside of it individually.
[00:07:36] And so we'll be able to very easily, with one CSS rule, create this alternating pattern. So, all we really need to do, since I've already done the work of writing that CSS, we just simply need to create eight divs, one for each row, and then, inside of each row, create eight divs for the columns, and the CSS will do the rest.
[00:07:57] If we go and look at that code, just so in case you're curious, here's the trick. We use the nth-child selector. So you notice this first div is the row cuz that's the direct descendant of the board is the row. And what I'm saying, is the 2n divs and we'll come back to that in just a moment.
[00:08:17] And then for all of those rows, we wanna target the 2n+1 cells or tiles. And we wanna target the 2n+1 rows at the position 2n in the tile. That's what we're saying here, so this is a compound selector. For any of those make them block, the rest of them leave white, okay?
[00:08:45] Quick little note on this 2n thing and being of course the indexing, the counting of the child elements. But here's a little trick that you may not know about CSS. CSS is 1-based not 0-based, so whereas we might think of 2n is being even or 2n+1 as being odd, it's actually different.
[00:09:10] So we're targeting the odd row and the even tile, and the even row and the odd tile. It's kind of a, just got to keep straight the whole n is 1-based in CSS that always trips me up. I don't know if it trips anybody else up. Okay. But that CSS selector, if we create those divs, the CSS selectors are gonna do the coloring for us, which is great.
[00:09:33] So, all we need to do is write that code. Now here's where I promised that we were gonna actually spend a little bit of effort in native DOM work. First thing I wanna do is I'm gonna need, and it'll become obvious later why, I'm gonna need to keep a reference to the board EL, the DOM element that is the parent element for our board.
[00:09:58] That's being passed into the draw function, and I need to save that off. So I'm gonna say, very first thing, origBoardEL = boardEL. To construct eight rows of eight tiles each, the most straightforward way of doing this is two loops. I loop nested inside of another loop. We're not gonna do anything more complicated than let i equal 0, i less than or equal to 7, i++.
[00:10:30] Quick little note here, since I'm using less than or equal to 7, we know that this is going to do 8 iterations. I actually think this is a little bit more semantic because it shows the eight. Some people like the less than or equal and then the number because they they don't like it to think about it as beyond the bounds.
[00:10:50] But I just think the eight kind of communicates, so you can do less than or equal to seven or less than eight, whichever one. It's gonna do the same number of iterations. But just from a code communication perspective, I like being able to see eight there. I would for example use a constant for this I might say something like, NUM-ROWS = 8, and then I would wanna use that NUM-ROWS there I wouldn't wanna do NUM-ROWS minus one, if I what I'm saying.
[00:11:18] So to me, that's a little bit of a more semantic signal to use the eight. I'm gonna leave off the constants just to keep a little less code that we're digging into, but you get the point there. Okay, so our nested loop i being the row index and j will make us the, We're good algorithmists, we like to use single letter variables for everything.
[00:11:43] We'll use better variable names elsewhere, but for right now, we'll just use i and j for row and tile index, I think. Column index, tile index, those will be interchangeable for us. Okay, so we need to create a div. Some of you have never done this before, but document.createElement("div").
[00:12:07] It's not quite as cool looking as JSX, but it gets the job done. JSX compiles to document.createElement, so it's the same thing. We also need a real element. I neglected to do that one. For each row, we're gonna need to create a parent row element. So, let's go back and do that.
[00:12:39] Same way, row elements and tile element. What do we do with a tile element? We append it to the parent row element. So we do rowEl.appendChild(titleEl). And after we've appended all of the tile elements to a row element, what do we do with the row element we append it to the board element.
[00:13:14] Let's switch over to the browser. I've got a web server running on this code. And when I refresh, boom, there's our chess board. One other thing to note is that our chessboard isn't clickable yet, but it will be clickable when we write our code. So the idea of this is that I come along here and I click one of these, and that's when it should highlight.