Ich versuche, Monte-Carlo-Simulation in C# Windows Form Anwendung mit gewichteten Quick Union mit Pfadkomprimierung Methode zu implementieren. Zum einen nehme ich gridSize
und erzeugen dann ein Gitter zu gridSize * gridSize
gleich und besteht aus schwarzem Hintergrund Etiketten, die Websites darstellen, dann ich zufällig Vereinigung einige Websites und ihren Hintergrund in weiß machen. Das Problem ist, wenn ich das Projekt laufen lasse, bekomme ich die ganzen Seiten in schwarz -noch egal, wie oft ich versuche-, aber wenn ich Haltepunkte hinzugefügt habe und Schritt für Schritt vorgegangen bin, bekomme ich einige weiße Seiten wie beabsichtigt !!! HierSeltsames Verhalten bei der Implementierung von Monte Carlo Simulation in C#
ist der Code:
public partial class Form1 : Form
{
int gridSize = 0;
byte siteSize = 50;
FlowLayoutPanel flowLayoutPanel;
UnionFind uf;
int randomFirstNumber;
int randomSecondNumber;
string labelName = string.Empty;
Random rnd = new Random();
int numberOfAttempts;
Label label;
HashSet<int> excludeHashSet = new HashSet<int>();
public Form1()
{
InitializeComponent();
}
private void setGridSizeButton_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(gridSizeTextbox.Text) && int.TryParse(gridSizeTextbox.Text, out gridSize))
{
if (gridSize > 0)
{
var flowLayoutPanel = createFlowLayoutPanelAndLabels();
setGridSizeButton.Enabled = false;
gridSizeTextbox.Enabled = false;
randomlyUnionSitesAndWhiteThem();
}
}
}
private void reset_Click(object sender, EventArgs e)
{
setGridSizeButton.Enabled = true;
gridSizeTextbox.Enabled = true;
gridSizeTextbox.Text = string.Empty;
flowLayoutPanel.Dispose();
excludeHashSet = new HashSet<int>();
gridSizeTextbox.Focus();
}
private FlowLayoutPanel createFlowLayoutPanelAndLabels()
{
flowLayoutPanel = new FlowLayoutPanel();
flowLayoutPanel.Name = "flowLayoutPanel";
flowLayoutPanel.Location = new Point(30, 60);
flowLayoutPanel.Size = new Size(gridSize, gridSize);
flowLayoutPanel.BorderStyle = BorderStyle.Fixed3D;
flowLayoutPanel.Width = siteSize * gridSize + 10 * gridSize;
flowLayoutPanel.Height = siteSize * gridSize + 10 * gridSize;
for (int i = 0; i < gridSize * gridSize; i++)
{
var label = new Label();
label.Text = "";
label.Name = i.ToString();
label.Width = siteSize;
label.Height = siteSize;
label.BackColor = Color.Black;
label.Margin = new Padding(3);
label.BorderStyle = BorderStyle.FixedSingle;
flowLayoutPanel.Controls.Add(label);
}
this.Controls.Add(flowLayoutPanel);
return flowLayoutPanel;
}
private void randomlyUnionSitesAndWhiteThem()
{
uf = new UnionFind(gridSize * gridSize);
numberOfAttempts = rnd.Next(0, gridSize * gridSize);
for (int i = 0; i < numberOfAttempts; i++)
{
randomFirstNumber = getRandomNumber(0, gridSize * gridSize, excludeHashSet);
randomSecondNumber = getRandomNumber(0, gridSize * gridSize, excludeHashSet);
labelName = uf.union(randomFirstNumber, randomSecondNumber).ToString();
if (Convert.ToInt16(labelName) > -1)
{
label = (Label)flowLayoutPanel.Controls.Find(labelName, false).First();
label.BackColor = Color.White;
excludeHashSet.Add(Convert.ToInt16(labelName));
}
}
}
private int getRandomNumber(int min, int max, HashSet<int> excludes)
{
int randomNumber;
do
{
var range = Enumerable.Range(min, max).Where(i => !excludes.Contains(i));
var rand = new Random();
int index = rand.Next(0, max - excludes.Count);
randomNumber = range.ElementAt(index);
}
while (excludes.Any(x => x == randomNumber));
return randomNumber;
}
}
Und das ist mein Union
Methode:
class UnionFind
{
.....
public int union(int firstNumber, int secondNumber)
{
firstNumber = getRoot(firstNumber);
secondNumber = getRoot(secondNumber);
if (firstNumber == secondNumber)
{
return -1;
}
if (sizes[firstNumber] < sizes[secondNumber])
{
array[firstNumber] = secondNumber;
sizes[secondNumber] += sizes[firstNumber];
return array[firstNumber];
}
else
{
array[secondNumber] = firstNumber;
sizes[firstNumber] += sizes[secondNumber];
return array[secondNumber];
}
}
.....
}
Also, im Grunde war Alex richtig, auch wenn die Erklärung einige Details verpasste.Und wenn man eine einzelne "Random" -Instanz anstelle einer neuen basierend auf der aktuellen Zeit verwendet, dann erscheint eine weitere neue, die ebenfalls auf der (unveränderten) aktuellen Zeit basiert, als eine viel bessere Lösung als willkürlich gewählte Verzögerungen, um zu verhindern, dass die gleiche Zeit gesehen wird zweimal. – hvd