You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RestartClicked()触发异常:井字棋重启后Enter键行为异常求助

井字棋方向键控制重启后Enter键异常问题

我正在做学校的井字棋项目,鼠标操作版本完全正常,现在改成方向键控制。页面首次加载/刷新时功能正常,但点击Restart按钮重置所有值后,Enter键会随机重置红框位置,同时数组每次只填充一个值且重复操作。尝试了多种调试方法没解决,求找出原因。

方向键处理函数

function keyDown(e) {
    console.log(e.keyCode);

    let prevBox = boxes[prevActive];
    prevBox.style.backgroundColor = "";


    switch (e.keyCode) {
        //right arrow key
        case 39:
            xPos = xPos < 2 ? xPos + 1 : xPos = 0;

            break;
        //left arrow key
        case 37:
            xPos = xPos > 0 ? xPos - 1 : xPos = 2;

            break;
        // down arrow key
        case 40:
            yPos = yPos < 2 ? yPos + 1 : yPos = 0;
 
            break;
        // up arrow key
        case 38:
            yPos = yPos > 0 ? yPos - 1 : yPos = 0;
            break;

    }
    console.log([xPos, yPos]);
    
    active = yPos * 3 + xPos;
    redBox = boxes[active].style.backgroundColor = "red";
    
    console.log(active);
    
    prevActive = active;
    prevBox = boxes[prevActive];

    if (e.keyCode == 13) {

        if(!spaces[active]) {
            spaces[active] = currentPlayer;
            boxes[active].innerText = currentPlayer;

            currentPlayer = currentPlayer == letterX ? letterO : letterX;

            if (winner() !== false) {
                playerText = `${currentPlayer} has won!`
        
                let winCombo = winner();
        
                console.log(winCombo);
            }
        }
    }
}

Restart按钮函数

restartBtn.addEventListener('click', restartClicked);

function restartClicked() {
    spaces.fill(null);

    boxes.forEach( box => {
        box.innerText = '';

        box.style.backgroundColor = "";
    });

    boxes[0].style.backgroundColor = "red";
    active = 0;
    prevActive = 0;

    xPos = 0; yPos = 0;

    currentPlayer = letterX
}

startGame();

HTML文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container">
        <h1 id="tictactoe">Tic Tac Toe</h1>
        <button id="restartBtn">Restart</button>

        <div id="gameTable">
            <div class="box" id="0"></div>
            <div class="box" id="1"></div>
            <div class="box" id="2"></div>
            <div class="box" id="3"></div>
            <div class="box" id="4"></div>
            <div class="box" id="5"></div>
            <div class="box" id="6"></div>
            <div class="box" id="7"></div>
            <div class="box" id="8"></div>
        </div>

        <h1 id="currentPlayerTxt"></h1>

        <script src="index2.js"></script>
    </div>
</body>
</html>

CSS文件

@font-face {
  font-family: 'Nunito';
  src: url('Fonts/Nunito-Regular.ttf');
}


html, body {
  height: 100%;
  font-family: 'Nunito';
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0;
  background-color: #c2415d;
}

  
.boxContainer {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 400px;
  height: 450px;
  background-color: lightgray;
  margin: 10px;
  border-radius: 50px;
}

.boxBtn {
  font-size: 50px;
  background-color:rgb(255, 0, 0);
  line-height: 60px;
  width: 60%;
  font-size: 24px;
  user-select: none;
  color: rgb(255, 255, 255);
  text-align: center;
  border-radius: 50px;
}

a {
  text-decoration: none;
  color: inherit
}

#tictactoe {
  color: #ffffff;
}

#gameTable {
  width: 450px;
  display: flex;
  flex-wrap: wrap;
  margin-top: 40px;
  background-color: #ffffff;
}

.box { 
  height: 150px;
  width: 150px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 120px;
  outline: 2px solid;
  border-bottom: 2px solid;
  user-select: none;
}

.box:nth-child(6) ~ .box {
  border-bottom: none;
}

期望结果

重启后的行为与页面首次加载时一致,红框位置正常更新,Enter键不会出现异常重置的情况。


问题原因及修复

核心问题

  1. Enter键触发了红框重置逻辑:当前keyDown函数中,不管按下的是方向键还是Enter键,都会先执行清除上一个红框、重新计算位置并设置红框的代码。但Enter键并不改变xPos/yPos,这会导致代码错误地重复设置当前active位置,加上Restart后变量状态的微小偏差,引发异常。
  2. Restart按钮获取焦点导致按键冲突:点击Restart按钮后,按钮会获得焦点,此时按下Enter会触发按钮的点击事件(相当于再次Restart),这是另一个隐性异常源。

修复方案

1. 拆分方向键与Enter键逻辑

修改keyDown函数,仅在按下方向键时执行红框移动代码,Enter键单独处理落子:

function keyDown(e) {
    console.log(e.keyCode);

    // 仅方向键触发红框移动
    if ([37, 38, 39, 40].includes(e.keyCode)) {
        let prevBox = boxes[prevActive];
        prevBox.style.backgroundColor = "";

        switch (e.keyCode) {
            case 39: // 右箭头
                xPos = xPos < 2 ? xPos + 1 : 0;
                break;
            case 37: // 左箭头
                xPos = xPos > 0 ? xPos - 1 : 2;
                break;
            case 40: // 下箭头
                yPos = yPos < 2 ? yPos + 1 : 0;
                break;
            case 38: // 上箭头
                yPos = yPos > 0 ? yPos - 1 : 0;
                break;
        }

        console.log([xPos, yPos]);
        active = yPos * 3 + xPos;
        boxes[active].style.backgroundColor = "red";
        console.log(active);
        prevActive = active;
    }

    // Enter键单独处理落子
    if (e.keyCode === 13) {
        if (!spaces[active]) {
            spaces[active] = currentPlayer;
            boxes[active].innerText = currentPlayer;

            currentPlayer = currentPlayer === letterX ? letterO : letterX;

            if (winner() !== false) {
                playerText = `${currentPlayer} has won!`
                let winCombo = winner();
                console.log(winCombo);
            }
        }
    }
}

2. 消除Restart按钮焦点冲突

在restartClicked函数末尾添加代码,将焦点从按钮移开:

function restartClicked() {
    spaces.fill(null);

    boxes.forEach( box => {
        box.innerText = '';
        box.style.backgroundColor = "";
    });

    boxes[0].style.backgroundColor = "red";
    active = 0;
    prevActive = 0;
    xPos = 0; yPos = 0;
    currentPlayer = letterX;

    // 移除按钮焦点,避免Enter触发重复Restart
    restartBtn.blur();
    // 可选:将焦点移到游戏容器,确保按键事件正常监听
    document.getElementById('gameTable').focus();
}

内容的提问来源于stack exchange,提问作者Slam4

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 00:17:03