Как я могу исправить ошибку неперехваченного типа в этом коде?

#javascript #typeerror

#javascript #ошибка типа

Вопрос:

Я не верю, что могу установить тип переменной перед функцией, которая расширяет массив, и она устанавливается в этой функции. Итак, я не уверен, почему у него будет ошибка типа.

Таким образом, переменной с проблемой playercontrolledf присваивается значение false во всем массиве, как только она впервые инициализируется.

Заранее прошу прощения, если я неправильно разместил или нарушил какой-либо этикет, прошло некоторое время с тех пор, как я был в stack overflow, и я относительно новичок в javascript и stack overflow. Также, чтобы действительно увидеть, что делает код, вам нужно будет переключить его на полноэкранный режим.

Ошибка, которую я получаю в Chrome

 Uncaught TypeError: Cannot read property '127' of undefined
at gameTurn (main.js:76)
at endTurn (main.js:120)
at reposition (main.js:206)
at HTMLDocument.<anonymous> (main.js:233)
  

Вот мой код для игры

 /* Dunegon Valley by heromedel all rights reserved */
function gameloop() { // Entire Game contained withing function
  var mainArray = []; // most game data will be held withing the array
  var mapSizeX = 32; // sets the height of the rendered map and corresponding array coordinates
  var mapSizeY = 128; // sets the width
  var idPos = {
    x: 16,
    y: 64
  }; // currently used to set player location and check for collisions
  var rendFlr = 0; // sets which floor to render
  var curFlr = 0; // sets which floor is currently accepting input 
  var maxlayout = 10; // sets the number of floors to generate
  var curTurnX = 0;
  var curTurnY = 0;
  var gameState = 0;


  var tile = { // lists charcters used for rendered tiles and objects
    player: "☺",
    bunny: "b",
    rabbit: "r",
    empty: ".",
    wall: "#",
    oak: "♠",
    maple: "♣",
    grass: "‚",
    tallgrass: "„",
    water: "≈"

  };

  function getRndInteger(min, max) { // returns random number from min to max number appears to not function predictably if min and max are the same number
    return Math.floor(Math.random() * (max - min   1))   min;
  }

  function nl() { // Creates a new line in the rendered text
    GameScreen.innerText  = "n";
  }

  function gameTurn(cx, cy) { // progresses through each tile checking if its player controlled or not using the while statement in end turn
    if (mainArray[cx][cy]['playercontrolledf'   curFlr] === "true") {
      render(rendFlr);
      mainArray[cx][cy]['entTurnf'   curFlr] = "true";
      gameState = 1;
    }

    if (mainArray[cx][cy]['playercontrolledf'   curFlr] != "true") { // call functions for non player controlled tiles
      //mainArray[cx][cy]['entTurnf'   curFlr] = "true";

      if (mainArray[cx][cy]['entityf'   curFlr] === "bunny") {

        //alert("Bunny Turn" );
        mainArray[cx][cy]['entityf'   curFlr] = "rabbit" // to show that each bunny is getting selected this line changes the bunnny into a rabbit


      }

    }

    // progress to next turn / tile
    if (curTurnX < mapSizeX) {
      curTurnX  ;
    }

    if (curTurnX === mapSizeX) {
      if (curTurnY < mapSizeY) {
        curTurnX = 0;
        curTurnY  ;
      }

      if (curTurnX === mapSizeX) {
        if (curTurnY === mapSizeY) {
          alert("worked"); // why does this never trigger
          curTurnX = 0;
          curTurnY = 0;
        }
      }


    }
  }

  function endTurn() {
    while (gameState === 0) {
      gameTurn(curTurnX, curTurnY);
      //alert("Turn "  (curTurnX   curTurnY));
      //render(rendFlr);
    }
  }

  function initMap(mapSizeX, mapSizeY) { // expands and populates the array
    for (var i = 0; i < mapSizeX; i  ) {
      mainArray.push([]) // I belive this is only expaning it 2 dimesionaly and matching the height

      for (var j = 0; j < mapSizeY; j  ) {
        for (var k = 0; k < maxlayout; k  ) {
          const obj = mainArray[i][j] || {}; // creates on object to alter and add back into the main array
          obj['tilef'   k] = tile.empty;
          obj['terrainf'   k] = "empty";
          obj['solidf'   k] = "false";
          obj['entityf'   k] = "none";
          obj['playercontrolledf'   k] = "false";
          obj['entTurnf'   k] = "false";
          obj['finished'   k] = "false";
          mainArray[i][j] = obj;

          if (k > 0) {
            if (j == 0 || // wraps the underground floor 1 in walls
              j == mapSizeY - 1 ||
              i == 0 ||
              i == mapSizeX - 1) {
              mainArray[i][j]['terrainf'   k] = "wall";
              mainArray[i][j]['solidf'   k] = "Wall";
            }
          }

        }

        //else{                                 // unneeded as the above for j is already creating empties
        //mainArray[i][j].terrain = "empty";
        //mainArray[i][j].solid = "false";
        //}
      }
    }
  }


  function randAdd(odds, feature, solid, flr, type) { // A chance to add named feature and solid type
    for (var i = 0; i < mapSizeX; i  ) {
      for (var j = 0; j < mapSizeY; j  ) {
        if (mainArray[i][j][type   'f'   flr] === "empty" || mainArray[i][j][type   'f'   flr] === "none") {
          roll = getRndInteger(1, odds);
          if (roll === odds) {
            mainArray[i][j][type   'f'   flr] = feature;
            mainArray[i][j]['solidf'   flr] = solid;
          }
        }
      }
    }
  }


  function genMaps() { // Inside this function each line uses randAdd to randomly add a terrain type to a specified floor 
    randAdd(200, "wall", "solid rock", 0, 'terrain');
    randAdd(100, "oak", "a tree", 0, 'terrain'); //  (odds,terrain,solid,floor,type) 
    randAdd(100, "maple", "a tree", 0, 'terrain');
    randAdd(2, "grass", "False", 0, 'terrain');
    randAdd(2, "tallgrass", "False", 0, 'terrain');
    randAdd(200, "bunny", "false", 0, 'entity');
    randAdd(3, "wall", "solid rock", 1, 'terrain');
    randAdd(2, "wall", "solid rock", 2, 'terrain');
    randAdd(1, "wall", "solid rock", 3, 'terrain');
    randAdd(1, "wall", "solid rock", 4, 'terrain');
    randAdd(1, "wall", "solid rock", 5, 'terrain');
    randAdd(1, "water", "false", 8, 'terrain');
    randAdd(1, "water", "false", 9, 'terrain');
  }



  function tileSelect() {
    for (var i = 0; i < mapSizeX; i  ) {
      for (var j = 0; j < mapSizeY; j  ) {

        if (mainArray[i][j]['entityf'   rendFlr] === "none") {
          mainArray[i][j]['tilef'   rendFlr] = tile[mainArray[i][j]['terrainf'   rendFlr]];
        } else {
          mainArray[i][j]['tilef'   rendFlr] = tile[mainArray[i][j]['entityf'   rendFlr]]
        }

      }
    }
  }

  function render(flr) { // displays the array tiles to the browser
    GameScreen.innerText = mainArray.map(arr => arr.map(cell => cell['tilef'   flr]).join("")).join("n");
    nl();
    nl();
  }


  function reposition(xChange, yChange, strA) { // checks if target position is not blocked and if not moves the player
    if (mainArray[idPos.x   xChange][idPos.y   yChange]['solidf'   curFlr] === "false" ||
      mainArray[idPos.x   xChange][idPos.y   yChange]['solidf'   curFlr] === "False" ||
      mainArray[idPos.x   xChange][idPos.y   yChange]['solidf'   curFlr] === "") {
      idPos.x = idPos.x   xChange;
      idPos.y = idPos.y   yChange;
      mainArray[idPos.x][idPos.y]['entityf'   curFlr] = "player";
      mainArray[idPos.x - xChange][idPos.y - yChange]['entityf'   curFlr] = "none";
      GameLog.innerText = "You take a step to the "   strA
    } else {
      GameLog.innerText = "You can not enter "   mainArray[idPos.x   xChange][idPos.y   yChange]['solidf'   curFlr];
    }
    mainArray[idPos.x][idPos.y]['terrainf'   curFlr] != "empty" ?
      GameLog.innerText  = "n There is "   mainArray[idPos.x][idPos.y]['terrainf'   curFlr]   " in this spot" :
      GameLog.innerText  = "n There is nothing in this spot";
    GameLog.innerText  = "n n Elevation "   (curFlr * 50 * -1);

    tileSelect();
    render(rendFlr);
    gameState = 0;
    endTurn();
  }



  //Startup
  initMap(32, 128);
  genMaps();
  mainArray[idPos.x][idPos.y]['entityf'   curFlr] = "player";
  mainArray[idPos.x][idPos.y]['playercontrolledf'   curFlr] = "true";
  //First Render
  tileSelect();
  render(rendFlr);





  document.addEventListener('keydown', function(event) {
    if (event.keyCode === 38) { // up arrow
      reposition(-1, 0, "North");
      //alert(curTurnX);
    }
    if (event.keyCode === 40) { // down arrow
      reposition(1, 0, "South");
    }
    if (event.keyCode === 37) { // left arrow
      reposition(0, -1, "West");
    }
    if (event.keyCode === 39) { // right arrow
      reposition(0, 1, "East");
    }
    if (event.keyCode === 190) { // period
      if (rendFlr < maxlayout - 1) {
        mainArray[idPos.x][idPos.y]['entityf'   (curFlr   1)] = "player";
        mainArray[idPos.x][idPos.y]['entityf'   (curFlr)] = "none";
        curFlr  ;
        rendFlr  ;
        GameLog.innerText = "You descened. n n Elevation "   (curFlr * 50 * -1);
      }
      tileSelect();
      render(rendFlr);
    }
    if (event.keyCode === 188) { // comma
      if (rendFlr > 0) {
        mainArray[idPos.x][idPos.y]['entityf'   (curFlr - 1)] = "player";
        mainArray[idPos.x][idPos.y]['entityf'   (curFlr)] = "none";
        curFlr--;
        rendFlr--;
        GameLog.innerText = "You ascened. n n Elevation "   (curFlr * 50 * -1);
      }
      tileSelect();
      render(rendFlr);
    }
    //alert(event.keyCode);
  });
}



gameloop();  
 /* Dunegon Valley by heromedel all rights reserved */

.info {
  color: #7d7d7d;
  font-family: Lucida Console;
}

.info span {
  color: #ABABAB;
  font-family: Lucida Console;
  font-size: 0.5em;
}

#GameScreen {
  color: #000000;
  font-family: Lucida Console;
  font-weight: italic;
  margin-left: auto;
  margin-right: auto;
}

#GameLog {
  color: #000000;
  font-family: Lucida Console;
}  
 <!DOCTYPE html>
<!-- Dunegon Valley by heromedel all rights reserved -->
<html>

<head>
  <link rel="stylesheet" href="styles.css">
  <meta charset="utf-8">
  <title>Dungeon Valley</title>
</head>

<body>
  <br>
  <p class="info">Dungeon Valley.<br>
    <span class="">
    Taming the Borderlands.<br> v0.011 By heromedel.
  </span>
  </p>
  <span id="GameScreen"></span>
  <section id="GameLog">Arrow Keys to move.<br></section>
  <script src="main.js"></script>
</body>

</html>  

Комментарии:

1. Проблема в том cy == 128 , что длина mainArray[cx]

2. Я думаю, что словоблудие TypeError сбивает вас с толку — проблема в том, что mainArray[cx][cy] появляется as undefined , поэтому, когда он пытается выполнить mainArray[cx][cy]['playercontrolledf' curFlr] , он выдает эту ошибку, потому что он оценивает to undefined['playercontrolledf' curFlr] .

Ответ №1:

Проблема в том, что curTurnY он слишком большой. Этот код:

       if (curTurnY < mapSizeY) {
        curTurnX = 0;
        curTurnY  ;
      }
  

позволяет ему стать слишком высоким. Максимальное значение curTurnY должно быть 127 . Но когда значение уже 127 есть, этот код увеличит его до 128 , которое находится за пределами массива. Измените условие на:

       if (curTurnY < mapSizeY-1) {
        curTurnX = 0;
        curTurnY  ;
      }
  

Проверьте все другие ваши условия на наличие подобных ошибок.

Комментарии:

1. Спасибо за ответ, я понимаю, что вы говорите, просматривая размер массива или карты, я попал в точку, где данные не определены, верно? Я удивлен, что следующий оператор if улавливает его до того, как он сможет перейти. Я не думал, что curTurnY может быть максимальным без того, чтобы curTurnX также был максимальным. Но имеет смысл иметь меры предосторожности для предотвращения переполнения. как ни странно, когда я вношу это изменение, сообщение об ошибке изменяется на неперехваченный TypeError: Не удается прочитать свойство ‘127’ из undefined, которое звучит как относящееся к тому же размеру карты. Я не уверен, та ли это проблема или другая.

2. Я также подумал, что делать то же самое для curTurnX, что вы предложили для Y, имело бы смысл, но, похоже, это просто замораживает игру после ввода ввода. Я постараюсь продолжить изучение этой проблемы с переходом на ограничение и аналогичные условия.

3. Вы исправили все места, где вы увеличиваете и уменьшаете X и Y?