Michael
Michael

Reputation: 19

I'm am having issues getting this javascript program to execute

Every time I run the program and enter a pile and circle number, I get a "TypeError: piles[pileChoice] is undefined" error. I have tried debugging it several times but I still cannot get it to function properly.

var piles = [
  {name: 'Pile A', circles: 'ooooo'},
  {name: 'Pile B', circles: 'ooooo'},
  {name: 'Pile C', circles: 'ooooo'}
];

function boardPrint(){
  console.log("NIM");
  for(var i = 0; i < piles.length; i++) {
    console.log(piles[i].name + ": " + piles[i].circles);
  }
}

function getUserInput(){
  return prompt("Enter the letter for the pile (A-C) and the number of stones you want to remove (1-5). Example: A3").toLowerCase();
}

function userMove(){
  var pileIdx = 0;
  var valid = false;
  var numToRemove = 0;

  while(!valid) {
    var gameIns = getUserInput(); // This will now get called multiple times until user enters valid input
    var pileChoice = gameIns[0]; // This makes 'A' turn into 'a', which makes further logic easier.

    // I rebuilt this part of the function to be a bit cleaner and to show you how switch statements could be used
    switch(pileChoice){
      case 'a':
      pileIdx = 0;
      valid = true;
      break;
      case 'b':
      pileIdx = 1;
      valid = true;
      break;
      case 'c':
      pileIdx = 2;
      valid = true;
      break;
      default:
      alert('Error! Invalid input.');
    }
    numToRemove = Math.min(gameIns[1],piles[pileChoice].circles.length); // This way, they can't select a number that is greater than the number remaining in the pile.
  }

  piles[pileIdx].circles = piles[pileIdx].circles.slice(numToRemove);
}

function computerMove(move){
  // Task 1: pick a pile

  var pileIdx = 0;

  if(piles[0].circles.length > 0) { // tests for whether there are circles left in pile A
    piles[0].circles = piles[0].circles.slice(pileIdx);  // do something

  } else if(piles[1].circles.length > 0) {
    piles[1].circles = piles[1].circles.slice(pileIdx);  // do something

  } else if(piles[2].circles.length > 0) {
    piles[2].circles = piles[2].circles.slice(pileIdx);  // do something
  }

  // Task 2: pick a number to remove from the pile

  // Optional: see how many piles are left and base your number to remove on that
  //var pilesCount = 0;

  // [some logic for counting piles]

  // Otherwise, just remove all that are remaining from a pile
  //var numToRemove = 0;

  if (pilesCount > 1){
    // select a number to remove
  }
  else {
    // select another number to remove
  }

  piles[pileIdx].circles = piles[pileIdx].circles.slice(numToRemove);
}

while(true) {
  boardPrint();
  userMove();

  if (boardEmpty() === true) {
    boardPrint();
    console.log("You win!");
    break;
  }

  boardPrint();
  computerMove();

  if (boardEmpty() === true) {
    boardPrint();
    console.log("Computer wins!");
    break;
  }
}

function boardEmpty() {
  // Check if the board is empty
}

Upvotes: 1

Views: 53

Answers (3)

Marnix Harderwijk
Marnix Harderwijk

Reputation: 1313

You are trying to reference piles[pileChoice] like piles['a'], piles['b'] and so on in gameIns[0], but the piles array is not formatted in that way because piles is an array of objects.

You could try rethink the way you model piles or try a workaround like the following for getting the circles.length:

// define pileCircleCount
var pileCircleCount;

// go over your piles array
piles.forEach(function(pile) {

 // get the pile name value and retrieve the last char which is A/B/C
 // and convert it to lowercase
 var pileId = pile.name.substr(pile.name.length - 1).toLowerCase();

 // now match it up with the pileChoice, if a match is found get its
 // circle length and set it to the pileCircleCount
 if(pileId === pileChoice) {
   pileCircleCount = pile.circles.length;
 }
});

numToRemove = Math.min(gameIns[1], pileCircleCount); 

Upvotes: 0

Mark Adelsberger
Mark Adelsberger

Reputation: 45819

In your userMove function, at the end of the while loop you try to set numToRemove with the following line:

numToRemove = Math.min(gameIns[1],piles[pileChoice].circles.length); // This way, they can't select a number that is greater than the number remaining in the pile.

But pileschoice is either 'a', 'b', or 'c', right? That's why you calculated pileIdx in your switch. You need to use it instead, because the way you've defined piles it can't be indexed with 'a', 'b', or 'c'.

Upvotes: 1

mherzig
mherzig

Reputation: 1587

I think the issue is here:

You have

var piles = [
  {name: 'Pile A', circles: 'ooooo'},
  {name: 'Pile B', circles: 'ooooo'},
  {name: 'Pile C', circles: 'ooooo'}
];

and then later

numToRemove = Math.min(gameIns[1],piles[pileChoice].circles.length);

I think you meant for that to be piles[pileIdx]? pileChoice is going to be a letter, and you have an array of objects so you would need to access the correct one with in index.

Upvotes: 0

Related Questions