如何实现双玩家创建共用模态框并限制标记互斥?
Tic-Tac-Toe玩家创建模态框的互斥标记实现方案
我正在为Odin Project开发Tic-Tac-Toe游戏,现有两个Enter Player按钮,点击后希望打开同一个模态框,分别输入两个玩家的参数并保存。需求是:当一个玩家选择X作为标记后,另一个玩家无法选择X,只能选O,请问该怎么实现?
现有代码
HTML
<body> <header> TIC-TAC-TOE</header> <section id="large-container"> <article class="Players" id="player1"> Player1 <button id="player1-btn"> Enter Player </button> </article> <div class="container"> <div class="item"><button id="cell0">0</button></div> <div class="item"><button id="cell1">1</button></div> <div class="item"><button id="cell2">2</button></div> <div class="item"><button id="cell3">3</button></div> <div class="item"><button id="cell4">4</button></div> <div class="item"><button id="cell5">5</button></div> <div class="item"><button id="cell6">6</button></div> <div class="item"><button id="cell7">7</button></div> <div class="item"><button id="cell8">8</button></div> </div> <article class="Players" id="player2"> Player2 <button id="player2-btn"> Enter Player </button> </article> <dialog class="PlayerDialog"> <form> <p> <label for="playerName">What is the Player's Name</label> <input type="text" id="PName" name="PName"> <label for="playerMarker">What is the Players marker? <select id="markerSelect"> <option value="X" id="X" name="Marker">X</option> <option value="O" id="O" name="Marker">O</option> </select> </label> </p> <button value="cancel" formmethod="dialog">Cancel</button> <button id="Confirm" value="default">Confirm</button> </form> </dialog> </section> <script src="Main3.js"></script> </body>
注:已修正原代码中ID重复的问题(原article和button共享同一ID,棋盘按钮ID也重复),避免DOM选择逻辑出错。
原JS代码
const playerCreationButtons = document.querySelectorAll(".Players > button") const playerCreation = document.querySelector(".PlayerDialog") const PlayerDisplay = document.querySelector("article.Players") const confirmBtn = document.querySelector("#Confirm") const playerName = document.getElementById("#PName") // 此处多了#,属于选择错误 const playerMarkerX = document.getElementById("X") playerCreationButtons.forEach((button)=>{ button.addEventListener("click", ()=>{ /// (Some code here to alter the modal for each player before it's shown)/// playerCreation.showModal() console.log(`${button.id}`) }) })
实现方案
核心思路:用变量记录已被选择的标记,打开模态框时根据已选状态禁用对应选项;同时跟踪当前编辑的玩家ID,确认后保存信息并更新标记状态。
修改后的JS代码如下:
// 获取DOM元素 const playerCreationButtons = document.querySelectorAll(".Players > button"); const playerCreationDialog = document.querySelector(".PlayerDialog"); const confirmBtn = document.querySelector("#Confirm"); const playerNameInput = document.getElementById("PName"); // 修正ID选择错误 const markerSelect = document.getElementById("markerSelect"); const xOption = document.getElementById("X"); const oOption = document.getElementById("O"); // 存储玩家信息和已选标记 const players = { player1: { name: "Player1", marker: null }, player2: { name: "Player2", marker: null } }; let currentEditingPlayer = null; // 记录当前正在编辑的玩家ID // 玩家按钮点击事件:初始化模态框并打开 playerCreationButtons.forEach((button) => { button.addEventListener("click", () => { // 从按钮ID提取当前编辑的玩家标识 currentEditingPlayer = button.id.replace("-btn", ""); const targetPlayer = players[currentEditingPlayer]; // 初始化输入框:填充已有玩家名称 playerNameInput.value = targetPlayer.name; // 根据已选标记设置选项禁用状态 const usedMarker = players.player1.marker || players.player2.marker; if (usedMarker) { // 禁用已被选择的标记,强制选中剩余标记 if (usedMarker === "X") { xOption.disabled = true; markerSelect.value = "O"; } else { oOption.disabled = true; markerSelect.value = "X"; } } else { // 无标记被选中时,恢复所有选项可用 xOption.disabled = false; oOption.disabled = false; markerSelect.value = "X"; // 默认选中X } playerCreationDialog.showModal(); }); }); // 确认按钮事件:保存玩家信息 confirmBtn.addEventListener("click", (e) => { e.preventDefault(); // 阻止表单默认提交行为 if (!currentEditingPlayer) return; // 获取输入值,无输入时使用默认名称 const name = playerNameInput.value.trim() || `Player${currentEditingPlayer.slice(-1)}`; const marker = markerSelect.value; // 保存玩家信息到对象 players[currentEditingPlayer] = { name, marker }; // 更新页面上的玩家名称显示 document.getElementById(currentEditingPlayer).textContent = name; // 关闭模态框并重置输入 playerCreationDialog.close(); playerNameInput.value = ""; }); // 模态框关闭事件:重置编辑状态 playerCreationDialog.addEventListener("close", () => { currentEditingPlayer = null; playerNameInput.value = ""; // 恢复所有标记选项可用(支持重新编辑玩家信息) xOption.disabled = false; oOption.disabled = false; });
关键逻辑说明
- 标记互斥控制:打开模态框时检查另一个玩家的标记,若已有玩家选择X,则禁用X选项并强制当前玩家选O,反之亦然。
- 玩家状态跟踪:用
currentEditingPlayer变量记录当前编辑对象,确保信息保存到对应玩家的存储空间。 - 用户体验优化:打开模态框时自动填充已有玩家名称,取消操作后重置输入状态。
- ID规范修正:原代码中重复ID会导致DOM选择异常,已统一修改为唯一ID(如
player1、player1-btn)。
内容的提问来源于stack exchange,提问作者El0din Ruh
相关产品推荐
相关产品推荐

