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

JavaScript井字棋问题:如何显示当前玩家及获胜者昵称

解决本地多人井字棋游戏的玩家昵称显示问题

我是JavaScript初学者,开发了一款本地多人Tic Tac Toe(井字棋)游戏,需求为从两个输入框获取玩家昵称,并在游戏中显示当前回合玩家昵称及获胜者昵称。目前能在控制台访问存储在p1和p2对象中的值(p1.name、p1.val、p2.name、p2.val),但不清楚如何在setTurnIndicator函数中调用这些值,也不知道如何在判断获胜时展示获胜者昵称。尝试使用localStorage存储并读取这些昵称,但未成功。

原有代码

// Multiplayer Options
let ps = document.getElementById('btn');
let c1 = document.getElementsByName('characP1');
let c2 = document.getElementsByName('characP2');
let msg = document.getElementById('message');
let char1;
let char2;

function Player(name, val) {
    this.name = name;
    this.val = val;
}
for (i = 0; i < c1.length; i++) {
    c1[i].addEventListener('change', function () {
        if (this.checked) {
            this.value == 'X' ? c2[1].checked = true : c2[0].checked = true;
            char1 = this.value;
            char2 = this.value == 'X' ? 'O' : 'X';
        }
    });
}
for (i = 0; i < c2.length; i++) {
    c2[i].addEventListener('change', function () {
        if (this.checked) {
            this.value == 'X' ? c1[1].checked = true : c1[0].checked = true;
            char2 = this.value
            char1 = this.value == 'X' ? 'O' : 'X';
        }
    });
}
ps.addEventListener('click', function () {
    let player1 = document.getElementById('p1').value;
    let player2 = document.getElementById('p2').value;
    p1 = new Player(player1, char1);
    p2 = new Player(player2, char2);
    if (p1.name && p1.val && p2.name && p2.val) {
        msg.innerHTML = p1.name + ' : ' + p1.val + '<br />' + p2.name + ' : ' + p2.val;
    } else {
        msg.innerHTML = 'Please fill all input fields';
    }
    // return playerOne, playerTwo;
    // window.localStorage.setItem('nume1', p1.name);
    // window.localStorage.setItem('nume2', p2.name);
});

// Hide Players Options
function hidePlayersOptions() {
    let x = document.getElementById("mpOptions");
    if (x.style.display === "none") {
      x.style.display = "block";
    } else {
      x.style.display = "none";
    }
    let y = document.getElementById("game");
    if (y.style.display === "none") {
        y.style.display = "block";
      } else {
        y.style.display = "block";
      }
  }

// Multiplayer Game Logic
/* Tic-Tac-Toe functions */
let TicTacToe = {
    /* initialize the Tic-Tac-Toe variables */
    init: function() {
        this.symbols = [`X`, `O`];
        this.name = [window.localStorage.getItem('nume1'), window.localStorage.getItem('nume2')];
        this.squares = Array.from(document.querySelectorAll(".square"));
        this.turnIndicator = document.querySelector(".turnIndicator");
        this.button = document.querySelector(".newGame");
        this.board = document.querySelector(".board");
        // square positions in which you can get 3-in-a-row
        this.winningSets = [
            // horizontal sets
            [0,1,2], [3,4,5], [6,7,8],
            // vertical sets
            [0,3,6], [1,4,7], [2,5,8],
            // diagonal sets
            [0,4,8], [2,4,6]
        ];
        // add click event listeners to squares and button
        this.addEventListeners();
        // reset the game
        this.newGame();
    },

    // add click event listeners to squares and button
    addEventListeners: function() {
        let ttt = this;
        // for each square, add a click listener which will call "play()"
        this.squares.forEach(function(x) {
            x.addEventListener("click",function() {
                ttt.play(this);
            }, false)
        })
        // when the new game button is clicked, call "newGame()"
        this.button.addEventListener("click", function() {
            ttt.newGame();
        }, false);
    },

    // reset the game
    newGame: function() {
        // set player to first player (X)
        this.activePlayer = 0;
        // reset the game over variable
        this.gameOver = false;
        // remove all X and O classes from every square
        this.squares.forEach(function (x) {
            x.classList.remove(TicTacToe.symbols[0]);
            x.classList.remove(TicTacToe.symbols[1]);
        })
        // remove gameOver class from board if it exists
        this.board.classList.remove("gameOver");
        // set the turn indicator (X's turn)
        this.setTurnIndicator();
    },

    // set the turn indicator to indicate whose turn it is
    setTurnIndicator: function() {
        this.turnIndicator.innerText = this.symbols[this.name[this.activePlayer]] + "'s turn."
        // this.turnIndicator.innerText = this.symbols["window.localStorage.getItem('nume1')"] + "'s turn."
        // this.turnIndicator.innerText = this.symbols[window.localStorage.getItem('nume1')[this.activePlayer]];
    },

    play: function(el) {
        // make sure that the square is not filled
        if (!this.gameOver && el.classList.length == 1) {
            // set the contents to your player's symbol
            el.classList.add(this.symbols[this.activePlayer]);
            // check if you won
            if (this.checkWin()) {
                // set the game text to display the winner
                this.turnIndicator.innerText = this.symbols[this.activePlayer] + " wins!";
                // call the game over function
                this.endGame();
            }
            // check if there is a draw
            else if (this.checkDraw()) {
                // set the game text to say it is a draw
                this.turnIndicator.innerText = "It's a draw!";
                // call the game over function
                this.endGame();
            }
            // go to the next player's turn
            else {
                // change the turn (0 -> 1 or 1 -> 0)
                this.activePlayer = 1 - this.activePlayer;
                // set the turn indicator text
                this.setTurnIndicator();
            }
        }
    },

    // check if current player won
    checkWin: function() {
        let ttt = this;
        // if for any of the winning sets,
        // every square in the set is filled with
        // the current player's symbol, return true
        // otherwise, return false
        return this.winningSets.some(function (x) {
            return x.every(function(i) {
                return Array.from(ttt.squares[i].classList).indexOf(ttt.symbols[ttt.activePlayer]) > -1;
            })
        })
    },

    // check if there is a draw
    checkDraw: function() {
        // return true if every square
        // has more than 1 class (is filled)
        // otherwise, return false
        return this.squares.every(function (x) {
            return x.classList.length > 1;
        })
    },

    // set the game over variable and board class when the game ends
    endGame: function() {
        this.gameOver = true;
        this.board.classList.add("gameOver");
    }
}

// call the init() function of TicTacToe when the page loads
TicTacToe.init();

解决方案

1. 核心问题

TicTacToe对象无法直接访问全局作用域的p1、p2变量,且页面初始化时localStorage还未存储玩家昵称,导致读取失败。

2. 具体修改步骤

(1)让TicTacToe持有玩家信息

在按钮点击事件中,创建玩家对象后,直接将玩家数据传递给TicTacToe:

ps.addEventListener('click', function () {
    let player1 = document.getElementById('p1').value;
    let player2 = document.getElementById('p2').value;
    p1 = new Player(player1, char1);
    p2 = new Player(player2, char2);
    if (p1.name && p1.val && p2.name && p2.val) {
        msg.innerHTML = p1.name + ' : ' + p1.val + '<br />' + p2.name + ' : ' + p2.val;
        // 将玩家数组传入TicTacToe
        TicTacToe.players = [p1, p2];
        // 实时更新回合提示
        TicTacToe.setTurnIndicator();
    } else {
        msg.innerHTML = 'Please fill all input fields';
    }
});

同时修改TicTacToe的init方法,初始化players属性:

init: function() {
    this.symbols = [`X`, `O`];
    this.players = []; // 初始化玩家数组
    this.squares = Array.from(document.querySelectorAll(".square"));
    // ... 保留原有其他代码
}

(2)修改回合提示函数

更新setTurnIndicator,优先显示玩家昵称,无昵称时用符号兜底:

setTurnIndicator: function() {
    const currentPlayer = this.players[this.activePlayer];
    const displayText = currentPlayer ? `${currentPlayer.name}'s turn.` : `${this.symbols[this.activePlayer]}'s turn.`;
    this.turnIndicator.innerText = displayText;
}

(3)修改获胜提示

在play函数的获胜判断部分,替换为显示玩家昵称:

if (this.checkWin()) {
    const currentPlayer = this.players[this.activePlayer];
    const displayText = currentPlayer ? `${currentPlayer.name} wins!` : `${this.symbols[this.activePlayer]} wins!`;
    this.turnIndicator.innerText = displayText;
    this.endGame();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 11:40:38