接上篇
C#使用随机数模拟器来模拟世界杯排名(二)_斯内科的博客-CSDN博客
上一篇我们使用随机数匹配比赛的世界杯国家,
这一篇我们使用随机数以及胜率模拟器 决赛出 世界杯冠军、亚军。
我们在主界面 新增按钮【开始比赛 直到 决出冠军】和【刷新重新随机分配】
面板Panel:pnlWorldCup
按钮:【开始比赛 直到 决出冠军】btnStart
按钮:【刷新重新随机分配】btnRefresh
富文本控件RichTextBox:rtxtDisplay
窗体FormWorldCupRanking设计如图:
更新CountryUtil.cs,增加SoccerGame方法,用于获取两个参赛世界杯国家胜利的一方。
CountryUtil源程序如下:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WorldCupRankingDemo
{
internal class CountryUtil
{
/// <summary>
/// 所有参赛的世界杯国家
/// </summary>
public static List<Country> ListWorldCup = new List<Country>();
/// <summary>
/// 初始化世界杯各个参赛国家
/// </summary>
public static void InitCountry()
{
ListWorldCup.Clear();
AddCountry(new Country()
{
CountryName = "法国",
WinningRatio = 90,
NationalFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "NationalFlagImage\\法国.png")
});
AddCountry(new Country()
{
CountryName = "阿根廷",
WinningRatio = 95,
NationalFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "NationalFlagImage\\阿根廷.png")
});
AddCountry(new Country()
{
CountryName = "巴西",
WinningRatio = 98,
NationalFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "NationalFlagImage\\巴西.png")
});
AddCountry(new Country()
{
CountryName = "荷兰",
WinningRatio = 80,
NationalFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "NationalFlagImage\\荷兰.png")
});
AddCountry(new Country()
{
CountryName = "克罗地亚",
WinningRatio = 70,
NationalFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "NationalFlagImage\\克罗地亚.png")
});
AddCountry(new Country()
{
CountryName = "葡萄牙",
WinningRatio = 75,
NationalFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "NationalFlagImage\\葡萄牙.png")
});
AddCountry(new Country()
{
CountryName = "摩洛哥",
WinningRatio = 65,
NationalFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "NationalFlagImage\\摩洛哥.png")
});
AddCountry(new Country()
{
CountryName = "英格兰",
WinningRatio = 85,
NationalFlag = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "NationalFlagImage\\英格兰.png")
});
}
/// <summary>
/// 添加一个国家
/// </summary>
/// <param name="country"></param>
public static void AddCountry(Country country)
{
ListWorldCup.Add(country);
}
/// <summary>
/// 两个匹配的世界杯国家进行比赛,根据胜率,进行随机,返回胜利的国家
/// 胜利国家算法如下:先随机出一个胜率之和之间的随机数,
/// 如果随机数小于【最小数的2倍】并且是奇数,则认为 胜率低的国家胜利,否则 胜率高的国家胜利
/// </summary>
/// <param name="tuple"></param>
/// <returns></returns>
public static Country SoccerGame(Tuple<Country, Country> tuple, out int randomNumber)
{
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);
Country bigWin = null;//高胜率
Country 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倍】并且是奇数,则认为 胜率低的国家胜利,否则 胜率高的国家胜利
return smallWin;
}
return bigWin;
}
}
}
窗体FormWorldCupRanking,源程序如下:
(忽略设计器自动生成的代码)
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 WorldCupRankingDemo
{
public partial class FormWorldCupRanking : Form
{
/// <summary>
/// 比赛次数
/// </summary>
private static int matchCount = 0;
/// <summary>
/// 获胜世界杯国家列表,将进入下一轮
/// </summary>
private static List<Country> WinCountryList = new List<Country>();
public FormWorldCupRanking()
{
InitializeComponent();
rtxtDisplay.ReadOnly = true;
}
private void FormWorldCupRanking_Load(object sender, EventArgs e)
{
CountryUtil.InitCountry();
LoadMatchCountry(CountryUtil.ListWorldCup);
}
/// <summary>
/// 随机分配参赛国家列表
/// </summary>
/// <param name="countryList"></param>
private void LoadMatchCountry(List<Country> countryList)
{
pnlWorldCup.Controls.Clear();
DisplayMessage($"开始加载世界杯参赛国家.参赛国家[{countryList.Count}]个.参赛国:\n{string.Join(",", countryList.Select(c => c.CountryName))}");
Application.DoEvents();
//Thread.Sleep(500);
int[] indexArray = new int[countryList.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[] matchNations = new string[rowCount];//比赛对战国家
for (int i = 0; i < rowCount; i++)
{
UcCountry ucCountry1 = new UcCountry();
ucCountry1.Name = $"ucCountry{i * 2 + 1}";
Country country1 = countryList[destArray[i * 2]];
ucCountry1.lblCountryName.Text = country1.CountryName;
ucCountry1.lblWinningRatio.Text = $"胜率:{country1.WinningRatio}";
ucCountry1.picNationalFlag.BackgroundImage = country1.NationalFlag;
ucCountry1.Tag = country1;
ucCountry1.Location = new Point(5, i * 200 + 5);
pnlWorldCup.Controls.Add(ucCountry1);
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;//不允许界面交互
pnlWorldCup.Controls.Add(button);
Country item2 = null;
if (i * 2 + 1 < destArray.Length)
{
//对奇数个世界杯比赛国家特殊处理,最后一个国家直接胜利
UcCountry ucCountry2 = new UcCountry();
ucCountry2.Name = $"ucCountry{i * 2 + 2}";
Country country2 = countryList[destArray[i * 2 + 1]];
ucCountry2.lblCountryName.Text = country2.CountryName;
ucCountry2.lblWinningRatio.Text = $"胜率:{country2.WinningRatio}";
ucCountry2.picNationalFlag.BackgroundImage = country2.NationalFlag;
ucCountry2.Tag = country2;
ucCountry2.Location = new Point(455, i * 200 + 5);
pnlWorldCup.Controls.Add(ucCountry2);
item2 = country2;
}
//对按钮进行数据绑定 对应两个世界杯参赛国家
button.Tag = Tuple.Create(country1, item2);
button.Click += Button_Click;
matchNations[i] = $"【{country1.CountryName} VS {(item2 == null ? "无" : item2.CountryName)}】";
}
DisplayMessage($"加载世界杯对战国家匹配完成.对战情况\n{string.Join(",\n", matchNations)}");
}
/// <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<Country, Country> tuple = button.Tag as Tuple<Country, Country>;
if (tuple == null)
{
return;
}
int randomNumber;
Country winCountry = CountryUtil.SoccerGame(tuple, out randomNumber);
WinCountryList.Add(winCountry);//将获胜国家插入列表
DisplayMessage($"世界杯参赛国家【{tuple.Item1.CountryName},胜率:{tuple.Item1.WinningRatio}】 VS 【{(tuple.Item2 == null ? "无" : $"{tuple.Item2.CountryName},胜率:{tuple.Item2.WinningRatio}")}】");
DisplayMessage($" 胜利国家【{winCountry.CountryName}】,模拟随机数【{randomNumber}】");
UcCountry ucCountry = FindWinCountry(button, winCountry);
if (ucCountry == null)
{
return;
}
Panel panel = new Panel();
panel.Name = $"panel{button.Name.Substring(6)}";
panel.Location = new Point(ucCountry.Location.X + 250, ucCountry.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;
pnlWorldCup.Controls.Add(panel);
}
/// <summary>
/// 获取两个世界杯比赛国家胜利一方对应的控件
/// </summary>
/// <param name="button"></param>
/// <param name="winCountry"></param>
/// <returns></returns>
private UcCountry FindWinCountry(Button button, Country winCountry)
{
int index = int.Parse(button.Name.Substring(6)) - 1;
Control[] controls = pnlWorldCup.Controls.Find($"ucCountry{index * 2 + 1}", true);
Control[] controls2 = pnlWorldCup.Controls.Find($"ucCountry{index * 2 + 2}", true);
if (controls != null && controls.Length > 0)
{
Country cTemp = ((UcCountry)controls[0]).Tag as Country;
if (cTemp.CountryName == winCountry.CountryName)
{
return (UcCountry)controls[0];
}
else
{
if (controls2 != null && controls2.Length > 0)
{
cTemp = ((UcCountry)controls2[0]).Tag as Country;
if (cTemp.CountryName == winCountry.CountryName)
{
return (UcCountry)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)
{
Country[] FinalTwoCountry = new Country[2];//最终决赛的两个国家,分出冠军、亚军
do
{
WinCountryList.Clear();
for (int i = 0; i < matchCount; i++)
{
Button button = pnlWorldCup.Controls.Find($"button{i + 1}", true)[0] as Button;
Button_Click(button, null);
Application.DoEvents();
Thread.Sleep(2000);
}
if (WinCountryList.Count == 1)
{
//只有最后一个胜利国家,循环终止,找到亚军
Country secondPlace = Array.Find(FinalTwoCountry, c => c.CountryName != WinCountryList[0].CountryName);
DisplayMessage($"最终胜利国家,冠军【{WinCountryList[0].CountryName}】,亚军【{secondPlace.CountryName}】");
MessageBox.Show($"最终胜利国家,冠军【{WinCountryList[0].CountryName}】,亚军【{secondPlace.CountryName}】", "圆满结束");
break;
}
DisplayMessage($"当前胜利的世界杯国家为【{string.Join(",", WinCountryList.Select(country => country.CountryName))}】");
Application.DoEvents();
Thread.Sleep(3000);
if (WinCountryList.Count == 2)
{
WinCountryList.CopyTo(FinalTwoCountry);
string worldCupBattle = $"世界杯决战即将开始,最终决赛双方:【{WinCountryList[0].CountryName} VS {WinCountryList[1].CountryName}】";
DisplayMessage(worldCupBattle);
Application.DoEvents();
Thread.Sleep(1000);
MessageBox.Show(worldCupBattle, "世界杯决战");
}
LoadMatchCountry(WinCountryList);
} while (WinCountryList.Count >= 2);
}
private void btnRefresh_Click(object sender, EventArgs e)
{
WinCountryList.Clear();
FormWorldCupRanking_Load(null, null);
}
}
}
窗体运行如图:
四强比赛:
世界杯决赛: