Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Избежать выхода за пределы массива (https://javascript.ru/forum/misc/80171-izbezhat-vykhoda-za-predely-massiva.html)

Retro_1477 05.05.2020 18:58

Избежать выхода за пределы массива
 
Делаю игру крестики и нолики, под пользовательские размеры, не могу реализовать выигрыш по вертикале и диагонали.

field - хранит двумерный массив.
gameTurn - ход игрока.
1 игрок = 1
2 игрок = -1
пустая ячейка = 0

const checkWin = (field) =>{
    for (let i = 0; i < field.length; i++) {
      for(let j = 0; j < field[i].length; j++){
        if(gameTurn === field[i][j] && 
          (field[i][j] === field[i][j+1] && field[i][j] === field[i][j+2]))
             alert('Ты победил!')
      }
    }
  }

рони 05.05.2020 19:24

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

рони 05.05.2020 19:40

Retro_1477,
https://javascript.ru/forum/showthre...153#post498153

od0201 08.05.2020 00:23

Я б на твоем месте прислушался к Рони, но раз ты так начал, то здесь продолжение

const checkWin = (field) =>{
    for (let i = 0; i < field.length; i++) {
      for(let j = 0; j < field[i].length; j++){
        if(gameTurn === field[i][j] &&
          (field[i][j+1] !==undefined && gameTurn === field[i][j+1] && 
            field[i][j+2] !==undefined && gameTurn === field[i][j+2]) ||
          (field[i+1][j] !==undefined && gameTurn === field[i+1][j] && 
            field[i+2][j] !==undefined && gameTurn === field[i+2][j]) ||
          (field[i+1][j+1] !==undefined && gameTurn === field[i+1][j+1] && 
            field[i+2][j+2] !==undefined && gameTurn === field[i+2][j+2]) ||
          (field[i-1][j-1] !==undefined && gameTurn === field[i-1][j-1] && 
            field[i-2][j-2] !==undefined && gameTurn === field[i-2][j-2])
        )
          alert('Ты победил!')
      }
    }
  }


но лучше делать отдельные циклы по всем четырем направлениям (горизонт, вертикаль, диагонали в разных направлениях) и в for "не добегать" до края на 2 клетки. И тогда у нас можно не проверять на существования элемента и меньше операций будет совершено


const checkWin = (field) =>{
    gameTurn=1;
    for (let i = 0; i < field.length; i++) {
      for(let j = 0; j < field[i].length-2; j++){
        if(gameTurn === field[i][j] &&
          (gameTurn === field[i][j+1] && gameTurn === field[i][j+2])
        )
          alert('Ты победил! 1')
      }
    }
    for (let i = 0; i < field.length-2; i++) {
      for(let j = 0; j < field[i].length; j++){
        if(gameTurn === field[i][j] &&
          (gameTurn === field[i+1][j] && gameTurn === field[i+2][j])
        )
          alert('Ты победил! 2')
      }
    }
    for (let i = 0; i < field.length-2; i++) {
      for(let j = 0; j < field[i].length-2; j++){
        if(gameTurn === field[i][j] &&
          (gameTurn === field[i+1][j+1] && gameTurn === field[i+2][j+2])
        )
          alert('Ты победил! 3')
      }
    }
    for (let i = 0; i < field.length-2; i++) {
      for(let j = 2; j < field[i].length; j++){
        if(gameTurn === field[i][j] &&
          (gameTurn === field[i+1][j-1] && gameTurn === field[i+2][j-2])
        )
          alert('Ты победил! 4')
      }
    }
  }

  checkWin([[,1,1],[,1,],[1,,]])

рони 08.05.2020 00:30

od0201,
вопрос был про j+1 и т.д. , про то что таких ячеек нет!!!

od0201 08.05.2020 00:42

Цитата:

Сообщение от рони (Сообщение 523955)
od0201,
вопрос был про j+1 и т.д. , про то что таких ячеек нет!!!

исправил, тему не дочитал

рони 08.05.2020 00:42

od0201,
маловато undefined, код не рабочий.

рони 08.05.2020 00:46

od0201,
ок.

рони 08.05.2020 00:59

крестики нолики на поле любой величины
 
при игре на поле более 3х3, и размером выгрыша 3 ячейки подряд, тот кто ходит первым, он выигрывает, но если вы дадите шанс компьютеру ...
:write: дело было вечером ...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
body{text-align: center;}
.game > div{
    outline: 1px solid black;
    height: 0;
    background-color: #FFFFFF;
    transition: 1s;
    padding-bottom: 100%;

}
.game > div.red{
    background-color: #FF0000;
    color: #FFFFFF;
}
.game {
    display:  grid;
    grid-template-columns: repeat(var(--colls), 1fr);
    grid-column-gap: 0px;
    grid-row-gap: 0px;
    width: 400px;
    margin: 30px auto;
    line-height: calc(400px/var(--colls));
    font-size: calc(400px/var(--colls));
}
h3{
    height: 2em;
}

</style>
</head>
<body>
<h3>Step X</h3>
<div class="game"></div>

</body>
<script>
let length = 3 + Math.trunc(Math.random() * 7);
let rows = 3 + Math.trunc(Math.random() * 5);
let parent = document.querySelector('.game');
parent.style.setProperty('--colls', length);
let div = document.createElement('div');
for (var i = 0; i < length * rows; i++) {
    parent.append(div.cloneNode())
};
let boxs = parent.querySelectorAll('div');
let value = 'O';
const checkWin = (cells, length, value, free) => {
    const arrWin = [
        [-length, length],
        [-1, 1],
        [-length - 1, length + 1],
        [-length + 1, length - 1]
    ];
    const arrContinue = [0, length - 1, cells.length - length, cells.length - 1];
    let temp = [];
    for (let i = 0; i < cells.length; i++) {
        if (arrContinue.includes(i)) continue;
        let cell = cells[i];
        if (cell !== value && !free) continue;
        let check = arrWin.slice(0);
        if (i < arrContinue[1] || i > arrContinue[2]) check = [[-1, 1]];
        if (i % length === 0 || i % length === length - 1) check = [[-length, length]];
        check = check.map(([a, b]) => [a + i, b + i]).filter(([a, b]) => {
        a = cells[a];
        b = cells[b];
        let c = [a, b, cell].filter(a => a === value);
        return free ? (!a || !b || !cell) && c.length === 2 : (a === value && b === value)
        })
        if (check.length) {
            temp = temp.concat(Array.from(check, a => (a.splice(1, 0, i), a)));
        }
      }
     if(free && temp.length) {
              temp = temp.flat().filter(a => !cells[a]);
              let set = new Set();
              set.add(...temp);
              temp = [...set]
            }

    return temp;
}
let out = document.querySelector('h3');
let combo = { 1 : 10, 2 : 25, 3 : 50, 4 : 80, 5 : 100, 6 : 150};
let compute;
const gameClick = ({target}) => {
    if (compute) return;
    if (target.textContent) return;
    let title = `Step ${value}`;
    value = value == 'X' ? 'O' : 'X';
    target.textContent = value;
    let cells = Array.from(boxs, ({textContent}) => textContent);
    let win = checkWin(cells, length, value);
    if (win.length) {
        let set = new Set();
        win.forEach(a => a.forEach(i => {
        set.add(i);
        boxs[i].classList.add('red')
        }));
        parent.removeEventListener('click', gameClick);
        title = `Win ${value}!!!<br> Total : ${set.size} &times; ${combo[win.length]} = ${set.size * combo[win.length]}!!!`
    };
    out.innerHTML = title;
    win.length || value == 'X' && autoClick(value);
}
const randomItem = arr => arr[Math.trunc(arr.length * Math.random())]
const autoClick = (val) => {
    compute = true;
    let oldTitle = out.innerHTML;
    out.innerHTML = `... examination of options for ${val}`
    let cells = Array.from(boxs, ({
        textContent
    }) => textContent);
    val = val == 'X' ? 'O' : 'X';
    out.innerHTML = `... examination of options for ${val}`
    let win = checkWin(cells, length, val, true);
    let box;
    if (!win.length) {
        val = val == 'X' ? 'O' : 'X';
        win = checkWin(cells, length, val, true);
    };
    if (win.length) {
        let i = randomItem(win);
        box = boxs[i]
    } else {
        win = [...boxs].filter(({
            textContent
        }) => !textContent)
        box = randomItem(win);
    };

    if (box) {
        window.setTimeout(() => {
            compute = false;
            gameClick({
                target: box
            })
        }, 800)
    } else out.innerHTML = `End!`
}

parent.addEventListener('click', gameClick)
</script>
</html>

Retro_1477 10.05.2020 10:37

Этот ответ мне более понятен, но я понимаю какое это говнокодище.:D


Часовой пояс GMT +3, время: 06:51.