3

I've made a Knight's Tour game in javascript. You can try it here. (Particularly for reproducing the error)

The error I'm having so much trouble finding reads

Uncaught TypeError: Cannot read property 'innerHTML' of undefined

but I'm not sure why it's undefined. I have a table with 64 cells (making a chessboard). They're all built as plain and empty

<table border=1 style="border: 1px solid black; table-layout: fixed;">
  <tr>
    <td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
  </tr><tr>
    ...

This is the only table on the page. I use javascript to retrieve all of the td elements and I iterate through them adding ids, classes, background color and onclick eventListeners for gameplay.

var tds;
window.onload = function() {
    tds = document.getElementsByTagName("td");
    for (var i = 0; i < tds.length; i++) {
        if (typeof window.addEventListener === 'function') {
            (function (td) {
                ...
                td.addEventListener('click', function() {
                    ...

There seems to be a few different cells that repeatably have this error occur. Sometimes I can get the individual cell to produce an error, other times I can't. One repeatable example is to move first on the bottom row, second to last cell, and then try to move onto the cell two up and one right from it along the side.

I read the innerHTML attribute frequently inside the onclick. I refer to the global tds array of td elements. Here are basically all forms of myself accessing them.

if (tds[cell].innerHTML === "") {
if (tds[n].innerHTML === "♞") {
tds[cell].innerHTML = "♞";
tds[target].innerHTML = "♘";
td.innerHTML = "♞";

I really thought I had it figured out when I was reading about the difference between declaring a variable using var and when not using it, but I couldn't figure out a single var that was causing this error. Any help would be appreciated.

agweber
  • 1,295
  • 2
  • 17
  • 26
  • 2
    Your error - it's about reading the `innerHTML` property - where are you actually doing that? Show us __THAT__ code. – Benjamin Gruenbaum Sep 06 '13 at 13:55
  • @Benjamin Added. Gave all the ways I call it that I came across, some of those occur many times in the code. – agweber Sep 06 '13 at 13:59
  • The problem is that `n` at that point is equal to 64. The total length of `tds` is 64 (or 0 to 63) and it's generating an error because element that `n` represents is outside the range of the array. – Andy Sep 06 '13 at 14:00
  • @Andy Wouldn't that generate an out of array index error instead? And the cells that this occurs are in multiple locations in the table. – agweber Sep 06 '13 at 14:01
  • 1
    It says that `tds[n]` is `undefined`, not the `innerHTML`. If you don't believe me about `n` being 64, run your own test. – Andy Sep 06 '13 at 14:02
  • @Andy Added cheap "n < 64 && " tests to all of my moves and it has fixed the bug. Thanks. Would you like to offer up an answer for me to accept or shall I just delete this question? I'm off to class for the time being. – agweber Sep 06 '13 at 14:05
  • @agweber- I've added the answer. – Andy Sep 06 '13 at 14:07

2 Answers2

2

The boundary test:

 if (x > 0 && y < 6) { //bottom right

isn't right, the x condition should be x < 7; it's the right hand column you are trying to avoid not the left.

To avoid all that duplication (and subsequent likelihood of a trivial copy-paste-edit error like this), I recommend doing the position calculation in x/y co-ordinate terms and then calculating the cell index from there instead of working in cell indices and checking each boundary separately. And actually, tables have rows/cells properties so you don't have to do the cell index calculation either. For example:

var knight_moves = [[-1, -2], [1, -2], [-2, -1], [2, -1], [-2, 1], [2, 1], [-1, 2], [1, 2]];

for (var i= knight_moves.length; i-->0;) {
    var other_x = x + knight_moves[i][0];
    var other_y = y + knight_moves[i][1];
    if (other_x>=0 && other_x<8 && other_y>=0 && other_y<8) {
        var cell = table.rows[other_y].cells[other_x];
        if (cell.innerHTML=='♞') ...
    }
}
bobince
  • 528,062
  • 107
  • 651
  • 834
  • I started doing this before and reverted back to the crazy duplication when I ran into issues before I had realized that I could do a coordinate system. Thanks for looking into the code and finding a way to improve! – agweber Sep 06 '13 at 15:15
1

The problem is that n at that point is equal to 64. The total length of the tds array is 64 (or 0 to 63) and it's generating an error because element that n represents is outside the range of the array.

Andy
  • 61,948
  • 13
  • 68
  • 95