PHP Secret Santa 脚本:解决奇数用户配对问题

PHP Secret Santa 脚本:解决奇数用户配对问题

第一段引用上面的摘要:

本文旨在解决使用 php Zend 框架编写 Secret Santa 脚本时,当用户数量为奇数时出现的配对问题。我们将分析问题代码,找出导致最后一个用户重复出现的原因,并提供修复方案。此外,还将介绍一种更优雅的实现方式,避免出现“No Pair”的情况,确保所有用户都能参与到 Secret Santa 活动中。

问题分析

原代码在处理奇数用户时,由于递归调用 generateUsers 函数,导致在仅剩一个用户时,仍然会进入 if (count($users) === 1) 的判断分支,从而将该用户与 “No Pair” 重复配对。

解决方案

修改后的 generateUsers 方法,在递归调用之前增加一个判断条件,确保 newUsers 的数量大于 1,避免在只有一个用户时进行递归调用。

function generateUsers(array $defaultUsers, array $updatedUsers = []): bool {     $users = (!empty($updatedUsers)) ? $updatedUsers : $defaultUsers;      if (count($users) > 1) {         if ($this->matchedUsers !== count($this->startingUsers)) {             // Pick random user and match with current user. Reset array and repeat until 1 or no users left.             $randomUserIndex = rand(1, count($users) - 1);             $this->pairs[] = [$users[0], $users[$randomUserIndex]];             unset($users[$randomUserIndex]);             unset($users[0]);              // Remove pair from list so they can't be assigned again. Reset array for 0 based index $users[0]             $newUsers = array_values($users);             // Check that there are two or more users             if(count($newUsers) > 1){                 $this->generateUsers($this->startingUsers, $newUsers);             }             $this->matchedUsers += 2;         }     }      // If only one user remains can't allocate a Pair     if (count($users) === 1) {         $orderedUsers = array_values($users);         $this->pairs[] = [$orderedUsers[0], "No Pair"];          return true;     }      return true; }

代码解释:

  • 在递归调用 generateUsers 之前,添加了 if(count($newUsers) > 1) 的判断,只有当剩余用户数量大于 1 时,才进行递归调用。这避免了在只有一个用户时重复配对 “No Pair” 的情况。

更优雅的实现方式:循环配对

为了避免出现 “No Pair” 的情况,可以采用循环配对的方式,将所有用户链接成一个环,确保每个人都有礼物可收。

class Match {     protected $startingUsers = [         "User1",         "User2",         "User3",         "User4",         "User5",     ];      protected $pairs = [];      function getPairs(): array     {         $users = $this->startingUsers;         shuffle($users); // 打乱用户顺序          for ($i = 0; $i < count($users); $i++) {             $giver = $users[$i];             $receiver = $users[($i + 1) % count($users)]; // 使用模运算实现循环             $this->pairs[] = [$giver, $receiver];         }          return $this->pairs;     } }  $match = new Match();  foreach ($match->getPairs() as $pair) {     echo "$pair[0] gets $pair[1]";     echo "n"; }

代码解释:

  1. shuffle($users);: 首先使用 shuffle 函数打乱用户数组的顺序,确保配对的随机性。
  2. $receiver = $users[($i + 1) % count($users)];: 使用模运算 % 来计算接收者的索引。当 $i 为最后一个用户的索引时,($i + 1) % count($users) 的结果为 0,从而实现最后一个用户与第一个用户配对,形成循环。

优点:

  • 避免了 “No Pair” 的情况,确保所有用户都能参与。
  • 代码更简洁易懂。

总结

本文针对 PHP Secret Santa 脚本中奇数用户配对问题,提供了两种解决方案。第一种方案通过修改递归调用条件,避免了重复配对 “No Pair” 的情况。第二种方案则采用循环配对的方式,从根本上避免了 “No Pair” 的出现,是一种更优雅的实现方式。开发者可以根据实际需求选择合适的方案。在实际应用中,还可以增加邮件通知等功能,提升用户体验。

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享