...

# Checking 2D array line lengths of equal content

Diogenes
05-23-2012, 01:30 AM
Hello,
I'm sorry about the vague title, here's the full synopsis of the bug:

This is for Connect4 program in Javascript that keeps track of the board in a 2D array: 'r' for red pieces, 'b' for blue/black pieces. I had originally written it in C++, and copy+pasted much of the base code here. The LineLength() function takes in the current location, color, and direction, and returns how many pieces there are extending in that direction of the same color, starting at and including the first one. For example:

[r][r][b]

Run on the first [r] with direction to the right, it will return 2; run on any other direction, it will return 1. This worked just fine in C++, but apparently in Javascript, the function returns the correct amount for all directions except to the right. I've re-copied it over a few times from different source versions, and spell-checked as best as I could, but it still has the same problem.

If anybody could show me what I'm doing wrong here (or a superior way to code Connect4) I'd be hugely grateful. The code for a function that calls all the directions statically, HasVictory(), and the LineLength() itself, is below, while the C++ source files, main and SuperBoard, and the JavaScript file engine are attached as .txt for reference.

Thank you very much!

Edit: By the way, location (0,0) is the upper left corner of the grid. That might be helpful ;) Also, most of the clumps of lines of code are just variations on each other.

function HasVictory(me) {
var lol = "";
// directions: 0 for up, 1 for left/up, 2 for left, 3 for left/down, etc.
var leftdown = LineLength(me, placed, peaks[placed], 0, 5, 4) - 1;
var rightup = LineLength(me, placed, peaks[placed], 0, 1, 4) - 1;
var left = LineLength(me, placed, peaks[placed], 0, 6, 4) - 1;
var right = LineLength(me, placed, peaks[placed], 0, 2, 4) - 1;
var leftup = LineLength(me, placed, peaks[placed], 0, 7, 4) - 1;
var rightdown = LineLength(me, placed, peaks[placed], 0, 3, 4) - 1;
var down = LineLength(me, placed, peaks[placed], 0, 4, 4) - 1;

lol += "rightup: " + rightup + "<br />";
lol += "leftdown: " + leftdown + "<br />";
lol += "right: " + right + "<br />";
lol += "left: " + left + "<br />";
lol += "rightdown: " + rightdown + "<br />";
lol += "leftup: " + leftup + "<br />";
lol += "down: " + down + "<br />";

document.getElementById("extra").innerHTML = lol;

if (down >= 3) return true;
if (rightdown + leftup >= 3) return true;
if (right + left >= 3) return true;
if (rightup + leftdown >= 3) return true;
return false;
}

// color, width location, height location, current length, direction, max length (4)
function LineLength(me, w, h, length, dir, cap) {
if (w < 0 || h < 0 || h > HEIGHT - 1 || w > WIDTH - 1)
return length;
if (board[h][w] != me || board[h][w] == '.')
return length;

++length;
if (length == cap)
return length;

if (dir == 0)
return LineLength(me, w, h - 1, length, dir, cap);
if (dir == 1)
return LineLength(me, w + 1, h - 1, length, dir, cap);
if (dir == 2)
return LineLength(me, w + 1, h, length, dir, cap);
if (dir == 3)
return LineLength(me, w + 1, h + 1, length, dir, cap);
if (dir == 4)
return LineLength(me, w, h + 1, length, dir, cap);
if (dir == 5)
return LineLength(me, w - 1, h + 1, length, dir, cap);
if (dir == 6)
return LineLength(me, w - 1, h, length, dir, cap);
if (dir == 7)
return LineLength(me, w - 1, h - 1, length, dir, cap);

return -96; // This will never be reached in the actual game.
}

Old Pedant
05-23-2012, 02:31 AM
Can you show it live? So we don't have to duplicate your web page?

Diogenes
05-23-2012, 03:17 AM
Sure, sorry about that - here (http://rising-studios.com/Other%20Projects/CF/test.htm).

Old Pedant
05-23-2012, 04:31 AM
Ahhh...just a little debugging reveals the problem!

You are doing buttonPress('0')

So you are passing a *STRING* to the function!

Which in turn becomes the place argument which then becomes w.

And when you do w = w + 1 you get (for example) "11"!!!

REMOVE the apostrophes!

buttonPress(0)

***********

I hope you won't mind too much if I say it could all be written in a *lot* less code.

Diogenes
05-23-2012, 04:35 AM
Ahhh...just a little debugging reveals the problem!

You are doing buttonPress('0')

So you are passing a *STRING* to the function!

Which in turn becomes the place argument which then becomes w.

And when you do w = w + 1 you get (for example) "11"!!!

REMOVE the apostrophes!

buttonPress(0)

***********

I hope you won't mind too much if I say it could all be written in a *lot* less code.

Haha not at all, thank you very much for the help! If you'd be kind enough to give me some pointers, that'd be great - I normally don't do this type of coding in Javascript (or at all). I could probably use arrays for directional stuff and automate the table printing, but haven't done it yet for debugging purposes.
Just wondering, why was this working for some directions and not others?

Old Pedant
05-23-2012, 05:03 AM
It worked for any MINUS direction, because JS *will* convert a string to a number to do subtraction. But any PLUS direction it would blow up on. RIGHT UP wasen't working, either. You didn't test thoroughly enough. LEFT DOWN also didn't work.

Here's a *POSSIBLE* set of changes for your code. UNTESTED. Just typed in with Notepad.

function HasVictory(me) {
var lol = "";
var leftdown = LineLength(me, "ld");
var rightup = LineLength(me, "ru");
var left = LineLength(me, "l");
var right = LineLength(me, "r");
var leftup = LineLength(me, "lu");
var rightdown = LineLength(me, "rd");
var down = LineLength(me, "d");

lol += "rightup: " + rightup + "<br />";
lol += "leftdown: " + leftdown + "<br />";
lol += "right: " + right + "<br />";
lol += "left: " + left + "<br />";
lol += "rightdown: " + rightdown + "<br />";
lol += "leftup: " + leftup + "<br />";
lol += "down: " + down + "<br />";

document.getElementById("extra").innerHTML = lol;

return ( (down >= 4) || (rightdown + leftup >= 4)
|| (right + left >= 4) || (rightup + leftdown >= 3) );
}

function LineLength(me, dir)
{
var w = placed;
var h = peaks[placed];
var dw = 0;
var dh = 0;
switch ( dir )
{
case "r": dw = +1; break;
case "l": dw = -1; break;
case "d": dh = -1; break;
case "ru": dw = +1; dh = -1; break;
case "rd": dw = +1; dh = +1; break;
case "lu": dw = -1; dh = -1; break;
case "ld": dw = -1; dh = +1; break;
}
var length = 1;
while ( length <= 4 )
{
h += dh;
w += dw;
if ( w < 0 || h < 0 || h > HEIGHT - 1 || w > WIDTH - 1 ) return length;
if ( board[h][w] != me || board[h][w] == '.') return length;
++length;
}
return 4;
}

Old Pedant
05-23-2012, 05:05 AM
You could pass dh and dw into LineLength instead of dir and save even more.

Diogenes
05-23-2012, 06:25 AM
Ha, that is way more elegant than what I had. I'll be sure to test WAY more thoroughly. Thanks again!