生成赛事对阵图-洗牌

本文并非介绍框架设计。只是想通过这个案例,单地表述解决本文问题思路。

基于上一篇《生成赛事对阵图-排序》,得到小区归总有序的前16名信息

[TOC]

问题

  1. 让前4名有机会同时出现在冠军赛和季军赛
  2. 其它情况随机分组

已知

  1. 保证集合有序,且长度>=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生成赛事对阵图-排序