c# newb question from "Head Start C# Greyhound Lab" - c#

i'm new at C # and i'm creating a racetrack simulator, but i'm currently encountering some issues when i run my code. I have an array of four Greyhound objects, and if I call Greyhound.Run on my form1.cs and i don't have a "MessageBox.Show("Distance" + distance)" on my Run method, which shows me how many pixels each greyhound is supposed to move, all of the greyhounds end up moving the same distance. I don't understand why this is happening
namespace Race
{
class Greyhound
{
public int StartingPosition;
public int RacetrackLength;
public PictureBox MyPictureBox = null;
public int Location = 0;
public Random Randomizer;
public bool Run()
{
Point p = MyPictureBox.Location;
if (p.X + MyPictureBox.Width >= RacetrackLength)
{
//TakeStartingPostion();
return true;
}
else
{
Randomizer = new Random();
int distance = Randomizer.Next(100);
MessageBox.Show("Distance is " + distance);
p.X += distance;
MyPictureBox.Location = p;
return false;
}
}
public void TakeStartingPostion()
{
Point P = MyPictureBox.Location;
P.X = StartingPosition;
MyPictureBox.Location = P;
}
}
}
namespace Race
{
public partial class Form1 : Form
{
Guy[] guys = new Guy[3];
Greyhound[] hounds = new Greyhound[4];
public Form1()
{
InitializeComponent();
hounds[0] = new Greyhound()
{
StartingPosition = 12,
MyPictureBox = GreyHound1,
RacetrackLength = 636
};
hounds[1] = new Greyhound()
{
StartingPosition = 12,
MyPictureBox = GreyHound2,
RacetrackLength = 636
};
hounds[2] = new Greyhound()
{
StartingPosition = 12,
MyPictureBox = GreyHound3,
RacetrackLength = 636
};
hounds[3] = new Greyhound()
{
StartingPosition = 12,
MyPictureBox = GreyHound4,
RacetrackLength = 636
};
}
private void button2_Click(object sender, EventArgs e)
{
for (int i = 0; i < hounds.Length; i++)
{
hounds[i].Run();
}
}
}
}

It's because you're calling new Random() each time the Run() method hits the else block. The default Random constructor initializes the pseudorandom number generator based on the current time. When there's no interruption, all 4 method run at "the same time", so they spit out the same random numbers. To fix this, either create only a single Random, or else use a different seed for each one (by using the Random constructor that takes a seed as a parameter.)
Something like this would work:
public class Greyhound
{
public static Random randomizer = new Random();
// ... In the run method ...
int distance = Greyhound.randomizer.Next(100);
}
Update: As Groo points out, if you were actually calling Next() from multiple threads, the code I've shown isn't thread-safe. While that's not the case with your code, it's a good idea to be aware of issues like this earlier rather than later. The general solution to this (potential) problem is to surround the call to Next() with a lock, like so:
// ... After the declaration of randomizer ...
private static object randomLock = new object();
// ... New Next() call...
lock (randomLock)
Greyhound.randomizer.Next(100);

Since you probably call the Run methods of all of your objects quickly in succession, each instance of the Random class gets instantiated with the same seed, returning the same pseudo-random number.
You can solve this problem by creating a static random class which will have a single (Singleton) Random instance, making sure that each of your callers gets the next number in succession.
With some locking for thread safety, it would look something like:
public class StaticRandom
{
private static readonly Random _r = new Random();
private static object _lock = new object();
public static int Next(int max)
{
lock (_lock)
return _r.Next(max);
}
}
And then use it without instantiating it:
// no need for the "Randomizer" field anymore
int distance = StaticRandom.Next(100);
Jon Skeet has the full implementation in his miscutil library, along with some usage info.

Related

How to get some random numbers printing continually in the console?

My problem is that when I am trying to use Unity to spawn some objects at randomized locations, for some unknown reason, the location of those spawned objects is the same location.
I tried to add Thread.Sleep() to my code and the location will be randomized.
Here is an example:
class Program
{
static void Main(string[] args)
{
var mytest = new Program();
Console.WriteLine(mytest.test());
Thread.Sleep(500);
Console.WriteLine(mytest.test());
Thread.Sleep(500);
Console.WriteLine(mytest.test());
Thread.Sleep(500);
}
public int test()
{
Random random = new Random();
int testrandom = random.Next(5, 100);
return testrandom;
}
}
I don't want to use Thread.Sleep() all the time, is there a way to get past this problem?
While using debugging, I found that without using Thread.Sleep(), the local variable testrandom will be randomly updated as testrandom = 30,testrandom=32,testrandom=13..., but the result is different, the result is testrandom=30 and repeats itself 3 times. Can someone tell me why is this happening? Maybe it runs too fast?
.NET Random class is seeded by system clock if no explicit seed is given, so if you create new instances in short time apart from each other each instance will give you same number. This is also reason why adding sleep between calls to mytest.test() mitigates problem, as system clock has advanced by the time Thread.Sleep is over.
You should reuse same instance of Random, and use that instance every time:
class Program
{
private Random random = new Random();
static void Main(string[] args)
{
var mytest = new Program();
Console.WriteLine(mytest.test());
Console.WriteLine(mytest.test());
Console.WriteLine(mytest.test());
}
public int test()
{
int testrandom = random.Next(5, 100);
return testrandom;
}
}
Also, you can declare your test() method and Random instance as static, so you don't have to create instance of Program-class:
class Program
{
private static Random random = new Random();
static void Main(string[] args)
{
Console.WriteLine(test());
Console.WriteLine(test());
Console.WriteLine(test());
}
public static int test()
{
int testrandom = random.Next(5, 100);
return testrandom;
}
}

Change timer at runtime c#

Iv'e created a timer using dispatcher time :
time = new DispatcherTimer();
time.Interval = new TimeSpan(0, 0, 0, 0, 80);
and I use it for the speed of an object.Each tick the objects moves 10 pixels.
I would like to know how to increase the speed of the object without changing the pixels it moves each tick, meaning I want to make the timer itself faster during run time every 10 seconds or so.
Is there a way I can do it?Ive tried making a variable speed=0 and increasing it each time I count 10 and then
time.Interval = new TimeSpan(0, 0, 0, 0, 80-speed);
but The object stayed in the same speed.So do I have to make my own timer class instead of using the built in dispatcher time, if so how do I do that?or is there another solution for this?
I think that DispatcherTimer is not your best ally for this task. The class is by no means designed to execute actions at precise intervals.
I'll try to better explain myself: even if the DispatcherTimer, as its name suggests, dispatches actions timely and with a great precision, the dispatched actions will be queued and then executed when the underlying GUI thread decides to process them.
Normally, a GUI thread has a resolution of around 8ms (it's an approximation, but I don't think we need to measure this right now)... and you are using a starting Interval of 80ms that is going to decrease over time until it probably goes beyond that tolerance limit of 8ms or so. In the meanwhile, you are also repainting your interface (or part of it) over and over and this impacts the performance and the responsiveness of the GUI even more: if the GUI thread is busy repainting and that requires more than the Interval value to be accomplished, the next dispatched action will be processed only once the GUI thread completes the undergoing task.
If you need a more precise scheduling, avoiding hangings / losses of responsiveness / delayed actions, you need to use a timer class that runs in background like System.Threading.Timer (google for SyncronizationContext, that would be helpful) or System.Timers.Timer.
On the top of that, never play with intervals when showing a change in speed. Work with a fixed interval and increase/decrease the movement "size" in pixels. You should be able to calculate the delta without problems. Just to make things clearer: if I want to slow that the speed of an object doubled, I don't half the timer interval that draws the object, but I double the amount of pixels my object traverses at each step.
using System;
using System.Collections.Generic;
using System.Linq;
namespace CQRS_and_EventSourcing
{
internal class Program
{
//CQRS = command query responsibility segregation
//CQS= command query separation
//COMMAND
public class PersonStroge
{
Dictionary<int, Person> people;
}
public class Person
{
public int UniqueId;
public int age;
EventBroker broker;
public Person(EventBroker broker)
{
this.broker = broker;
broker.Commands += BrokerOnCommands;
broker.Queries += BrokeronQueries;
}
private void BrokeronQueries(object sender, Query query)
{
var ac = query as AgeQuery;
if (ac != null && ac.Target == this)
{
ac.Result = age;
}
}
private void BrokerOnCommands(object sender, Command command)
{
var cac = command as ChangeAgeCommand;
if (cac != null && cac.Target == this)
{
if (cac.Register)
broker.AllEvents.Add(new AgeChangedEvent(this, age, cac.Age));
age = cac.Age;
}
}
public bool CanVote => age >= 16;
}
public class EventBroker
{
//1. All events that happened.
public IList<Event> AllEvents = new List<Event>();
//2. Commands
public event EventHandler<Command> Commands;
//3. Query
public event EventHandler<Query> Queries;
public void Command(Command c)
{
Commands?.Invoke(this, c);
}
public T Query<T>(Query q)
{
Queries?.Invoke(this, q);
return (T)q.Result;
}
public void UndoLast()
{
var e = AllEvents.LastOrDefault();
var ac = e as AgeChangedEvent;
if (ac != null)
{
Command(new ChangeAgeCommand(ac.Target, ac.OldValue) { Register = false });
AllEvents.Remove(e);
}
}
}
public class Query
{
public object Result;
}
public class AgeQuery : Query
{
public Person Target;
}
public class Command : EventArgs
{
public bool Register = true;
}
public class ChangeAgeCommand : Command
{
public Person Target;
//public int TargetId;
public int Age;
public ChangeAgeCommand(Person target, int age)
{
Target = target;
Age = age;
}
}
public class Event
{
//backtrack
}
public class AgeChangedEvent : Event
{
public Person Target;
public int OldValue, NewValue;
public AgeChangedEvent(Person target, int oldValue, int newValue)
{
Target = target;
OldValue = oldValue;
NewValue = newValue;
}
public override string ToString()
{
return $"Age changed from {OldValue} to {NewValue}";
}
}
static void Main(string[] args)
{
var eb = new EventBroker();
var p = new Person(eb);
eb.Command(new ChangeAgeCommand(p, 123));
foreach (var e in eb.AllEvents)
{
Console.WriteLine(e);
}
//int age;
//age = eb.Query<int>(new AgeQuery { Target = p });
//Console.WriteLine(age);
//eb.UndoLast();
//foreach (var e in eb.AllEvents)
//{
// Console.WriteLine(e);
//}
//age = eb.Query<int>(new AgeQuery { Target = p });
//Console.WriteLine(age);
Console.ReadKey();
}
}
}
İf you couldnt make look at this repository;
[1]:https://github.com/kYasinAblay/DNesteruk.Additional.Lectures/blob/master/CQRS_and_EventSourcing/Program.cs

Manipulate form control properties from other classes?

I'm trying to manipulate the properties of a control in my main form via one of my classes.
Basically I'm trying to update a label, I've set it to public like so:
public Label DicerollLabel;
And I'm refering to my main form from my class like this:
private Form1 _mainForm;
When I try to access the label and set a value to it like this:
_mainForm.DicerollLabel.Text = "Hello World!";
I get the following error:
An unhandled exception of type 'System.NullReferenceException' occurred.
My entire code to the two files involed is below:
Main Form:
namespace BettingGame
{
public partial class Form1 : Form
{
private Player _playerOne;
private Player _playerTwo;
private DiceRoller _diceRoller;
private decimal _prizePool;
private Random _random;
public int ProgressBar
{
get {return progressBar1.Value;}
set { progressBar1.Value = value; }
}
public Label DicerollLabel;
public Form1()
{
InitializeComponent();
_playerOne = new Player() {PlayerName = "x", PlayerFunds = 100};
_playerTwo = new Player() {PlayerName = "x", PlayerFunds = 100};
_diceRoller = new DiceRoller();
_random = new Random();
playerOneFundsLabel.Text = "Funds: " + _playerOne.PlayerFunds.ToString(CultureInfo.CurrentCulture) + "$";
playerTwoFundsLabel.Text = "Funds: " + _playerTwo.PlayerFunds.ToString(CultureInfo.CurrentCulture) + "$";
PrizeAmountLabel.Text = "";
diceRollLabel.Text = "";
}
private void button1_Click(object sender, EventArgs e)
{
_playerOne.PlayerBetAmount = (decimal) playerOneBet.Value;
_playerTwo.PlayerBetAmount = (decimal) playerTwoBet.Value;
if (!(_playerOne.PlayerBetAmount <= 0) || !(_playerTwo.PlayerBetAmount <= 0)
&& (_playerOne.PlayerBetAmount > 0) && (_playerTwo.PlayerBetAmount > 0))
{
_prizePool = _playerOne.PlayerBet() + _playerTwo.PlayerBet();
PrizeAmountLabel.Text = _prizePool.ToString(CultureInfo.CurrentCulture);
FormUpdate();
}
else
{
MessageBox.Show("Invalid bets! Bet amount must be greater than 0!");
}
}
private void FormUpdate()
{
playerOneFundsLabel.Text = "Funds: " + _playerOne.PlayerFunds.ToString(CultureInfo.CurrentCulture) + "$";
playerTwoFundsLabel.Text = "Funds: " + _playerTwo.PlayerFunds.ToString(CultureInfo.CurrentCulture) + "$";
}
private void button2_Click(object sender, EventArgs e)
{
//for (int i = 0; i < 45; i++)
//{
// int value = _random.Next(1, 50);
// diceRollLabel.Text = value.ToString();
// diceRollLabel.Update();
// Thread.Sleep(50);
//}
_diceRoller.RollDice();
}
}
}
And the DiceRoller class:
namespace BettingGame
{
class DiceRoller
{
private Random _random = new Random();
private Form1 _mainForm;
public void RollDice()
{
_mainForm.DicerollLabel.Text = "Hello World!";
}
}
What am I doing wrong? Note that I'm only in my second week of programming so I'm still learning!
change your DiceRoller class to define the following constructor:
public DiceRoller(Form1 host) {
_mainForm = host;
}
Then in your Form1 where you create an instance of DiceRoller:
private DiceRoller _diceRoller = new DiceRoller(this);
This is a really terrible design long term. It's definitely code I would expect from a new programmer - so don't feel bad. You're doing fine.
In the future try to think about reusability. By making your DiceRoller dependent on Form1 (and the specific controls in Form1) you are faced with two challenges later on:
1. You can not use DiceRoller in another project (or possibly even in your same project) without modification.
2. If you change any of the controls that DiceRoller depends upon you must also change DiceRoller.
I'll let you think about how you might avoid these issues. I'm sure if you need help with them you'l post another question. :)
You need to have a reference to the Form1 created. This is not named Form1, but within the Form1 you can refer to it using the keyword "this" and you can pass that into a constructor for your DiceRoller class.
class DiceRoller
{
private Random _random = new Random();
private Form1 _mainForm;
public DiceRoller(Form1 f)
{
_mainForm = f;
}
public void RollDice()
{
_mainForm.DicerollLabel.Text = "Hello World!";
}
}
Then you call this within your constructor for Form1:
public Form1()
{
InitializeComponent();
_playerOne = new Player() {PlayerName = "x", PlayerFunds = 100};
_playerTwo = new Player() {PlayerName = "x", PlayerFunds = 100};
_diceRoller = new DiceRoller(this);
....
These are the minimal changes needed to make your code work. However, you might consider other changes such as passing in the label instead of the form.

How to know if EventWaitHandle.Set was invoked

Is there a way to know which EventWaitHandle was invoked.
i have two custom class with 2 different System Wide Event names.
The reason I had them is to distinguish which function to trigger.
The problem I have right now is how can I distinguish which event was triggered?
EventWaitHandle _ew1 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode1");
EventWaitHandle _ew2 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode2");
So if _ew1.Set() is invoked then I need to execute Process1.
If _ew2.Set() is invoked then I need to execute Process2.
Update: Added More Info.
the main thread is a windows service. which is signaled by a web application and a desktop application. so basically the service needs to identify who triggered the event either from a web application or a desktop application if it's a WebAppliation then Execute SP1 else if it's a Windows Application then Execute SP2.
Idea 1
WaitHandle.WaitAny static method returns index of signaled wait handle, so the simplest solution would be to check that index.
Example
static class Program
{
private static Random _random = new Random();
private static AutoResetEvent[] _eventHandles = new[] {new AutoResetEvent(false), new AutoResetEvent(false)};
static void Main()
{
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
var handleIndex = WaitHandle.WaitAny(_eventHandles);
Console.WriteLine(handleIndex == 0 ? "Process1" : "Process2");
}
}
static void Method()
{
if (_random.Next()%2 == 0)
_eventHandles[0].Set();
else
_eventHandles[1].Set();
}
}
Idea 2
You can also use one event handle along with a volatile field that will indicate what conditional statement has been met in order to execute appropriate process after signal.
Example
enum Process
{
Process1,
Process2
}
static class Program
{
private static Random _random = new Random();
private static AutoResetEvent _eventHandle = new AutoResetEvent(false);
private static volatile Process _selectedProcess = Process.Process1;
static void Main()
{
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
_eventHandle.WaitOne();
Console.WriteLine(_selectedProcess == Process.Process1 ? "Process1" : "Process2");
}
}
static void Method()
{
_selectedProcess = _random.Next()%2 == 0 ? Process.Process1 : Process.Process2;
_eventHandle.Set();
}
}
Idea 3
If you are unable to modify external components and you have only event handles, then you may try start new threads for each option and wait there for respective signal in order to perform appropriate operation.
Example
static class Program
{
private static Random _random = new Random();
private static AutoResetEvent[] _eventHandles = new[] {new AutoResetEvent(false), new AutoResetEvent(false)};
static void Main()
{
Thread[] processThreads = new Thread[2];
processThreads[0] = new Thread(Process1);
processThreads[0].Start();
processThreads[1] = new Thread(Process2);
processThreads[1].Start();
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
}
}
static void Method()
{
if (_random.Next()%2 == 0)
_eventHandles[0].Set();
else
_eventHandles[1].Set();
}
static void Process1()
{
while (true)
{
_eventHandles[0].WaitOne();
Console.WriteLine("Process1");
}
}
static void Process2()
{
while (true)
{
_eventHandles[1].WaitOne();
Console.WriteLine("Process2");
}
}
}
Idea 4
If processes require small amount of time, you can use ThreadPool.RegisterWaitForSingleObject Method
Example
static class Program
{
private static Random _random = new Random();
private static AutoResetEvent[] _eventHandles = new[] {new AutoResetEvent(false), new AutoResetEvent(false)};
static void Main()
{
ThreadPool.RegisterWaitForSingleObject(_eventHandles[0], Process1, null, Timeout.Infinite, false);
ThreadPool.RegisterWaitForSingleObject(_eventHandles[1], Process2, null, Timeout.Infinite, false);
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
}
}
static void Method()
{
if (_random.Next()%2 == 0)
_eventHandles[0].Set();
else
_eventHandles[1].Set();
}
static void Process1(object state, bool timedOut)
{
Console.WriteLine("Process1");
}
static void Process2(object state, bool timedOut)
{
Console.WriteLine("Process2");
}
}
Use WaitHandle.WaitAny to wait on multiple event handles. When one or more of the events is set it'll return the index of the event that caused the wait to return.
EventWaitHandle _ew1 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode1");
EventWaitHandle _ew2 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode2");
WaitHandle[] handles={_ew1, _ew2};
int index=WaitHandle.WaitAny(handles)
if(index==0)
{
// mode 1
}
else if(index==1)
{
// mode 2
}
An IDEA I can suggests is to create your own EventWaitHandler, that can reuse the name of handler, later this name should be returned from the Wait method and works as an identifier of caller
for this you have to implement your own Wait method (i implemented WaitNew to cater and extend WaitOne)
See the following code for working code:
//Client application environments
public class WindowsApplication
{
public void ExecuteWindowsService()
{
var ws = new WindowsService();
var _eventHandle = new MyEventWaitHandler(false, EventResetMode.AutoReset, "WindowsApplicationMode");
ws.Execute(_eventHandle);
_eventHandle.Set();
}
}
public class WebApplication
{
public void ExecuteWebService()
{
var ws = new WindowsService();
var _eventHandle = new MyEventWaitHandler(false, EventResetMode.AutoReset, "WebApplicationMode");
ws.Execute(_eventHandle);
_eventHandle.Set();
}
}
//Windows Service Environment
public class MyEventWaitHandler : EventWaitHandle
{
public MyEventWaitHandler(bool initialState, EventResetMode mode, string name)
: base(initialState, mode, name)
{
this.EventHandlerName = name;
}
//it should not be set to empty string from external
public string EventHandlerName;
public string WaitNew()
{
if (base.WaitOne())
return EventHandlerName;
else return String.Empty;
}
}
public class WindowsService
{
public void Execute(MyEventWaitHandler _eventHandle)
{
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
string name = _eventHandle.WaitNew();
if (name == "WindowsApplicationMode")
{
//Execute case for first process
}
else if (name == "WebApplicationMode")
{
//Execute case for second process
}
}
}
static void Method()
{
//Some Task
}
}
Let me know if I understand your requirement correct?
Inherit from EventWaitHandle, add a volatile "Caller" property. Every signaller must pass his ID, or Ref.
After Signalled, Interlock check the property.
How about this?
bool signaled = eventWaitHandle.WaitOne(TimeSpan.Zero);

A integer isn't upgraded by a thread c#

I have declared in C# a static public int then that int is suplyed to a thread in it's constructor the thread's job is very simple to increment it but it doesn't happen
Here I declare the static value:
class Global
{
static public int hardcap = 100;
public int speed;
static public Semaphore myhitpoints = new Semaphore(1, 1);
static public Semaphore oponenthitpoints = new Semaphore(1, 1);
static public int mhp = 100;
static public int ohp = 100;
static public int mmana = 0;
static public int omana = 0;
public static Charm dragonblade = new Charm(10, 30, 3, myhitpoints, oponenthitpoints, mhp, ohp, "dragon blade", mmana);
public static Charm dragonshield = new Charm(30, 10, 5, myhitpoints, oponenthitpoints, mhp, ohp, "dragon shield", mmana);
public static Charm b1charm;
public static Charm b2charm;
public static Opponent enemy;
}
class ManaWell
{
int mana_regen;
int cap = 1000;
int target;
public ManaWell(int x, int y)
{
mana_regen = x;
target = y;
}
public void Refill()
{
while (true)
{
// if (this.target + mana_regen <= cap)
if (target+mana_regen<cap)
{
Thread.Sleep(3000);
target += mana_regen;
MessageBox.Show(target.ToString());
}
}
}
}
ManaWell mw1 = new ManaWell(20,Global.mmana);
ManaWell mw2 = new ManaWell(20,Global.omana);
Thread tmw1 = new Thread(new ThreadStart(mw1.Refill));
Thread tmw2 = new Thread(new ThreadStart(mw2.Refill));
tmw1.Start();
tmw2.Start();
So target works fine but y won't increase.
Integer is passed as value and gets locally increased. it will not increase the statical variable which you pass in
Value vs Reference Types
If you want that your external static variable gets updated you could use the ref keyword.
Beside that you should synchronize the access to the variable as you access it from several threads...
if you have "targets" which should be stored and called later you should pass a delegate (which is pointing to the update method) to the constructor. this delegate you can store and call later
When you create your ManaWell object and pass in a variable, it will only be the variable's value that is assigned to target. So when you add to target, you are doing only that; the passed-in variable will not be affected (as you're seeing.)
If you're really passing in a public static int, then to increase it, just do math on it directly (and you don't even have to pass it in):
MyClass.MyStaticInt += aNumber;
The reason is that the value of the variable is passed to the constructor. You are only incrementing the variable local to your class.

Categories