Trying to call another GUI method within a different method c# - c#

I'm having a little trouble concisely describing what it is that I'm trying to do, which is hurting my ability to search for an answer. I'll try to be specific with my problem, if anyone could give a suggestion or point me in the direction of what to study, I'd greatly appreciate it.Tr
I'm trying to program a GUI version of the cardgame Dominion, where playing different cards will yield different results and choices. Many of these cards have similar starting choices (e.g. select a card from your hand and trash it/look at enemy hand), but different ending choices (e.g. upgrade that trashed card/give trashed card to another player). upon playing a card, the program looks for the unique numeric card code and begins executing code specific to that card.
Here's where I'm hung up:
I'd like to have more general methods that listen for user input INSIDE the unique card-code, but I keep getting errors. Ideally, I'd be able to do something like
for(int i = 0; i < totalPlayers; i++)
{
showEnemyHand(i);
}
or
for(int i = 0; i < totalPlayers; i++)
{
thiefEffect(i);
}
within a 'buttonclicked' event (the "play card" button, specifically.) The showEnemyHand(int) and thiefEffect(int) method would wait for user input, store responses, and then return right back to the for loop that it was called from, but its not as easy as I'd originally hoped.
I'm suffering most from not even knowing what it is that I should be searching for. I've been reading up on event handling and delegates, and I'm not sure that's what I need. Can anyone point me in the direction of what I need to learn, or maybe give me the topic of what I'm trying to solve so I can search for it a little easier? (of course, helping me solve it would be appreciated too =D)
Thanks a bunch!
Jake

Your solution would be fine for a command line based game, in a language with continuations/coroutines, or maybe in a multi-threaded application where showEnemyHand etc would block on user input. For a GUI-based game, an event driven architecture is really what would work best for you, so in principle I'd suggest learning more about it.
But if you really want to do that using a loop, I'd suggest then reading about threading and blocking calls. Once you understand the concepts, you should be able to:
Create a separate thread to host your loop;
Create a lock that will block execution until the user inputs something (see the example in the linked question);
Use that lock in your loop and on the callback for user input:
In the beginning of your loop, you wait on your lock;
When the user inputs something (which you'll detect using an event handler - see the docs for the particular GUI framework you're using) you save which action was chosen and frees the lock;
Your loop will automatically continue, reading the saved action and performing an iteration, until it reachs the same point again and waits for another user input.
Whether this method is easier or harder than coding your rules using the event driven logic, it's debatable. The same can be said about coroutines (though being less experienced with that, I can not opinate). The pointers I gave should help you get started though.

Related

Problem with adding with ++ operator, what can I do?

So, I as trying to create an "Open world exploration" game in C# WinForms, And while coding the mining, (which works just fine), I encountered a problem with saving the number of broken blocks to the inventory (a label). Basically, for every block player breaks, it gets added to the inventory as inventoryWrite.Text = $"Grass: {grassHolder}, Rock: {rockHolder}";.
Now, the thing is, sometimes, even though I use the ++ operator, it adds up to 4 to the inventory. I'm citing the code below.
private void Remove(object sender, EventArgs e, PictureBox itm)
{
if (itm.BorderStyle == BorderStyle.FixedSingle)
{
if (itm.Tag.Equals("grass") && items.Contains(itm))
{
grassHolder++;
itm.Tag = "";
}
if (itm.Tag.Equals("rock") && items.Contains(itm))
{
rockHolder++;
itm.Tag = "";
}
if (itm.Tag.Equals("dio") && items.Contains(itm))
{
dioHolder++;
itm.Tag = "";
}
this.Controls.Remove(itm);
items.Remove(itm);
}
}
I update the inventory in a public loop, don't worry about that (interval is 1ms). But I don't think that's the problem, since I tried putting it in the Remove() function, and nothing seemed to change.
I've even double locked the if statement, but nothing! It still adds more than 1. Can anybody tell me how to solve this? Thank you a lot.
EDIT:
As a reply to Ronald's comment, the if statement is called ONLY when the block is selected. ONLY once when the method is called.
There are too many points to cover in a comment and so I've had to enter an answer.
In itself the ++ operator is not the issue and will always behave as it should, but as someone reviewing a small piece of code the following points crop up.
grassHolder, rockHolder, dioHolder appear to have
accessibility beyond this function and so could be altered
elsewhere.
Function void Remove(object sender, EventArgs e, PictureBox itm) appears to be an event handler and yet there is no locking mechanism to ensure that the externally accessible parameters are not changed or used elsewhere whilst the function code is executed. Specifically items which is appears to be a collection of sorts and is used both in logic to determine whether parameters in (1) are incremented, but also has its contents changed within the function.
From comments made it would appear that this logic is run in
response to user interaction, maybe by use of a mouse button or key
event. Is this base event de-bounced to ensure that multiple
triggers aren't handled?
Your statement "saving the number of broken blocks to the inventory (a label)." Implies that you are storing game data within the UI. This should be avoided as it ties game data directly to the UI implementation and therefore makes it difficult to alter the game, but also ties any handling of game data directly to the UI thread.
Recommended actions:
Ensure that the parameters in question are not accessed and altered
elsewhere causing the issue seen.
Utilize a lock(x) statement to ensure that items is not changed
whilst this function is being executed. More information here
De-bounce the mouse button or key click that triggers this function
to ensure that multiple events aren't triggered. This is performed
by placing a minimum time between event triggers. A minimum time
period of say 150ms would be a good starting point. This would equate to a reasonably quick, conscious user action, but be slower than multiple events triggered by partial/poor switch contact. Incidentally this is especially true on touch screen interfaces.
Consider controlling access to global parameters through use of
access functions. For example
int IncrementRockHolder(){ rockHolder++;} Although implementation may appear onerous, they can greatly help with debugging as call stack information is then available showing what code is calling the function and thus making the change.
Implement a game engine class to control access to game data and implement game logic. This
would allow you to unit test game functionality whilst also freeing
it from UI implementation and restrictions.

No closure for delegates in anonymous function inside foreach loop

UPDATE: turns out that this is a problem with the Mono compiler used by Unity3D. I'm not sure if the current version of Mono (3.10.0) fixes it, but the old version used in the engine (2.0.5) seems to not implement this feature for delegates, or simply work as it should.
At some point in a game I'm developing (in the Unity3D engine), the player unlocks several items at once. For each of them I must present a simple information dialog that the user must click to advance to the next, until all have been read.
I have a simple C# static method to show a dialog (just a colored overlay with some text in Unity, and NOT in any way related to C# UI frameworks):
ConfirmationDialog.Create("Item X Unlocked!", callback);
When the user finally presses the dialog, callback is called.
I wanted to chain all dialogs so that each one is only created when the previous is clicked on, so I tried this:
Action callback = delegate {};
foreach (string item in unlockedItems) {
var cb = callback; // I though this would create a closure for delegates too
callback = (() => ConfirmationDialog.Create(item + " Unlocked!", cb));
}
callback();
This made sense in my head, as the anonymous function would use a different "cb" delegate in each iteration of the cycle. It seems I'm mistaken, though, as this code seems to result in the same dialog being repeatedly called when clicked, as would happen in a recursive function (which I guess is what it became).
I know I can, for example, do int value = i; inside a for loop (where i is the loop iterator) to use the correct value of i inside the anonymous function (I found a lot of material on this). Delegates seem different, but what in particular makes them not work in the same way? Or am I doing something terribly wrong? Could I do this chaining in some similar way? I say "similar" because I can certainly think of doing this in other - more complicated - ways...
Note: please DO correct me if my use of the words "closure", "delegate", etc, is not right :)
Do you have control over the ConfirmationDialog.Create("Item X Unlocked!", callback); API? If so, instead of taking a callback, you should look at refactoring that to use Task. If you had that, you could simply chain a bunch of tasks as continuations and have them execute one after the other.
I know with game development, these things are often quite asynchronous in nature, the way UI gets shown and subsequently reacted to ... so you could use TaskCompletionSource so you have a handle to something that you can signal that your task is done.

How to break down large 'macro' classes?

One application I work on does only one thing, looking from outside world. Takes a file as input and after ~5 minutes spits out another file.
What happens inside is actually a sequential series of action. The application is, in our opinion, structured well because each action is like a small box, without too many dependencies.
Usually some later actions use some information from previous one and just a few can be executed in parallel - for the sake of simplicity we prefer to the execution sequential.
Now the problem is that the function that executes all this actions is like a batch file: a long list of calls to different functions with different arguments. So, looking in the code it looks like:
main
{
try
{
result1 = Action1(inputFile);
result2 = Action2(inputFile);
result3 = Action3(result2.value);
result4 = Action4(result1.value, inputFile);
... //You get the idea. There is no pattern passed paramteres
resultN = ActionN(parameters);
write output
}
catch
{
something went wrong, display the error
}
}
How would you model the main function of this application so is not just a long list of commands?
Not everything needs to fit to a clever pattern. There are few more elegant ways to express a long series of imperative statements than as, well, a long series of imperative statements.
If there are certain kinds of flexibility you feel you are currently lacking, express them, and we can try to propose solutions.
If there are certain clusters of actions and results that are re-used often, you could pull them out into new functions and build "aggregate" actions from them.
You could look in to dataflow languages and libraries, but I expect the gain to be small.
Not sure if it's the best approach, but you could have an object that would store all the results and you would give it to each method in turn. Every method would read the parameters it needs and write its result there. You could then have a collection of actions (either as delegates or objects implementing an interface) and call them in a loop.
class Results
{
public int Result1 { get; set; }
public string Result2 { get; set; }
…
}
var actions = new Action<Results>[] { Action1, Action2, … };
Results results = new Results();
foreach (var action in actions)
action(results);
You can think of implementing a Sequential Workflow from Windows Workflow
First of all, this solution is far not bad. If the actions are disjunct, I mean there are no global parameters or other hidden dependencies between different actions or between actions and the environment, it's a good solution. Easy to maintain or read, and when you need to expand the functionality, you have just to add new actions, when the "quantity" changes, you have just to add or remove lines from the macro sequence. If there's no need for change frequently the process chain: don't move!
If it's a system, where the implementation of actions don't often changes, but their order and parameters yes, you may design a simple script language, and transform the macro class into that script. This script should be maintained by someone else than you, someone who is familiar with the problem domain in the level of your "actions". So, he/she can assembly the application using script language without your assistance.
One nice approach for that kind of problem splitting is dataflow programming (a.k.a. Flow-based programming). In dataflow programming, there are pre-written components. Components are black boxes (from the view of the application developer), they have consumer (input) and producer (output) ports, which can be connected to form a processing network, which is then the application. If there're a good set of components for a domain, many applications can created without programming new components. Also, components can be built of other components (they called composite components).
Wikipedia (good starting point):
http://en.wikipedia.org/wiki/Dataflow_programming
http://en.wikipedia.org/wiki/Flow-based_programming
JPM's site (book, wiki, everything):
http://jpaulmorrison.com/fbp/
I think, bigger systems must have that split point you describe as "macro". Even games have that point, e.g. FPS games have a 3D engine and a game logic script, or there's SCUMM VM, which is the same.

Should I use an event to notify a class or just use return?

I'm cutting my teeth on events and delegates today and to do so, I have been toying with the idea of experience bars, those progress bars from games. But I have a question about the better way to solve my problem - it could be as simple as bad design. Let me provide you some details.
I have modelled my idea with an ExperienceBar class.
It contains properties:
int StartValue
int CurrentValue
int EndValue
and a method
void UpdateBar(int)
UpdateBar adds the parameter to CurrentValue and then tests to see if it has reached EndValue. If it exceeds the amount, the EndValue increases and the amount continues on. Note that initially in my thinking, it is not concerned with the effects of reaching the maximum amount possible, just that the end value increases and the StartValue is reset to zero.
Another class called Player has a property of class ExperienceBar.
In my little demo, when Player.ExperienceBar.UpdateBar(int) reaches the EndValue it fires an event which is handled by the Player class. It updates the Player.Level property by one.
I've just realised that I could achieve the same thing by just changing UpdateBar(int) to return type "true". This method could be tested by the Player class and when true, Player.Level increases by one.
So my question - which is the best practice way to handle this rather specific circumstance? As a general rule of thumb for these kind of situations, is it better to handle events, or is it better just to keep it simple with the testing of return statements?
PS: I hope I've made this clear as possible, but I can try to clarify if anyone is having trouble. I believe there may be some redundancies already with my idea, but try not to deviate from the question please. I'm kind of aware of them! Thank you :)
Well... To me, events is the good way to do it.
However, if I was to design the application it would be down to one question: Will the ExperienceBars's event when it reaches EndValue ever be used by anyone else than the class calling UpdateBar.
If you are designing a component to be used in many places (which seems to be the goal), the answer to me seems to be an almost certain yes, therefore my answer is use events!
/Victor
In my opinion, there's no best way to do this. There are various ways to implement the class that, depending on how it is going to be used, are a better or worse fit.
Use events when you want to implement the observer pattern for many "clients" or "observers" who need to know the state of an object and need to be alerted when that state changes. this works for the degenerate case where there is only one client, but the caller of the the method that changes the object's state is not the one that needs to know about the change.
Use return values when the state only needs to be known by the caller, there are no other observers of the class. This is simple, and limits the scope of the knowledge of the state of the class to the item that immediately needs to know it.
And finally, do not over-design this. If it only needs to notify the caller, do not implement events. If at some later date the class needs to be "observed" then implement events at that point.
It all depends on the coupling of your components and the flow of your program. The downside to events is that you will increase the complexity of your program, because it is harder to trace exactly what the flow of execution will be when any piece of code can subscribe to your event. The upside is it allows for a more flexible and scalable design, since any piece of code can subscribe to your event.
So here is the thing, if Player is going to be in charge of handling all things related to leveling up, then having a tight coupling between Player and ExperienceBar is ok. Let's say you want to expose an AddIn framework, in that case you probably want to expose leveling up to external plugins, in which case an event makes a lot more sense.
Personally, I would have XP be a part of Player, and have Player expose a LevelUp event, but I don't know if that would be a good idea for you and your framework/domain modeling without seeing your existing code.
I would use events rather than a return value. Why? Two reasons:
What does returning true mean when returning from UpdateBar? That it was updated? That xyz happened? Someone else looking at this (or you, two months down the road) will wonder as well.
What if more than one thing should occur when the limit is reached? Then you have to tie all of the code related to those things (levelling, getting a new item, whatever) into the method that you used to update the bar in the first place.
I would have an event associated with reaching a certain level and then "listeners" for that event that can respond accordingly.
I don't think it makes sense to have Experience bar fire an event - in that case a return value would be fine. It could then call the Player's LevelUp function, which could fire an OnLevelUp event from the Player class, if needed.

Duplicate returned by Guid.NewGuid()?

We have an application that generates simulated data for one of our services for testing purposes. Each data item has a unique Guid. However, when we ran a test after some minor code changes to the simulator all of the objects generated by it had the same Guid.
There was a single data object created, then a for loop where the properties of the object were modified, including a new unique Guid, and it was sent to the service via remoting (serializable, not marshal-by-ref, if that's what you're thinking), loop and do it again, etc.
If we put a small Thread.Sleep( ...) inside of the loop, it generated unique id's. I think that is a red-herring though. I created a test app that just created one guid after another and didn't get a single duplicate.
My theory is that the IL was optimized in a way that caused this behavior. But enough about my theories. What do YOU think? I'm open to suggestions and ways to test it.
UPDATE: There seems to be a lot of confusion about my question, so let me clarify. I DON'T think that NewGuid() is broken. Clearly it works. Its FINE! There is a bug somewhere though, that causes NewGuid() to either:
1) be called only once in my loop
2) be called everytime in my loop but assigned only once
3) something else I haven't thought of
This bug can be in my code (MOST likely) or in optimization somewhere.
So to reiterate my question, how should I debug this scenario?
(and thank you for the great discussion, this is really helping me clarify the problem in my mind)
UPDATE # 2: I'd love to post an example that shows the problem, but that's part of my problem. I can't duplicate it outside of the whole suite of applications (client and servers).
Here's a relevant snippet though:
OrderTicket ticket = new OrderTicket(... );
for( int i = 0; i < _numOrders; i++ )
{
ticket.CacheId = Guid.NewGuid();
Submit( ticket ); // note that this simply makes a remoting call
}
Does Submit do an async call, or does the ticket object go into another thread at any stage.
In the code example you are reusing the same object. What if Submit sends the ticket in a background thread after a short delay (and does not take a copy). When you change the CacheId you are actually updating all the pending submits. This also explains why a Thread.Sleep fixes the problem. Try this:
for( int i = 0; i < _numOrders; i++ )
{
OrderTicket ticket = new OrderTicket(... );
ticket.CacheId = Guid.NewGuid();
Submit( ticket ); // note that this simply makes a remoting call
}
If for some reason this is not possible, try this and see if they are still the same:
ticket.CacheId = new Guid("00000000-0000-0000-0000-" +
string.Format("{0:000000000000}", i));
Thousands of developers use Guids in .NET. If Guid.NewGuid() had any tendency at all to get "stuck" on one value, the problem would have been encountered long ago.
The minor code changes are the sure culprit here. The fact that Thread.Sleep (which is less a red herring than a fish rotting in the sun) "fixes" your problem suggests that your properties are being set in some weird way that can't take effect until the loop stops blocking (either by ending or by Thread.Sleep). I'd even be willing to bet that the "minor change" was to reset all the properties from a separate thread.
If you posted some sample code, that would help.
It's a bug in your code. If you've managed to generate multiple guid's it is the most likely explanation. The clue is here in your question: "when we ran a test after some minor code changes to the simulator all of the objects generated by it had the same Guid"
See this article about how a Guid is created.
This artcile came from This answer.
Bottom line if you are creating the GUIDs too quickly and the clock hasn't moved forward that is why you are getting some as the same. However when you put a sleep in it works because the clock has moved.
The code in Submit and OrderTicket would be helpful as well...
You're reusing OrderTicket. I'd suspect that either you (or remoting itself) is batching calls out - probably in respect to # of connections/host limits - and picking up the last value of CacheId when it finally sends them along.
If you debug or Thread.Sleep the app, you're changing the timing so that the remoting call finishes before you assign a new CacheId.
Are you asyncing the remoting call? I'd think a sync call would block - but I'd check with a packet sniffer like Wireshark to be sure. Regardless, just changing to creating a new OrderTicket in each iteration would probably do the trick.
Edit: The question is not about NewGuid being broken...so my previous answer has been removed.
I dont know the details of how GUIDs are generated.. yet. However currently my org. is breeding GUIDs at a rate that would put rabbits to shame. So I can vouch for the fact that GUIDs aren't broken.. yet.
Post the source code if possible.. or a clone repro app. Many times I find the act of creating that clone app to repro the problem shows me the issue.
The other approach would be to comment out "those minor changes". If that fixes the problem, you can then triangularize to find the offending line of code. Eye-ball the minor changes hard... I mean real Hard.
Do let us know how it goes... this sounds interesting.
My gut is telling me something along these lines is going on...
class OrderTicket
{
Guid CacheId {set {_guid = new Guid("00000000-0000-0000-0000-");}
}
Log the value of CacheId into a log file every time its called with a stack trace ... Maybe someone else is setting it.

Categories

Resources