生成赛事对阵图-洗牌
本文并非介绍框架设计。只是想通过这个案例,单地表述解决本文问题思路。
基于上一篇《生成赛事对阵图-排序》,得到小区归总有序的前16名信息
[TOC]
问题
- 让前4名有机会同时出现在冠军赛和季军赛
- 其它情况随机分组
已知
- 保证集合有序,且长度>=16
解决
借鉴Knuth-Durstenfeld Shuffle的算法思路,本算法特别之处在于保打乱局部范围的元素,最终令相邻的元素在一个分组。决定打乱哪些元素由外层指定,如打乱奇数位的元素,则传入{1,3,5,7,9,11,13,15}
1. 满足需求1和2
- 1.1 第2名交换到索引9的位置,即第5组
- 1.2 第3名交换到索引5的位置,即第3组
- 1.3 第4名交换到索引13的位置,即第7组
- 1.4 至此第1,2,3,4名分别在索引{1,9,5,13}
2. 满足需求3
- 1.1 Shuffle(s, {1,9})打乱第1,2名的对阵位置。同理Shuffle(s, {5,13})打乱第3,4名对阵位置
- 1.2 Shuffle(s, {1,5}), Shuffle(s, {1,3}), Shuffle(s, {5,7})打乱其中2名在1至4分组的对阵位置,同理Shuffle(s, {9,13}),Shuffle(s, {9,11}),Shuffle(s, {13,15})打乱另外2名在5至8分组的对阵位置
- 1.3 Shuffle(s, {2,4,6,8,10,12,14}),即将剩下的名次,随机分组
- 1.4 将相邻的元素随机交换
Lua代码
math.randomseed(os.time())
local function Shuffle(s, l)
local i = #l
while i >= 2 do
local r = math.random(1, i)
local p1 = l[r]
local p2 = l[i]
local tmp = s[p2]
s[p2] = s[p1]
s[p1] = tmp
i = i - 1
end
end
local s = {}
for i = 1, 16, 1 do
s[i] = i
end
--第2名交换到索引9的位置
local tmp = s[2]
s[2] = s[9]
s[9] = tmp
--第3名交换到索引5的位置
local tmp = s[3]
s[3] = s[5]
s[5] = tmp
--第4名交换到索引13的位置
tmp = s[4]
s[4] = s[13]
s[13] = tmp
-- 打乱1,2名在左侧/右侧的位置
Shuffle(s, {1,9})
-- 打乱3,4名在左侧/右侧的位置
Shuffle(s, {5,13})
--打乱其中2名在1至4分组的对阵位置
Shuffle(s, {1,5,})
Shuffle(s, {1,3,})
Shuffle(s, {5,7})
--打乱另外2名在5至8分组的对阵位置
Shuffle(s, {9,13})
Shuffle(s, {9,11})
Shuffle(s, {13,15})
--剩下的名次,随机分组
Shuffle(s, {2,4,6,8,10,12,14,16})
--将相邻的元素随机交替
for i = 1, 16, 2 do
local r = math.random(0, 1)
if r == 1 then
local tmp = s[i]
s[i] = s[i+1]
s[i+1] = tmp
end
end
for i = 1, 16, 1 do
print(tostring(s[i])..",")
end
原文:
https://lizijie.github.io/2021/06/05/%E7%94%9F%E6%88%90%E8%B5%9B%E4%BA%8B%E5%AF%B9%E9%98%B5%E5%9B%BE-%E6%B4%97%E7%89%8C.html
作者github:
https://github.com/lizijie
PREVIOUS生成不重复题目-随机
NEXT生成赛事对阵图-排序