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

斯诺克计分应用优化:代码精简与规则限制实现咨询

斯诺克计分应用优化与规则实现方案

嘿,我帮你梳理下怎么优化这段代码,同时实现斯诺克的核心计分规则——这俩问题其实可以结合起来解决,让代码既简洁易维护,又完全符合规则要求。

一、先把代码改得简洁流畅

你原来的代码重复了大量的元素选择和事件绑定逻辑,这完全可以用数据驱动的方式重构,把重复代码抽成统一的逻辑:

优化思路

  1. 用一个数组统一存储所有球的配置信息(类名、分值、初始数量),后续要加/改球的信息直接改数组就行,不用重复写代码
  2. 循环这个数组,一次性完成元素选择、事件绑定,减少冗余

基础优化后的代码

// 统一管理所有球的配置:类名、对应分值、初始数量
const ballConfigs = [
  { className: 'red', points: 1, count: 15 },
  { className: 'yellow', points: 2, count: 1 },
  { className: 'green', points: 3, count: 1 },
  { className: 'brown', points: 4, count: 1 },
  { className: 'blue', points: 5, count: 1 },
  { className: 'pink', points: 6, count: 1 },
  { className: 'black', points: 7, count: 1 }
];

const scoreElement = document.querySelector('.score');
let scoreVal = 0;
scoreElement.textContent = scoreVal;

// 循环绑定事件,统一处理击球逻辑
ballConfigs.forEach(config => {
  const ballElement = document.querySelector(`.${config.className}`);
  ballElement.addEventListener('click', () => {
    // 这里先预留规则判断的位置,后面再补
    scoreVal += config.points;
    scoreElement.textContent = scoreVal;
  });
});

这样一来,原来十几行的重复代码直接缩成了几行,可读性和维护性都提升了不少。

二、实现击球限制与147分规则约束

接下来要加入斯诺克的核心规则,我们需要几个状态变量来跟踪游戏的当前阶段,然后在点击事件里做规则判断:

需要跟踪的状态

  • remainingReds: 剩余红球数(初始15)
  • canPotColour: 是否允许击打彩球(初始false,开局必须先打红球)
  • clearedReds: 是否已经清完所有红球(初始false)
  • remainingColours: 红球清台后剩余的彩球集合(初始包含所有彩球)
  • 额外加个最高分检测:当分数达到147时,直接禁用所有球的点击

完整规则实现代码

// 统一管理所有球的配置:类名、对应分值、初始数量
const ballConfigs = [
  { className: 'red', points: 1, count: 15 },
  { className: 'yellow', points: 2, count: 1 },
  { className: 'green', points: 3, count: 1 },
  { className: 'brown', points: 4, count: 1 },
  { className: 'blue', points: 5, count: 1 },
  { className: 'pink', points: 6, count: 1 },
  { className: 'black', points: 7, count: 1 }
];

const scoreElement = document.querySelector('.score');
let scoreVal = 0;
scoreElement.textContent = scoreVal;

// 游戏状态变量,跟踪当前阶段
let remainingReds = 15;
let canPotColour = false;
let clearedReds = false;
const remainingColours = new Set(['yellow', 'green', 'brown', 'blue', 'pink', 'black']);

// 检查是否达到最高分147
const isMaxScoreReached = () => scoreVal === 147;

// 禁用所有球的点击,并给视觉反馈
const disableAllBalls = () => {
  ballConfigs.forEach(config => {
    const ball = document.querySelector(`.${config.className}`);
    ball.style.pointerEvents = 'none';
    ball.style.opacity = '0.5'; // 变灰标记已禁用
  });
};

// 统一处理击球逻辑
const handleBallClick = (config) => {
  // 先判断是否已经达到最高分,直接返回
  if (isMaxScoreReached()) return;

  // 分阶段处理游戏逻辑
  if (!clearedReds) {
    // 红球未清台阶段:红球→彩球→红球循环
    if (config.className === 'red') {
      // 击打红球的条件:还有剩余红球,且当前不能打彩球(即刚打完彩球后要回到打红球)
      if (remainingReds > 0 && !canPotColour) {
        scoreVal += config.points;
        remainingReds--;
        canPotColour = true; // 打完红球后允许打彩球
        
        // 如果红球打完了,切换到彩球阶段
        if (remainingReds === 0) {
          clearedReds = true;
        }
        
        scoreElement.textContent = scoreVal;
        // 这里可以加红球剩余数量的显示,比如页面上加个.red-count元素:
        // document.querySelector('.red-count').textContent = remainingReds;
      }
    } else {
      // 击打彩球的条件:刚打完红球(canPotColour为true),且彩球还在台上
      if (canPotColour && config.count > 0) {
        scoreVal += config.points;
        canPotColour = false; // 打完彩球后必须回到打红球(如果还有红球)
        scoreElement.textContent = scoreVal;
      }
    }
  } else {
    // 红球已清台阶段:只能打剩余的彩球,打一个少一个
    if (remainingColours.has(config.className)) {
      scoreVal += config.points;
      remainingColours.delete(config.className);
      scoreElement.textContent = scoreVal;
      
      // 如果最后一颗黑球被击落,直接禁用所有球
      if (config.className === 'black' && remainingColours.size === 0) {
        disableAllBalls();
      }
    }
  }

  // 每次击球后检查是否达到最高分,达到则禁用所有球
  if (isMaxScoreReached()) {
    disableAllBalls();
  }
};

// 循环绑定所有球的点击事件
ballConfigs.forEach(config => {
  const ballElement = document.querySelector(`.${config.className}`);
  ballElement.addEventListener('click', () => handleBallClick(config));
});

规则说明

  1. 击球顺序约束:开局必须先打红球,打完红球才能打任意彩球,打完彩球回到打红球,直到15颗红球全部清台
  2. 彩球阶段约束:红球清台后,只能打剩余的彩球,每颗彩球只能打一次,最后一颗黑球打完后所有球禁用
  3. 最高分约束:只要分数达到147,立即禁用所有球的点击,不管当前处于哪个阶段

这样改造后,代码既简洁,又完全符合你描述的斯诺克计分规则啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:06:37