ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

go 随机数 rand 的简单使用,年会活动积分赛程设置,小组赛对战顺序

2022-01-06 18:59:00  阅读:180  来源: 互联网

标签:Println rand displayCount i1 fmt i2 对战 go


背景

公司年会举办活动,我来组织乒乓球赛,由于人数不是很多而且时间比较紧迫。第一轮采用分组积分赛制,组内人人都会对战一次,程序实现了一下对战顺序。

go 的随机数 rand

gomath/rand 包实现了伪随机数生成器。
如下示例,生成 10 以内的随机数 rand.Intn

func tMathRand() {
	for i := 0; i < 100; i++ {
		fmt.Println(rand.Intn(10))
	}
}

不管运行几次,生成结果都如下:

1
7
7
9
1
8
5
0
6
0

这里是因为没有设置随机数种子,一般来说,使用方法如下 rand.Seed

func tMathRand() {
	rand.Seed(time.Now().Unix())
	for i := 0; i < 100; i++ {
		fmt.Println(rand.Intn(10))
	}
}

程序实现积分赛程安排

package main

import (
	"errors"
	"fmt"
	"math/rand"
	"strings"
	"time"
)

func main() {
	fmt.Println("请输入需要参赛的队伍,用英文逗号 ',' 分隔")
	var peopleStr string
	for {
		_, err := fmt.Scanf("%s", &peopleStr)
		if err != nil {
			fmt.Println("输入有误,请重新输入:", err)
			continue
		}
		break
	}

	p := strings.Split(peopleStr, ",")
	res, err := pingpongRand(p)
	if err != nil {
		fmt.Println(err.Error())
	} else {
		fmt.Println(res)
	}

	fmt.Println()
	fmt.Println("请输入任意值退出...")

	fmt.Scan(&peopleStr)
	//fmt.Scanln(&peopleStr)
}

type peopleRand struct {
	Count        int   // 已出现的次数
	MatchedIndex []int // 匹配过的人 下标
}

func (p *peopleRand) Matched(index int) bool {
	for _, v := range p.MatchedIndex {
		if v == index {
			return true
		}
	}
	return false
}

// 输入参赛选手,输出对战信息
func pingpongRand(people []string) ([][]string, error) {
	rand.Seed(time.Now().Unix())
	peopleLength := len(people)
	if peopleLength <2 {
		return [][]string{}, errors.New("参赛至少为 2 组")
	}

	resLength := (peopleLength - 1) * peopleLength / 2
	res := make([][]string, 0, resLength)

	peopleCount := peopleLength - 1 // 1 个人最多出现的次数

	var displayCount = make(map[int]*peopleRand) // 每个人出现的次数
	for {
		i1 := rand.Intn(peopleLength) // 人员下标
		_, ok := displayCount[i1]
		if !ok {
			p := new(peopleRand)
			p.Count = 1
			displayCount[i1] = p
		}
		if displayCount[i1].Count > peopleCount {
			continue
		}
		displayCount[i1].Count++
		couple := make([]string, 2) // 存放对战人名单
		// 判断 i1 已出现的次数
		couple[0] = people[i1]

		for {
			i2 := rand.Intn(peopleLength)
			if i2 == i1 { // 剔除自己
				continue
			}
			_, ok := displayCount[i2]
			if !ok {
				p2 := new(peopleRand)
				p2.Count = 1
				displayCount[i2] = p2
			}
			if displayCount[i2].Count > peopleCount {
				continue
			}
			// 剔除已匹配过的
			if displayCount[i1].Matched(i2) {
				continue
			}

			displayCount[i2].Count++
			displayCount[i2].MatchedIndex = append(displayCount[i2].MatchedIndex, i1)
			displayCount[i1].MatchedIndex = append(displayCount[i1].MatchedIndex, i2)
			couple[1] = people[i2]
			break
		}

		res = append(res, couple)
		if len(res) == resLength {
			break
		}
	}

	return res, nil
}

输出如下:
在这里插入图片描述

总结

刚开始进行赛程分配的时候,是自己列表格来排的,感觉有点蠢。。。 还是代码方便些。
在这里插入图片描述

标签:Println,rand,displayCount,i1,fmt,i2,对战,go
来源: https://blog.csdn.net/DisMisPres/article/details/122350348

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有