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

JavaScript石头剪刀布游戏:选择展示与胜负渲染实现方案问询

石头剪刀布JS功能实现方案

两种动态渲染方式的选择结论

优先选创建DOM节点后追加元素的方案,比拼接innerHTML更适合你的场景,原因如下:

  • 你已经在SELECTIONS数组里存储了对应选项的icon DOM引用,直接克隆节点追加不需要重复写img的src、alt属性,减少冗余代码
  • 动态添加类名时直接操作DOM的classListAPI,不需要在字符串里做复杂的类名拼接,避免出现漏空格、属性写错的低级bug
  • 不会破坏原有选择按钮上的图标元素(直接移动原有DOM会导致按钮上的图标消失,克隆节点不存在这个问题)
  • 不存在innerHTML拼接带来的XSS风险,后续要给结果图标加自定义属性、交互事件时,操作DOM节点比改字符串灵活太多

两种方式在你这个小规模渲染场景下性能没有明显差异,但DOM追加方案的可维护性、出错率都远优于innerHTML拼接,是最优选择。

现有代码的前置问题修复

你的原有代码有3个会导致功能异常的bug,需要先修正:

  1. SELECTIONS中剪刀选项的beats属性配置错误,原代码写的是赢剪刀,实际应该赢布
  2. addSelectionReult函数名拼写错误(少了s,正确为addSelectionResult),且函数内部无法访问makeSelection作用域下的yourWinner、computerWinner变量,需要调整传参
  3. 直接引用原有按钮的icon节点会导致原按钮图标丢失,需要做深克隆处理

完整可运行实现代码

const selectionButtons = document.querySelectorAll('[data-selection]')
const finalColumn = document.querySelector('[data-final-column]')

// 修复剪刀的胜负逻辑配置
const SELECTIONS = [
  {
    name: 'rock',
    icon: document.querySelector('#uRock'),
    beats: 'scissors'
  },
  {
    name: 'paper',
    icon: document.querySelector('#uPaper'),
    beats: 'rock'
  },
  {
    name: 'scissors',
    icon: document.querySelector('#uScissors'),
    beats: 'paper'
  }
]

selectionButtons.forEach(selectionButton => {
  selectionButton.addEventListener('click', () =>{
    const selectionName = selectionButton.dataset.selection
    const selection = SELECTIONS.find(selection => selection.name === selectionName)
    makeSelection(selection)
  })
})

function makeSelection(selection) {
  const computerSelection = randomSelection();
  const yourWinner = isWinner(selection, computerSelection)
  const computerWinner = isWinner(computerSelection, selection)
  
  // 按顺序先插入电脑选择(左侧)、再插入玩家选择(右侧),传入归属方参数方便加类名
  addSelectionResult(computerSelection, computerWinner, 'computer')
  addSelectionResult(selection, yourWinner, 'player')    
}

function addSelectionResult(selection, isCurrentWinner, side) {
  const div = document.createElement('div')
  div.classList.add('result-selection')

  // 深克隆原有图标节点,不影响按钮上的原图标
  const resultIcon = selection.icon.cloneNode(true)

  // 按照规则给图标加对应类名
  if (side === 'computer') {
    resultIcon.classList.add(isCurrentWinner ? 'winner' : 'computerLost')
  }
  if (side === 'player') {
    resultIcon.classList.add(isCurrentWinner ? 'winner' : 'playerLost')
  }

  // 追加图标到结果容器
  div.appendChild(resultIcon)
  finalColumn.after(div)
}

function isWinner(selection, opponentSelection){
  return selection.beats === opponentSelection.name
}

function randomSelection() {
  const randomIndex = Math.floor(Math.random() * SELECTIONS.length) 
  return SELECTIONS[randomIndex]
}

实现效果说明

代码运行后完全符合你的需求:

  • 点击选择按钮后自动获取对应选项的图标
  • 结果区按左电脑、右玩家的顺序展示双方选择
  • 类名完全匹配规则:电脑获胜则电脑图标加winner、玩家图标加playerLost;玩家获胜则玩家图标加winner、电脑图标加computerLost
  • 最终生成的DOM结构和你给出的参考HTML完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 18:01:04