基于JavaScript开发一个有趣的分组抽签小程序

 更新时间:2023年05月30日 08:35:27   作者:𝑺𝒉𝒊𝒉𝑯𝒔𝒊𝒏𝒈  
在团队合作开发中,经常需要将团队成员分组,来完成各自的任务,而抽签的方式自然是最公平、最简单的方法之一,所以本文就来开发一个有趣的分组抽签小程序吧

前言

今天我要和大家分享一个非常有用的js算法:分组抽签。在团队合作开发中,经常需要将团队成员分组,来完成各自的任务。而抽签的方式自然是最公平、最简单的方法之一。

需求分析

在介绍具体的抽签算法之前,我们先来分析一下这个问题的需求。我们需要从团队成员列表中随机抽取若干人,并将这些人分配到不同的组中。那么,如何才能确保分组的公平性呢?

公平性的要求

首先,我们需要确保每个人只会被抽中一次,避免出现某个人被抽到多个组的情况。其次,我们需要尽可能地让每个组的人数相近,以确保各组的工作量基本相同。

算法设计思路

在满足上述需求的前提下,我们可以通过以下算法来进行分组抽签:

1.将团队成员列表随机排序。

2.根据分组的数量,计算每个组应该包含的人数,记为baseNum。

3.依次遍历团队成员列表,将每个人放入对应的组中。具体操作步骤如下:

  • 如果该人已经被分配了组,直接跳过。
  • 如果该人所在的组未满员,将其加入该组,并标记为已分组。
  • 如果该人所在的组已满员,寻找下一个未满员的组,将其加入该组,并标记为已分组。如果没有未满员的组,则随机选择一个非自己所在组的未满员组,将其加入该组,并标记为已分组。

通过以上阐述可知,核心的算法思路是要随机排序、尽量平均分组并避免同一人多次参与。现在我们开始着手编写这个算法。

开始编码

随机排序

为了实现随机排序,我们可以先将团队成员数组进行浅拷贝,然后使用Array.sort()方法来进行排序,代码如下:

function shuffle(array) {
  const arr = [...array]; // 进行浅拷贝
  for (let i = arr.length - 1; i > 0; i--) { // 遍历数组元素
    const j = Math.floor(Math.random() * (i + 1)); // 生成随机下标
    [arr[i], arr[j]] = [arr[j], arr[i]]; // 交换位置
  }
  return arr; // 返回排序后的数组
}

该方法接受一个数组作为参数,返回乱序排列之后的新数组。

尽可能平均分组

为了实现尽量平均分组,我们可以使用Math.ceil()方法来向上取整,保证每个组的人数不少于baseNum。代码如下:

const team = ['张三', '李四', '王五', '赵六', '钱七', '孙八']; // 假设有6名成员
const groupNum = 3; // 定义需要抽几组
const baseNum = Math.ceil(team.length / groupNum); // 计算每组包含的人数
console.log(baseNum); // 输出2

避免同一人多次参与

为了避免同一个人多次参与分组,我们需要给已经分配了组的成员打上已分组的标记,这样在后续循环中就可以跳过已经分配了组的成员。代码如下:

const team = ['张三', '李四', '王五', '赵六', '钱七', '孙八']; // 团队成员数组
const groupNum = 3; // 分组数
const baseNum = Math.ceil(team.length / groupNum); // 计算每组需要包含多少人
const shuffledTeam = shuffle(team); // 乱序排列团队成员 
let assignedCount = 0; // 计数器,记录已分配的人数
let groups = []; // 定义一个空数组,用来存放每个分组的成员
// 遍历随机排序后的团队成员列表,进行分组
shuffledTeam.forEach(member => {
  if (member.assigned) return; // 如果该成员已被分配,则跳过
  for (let i = 0; i < groupNum; i++) {
    const group = groups[i] || []; // 如果当前分组未定义,则将其初始值设为空数组
    if (group.length < baseNum && !group.includes(member)) { // 如果该分组未满员,并且该成员没有被分配到其他组内
      group.push(member); // 将该成员加入当前分组
      member.assigned = true; // 给该成员打上已分组标记
      assignedCount++; // 记录已分配人数
      groups[i] = group; // 将该分组重新赋值给原数组
      break; // 遍历下一个成员
    }
  }
});

在上述代码中,我们使用了一个名为assigned的属性作为已分组标记。每位成员在初始化时都未被分组,因此默认为undefined。当某位成员被分配到某个组内后,我们就会将其assigned属性设置为true,以避免重复分组。

上手练习

接下来让我们来进行一个简单的实现过程和实验,使大家更加深入理解如何实现一个前端抽签小程序。

HTML结构

首先,我们需要先创建一些基本的HTML结构,来让用户输入团队成员信息,并设定分组数量和按钮控制器:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>分组抽签小程序</title>
  <script src="main.js"></script>
</head>
<body>
  <h1>分组抽签小程序</h1>
  <form id="form">
    <div>
      <label for="members">团队成员:</label>
      <textarea id="members" name="members" placeholder="请用英文半角逗号分隔不同的成员"></textarea>
    </div>
    <div>
      <label for="groups">分组数量:</label>
      <input type="number" id="groups" name="groups" value="2" min="2">
    </div>
    <button type="submit">开始抽签</button>
  </form>
  <div id="result"></div>
</body>
</html>

JS代码

在JavaScript中,我们需要编写3个函数来实现这个小程序:一是获取关键DOM元素(getInputs),二是执行抽签操作并输出结果(drawLots),三是事件监听逻辑(handleSubmit)。代码如下:

// 获取form表单输入值的函数
function getInputs(form) {
  const members = form.members.value.trim().split(/[,\n]/).map(m => m.trim()).filter(m => m); // 转换成数组格式,并清理空格和空白行
  const groups = +form.groups.value; // 输入分组数量
  return { members, groups };
}
// 主要操作函数
function drawLots(members, groups) {
  const baseNum = Math.ceil(members.length / groups); // 计算每组包含多少成员
   const shuffledMembers = shuffle(members); // 将成员数组随机排序
  let assignedCount = 0; // 计数器,记录已分配的人数
  let result = ''; // 定义一个空字符串,用来存放抽签结果
  let groupsRes = []; // 定义一个空数组,用来存放每个分组的成员
  // 遍历随机排序后的成员列表,进行分组
  shuffledMembers.forEach(member => {
    if (member.assigned) return; // 如果该成员已被分配,则跳过
    for (let i = 0; i < groups; i++) {
      const group = groupsRes[i] || []; // 如果当前分组未定义,则将其初始值设为空数组
      if (group.length < baseNum && !group.includes(member)) { // 如果该分组未满员,并且该成员没有被分配到其他组内
        group.push(member); // 将该成员加入当前分组
        member.assigned = true; // 给该成员打上已分组标记
        assignedCount++; // 记录已分配人数
        groupsRes[i] = group; // 将该分组重新赋值给原数组
        break; // 遍历下一个成员
      }
    }
  });
  // 输出结果
  groupsRes.forEach((group, index) => {
    result += `<h3>第${index+1}组:</h3><ul>`;
    group.forEach(member => result += `<li>${member}</li>`);
    result += `</ul>`;
  });
  document.getElementById('result').innerHTML = result; // 修改DOM节点内容,将抽签结果展示给用户
}
// 监听表单提交事件
function handleSubmit(event) {
  event.preventDefault();
  const form = event.currentTarget;
  const { members, groups } = getInputs(form);
  if (members.length === 0) {
    alert('请输入团队成员!');
    return;
  }
  drawLots(members, groups);
}
document.getElementById('form').addEventListener('submit', handleSubmit); // 挂载监听函数

代码中包括了浅层的代码实现方法,只要牢记三个阶段内容,便可轻松完成这个小程序。

以上就是基于JavaScript开发一个有趣的分组抽签小程序的详细内容,更多关于JavaScript分组抽签程序的资料请关注脚本之家其它相关文章!

相关文章

  • javascript 子窗体父窗体相互传值方法

    javascript 子窗体父窗体相互传值方法

    javascript 子窗体父窗体相互传值方法,一般都是用window.open函数,下面脚本之家给出具体的代码。
    2010-05-05
  • JavaScript this 深入理解

    JavaScript this 深入理解

    一直以来,对于JavaScript 中的this的理解都是很模糊的, 特别是对函数进行apply 与 call 调用。这两个操作如果没有很好的理解 JavaScript中this的概念,会越搞越迷糊。
    2009-07-07
  • JS 中 reduce()方法使用小结

    JS 中 reduce()方法使用小结

    reduce是一个对数组累积操作的方法,使用时要加上 return 返回累积操作的数据,这样 prev 才能获取上一次执行的结果,否则是 undefined,这篇文章主要介绍了JS 中 reduce()方法及使用详解,需要的朋友可以参考下
    2023-12-12
  • 利用JS重写Cognos右键菜单的实现代码

    利用JS重写Cognos右键菜单的实现代码

    我写了一个利用JS禁用Cognos右键菜单,下面的JS可以实现重写Cognos的右键菜单。只要将下面的代码拷到一个HTML项里即可。
    2010-04-04
  • 利用js canvas实现五子棋游戏

    利用js canvas实现五子棋游戏

    这篇文章主要为大家详细介绍了利用js canvas实现五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-10-10
  • window.open打开新页面失效解决方案

    window.open打开新页面失效解决方案

    这篇文章主要给大家介绍了关于window.open打开新页面失效的解决方案,移动端和PC端全部通过window.open()来跳转页面窗口,文中给出了详细的解决方案,需要的朋友可以参考下
    2023-07-07
  • JS实现向表格行添加新单元格的方法

    JS实现向表格行添加新单元格的方法

    这篇文章主要介绍了JS实现向表格行添加新单元格的方法,涉及javascript针对表格进行动态操作的技巧,需要的朋友可以参考下
    2015-03-03
  • JS去掉第一个字符和最后一个字符的实现代码

    JS去掉第一个字符和最后一个字符的实现代码

    本篇文章主要是对JS去掉第一个字符和最后一个字符的实现代码进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-02-02
  • JS动态添加元素及绑定事件造成程序重复执行解决

    JS动态添加元素及绑定事件造成程序重复执行解决

    这篇文章主要给大家介绍了关于JS动态添加元素及绑定事件造成程序重复执行的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-12-12
  • 值得学习的JavaScript调试技巧分享

    值得学习的JavaScript调试技巧分享

    这篇文章主要给大家介绍了一些JavaScript调试技巧,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06

最新评论