瑞士轮赛制的由来
瑞士制:又称积分循环制,最早出现于1895年在瑞士苏黎世举办的国际象棋比赛中,故而得名。其基本原则是避免种子选手一开始就交锋、拼掉,是比较科学合理、用得最多的一种赛制;英语名称为Swiss System。
欲通过瑞士轮的考验进入淘汰赛,那么需要在此阶段拿下三场胜利,反之遭遇三场失利就会被淘汰。瑞士轮阶段的比赛,包含了五个轮次的比赛,每轮的比赛对阵都由抽签来决定。
第一轮有8场比赛:比赛全部为BO1(同赛区规避),这8场比赛结束之后,16支队伍会按照胜负情况分为两组,1-0战绩的队伍8支,0-1战绩的队伍8支。
第二轮同样也是8场BO1的比赛:抽签后的对阵原则是1-0战绩的队伍和1-0战绩的队伍打(也就是第一轮的胜者打胜者),0-1战绩的队伍和0-1战绩的队伍打(也就是第一轮的败者打败者)。此轮比赛结束后,会有4支2-0的队伍,4支0-2的队伍,8支1-1的队伍。
第三轮的比赛就显得复杂一些了,因为第三轮就会诞生率先晋级淘汰赛以及不得不遗憾出局的队伍了:关乎淘汰和晋级的比赛都将是BO3的设定,2-0的队伍打2场BO3, 1-1的队伍打4场BO1,0-2的队伍打2场BO3。第三轮比赛结束之后,会宣告2支队伍以3-0的成绩晋级淘汰赛,2支队伍以0-3的成绩遗憾出局。
第四轮的比赛最为残酷:2-1的队伍打3场BO3,胜者晋级淘汰赛,1-2的队伍打3场BO3。比赛结束后晋级3支队伍,淘汰3支队伍;留在场上的6支队伍是全部都会是2-2的胜负场情形。
第五轮的比赛是晋级淘汰赛的最后机会,2-2的队伍们打3场BO3,晋级3支队伍淘汰3支队伍。
综上所述:通过五个轮次的比赛,8支队伍得以晋级,8支队伍遭遇淘汰。
一文读懂2023英雄联盟全球总决赛瑞士轮赛制
我们新建一个仿真窗体应用程序LOL_S13Demo。
将默认的Form1重命名为FormLOL_S13
一、新建图片文件夹TeamFlagImage,将各个战队图标导入,并设置为始终复制
二、然后新建随机数类RandomUtil,源程序如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LOL_S13Demo
{
public class RandomUtil
{
private static int[] nums;
private static Random rand = new Random();
/// <summary>
/// 初始化数组索引
/// </summary>
/// <param name="indexArray"></param>
public static void Init(int[] indexArray)
{
nums = indexArray;
}
/// <summary>
/// 洗牌算法,洗牌算法的时间复杂度是 O(N)
/// 第一次有N种可能,第二次有N-1种可能,第三次有N-2种可能
/// ...最后一次只有一种可能
/// </summary>
/// <returns></returns>
public static int[] Shuffle()
{
int n = nums.Length;
int[] copy = new int[n];
Array.Copy(nums, copy, n);
for (int i = 0; i < n; i++)
{
// 生成一个 [i, n-1] 区间内的随机数
int r = i + rand.Next(n - i);
// 交换 nums[i] 和 nums[r],即获取第r个数【放到第i个位置】
Swap(copy, i, r);
}
return copy;
}
/// <summary>
/// 交换数组两个数的值
/// </summary>
/// <param name="nums"></param>
/// <param name="i"></param>
/// <param name="j"></param>
private static void Swap(int[] nums, int i, int j)
{
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}
三、新建战队类Team,属性如下:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LOL_S13Demo
{
/// <summary>
/// 英雄联盟S13参赛战队
/// </summary>
class Team
{
/// <summary>
/// 战队名称
/// </summary>
public string TeamName { get; set; }
/// <summary>
/// 战队胜率
/// </summary>
public decimal WinningRatio { get; set; }
/// <summary>
/// 战队图标
/// </summary>
public Image TeamFlag { get; set; }
}
}
四、新建自定义控件UcTeam,设计器源码如下:
文件 UcTeam.designer.cs
using System.Windows.Forms;
namespace LOL_S13Demo
{
partial class UcTeam
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.panel2 = new System.Windows.Forms.Panel();
this.lblWinningRatio = new System.Windows.Forms.Label();
this.lblTeamName = new System.Windows.Forms.Label();
this.picTeamFlag = new System.Windows.Forms.PictureBox();
this.panel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picTeamFlag)).BeginInit();
this.SuspendLayout();
//
// panel2
//
this.panel2.Controls.Add(this.lblWinningRatio);
this.panel2.Controls.Add(this.lblTeamName);
this.panel2.Controls.Add(this.picTeamFlag);
this.panel2.Location = new System.Drawing.Point(3, 2);
this.panel2.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(257, 127);
this.panel2.TabIndex = 2;
//
// lblWinningRatio
//
this.lblWinningRatio.AutoSize = true;
this.lblWinningRatio.ForeColor = System.Drawing.Color.Green;
this.lblWinningRatio.Location = new System.Drawing.Point(155, 5);
this.lblWinningRatio.Name = "lblWinningRatio";
this.lblWinningRatio.Size = new System.Drawing.Size(29, 12);
this.lblWinningRatio.TabIndex = 5;
this.lblWinningRatio.Text = "胜率";
//
// lblTeamName
//
this.lblTeamName.AutoSize = true;
this.lblTeamName.ForeColor = System.Drawing.Color.Blue;
this.lblTeamName.Location = new System.Drawing.Point(21, 5);
this.lblTeamName.Name = "lblTeamName";
this.lblTeamName.Size = new System.Drawing.Size(29, 12);
this.lblTeamName.TabIndex = 4;
this.lblTeamName.Text = "战队";
//
// picTeamFlag
//
this.picTeamFlag.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.picTeamFlag.Location = new System.Drawing.Point(21, 21);
this.picTeamFlag.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
this.picTeamFlag.Name = "picTeamFlag";
this.picTeamFlag.Size = new System.Drawing.Size(214, 106);
this.picTeamFlag.TabIndex = 3;
this.picTeamFlag.TabStop = false;
//
// UcTeam
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.panel2);
this.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
this.Name = "UcTeam";
this.Size = new System.Drawing.Size(262, 131);
this.panel2.ResumeLayout(false);
this.panel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picTeamFlag)).EndInit();
this.ResumeLayout(false);
}
#endregion
private Panel panel2;
public PictureBox picTeamFlag;
public Label lblWinningRatio;
public Label lblTeamName;
}
}
UcTeam.cs源程序如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LOL_S13Demo
{
public partial class UcTeam : UserControl
{
public UcTeam()
{
InitializeComponent();
}
}
}
五、新建战队与操作比赛相关类TeamUtil
TeamUtil.cs源程序如下:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LOL_S13Demo
{
internal class TeamUtil
{
/// <summary>
/// 所有参赛的世界杯战队
/// </summary>
public static List<Team> ListTeam = new List<Team>();
/// <summary>
/// 初始化世界杯各个参赛战队
/// </summary>
public static void InitTeam()
{
ListTeam.Clear();
AddTeam(new Team()
{
TeamName = "JDG",
WinningRatio = 90,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\JDG.jpg")
});
AddTeam(new Team()
{
TeamName = "LNG",
WinningRatio = 85,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\LNG.jpg")
});
AddTeam(new Team()
{
TeamName = "BLG",
WinningRatio = 80,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\BLG.jpg")
});
AddTeam(new Team()
{
TeamName = "WBG",
WinningRatio = 75,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\WBG.jpg")
});
AddTeam(new Team()
{
TeamName = "GEN",
WinningRatio = 90,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\GEN.jpg")
});
AddTeam(new Team()
{
TeamName = "T1",
WinningRatio = 85,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\T1.jpg")
});
AddTeam(new Team()
{
TeamName = "KT",
WinningRatio = 80,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\KT.jpg")
});
AddTeam(new Team()
{
TeamName = "DK",
WinningRatio = 75,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\DK.jpg")
});
AddTeam(new Team()
{
TeamName = "FNC",
WinningRatio = 80,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\FNC.jpg")
});
AddTeam(new Team()
{
TeamName = "BDS",
WinningRatio = 70,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\BDS.jpg")
});
AddTeam(new Team()
{
TeamName = "C9",
WinningRatio = 75,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\C9.jpg")
});
AddTeam(new Team()
{
TeamName = "G2",
WinningRatio = 70,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\G2.jpg")
});
AddTeam(new Team()
{
TeamName = "GAM",
WinningRatio = 75,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\GAM.jpg")
});
AddTeam(new Team()
{
TeamName = "MAD",
WinningRatio = 75,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\MAD.png")
});
AddTeam(new Team()
{
TeamName = "NRG",
WinningRatio = 65,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\NRG.png")
});
AddTeam(new Team()
{
TeamName = "TL",
WinningRatio = 85,
TeamFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "TeamFlagImage\\TL.png")
});
}
/// <summary>
/// 添加一个战队
/// </summary>
/// <param name="Team"></param>
public static void AddTeam(Team Team)
{
ListTeam.Add(Team);
}
/// <summary>
/// 两个匹配的战队进行比赛,根据胜率,进行随机,返回胜利的战队
/// 胜利法则如下:先随机出一个胜率之和之间的随机数,
/// 如果随机数小于【最小数的2倍】并且是奇数,则认为 胜率低的战队胜利,否则 胜率高的战队胜利
/// </summary>
/// <param name="tuple">参赛战队</param>
/// <param name="failTeam">失败战队</param>
/// <returns></returns>
public static Team SoccerGame(Tuple<Team, Team> tuple, out Team failTeam, out int randomNumber)
{
failTeam = tuple.Item2;
randomNumber = -1;
if (tuple == null || tuple.Item1 == null)
{
throw new Exception("世界比赛无参赛的战队或者第一个参赛战队不存在");
}
if (tuple.Item2 == null)
{
//无第二个世界参赛战队,直接躺赢【对奇数个参赛战队的特殊处理】
return tuple.Item1;
}
decimal minWinningRatio = Math.Min(tuple.Item1.WinningRatio, tuple.Item2.WinningRatio);
Team bigWin = null;//高胜率
Team smallWin = null;//低胜率
if (tuple.Item1.WinningRatio < tuple.Item2.WinningRatio)
{
bigWin = tuple.Item2;
smallWin = tuple.Item1;
}
else
{
bigWin = tuple.Item1;
smallWin = tuple.Item2;
}
int total = (int)(tuple.Item1.WinningRatio + tuple.Item2.WinningRatio);
Random random = new Random(Guid.NewGuid().GetHashCode());
//先随机出一个胜率之和之间的随机数
randomNumber = random.Next(total);
if (randomNumber < minWinningRatio * 2 && (randomNumber & 1) != 0)
{
//如果随机数小于【最小数的2倍】并且是奇数,则认为 胜率低的战队胜利,否则 胜率高的战队胜利
failTeam = bigWin;
return smallWin;
}
failTeam = smallWin;
return bigWin;
}
}
}
六、窗体FormLOL_S13的设计器程序如下:
FormLOL_S13.designer.cs
using System.Windows.Forms;
namespace LOL_S13Demo
{
partial class FormLOL_S13
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnStart = new System.Windows.Forms.Button();
this.btnRefresh = new System.Windows.Forms.Button();
this.rtxtDisplay = new System.Windows.Forms.RichTextBox();
this.pnlTeam = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// btnStart
//
this.btnStart.Location = new System.Drawing.Point(871, 5);
this.btnStart.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
this.btnStart.Name = "btnStart";
this.btnStart.Size = new System.Drawing.Size(152, 28);
this.btnStart.TabIndex = 0;
this.btnStart.Text = "开始比赛 直到 决出冠军";
this.btnStart.UseVisualStyleBackColor = true;
this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
//
// btnRefresh
//
this.btnRefresh.Location = new System.Drawing.Point(1065, 5);
this.btnRefresh.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
this.btnRefresh.Name = "btnRefresh";
this.btnRefresh.Size = new System.Drawing.Size(133, 28);
this.btnRefresh.TabIndex = 1;
this.btnRefresh.Text = "刷新重新随机分配";
this.btnRefresh.UseVisualStyleBackColor = true;
this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
//
// rtxtDisplay
//
this.rtxtDisplay.Location = new System.Drawing.Point(854, 37);
this.rtxtDisplay.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
this.rtxtDisplay.Name = "rtxtDisplay";
this.rtxtDisplay.Size = new System.Drawing.Size(378, 761);
this.rtxtDisplay.TabIndex = 2;
this.rtxtDisplay.Text = "";
//
// pnlTeam
//
this.pnlTeam.AutoScroll = true;
this.pnlTeam.Location = new System.Drawing.Point(1, 1);
this.pnlTeam.Name = "pnlTeam";
this.pnlTeam.Size = new System.Drawing.Size(847, 797);
this.pnlTeam.TabIndex = 3;
//
// FormLOL_S13
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1255, 802);
this.Controls.Add(this.pnlTeam);
this.Controls.Add(this.rtxtDisplay);
this.Controls.Add(this.btnRefresh);
this.Controls.Add(this.btnStart);
this.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
this.Name = "FormLOL_S13";
this.Text = "英雄联盟S13赛季_瑞士轮随机排名模拟器";
this.Load += new System.EventHandler(this.FormTeam_Load);
this.ResumeLayout(false);
}
#endregion
private Button btnStart;
private Button btnRefresh;
private RichTextBox rtxtDisplay;
private Panel pnlTeam;
}
}
窗体FormLOL_S13代码随机匹配如下
FormLOL_S13.cs文件
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LOL_S13Demo
{
public partial class FormLOL_S13 : Form
{
/// <summary>
/// 比赛次数
/// </summary>
private static int matchCount = 0;
/// <summary>
/// 获胜战队列表,将进入下一轮,瑞士轮胜者组进行比赛
/// </summary>
private static List<Team> WinTeamList = new List<Team>();
/// <summary>
/// 失败战队列表,将进入下一轮,瑞士轮败者组进行比赛
/// </summary>
private static List<Team> FailTeamList = new List<Team>();
/// <summary>
/// 战队积分,胜利一场积分加1,失败一场积分加0
/// </summary>
private static Dictionary<Team, int> DictPoint = new Dictionary<Team, int>();
public FormLOL_S13()
{
InitializeComponent();
rtxtDisplay.ReadOnly = true;
rtxtDisplay.Text = @"英雄联盟全球总决赛S13比赛规则采用瑞士轮:
瑞士轮赛制的由来
瑞士制:又称积分循环制,最早出现于1895年在瑞士苏黎世举办的国际象棋比赛中,故而得名。
其基本原则是避免种子选手一开始就交锋、拼掉,是比较科学合理、用得最多的一种赛制;英语名称为Swiss System。
欲通过瑞士轮的考验进入淘汰赛,那么需要在此阶段拿下三场胜利,反之遭遇三场失利就会被淘汰。
瑞士轮阶段的比赛,包含了五个轮次的比赛,每轮的比赛对阵都由抽签来决定。
第一轮有8场比赛:比赛全部为BO1(同赛区规避),这8场比赛结束之后,16支队伍会按照胜负情况分为两组,1-0战绩的队伍8支,0-1战绩的队伍8支。
第二轮同样也是8场BO1的比赛:抽签后的对阵原则是1-0战绩的队伍和1-0战绩的队伍打(也就是第一轮的胜者打胜者),0-1战绩的队伍和0-1战绩的队伍打(也就是第一轮的败者打败者)。
此轮比赛结束后,会有4支2-0的队伍,4支0-2的队伍,8支1-1的队伍。
第三轮的比赛就显得复杂一些了,因为第三轮就会诞生率先晋级淘汰赛以及不得不遗憾出局的队伍了:关乎淘汰和晋级的比赛都将是BO3的设定,2-0的队伍打2场BO3, 1-1的队伍打4场BO1,0-2的队伍打2场BO3。
第三轮比赛结束之后,会宣告2支队伍以3-0的成绩晋级淘汰赛,2支队伍以0-3的成绩遗憾出局。
第四轮的比赛最为残酷:2-1的队伍打3场BO3,胜者晋级淘汰赛,1-2的队伍打3场BO3。比赛结束后晋级3支队伍,淘汰3支队伍;留在场上的6支队伍是全部都会是2-2的胜负场情形。
第五轮的比赛是晋级淘汰赛的最后机会,2-2的队伍们打3场BO3,晋级3支队伍淘汰3支队伍。
综上所述:通过五个轮次的比赛,8支队伍得以晋级,8支队伍遭遇淘汰。
决出八强后,直接进入淘汰赛,决出四强
四强抽签两两比赛,决出胜者组,败者组。败者组决出季军,胜者组决出冠军、亚军";
}
private void FormTeam_Load(object sender, EventArgs e)
{
TeamUtil.InitTeam();
DictPoint.Clear();
for (int i = 0; i < TeamUtil.ListTeam.Count; i++)
{
DictPoint.Add(TeamUtil.ListTeam[i], 0);
}
LoadMatchTeam(TeamUtil.ListTeam);
}
/// <summary>
/// 随机分配参赛战队列表
/// </summary>
/// <param name="TeamList"></param>
private void LoadMatchTeam(List<Team> TeamList)
{
pnlTeam.Controls.Clear();
DisplayMessage($"开始加载S13英雄联盟参赛战队.参赛战队[{TeamList.Count}]个.参赛战队:\n{string.Join(",", TeamList.Select(c => c.TeamName))}");
Application.DoEvents();
//Thread.Sleep(500);
int[] indexArray = new int[TeamList.Count];
for (int i = 0; i < indexArray.Length; i++)
{
indexArray[i] = i;
}
RandomUtil.Init(indexArray);
int[] destArray = RandomUtil.Shuffle();
int rowCount = (destArray.Length + 1) / 2;
matchCount = rowCount;
string[] matchTeams = new string[rowCount];//比赛对战战队
for (int i = 0; i < rowCount; i++)
{
UcTeam ucTeam1 = new UcTeam();
ucTeam1.Name = $"ucTeam{i * 2 + 1}";
Team Team1 = TeamList[destArray[i * 2]];
ucTeam1.lblTeamName.Text = Team1.TeamName;
ucTeam1.lblWinningRatio.Text = $"胜率:{Team1.WinningRatio}";
ucTeam1.picTeamFlag.BackgroundImage = Team1.TeamFlag;
ucTeam1.Tag = Team1;
ucTeam1.Location = new Point(5, i * 200 + 5);
pnlTeam.Controls.Add(ucTeam1);
Button button = new Button();
button.Name = $"button{i + 1}";
button.Text = "VS";
button.Font = new Font("宋体", 30, FontStyle.Bold);
button.Size = new Size(100, 100);
button.Location = new Point(310, i * 200 + 40);
button.Enabled = false;//不允许界面交互
pnlTeam.Controls.Add(button);
Team item2 = null;
if (i * 2 + 1 < destArray.Length)
{
//对奇数个比赛战队特殊处理,最后一个战队直接胜利
UcTeam ucTeam2 = new UcTeam();
ucTeam2.Name = $"ucTeam{i * 2 + 2}";
Team Team2 = TeamList[destArray[i * 2 + 1]];
ucTeam2.lblTeamName.Text = Team2.TeamName;
ucTeam2.lblWinningRatio.Text = $"胜率:{Team2.WinningRatio}";
ucTeam2.picTeamFlag.BackgroundImage = Team2.TeamFlag;
ucTeam2.Tag = Team2;
ucTeam2.Location = new Point(455, i * 200 + 5);
pnlTeam.Controls.Add(ucTeam2);
item2 = Team2;
}
//对按钮进行数据绑定 对应两个参赛战队
button.Tag = Tuple.Create(Team1, item2);
button.Click += Button_Click;
matchTeams[i] = $"【{Team1.TeamName} VS {(item2 == null ? "无" : item2.TeamName)}】";
}
DisplayMessage($"加载对战战队匹配完成.对战情况\n{string.Join(",\n", matchTeams)}");
}
/// <summary>
/// 淘汰赛,利用胜率获取随机数算法,获取比赛的胜利一方,并将获胜战队插入胜利列表,以便进行下一次的随机分配
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click(object sender, EventArgs e)
{
Button button = sender as Button;
if (button == null)
{
return;
}
Tuple<Team, Team> tuple = button.Tag as Tuple<Team, Team>;
if (tuple == null)
{
return;
}
int randomNumber;
Team failTeam;
Team winTeam = TeamUtil.SoccerGame(tuple, out failTeam, out randomNumber);
WinTeamList.Add(winTeam);//将获胜战队插入列表
FailTeamList.Add(failTeam);//失败战队
DictPoint[winTeam] = DictPoint[winTeam] + 1;
DisplayMessage($"参赛战队【{tuple.Item1.TeamName},胜率:{tuple.Item1.WinningRatio}】 VS 【{(tuple.Item2 == null ? "无" : $"{tuple.Item2.TeamName},胜率:{tuple.Item2.WinningRatio}")}】");
DisplayMessage($" 胜利战队【{winTeam.TeamName}】,失败战队【{failTeam.TeamName}】,模拟随机数【{randomNumber}】");
UcTeam ucTeam = FindWinTeam(button, winTeam);
if (ucTeam == null)
{
return;
}
Panel panel = new Panel();
panel.Name = $"panel{button.Name.Substring(6)}";
panel.Location = new Point(ucTeam.Location.X + 250, ucTeam.Location.Y + 10);
panel.Size = new Size(100, 100);
panel.BackgroundImage = null;
Bitmap bitmap = new Bitmap(panel.Width, panel.Height);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.DrawString("胜 利", new Font("华文楷体", 16), Brushes.Red, 10, 10);
graphics.Dispose();
panel.BackgroundImage = bitmap;
pnlTeam.Controls.Add(panel);
}
/// <summary>
/// 获取两个比赛战队胜利一方对应的控件
/// </summary>
/// <param name="button"></param>
/// <param name="winTeam"></param>
/// <returns></returns>
private UcTeam FindWinTeam(Button button, Team winTeam)
{
int index = int.Parse(button.Name.Substring(6)) - 1;
Control[] controls = pnlTeam.Controls.Find($"ucTeam{index * 2 + 1}", true);
Control[] controls2 = pnlTeam.Controls.Find($"ucTeam{index * 2 + 2}", true);
if (controls != null && controls.Length > 0)
{
Team cTemp = ((UcTeam)controls[0]).Tag as Team;
if (cTemp.TeamName == winTeam.TeamName)
{
return (UcTeam)controls[0];
}
else
{
if (controls2 != null && controls2.Length > 0)
{
cTemp = ((UcTeam)controls2[0]).Tag as Team;
if (cTemp.TeamName == winTeam.TeamName)
{
return (UcTeam)controls2[0];
}
}
}
}
return null;
}
private void DisplayMessage(string message)
{
this.BeginInvoke(new Action(() =>
{
if (rtxtDisplay.TextLength >= 40960)
{
rtxtDisplay.Clear();
}
rtxtDisplay.AppendText($"{DateTime.Now.ToString("HH:mm:ss")}-->{message}\n");
rtxtDisplay.ScrollToCaret();
}));
}
private void btnStart_Click(object sender, EventArgs e)
{
Team[] FinalTwoTeam = new Team[2];//最终决赛的两个战队,分出冠军、亚军
do
{
WinTeamList.Clear();
for (int i = 0; i < matchCount; i++)
{
Button button = pnlTeam.Controls.Find($"button{i + 1}", true)[0] as Button;
Button_Click(button, null);
Application.DoEvents();
Thread.Sleep(2000);
}
if (WinTeamList.Count == 1)
{
//只有最后一个胜利战队,循环终止,找到亚军
Team secondPlace = Array.Find(FinalTwoTeam, c => c.TeamName != WinTeamList[0].TeamName);
DisplayMessage($"最终胜利战队,冠军【{WinTeamList[0].TeamName}】,亚军【{secondPlace.TeamName}】");
MessageBox.Show($"最终胜利战队,冠军【{WinTeamList[0].TeamName}】,亚军【{secondPlace.TeamName}】", "圆满结束");
break;
}
DisplayMessage($"当前胜利的战队为【{string.Join(",", WinTeamList.Select(Team => Team.TeamName))}】");
Application.DoEvents();
Thread.Sleep(3000);
if (WinTeamList.Count == 2)
{
WinTeamList.CopyTo(FinalTwoTeam);
string TeamBattle = $"决战即将开始,最终决赛双方:【{WinTeamList[0].TeamName} VS {WinTeamList[1].TeamName}】";
DisplayMessage(TeamBattle);
Application.DoEvents();
Thread.Sleep(1000);
MessageBox.Show(TeamBattle, "决战");
}
LoadMatchTeam(WinTeamList);
} while (WinTeamList.Count >= 2);
}
private void btnRefresh_Click(object sender, EventArgs e)
{
rtxtDisplay.Clear();
WinTeamList.Clear();
FormTeam_Load(null, null);
}
}
}