Как связать входные данные из элемента 2D-массива с проверкой? - PullRequest
0 голосов
/ 01 февраля 2020

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

<script>
  let boxes = [
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""]
  ];

  function isValid(keyCode) {
    if ((keyCode >= 65 && keyCode <= 90) || (keyCode >= 97 && keyCode <= 122)) {
      return true;
    }
    return false;
  }
</script>
<main>
  <div class="root">
    {#each boxes as row, i}
    <div class="row">
      {#each row as column, j}
      <span class="column">
        <input
          class="col-input"
          type="text"
          bind:value="{boxes[i][j]}"
        />
      </span>
      {/each}
    </div>
    {/each}
  </div>
</main>

1 Ответ

1 голос
/ 02 февраля 2020

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

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

<script>
  let boxes = [
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""]
  ];

    function isValid(val, i, j) {
      if ((val.keyCode >= 65 && val.keyCode <= 90) || (val.keyCode >= 97 && val.keyCode <= 122)) {
        boxes[i][j] = val.key;
        return true;
      }
      return false;
    }

</script>

<main>
  <div class="root">
    {#each boxes as row, i}
    <div class="row">
      {#each row as column, j}
      <span class="column">
        <input
          class="col-input"
          type="text"
          bind:value="{boxes[i][j]}"
          on:keydown|preventDefault={e => isValid(e, i, j)}
        />
      </span>
      {/each}
    </div>
    {/each}
  </div>
</main>

Вот пример в REPL

РЕДАКТИРОВАТЬ: Если необходимо сохранить функциональность вкладок (при условии, что это не игра типа «укажи и щелкни»), необходимо будет добавить некоторые дополнительные функции, так как в этом случае warnDefault убивает клавишу вкладки.

Это можно сделать с помощью изменение привязки: значение для привязки: эту и все ссылки, которые могли бы изменить значение блоков, нужно будет заменить на боксы [i] [j] .value.

Я добавил некоторые дополнительные функции для обработки клавиш со стрелками и сохранить функцию клавиши табуляции, сохраняя фокус внутри сетки (обычно табуляция должна выпрыгивать из окна)

<script>
  let boxes = [
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""],
    ["", "", "", "", "", "", "", ""]
  ];

    function isValid(val, i, j) {
        const width = boxes[i].length, height = boxes.length, prevCol = j - 1, nextCol = j + 1, prevRow = i - 1, nextRow = i + 1, left = 37, up = 38, right = 39, down = 40, tab = 9;

        // Preserve tab functionality, 
        // loop to first input of next row 
        // when end of row is reached or to 
        // first row and column when end of 
        // matrix is reached
        if (val.keyCode == tab) {
            nextCol != width? boxes[i][nextCol].focus() : i != height - 1? boxes[nextRow][0].focus() : boxes[0][0].focus();
            return;
        }

        // Loop around single row with right and left arrows
        if (val.keyCode == right) {
            nextCol != width? boxes[i][nextCol].focus() : boxes[i][0].focus();
            return;
        }
        if (val.keyCode == left) {
            j != 0? boxes[i][prevCol].focus() : boxes[i][width - 1].focus();
            return;
        }

        // loop around single column with up and down arrows
        if (val.keyCode == up) {
            i != 0?  boxes[prevRow][j].focus() : boxes[height - 1][j].focus();
            return;
        }

        if (val.keyCode == down) {
            i != height - 1?  boxes[nextRow][j].focus() : boxes[0][j].focus();
            return;
        }


        if ((val.keyCode >= 65 && val.keyCode <= 90) || (val.keyCode >= 97 && val.keyCode <= 122)) {
          boxes[i][j].value = val.key;
          return true;
        }
        return false;
    }

</script>

<main>
  <div class="root">
    {#each boxes as row, i}
    <div class="row">
      {#each row as column, j}
      <span class="column">
        <input
          class="col-input"
          type="text"
          bind:this="{boxes[i][j]}"
          on:keydown|preventDefault={e => isValid(e, i, j)}
        />
      </span>
      {/each}
    </div>
    {/each}
  </div>
</main>

Вот ссылка к этому примеру REPL

...