|
@@ -2,6 +2,7 @@ package ludo
|
|
|
|
|
|
import (
|
|
|
"crypto/rand"
|
|
|
+ "encoding/binary"
|
|
|
"fmt"
|
|
|
"math/big"
|
|
|
"server/msg"
|
|
@@ -37,12 +38,50 @@ func getRandomItem[T any](slice []T) T {
|
|
|
}
|
|
|
|
|
|
// 随机获取一个人机名字
|
|
|
-func getRandomRobotName() string {
|
|
|
- n, err := rand.Int(rand.Reader, big.NewInt(100))
|
|
|
+func getRandomRobotName(existingNames []string) string {
|
|
|
+ allNames := []string{
|
|
|
+ "张三", "李四", "王五", "赵六",
|
|
|
+ "钱七", "孙八", "周九", "吴十",
|
|
|
+ }
|
|
|
+ return getRandomName(allNames, existingNames)
|
|
|
+}
|
|
|
+
|
|
|
+func getRandomName(allNames []string, existingNames []string) string {
|
|
|
+ // 1. 创建剩余名字的切片
|
|
|
+ remainingNames := make([]string, 0)
|
|
|
+
|
|
|
+ // 2. 构建已存在名字的映射(提高查找效率)
|
|
|
+ existingMap := make(map[string]bool)
|
|
|
+ for _, name := range existingNames {
|
|
|
+ existingMap[name] = true
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 筛选出未使用的名字
|
|
|
+ for _, name := range allNames {
|
|
|
+ if !existingMap[name] {
|
|
|
+ remainingNames = append(remainingNames, name)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 如果没有剩余名字,返回空字符串
|
|
|
+ if len(remainingNames) == 0 {
|
|
|
+ return ""
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 使用 crypto/rand 生成安全的随机索引
|
|
|
+ n, err := rand.Int(rand.Reader, big.NewInt(int64(len(remainingNames))))
|
|
|
if err != nil {
|
|
|
- panic(err) // 在实际应用中应该更优雅地处理错误
|
|
|
+ // 如果出现错误,作为后备方案使用不太安全但更可靠的方案
|
|
|
+ var fallbackSeed int64
|
|
|
+ binary.Read(rand.Reader, binary.LittleEndian, &fallbackSeed)
|
|
|
+ if fallbackSeed < 0 {
|
|
|
+ fallbackSeed = -fallbackSeed
|
|
|
+ }
|
|
|
+ return remainingNames[fallbackSeed%int64(len(remainingNames))]
|
|
|
}
|
|
|
- return fmt.Sprintf("robot_%d", n)
|
|
|
+
|
|
|
+ // 6. 返回随机选择的名字
|
|
|
+ return remainingNames[n.Int64()]
|
|
|
}
|
|
|
|
|
|
// 随机获取一个人机头像
|