#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]
появляется asundefined
, поэтому, когда он пытается выполнитьmainArray[cx][cy]['playercontrolledf' curFlr]
, он выдает эту ошибку, потому что он оценивает toundefined['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?