我无法从数组中删除特定元素

问题描述

<table>
                <tbody>
                    <tr>
                        <td><button class="btn-in"></button></td>
                        <td><button class="btn-in"></button></td>
                        <td><button class="btn-in"></button></td>
                    </tr>
                    <tr>
                        <td><button class="btn-in"></button></td>
                        <td><button class="btn-in"></button></td>
                        <td><button class="btn-in"></button></td>
                    </tr>
                    <tr>
                        <td><button class="btn-in"></button></td>
                        <td><button class="btn-in"></button></td>
                        <td><button class="btn-in"></button></td>
                    </tr>
                </tbody>
            </table>

我为所有按钮创建了数组

var btnIns = document.querySelectorAll(".btn-in");

然后我写了这个

var arrForPcTurns = [...btnIns];

所以 btnIns 和 arrForPcTurns 必须具有相同的值

然后我尝试从 arrForPcTurns 数组中删除特定元素

btnIns.forEach(obj => {
    // obj.addEventListener("click",function () {
    //     if (counter % 2 != 0) {
    //         sign = player;
    //         turn.textContent = "PC Turn";
    //     } else {
    //         sign = PC;
    //         turn.textContent = "Your Turn";
    //     }

    //     this.textContent = sign;
    //     counter++;

    //     if (obj != "") {
    //         this.style.cursor = "not-allowed";
    //         this.disabled = true;
    //     }

    //     if (counter == 10) {
    //         setTimeout(function () {
    //             reloadBtn.classList.remove("display-none");
    //             alert("Draw");
    //         },400);
    //     }

    //     checkWinProbablity();
        arrForPcTurns.splice(arrForPcTurns.indexOf(this));
    });
});

但单击它会从数组中删除所有 9 个元素 我该怎么办?

解决方法

这就是拼接的工作原理
让 myArray= [1,2,3,4,5];
让删除数组 = myArray.splice(0,3);
以下语句从第一个元素开始删除 myArray 的三个元素。
myArray 现在包含两个元素。 // [4,5]

splice(第一个要删除的item的位置,要删除的item个数)

  var btnIns = document.querySelectorAll(".btn-in");
  var arrForPcTurns = [...btnIns];
        console.log(arrForPcTurns);
 btnIns.forEach(obj => {
    obj.addEventListener("click",function () {
        arrForPcTurns.splice(arrForPcTurns.indexOf(this,1));
       console.log(arrForPcTurns);
       })
    });
<table>
                <tbody>
                    <tr>
                        <td><button class="btn-in"></button></td>
                        <td><button class="btn-in"></button></td>
                        <td><button class="btn-in"></button></td>
                    </tr>
                    <tr>
                        <td><button class="btn-in"></button></td>
                        <td><button class="btn-in"></button></td>
                        <td><button class="btn-in"></button></td>
                    </tr>
                    <tr>
                        <td><button class="btn-in"></button></td>
                        <td><button class="btn-in"></button></td>
                        <td><button class="btn-in"></button></td>
                    </tr>
                </tbody>
            </table>

,

如果您正在设计井字游戏,则需要跟踪当前的 turndone 状态。您可以抓取矩阵并抓取每个按钮(单元格)的玩家数据,以确定该单元格是否可用。

在玩家决定标记的位置后,您可以让AI玩家分析当前棋盘并进行移动。

这是查找第一个可用单元格的基本扫描:

const handleAI = (game,player) => {
   updateInfo(`Player ${player},is thinking...`,game);
   lock = true;
   setTimeout(() => {
     const cell = analyzeMatrix(stateMatrix());
     lock = false;
     triggerEvent(cell,'click');
   },cpuWait);
};

您可以在此函数中添加一些逻辑,通过在做出选择之前寻找模式来改进 AI 的决策。

演示

const find = (selector,parent = document) => parent.querySelector(selector);
const findAll = (selector,parent = document) => parent.querySelectorAll(selector);
const findParent = (selector,parent) => parent.closest(selector);

const triggerEvent = (el,eventName,data={}) => {
  let event;
  if (window.CustomEvent && typeof window.CustomEvent === 'function') {
    event = new CustomEvent(eventName,{ detail: data });
  } else {
    event = document.createEvent('CustomEvent');
    event.initCustomEvent(eventName,true,data );
  }
  el.dispatchEvent(event);
};

const addEvents = (el,events) => Object.entries(events)
  .forEach(([type,listener]) => el.addEventListener(type,listener));

const players = ['O','X'];

let
  turn = 0,done = false,lock = false;

const main = () => {
  findAll('.cell').forEach(btn => addEvents(btn,{
    'click': handleClick,'mouseenter': handleMouseEnter,'mouseleave': handleMouseLeave
  }));

  addEvents(find('.new-game'),{
    'click': handleReset
  });

  initialize(find('.tic-tac-toe'));
};

const currentPlayer = () => players[turn % players.length];

const stateMatrix = (tbody) =>
  [...findAll('tr',tbody)].map(tr =>
    [...findAll('td',tr)].map(td =>
      find('button',td)));

const markCell = (cell,player) => {
  cell.textContent = player;
  cell.dataset.player = player;
};

const initialize = (game) => {
  turn = 0;
  done = false
  cpuEnabled = true,cpuWait = 1000;

  const table = game.querySelector('table');

  findAll('button',table).forEach(btn => {
    btn.classList.remove('win');
    btn.textContent = '';
    delete btn.dataset.player;
  });

  promptPlayer(game);
};

const promptPlayer = (game) => {
  const player = currentPlayer();

  if (cpuEnabled && player === 'X') {
    handleAI(game,player);
  } else {
    updateInfo(`Player ${player},it's your turn.`,game);
  }
};

const handleAI = (game,cpuWait);
};

// Business logic here...
const analyzeMatrix = (matrix) => {
  for (let row = 0; row < matrix.length; row++) {
    for (let col = 0; col < matrix.length; col++) {
      const cell = matrix[row][col];
      if (cell.dataset.player == null) {
        return cell;
      }
    }
  }
  return null;
};

const handleClick = e => {
  const
    btn = e.target,game = findParent('.tic-tac-toe',btn);

  if (!done && !lock && btn.dataset.player == null) {
    const player = currentPlayer();
    markCell(btn,player);
    btn.textContent = player;
    btn.dataset.player = player;

    const result = checkWin(player,btn);

    if (result) {
      establishWin(result);
      displayWinCondition(game,result);
      done = true;
    } else {
      turn++;
      promptPlayer(game);
    }
  }
};

const establishWin = (result) => {
  switch (result.type) {
    case 'row':
      highlightRow(result.value,result.matrix);
      break;
    case 'column':
      highlightColumn(result.value,result.matrix);
      break;
    case 'diagonal':
      highlightDiagonal(result.value,result.matrix);
      break;
    case 'draw':
      break;
  }
};

const displayWinCondition = (game,result) => {
  if (result.type === 'draw') {
    updateInfo('Draw!',game);
  } else {
    updateInfo(`Player ${result.player} wins!`,game);
  }
};

// Check winning conditions

const checkWin = (player,btn) => {
  const matrix = stateMatrix(btn.closest('td').closest('tr').closest('tbody'));
  let result;

  result = checkWinRows(player,matrix);
  if (result) return result;

  result = checkWinCols(player,matrix);
  if (result) return result;

  result = checkWinDiagonals(player,matrix);
  if (result) return result;

  if (turn >= matrix.length ** 2 - 1) {
    return {
      type: 'draw'
    };
  }

  return null;
}

const checkWinRows = (player,matrix) => {
  for (let row = 0; row < matrix.length; row++) {
    if (matrix[row].every(col => col.dataset.player === player)) {
      return {
        player,matrix,type: 'row',value: row
      };
    }
  }
  return null;
}

const checkWinCols = (player,matrix) => {
  for (let col = 0; col < matrix.length; col++) {
    const values = [];
    for (let row = 0; row < matrix.length; row++) {
      values.push(matrix[row][col].dataset.player);
    }
    if (values.every(col => col === player)) {
      return {
        player,type: 'column',value: col
      };
    }
  }
  return null;
}

const checkWinDiagonals = (player,matrix) => {
  const
    valuesPositive = [],valuesNegative = [];
  for (let col = 0; col < matrix.length; col++) {
    for (let row = 0; row < matrix.length; row++) {
      if (row === col) {
        valuesPositive.push(matrix[row][col].dataset.player);
      }
      if (row === matrix.length - 1 - col) {
        valuesNegative.push(matrix[row][col].dataset.player);
      }
    }
  }
  if (valuesPositive.every(col => col === player)) {
    return {
      player,type: 'diagonal',value: +1
    };
  }
  if (valuesNegative.every(col => col === player)) {
    return {
      player,value: -1
    };
  }
  return null;
}

// Highlight wining sequence

const highlightRow = (index,matrix) => {
  for (let row = 0; row < matrix.length; row++) {
    if (row === index) {
      for (let col = 0; col < matrix[row].length; col++) {
        matrix[row][col].classList.add('win');
      }
    }
  }
};

const highlightColumn = (index,matrix) => {
  for (let row = 0; row < matrix.length; row++) {
    for (let col = 0; col < matrix[row].length; col++) {
      if (col === index) {
        matrix[row][col].classList.add('win');
      }
    }
  }
};

const highlightDiagonal = (index,matrix) => {
  for (let row = 0; row < matrix.length; row++) {
    for (let col = 0; col < matrix[row].length; col++) {
      if (
        (index === +1 && row === col) ||
        (index === -1 && row === matrix.length - 1 - col)
      ) {
        matrix[row][col].classList.add('win');
      }
    }
  }
};

// Handlers

const handleMouseEnter = e => {
  const btn = e.target;
  btn.classList.add('hover');
  if (done || btn.dataset.player != null) {
    btn.classList.add('taken');
  }
};

const handleMouseLeave = e => {
  const btn = e.target;
  btn.classList.remove('hover','taken');
};

const updateInfo = (text,game) => {
  game = game || find('.tic-tac-toe');
  const info = find('.game-info',game);
  info.textContent = text;
};

const handleReset = e => {
  initialize(findParent('.tic-tac-toe',e.target));
};

main();
html,body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  background: #222;
}

body {
  display: flex;
}

.game {
  display: flex;
  justify-content: center;
  align-items: center;
  flex: 1;
}

.tic-tac-toe {
  display: grid;
  grid-auto-flow: row;
  grid-row-gap: 0.667em;
  justify-content: center;
  align-items: center;
  border: thin solid #666;
  padding: 1em;
  background: #444;
  color: #EEE;
}

.tic-tac-toe>table,.tic-tac-toe tr,.tic-tac-toe td {
  margin: 0;
  padding: 0;
}

.tic-tac-toe>table {
  display: flex;
  margin: 0 auto;
}

.tic-tac-toe tbody {
  display: grid;
  grid-auto-flow: row;
  grid-row-gap: 0.25em;
  flex: 1;
}

.tic-tac-toe tr {
  display: grid;
  grid-auto-flow: column;
  grid-column-gap: 0.25em;
  flex: 1;
}

.tic-tac-toe td {
  display: flex;
  margin: 0;
  padding: 0;
  width: 2em;
  height: 2em;
}

.tic-tac-toe .cell {
  font-size: 1em;
  background: #555;
  border: none;
  text-align: center;
  flex: 1;
}

.tic-tac-toe .cell.hover {
  cursor: pointer;
  background: #777
}

.tic-tac-toe .cell.hover.taken {
  cursor: not-allowed;
  background: #644
}

.tic-tac-toe .cell.win {
  background: #484;
}

.tic-tac-toe .game-info {
  text-align: center;
  font-size: smaller;
}

.tic-tac-toe .new-game {
  margin: 0 auto;
  width: 8em;
  height: 2em;
  font-size: smaller;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" rel="stylesheet" />
<div class="game">
  <div class="tic-tac-toe">
    <table>
      <tbody>
        <tr>
          <td><button class="cell"></button></td>
          <td><button class="cell"></button></td>
          <td><button class="cell"></button></td>
        </tr>
        <tr>
          <td><button class="cell"></button></td>
          <td><button class="cell"></button></td>
          <td><button class="cell"></button></td>
        </tr>
        <tr>
          <td><button class="cell"></button></td>
          <td><button class="cell"></button></td>
          <td><button class="cell"></button></td>
        </tr>
      </tbody>
    </table>
    <div class="game-info"></div>
    <button class="new-game">New Game</button>
  </div>
</div>