Dice
必要な値を提供する小さなクラスを作成しました。
public class Dice
{
private Random _Random;
private BackgroundWorker _Worker;
/// <summary>
/// Initializes a new instance of the <see cref="Dice"/> class.
/// </summary>
public Dice()
{
_Random = new Random();
InitializeDefaultValues();
InitializeBackgroundWorker();
}
/// <summary>
/// Occurs when the dice finished rolling.
/// </summary>
public event EventHandler Rolled;
/// <summary>
/// Occurs while the dice is rolling and the value has changed.
/// </summary>
public event EventHandler RollingChanged;
/// <summary>
/// Gets or sets the including maximum value that the dice can return.
/// </summary>
/// <value>
/// The maximum value.
/// </value>
[DefaultValue(6)]
public int Maximum { get; set; }
/// <summary>
/// Gets or sets the including minimum value that the dice can return.
/// </summary>
/// <value>
/// The minimum.
/// </value>
[DefaultValue(1)]
public int Minimum { get; set; }
/// <summary>
/// Gets the result that this dice currently has.
/// </summary>
public int Result { get; private set; }
/// <summary>
/// Gets or sets the duration of the rolling.
/// </summary>
/// <value>
/// The duration of the rolling.
/// </value>
[DefaultValue(typeof(TimeSpan), "00:00:03")]
public TimeSpan RollingDuration { get; set; }
/// <summary>
/// Starts rolling the dice.
/// </summary>
public void Roll()
{
if (!_Worker.IsBusy)
{
CheckParameters();
_Worker.RunWorkerAsync();
}
}
private void CheckParameters()
{
if (Minimum >= Maximum)
{
throw new InvalidOperationException("Minimum value must be less than the Maximum value.");
}
if (RollingDuration <= TimeSpan.Zero)
{
throw new InvalidOperationException("The RollingDuration must be greater zero.");
}
}
private void InitializeBackgroundWorker()
{
_Worker = new BackgroundWorker();
_Worker.WorkerReportsProgress = true;
_Worker.DoWork += OnWorkerDoWork;
_Worker.ProgressChanged += OnWorkerProgressChanged;
_Worker.RunWorkerCompleted += OnWorkerRunWorkerCompleted;
}
private void InitializeDefaultValues()
{
Minimum = 1;
Maximum = 6;
Result = Minimum;
RollingDuration = TimeSpan.FromSeconds(3);
}
private void OnWorkerDoWork(object sender, DoWorkEventArgs e)
{
var finishTime = DateTime.UtcNow + RollingDuration;
while (finishTime > DateTime.UtcNow)
{
Result = _Random.Next(Minimum, Maximum + 1);
_Worker.ReportProgress(0);
// ToDo: Improve sleep times for more realistic rolling.
Thread.Sleep(50);
}
}
private void OnWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
RaiseEvent(RollingChanged);
}
private void OnWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
RaiseEvent(Rolled);
}
private void RaiseEvent(EventHandler handler)
{
var temp = handler;
if (temp != null)
{
temp(this, EventArgs.Empty);
}
}
}
最初の簡単な例では、フォーム(buttonRoll
)とラベル(labelDiceResult
)にボタンを追加し、次のコードを追加しました(フォームコンストラクターにinitializeメソッドを追加することを忘れないでください)。
private void InitializeDice()
{
_Dice = new Dice();
_Dice.RollingChanged += OnDiceRollingChanged;
_Dice.Rolled += OnDiceRolled;
}
void OnDiceRolled(object sender, EventArgs e)
{
buttonRoll.Enabled = true;
}
void OnDiceRollingChanged(object sender, EventArgs e)
{
// ToDo: Select desired picture from image list depending on _Dice.Result
labelDiceResult.Text = _Dice.Result.ToString();
}
private void OnButtonRollClick(object sender, EventArgs e)
{
buttonRoll.Enabled = false;
_Dice.Roll();
}
Thread.Sleep(50)
最後のステップとして、副鼻腔の立ち上がり部分とサイコロを時間の経過とともに遅くするための望ましい期間に応じて計算されたリストを使用して、時間の経過とともに異なる値を使用するように呼び出しを微調整します。しかし、私はこの部分を読者(または次の質問)に公開しました。