JS Свойство класса «не определено», даже если оно кажется определенным - PullRequest
0 голосов
/ 04 августа 2020

Я новичок в JS, и я пытаюсь сделать игру TicTacToe с доской нестандартного размера, пытаясь узнать немного больше. Сначала я закодировал только версию 3x3 и начал создавать оттуда.

Как только я прошел точку, где у меня был введен нестандартный размер сетки сразу после загрузки страницы и рендеринга сетки, я начал получать то же самое проблема при попытке щелкнуть любую ячейку, чтобы попытаться воспроизвести ход.

«this.game_state [clicked_cell_i] is undefined».

Я попытался открыть F12 и проверяя, является ли массив game_state (который представляет собой 2-мерный массив строк, отслеживающих, какая ячейка воспроизводится, а какая нет), но когда я это делаю, все кажется нормальным, и массив распечатывается без проблем. (изображение демонстрирует распечатку массива game_state в сетке 4x4) https://i.stack.imgur.com/gV0pY.png

Я был бы очень признателен, если бы кто-нибудь объяснил мне, что происходит, или даже лучше - помогите мне это исправить. Спасибо :)

Код: https://jsfiddle.net/z8649pxL


class game {
    status_display;
    is_game_active;
    curr_player;
    game_state;

    constructor() {
        this.status_display = document.querySelector('.status');
        this.is_game_active = true;
        this.curr_player = "X";
        this.game_state = matrix(rows, rows, "");
    }

    cell_played(clicked_cell, clicked_cell_i, clicked_cell_j){
        this.game_state[clicked_cell_i][clicked_cell_j] = this.curr_player;
        clicked_cell.innerHTML = this.curr_player;
        if(this.curr_player === "X"){
            document.getElementById((i*rows)+j).style.backgroundColor = "#ff6600";
        } else if(this.curr_player === "O"){
            document.getElementById((i*rows)+j).style.backgroundColor = "#33ccff";
        }
    }

    cell_click(clicked_cellEvent){
        debugger
        const clicked_cell = clicked_cellEvent.target;
        let clicked_cell_i = parseInt(clicked_cell.getAttribute('i'));
        let clicked_cell_j = parseInt(clicked_cell.getAttribute('j'));
        if(this.game_state[clicked_cell_i][clicked_cell_j] !== "" || !this.is_game_active) {
            return;
        }
        this.cell_played(clicked_cell, clicked_cell_i, clicked_cell_j);
        this.res_validation();
    }
};

let ex_game = new game();

function create_grid() {
    document.getElementById('hidestart').style.display = "none";
    var Container = document.getElementsByClassName("grid");
    Container.innerHTML = '';
    
    rows = prompt("n?");
    let i = 0, j = 0;
      
    document.documentElement.style.setProperty("--columns-row", rows);
    for (i = 0; i < rows ; i++) {
        for(j = 0; j < rows; j++){
            var div = document.createElement("div");
            div.className = "cell";
            div.id = (i*rows)+j;
            div.setAttribute("cell-index", (i*rows)+j);
            div.setAttribute("i", i);
            div.setAttribute("j", j);
            let wrapper = document.getElementsByClassName("grid");
            wrapper[0].appendChild(div);
        }
    }
    document.querySelectorAll('.cell').forEach(cell => cell.addEventListener('click', (e) => {
        ex_game.cell_click(e);
        e.stopPropagation();
    }));
    document.getElementById('hidestart').style.display = "block";
}

function matrix(rows, cols, defaultValue){
    var arr = [];
    // Creates all lines:
    for(var i=0; i < rows; i++){
        // Creates an empty line
        arr.push([]);
        // Adds cols to the empty line:
        arr[i].push(new Array(cols));
        for(var j=0; j < cols; j++){
          // Initializes:
          arr[i][j] = defaultValue;
        }
    }
    return arr;
}```

1 Ответ

0 голосов
/ 04 августа 2020

Когда вы вызываете

new game()

, вызывается конструктор этого класса. И в этом конструкторе вы вызываете матрицу , которая требует значения строк. Но изначально класс не имеет никакого значения.

Таким образом, в этот момент состояние не инициализируется. Вот почему, когда вы используете массив, он становится неопределенным.

Итак, чтобы решить эту проблему, вы можете просто попытаться получить объект класса game после получения строк от пользователя и передать эти строки в аргументы при вызове конструктора класса.

let ex_game = new game(rows);

И затем с помощью этого аргумента вызовите матрицу функции.

Изменить:

Я посмотрел в ваш код. Ошибка в методе под названием cell_played . вы используете неизвестные ему i и j. Пожалуйста, замените свой код следующей строкой. Это разрешит вашу ошибку.

  cell_played(clicked_cell, clicked_cell_i, clicked_cell_j){
      this.game_state[clicked_cell_i][clicked_cell_j] = this.curr_player;
        clicked_cell.innerHTML = this.curr_player;
        if(this.curr_player === "X"){
            document.getElementById((clicked_cell_i*rows)+clicked_cell_j).style.backgroundColor = "#ff6600";
        } else if(this.curr_player === "O"){
        document.getElementById((clicked_cell_i*rows)+clicked_cell_j).style.backgroundColor = "#33ccff";
        }
    }

А также удалите параметр rows из конструктора и просто вызовите конструктор после получения количества строк от пользователя.

let ex_game

function create_grid() {
    /* document.getElementById('hidestart').style.display = "none" */
    var Container = document.getElementsByClassName("grid");
    Container.innerHTML = '';
    rows = prompt("n?");
    let i = 0, j = 0;
    ex_game= new game().........
...