C#使用随机数模拟英雄联盟S13瑞士轮比赛

news2024/11/25 6:37:53

 瑞士轮赛制的由来

瑞士制:又称积分循环制,最早出现于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);
        }
    }
}

七、测试程序运行如图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1173813.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信内H5页面唤醒App

首先&#xff0c;简述一下这个需求的背景&#xff0c;产品希望能够让用户在微信内&#xff0c;打开一个h5页面&#xff0c;然后就能唤醒公司中维护的app&#xff0c;这个是为了能够更好的引流。 唤醒app的三种方案 IOS系统-Universal Link&#xff08;通用链接&#xff09; …

invoke方法传参String数组问题——wrong number of arguments

invoke方法传参String数组问题——wrong number of arguments 问题描述一、案例准备二、错误反射调用实例三、正确反射调用实例 问题描述 今天笔者在使用invoke方法的时候&#xff0c;发现报了一个这样一个错&#xff1a;“wrong number of arguments”&#xff0c;在网上冲浪…

【Python】-- python的基本图像处理(图像显示、保存、颜色变换、缩放与旋转等)

目录 一、图像文件的读写 操作步骤&#xff1a; 显示图像文件的三个常用属性&#xff1a; 例&#xff1a; 二、图像文件的处理 常用的图像处理方法 1、图像的显示 2、图像的保存 3、图像的拷贝与粘贴 4、图像的缩放与旋转 5、图像的颜色变换 6、图像的过滤与增强 7、序…

【MySQL】用户管理权限控制

文章目录 前言一. 用户管理1. 创建用户2. 删除用户3. 修改用户密码 二. 权限控制1. 用户授权2. 查看权限3. 回收权限 结束语 前言 MySQL的数据其实也以文件形式保存&#xff0c;而登录信息同样保存在文件中 MySQL的数据在Linux下默认路径是/var/lib/mysql 登录MySQL同样也可以…

全网超细,Pytest自动化测试框架入门到精通-实战整理,一篇打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、Pytest和Unitt…

交叉编译程序:以 freetype 为例

1 程序运行的一些基础知识 1.1 编译程序时去哪找头文件&#xff1f; 系统目录&#xff1a;就是交叉编译工具链里的某个 include 目录&#xff1b;也可以自己指定&#xff1a;编译时用 “ -I dir ” 选项指定。 1.2 链接时去哪找库文件&#xff1f; 系统目录&#…

二叉树OJ练习题(C语言版)

目录 一、相同的树 二、单值二叉树 三、对称二叉树 四、树的遍历 前序遍历 中序遍历 后序遍历 五、另一颗树的子树 六、二叉树的遍历 七、翻转二叉树 八、平衡二叉树 一、相同的树 链接&#xff1a;100. 相同的树 - 力扣&#xff08;LeetCode&#xff09; bool isSameTree(…

前端框架Vue学习 ——(一)快速入门

文章目录 Vue 介绍Vue快速入门 Vue 介绍 Vue 是一套前端框架&#xff0c;免除原生 JavaScript 中的 DOM 操作&#xff0c;简化书写。基于 MVVM (Model-View-ViewModel)思想&#xff0c;实现数据的双向绑定&#xff0c;将编程的关注点放在数据上。官网: https://v2.cn.vuejs.or…

Flow-based models(NICE);流模型+NICE+代码实现

参考&#xff1a; 李宏毅春季机器学习NICE: Non-linear Independent Components Estimationhttps://github.com/gmum/nice_pytorch 文章目录 大致思想数学预备知识Jacobian矩阵行列式以及其几何意义Change of Variable Theorem Flow-based modelNICE理论代码 大致思想 Flow-B…

【Linux系统化学习】开发工具——gdb(调试器)

个人主页点击直达&#xff1a;小白不是程序媛 Linux专栏&#xff1a;Linux系统化学习 个人仓库&#xff1a;Gitee 目录 前言&#xff1a; gdb版本检查和安装 Debug和Release gdb的使用 其他指令 前言&#xff1a; 前几篇文章分别介绍了在Linux下的代码编辑器、编译器。…

c面向对象编码风格(上)

面向对象和面向过程的基本概念 面向对象和面向过程是两种不同的编程范式&#xff0c;它们在软件开发中用于组织和设计代码的方式。 面向过程编程&#xff08;Procedural Programming&#xff09;是一种以过程&#xff08;函数、方法&#xff09;为核心的编程方式。在面向过程…

2021年电工杯数学建模B题光伏建筑一体化板块指数发展趋势分析及预测求解全过程论文及程序

2021年电工杯数学建模 B题 光伏建筑一体化板块指数发展趋势分析及预测 原题再现&#xff1a; 国家《第十四个五年规划和 2035 年远景目标纲要》中提出&#xff0c;将 2030 年实现“碳达峰”与 2060 年实现“碳中和”作为我国应对全球气候变暖的一个重要远景目标。光伏建筑一体…

七月论文审稿GPT第二版:从Meta Nougat、GPT4审稿到LongLora版LLaMA、Mistral

前言 如此前这篇文章《学术论文GPT的源码解读与微调&#xff1a;从chatpaper、gpt_academic到七月论文审稿GPT》中的第三部分所述&#xff0c;对于论文的摘要/总结、对话、翻译、语法检查而言&#xff0c;市面上的学术论文GPT的效果虽暂未有多好&#xff0c;可至少还过得去&am…

1.Netty概述

原生NIO存在的问题(Netty要解决的问题) 虽然JAVA NIO 和 JAVA AIO框架提供了多路复用IO/异步IO的支持&#xff0c;但是并没有提供给上层“信息格式”的良好封装。JAVA NIO 的 API 使用麻烦,需要熟练掌握 ByteBuffer、Channel、Selector等 , 所以用这些API实现一款真正的网络应…

题解:轮转数组及复杂度分析

文章目录 &#x1f349;前言&#x1f349;题目&#x1f34c;解法一&#x1f34c;解法二&#xff1a;以空间换时间&#x1f95d;补充&#xff1a;memmove &#x1f34c;解法三&#xff08;选看&#xff09; &#x1f349;前言 本文侧重对于复杂度的分析&#xff0c;题解为辅。 …

02-React组件与模块

组件与模块 前期准备 安装React官方浏览器调试工具&#xff0c;浏览器扩展搜索即可 比如红色的React就是本地开发模式 开启一个用React写的网站&#xff0c;比如美团 此时开发状态就变成了蓝色 组件也能解析出来 何为组件&模块 模块&#xff0c;简单来说就是JS代…

亚马逊云科技大语言模型下的六大创新应用功能

目录 前言 亚马逊云科技的AI创新应用 ​编辑 Amazon CodeWhisperer Amazon CodeWhisperer产品的优势 更快地完成更多工作 自信地进行编码 增强代码安全性 使用收藏夹工具 自定义 CodeWhisperer 以获得更好的建议 如何使用Amazon CodeWhisperer 步骤 1 步骤 2 具体…

php7.4.32如何快速正确的开启OpenSSL扩展库,最简单的办法在这里!

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&#x1…

GNU ld链接器 lang_process()(二)

一、ldemul_create_output_section_statements() 位于lang_process()中11行 。 该函数用于创建与目标有关的输出段的语句。这些语句将用于描述输出段的属性和分配。 void ldemul_create_output_section_statements (void) {if (ld_emulation->create_output_section_sta…

PS Raw中文增效工具Camera Raw 16

Camera Raw 16 for mac&#xff08;PS Raw增效工具&#xff09;的功能特色包括强大的图像调整工具。例如&#xff0c;它提供白平衡、曝光、对比度、饱和度等调整选项&#xff0c;帮助用户优化图像的色彩和细节。此外&#xff0c;Camera Raw 16的界面简洁易用&#xff0c;用户可…