JavaScript猜拳游戏是前端入门阶段非常经典的练手项目,基础的出拳判断实现后,完善计分系统和逻辑是提升项目完整度的关键步骤。很多初学者的版本会出现计分混乱、判断遗漏的情况,核心原因是没有设计清晰的计分结构和全面的判断规则。

计分系统的结构设计
计分系统需要记录三类数据:玩家胜利次数、电脑胜利次数、平局次数。我们可以使用一个对象来统一管理这些数据,避免分散定义变量导致的维护困难。
首先定义计分对象,初始化所有计数为0:
// 初始化计分系统
let score = {
playerWin: 0,
computerWin: 0,
draw: 0
};
每次游戏回合结束后,根据判断结果更新对应的计数即可。为了提升可维护性,我们可以封装一个更新计分的专用函数:
/**
* 更新计分数据
* @param {string} result 回合结果,可选值:playerWin/computerWin/draw
*/
function updateScore(result) {
if (score.hasOwnProperty(result)) {
score[result] += 1;
}
// 更新页面显示的计分元素
document.getElementById('player-score').innerText = score.playerWin;
document.getElementById('computer-score').innerText = score.computerWin;
document.getElementById('draw-score').innerText = score.draw;
}
完整的出拳判断逻辑
猜拳的核心逻辑是判断玩家出拳和电脑出拳的胜负关系,常见的出拳选项为石头、剪刀、布,我们需要覆盖所有9种组合情况,避免判断遗漏。
首先实现电脑随机出拳的函数,保证每个出拳选项的概率均等:
/**
* 生成电脑随机出拳
* @returns {string} 出拳结果,可选值:rock/scissors/paper
*/
function getComputerChoice() {
const choices = ['rock', 'scissors', 'paper'];
// 生成0-2的随机整数作为索引
const randomIndex = Math.floor(Math.random() * 3);
return choices[randomIndex];
}
接下来实现核心的胜负判断函数,这里采用对象映射的方式替代多层if判断,逻辑更清晰:
/**
* 判断单回合胜负结果
* @param {string} playerChoice 玩家出拳
* @param {string} computerChoice 电脑出拳
* @returns {string} 回合结果
*/
function judgeRound(playerChoice, computerChoice) {
// 平局判断
if (playerChoice === computerChoice) {
return 'draw';
}
// 胜负规则映射:key为玩家出拳_电脑出拳,value为结果
const ruleMap = {
'rock_scissors': 'playerWin',
'rock_paper': 'computerWin',
'scissors_rock': 'computerWin',
'scissors_paper': 'playerWin',
'paper_rock': 'playerWin',
'paper_scissors': 'computerWin'
};
const ruleKey = playerChoice + '_' + computerChoice;
return ruleMap[ruleKey] || 'draw';
}
逻辑边界情况处理
完善的游戏逻辑还需要处理一些边界情况,比如玩家未选择出拳就点击确认、重复点击导致计分异常等问题。
我们可以添加一个出拳状态标记,避免玩家未选择时触发判断:
let hasPlayerChoosed = false;
let currentPlayerChoice = '';
// 玩家选择出拳的点击事件
document.querySelectorAll('.choice-btn').forEach(btn => {
btn.addEventListener('click', function() {
currentPlayerChoice = this.getAttribute('data-choice');
hasPlayerChoosed = true;
// 高亮选中的出拳选项
document.querySelectorAll('.choice-btn').forEach(b => b.classList.remove('active'));
this.classList.add('active');
});
});
// 确认出拳的点击事件
document.getElementById('confirm-btn').addEventListener('click', function() {
if (!hasPlayerChoosed) {
alert('请先选择你的出拳');
return;
}
const computerChoice = getComputerChoice();
const roundResult = judgeRound(currentPlayerChoice, computerChoice);
updateScore(roundResult);
// 展示回合结果
showRoundResult(currentPlayerChoice, computerChoice, roundResult);
// 重置选择状态
hasPlayerChoosed = false;
currentPlayerChoice = '';
document.querySelectorAll('.choice-btn').forEach(b => b.classList.remove('active'));
});
计分重置功能实现
为了提升游戏体验,我们还需要添加计分重置功能,方便玩家重新开始游戏:
// 重置计分系统
document.getElementById('reset-btn').addEventListener('click', function() {
score = {
playerWin: 0,
computerWin: 0,
draw: 0
};
// 更新页面显示
document.getElementById('player-score').innerText = 0;
document.getElementById('computer-score').innerText = 0;
document.getElementById('draw-score').innerText = 0;
// 清空回合结果展示
document.getElementById('round-result').innerText = '';
});
完整示例整合
以下是整合了计分系统和完整逻辑的简化版完整代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>JavaScript猜拳游戏</title>
<style>
.choice-btn.active { background-color: #409eff; color: #fff; }
</style>
</head>
<body>
<div>
<p>玩家计分: <span id="player-score">0</span></p>
<p>电脑计分: <span id="computer-score">0</span></p>
<p>平局次数: <span id="draw-score">0</span></p>
</div>
<div>
<button class="choice-btn" data-choice="rock">石头</button>
<button class="choice-btn" data-choice="scissors">剪刀</button>
<button class="choice-btn" data-choice="paper">布</button>
</div>
<button id="confirm-btn">确认出拳</button>
<button id="reset-btn">重置计分</button>
<p id="round-result"></p>
<script>
let score = {
playerWin: 0,
computerWin: 0,
draw: 0
};
let hasPlayerChoosed = false;
let currentPlayerChoice = '';
function getComputerChoice() {
const choices = ['rock', 'scissors', 'paper'];
const randomIndex = Math.floor(Math.random() * 3);
return choices[randomIndex];
}
function judgeRound(playerChoice, computerChoice) {
if (playerChoice === computerChoice) return 'draw';
const ruleMap = {
'rock_scissors': 'playerWin',
'rock_paper': 'computerWin',
'scissors_rock': 'computerWin',
'scissors_paper': 'playerWin',
'paper_rock': 'playerWin',
'paper_scissors': 'computerWin'
};
const ruleKey = playerChoice + '_' + computerChoice;
return ruleMap[ruleKey] || 'draw';
}
function updateScore(result) {
if (score.hasOwnProperty(result)) {
score[result] += 1;
}
document.getElementById('player-score').innerText = score.playerWin;
document.getElementById('computer-score').innerText = score.computerWin;
document.getElementById('draw-score').innerText = score.draw;
}
function showRoundResult(player, computer, result) {
const resultMap = {
'playerWin': '你赢了',
'computerWin': '电脑赢了',
'draw': '平局'
};
const choiceMap = {
'rock': '石头',
'scissors': '剪刀',
'paper': '布'
};
document.getElementById('round-result').innerText =
'你出了' + choiceMap[player] + ',电脑出了' + choiceMap[computer] + ',' + resultMap[result];
}
document.querySelectorAll('.choice-btn').forEach(btn => {
btn.addEventListener('click', function() {
currentPlayerChoice = this.getAttribute('data-choice');
hasPlayerChoosed = true;
document.querySelectorAll('.choice-btn').forEach(b => b.classList.remove('active'));
this.classList.add('active');
});
});
document.getElementById('confirm-btn').addEventListener('click', function() {
if (!hasPlayerChoosed) {
alert('请先选择你的出拳');
return;
}
const computerChoice = getComputerChoice();
const roundResult = judgeRound(currentPlayerChoice, computerChoice);
updateScore(roundResult);
showRoundResult(currentPlayerChoice, computerChoice, roundResult);
hasPlayerChoosed = false;
currentPlayerChoice = '';
document.querySelectorAll('.choice-btn').forEach(b => b.classList.remove('active'));
});
document.getElementById('reset-btn').addEventListener('click', function() {
score = { playerWin: 0, computerWin: 0, draw: 0 };
document.getElementById('player-score').innerText = 0;
document.getElementById('computer-score').innerText = 0;
document.getElementById('draw-score').innerText = 0;
document.getElementById('round-result').innerText = '';
});
</script>
</body>
</html>
通过以上步骤,我们就可以实现一个计分准确、逻辑完整的JavaScript猜拳游戏,后续还可以根据需求扩展多回合制、历史记录等功能,进一步提升项目的丰富度。
JavaScript猜拳游戏计分系统游戏逻辑修改时间:2026-06-23 23:57:46