You've made the common mistake of thinking that DOM methods return arrays. They don't. That's not an array, it's a collection, and as such it doesn't have a lot of the methods arrays have. However, they can still be used with those methods; you just have to call them manually:
Code:
this.holes = Array.prototype.reverse.call(document.getElementsByName("p" + n));
As for the rest of your script and page:
Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
This DOCTYPE has been unnecessary for a good decade or so. Use Strict.
Code:
<link rel="stylesheet" type="text/css" href="mancala.css"/>
This XML-style ending syntax doesn't mean what you think it means in HTML, and what it does mean few browsers support.
Code:
<table border="1" bordercolor="#000000" width="100%" height="100%">
Avoid this presentational markup -- there's no reason not to use CSS.
Code:
<tr>
<td class="mancala" id="p2" rowspan="2"></td>
<td class="hole" name="p2" id="2-1" onClick="players[1].grab(1)"></td>
<td class="hole" name="p2" id="2-2" onClick="players[1].grab(2)"></td>
<td class="hole" name="p2" id="2-3" onClick="players[1].grab(3)"></td>
<!-- &c. -->
Since the game depends on Javascript, it would be neater to have Javascript generate the necessary markup. Also, IDs may not begin with a number.
Code:
this.turn = function(){
This results in the function being recreated each time a new instance is created, needlessly. Use prototypes:
Code:
Player.prototype.turn = function() {
Code:
for(i = 0; i < this.holes.length; i++) this.holes[i].style.backgroundColor = "red";
By omitting the var keyword, you've unwittingly made i public. You really do not want i to be public, since every man and his dog names their index variable i, and if someone else makes the same mistake and you start overwriting one another's index variables you're going to have a hell of a time debugging it. Personally I find it easiest to keep track of my index variables by declaring them at the top of the function, C-style, to avoid accidentally globalising them (with a missing var) or redefining them (with a superfluous var), but this is a matter of taste.
Code:
stones = this.holes[n - 1].innerHTML;
There's no reason to use innerHTML here. Avoid it where possible, since it's non-standard, misrepresents the DOM, and has side effects that people often don't anticipate. Using DOM methods in this case is an equally simple endeavour.
Code:
function change(){
if(current == 1) player[current = 0].turn();
else player[current = 1].turn();
}
function next(){
return current == 1 ? player[0] : player[1];
}
It would make more sense to store these on the Player function:
Code:
Player.change = function() {
/* ... */
};
Player.next = function() {
/* ... */
};
The players array looks as though it would make sense in there as well -- avoid globals wherever possible, especially ones with generic names like "players" and "current." Since current seems to be used nowhere else, you could put it in a closure around these two functions:
Code:
(function() {
var current = 0;
Player.change = function() {
/* ... */
};
Player.next = function() {
/* ... */
};
})();
Bookmarks