[.net] C# Windows Forms Memory game design questions.

Started by
6 comments, last by Spodi 14 years ago
Greetings all, I´m about to write a Memory game in C# with Windows forms but I need some guidance about code design choices. First, since I´m new with coding C# Window Forms programs .. what is the correct method of letting classes modify Windows objects (labels, buttons etc). Making a handle to the Form1 when creating the Game class should allow Game class to modify objects but is this the "right way"? Another issue I´m thinking about is where the Image/Bitmap objects should be created and maintained.. I´m using another custom game class that holds some variables (x/y position, state etc). Can Image/Bitmap objects within this Memory block class be written and updated on Form1 without too much hassle? Thanks in advance. [Edited by - Nali on March 29, 2010 2:27:02 PM]
Advertisement
The short answer is you don't.

Now for the long answer. You create public methods on your form to do the actions you need to do.

public void Move_Image(int amount_x, int amount y, string image_name)

That would move the named image a certain amount along the x and y axis.

The method on the form would make sure they are not moved off the screen, and that the image is a valid image to move.

So that is what I would call the "right" way.

theTroll
Some kind of custom event handler then :).

How about the second part?
I´m very unsure on how to approach this. Create the PictureBox/Image objects in form.cs and make a handle/id-tag them to the MemoryBlock objects? or create them in the objects (with a handle to form.cs so they can access surface to be drawn 2)?
Regarding both of your problems: you should split the visuals from the logic. The rules of the game don't change, no matter if you're playing it as a win forms app or in a console window, right? Clearly, the logic and the visual representation are two concerns. As such, you should split them in your code as well.

As a general guideline: split your solution into two projects, let's say Memory.Rules (a DLL) and Memory.UI (a winforms app). Memory.Rules should not have to reference System.Windows.Forms or System.Drawing at all, because those are related to visuals. Memory.UI on the other hand should only contain code related to visuals, that is forms and controls etc.

Your Game certainly class goes into Memory.Rules. It could have methods such as void TurnOverCard(int x, int y) or bool IsTurnedOver(int x, int y) and these methods deal with all the rules related to memory as an abstract game concept. You could then add an event to Game such as
public event EventHandler StateChanged;

that you raise whenever something important changes (time, score, turned over cards etc.) Your win form (which is responsible for drawing the board) can subscribe to this event and react accordingly (redraw the affected parts etc.). This pattern is referred to as Observer Pattern. Of course, other ways of achieving this decoupling are possible, e.g. MVC

Likewise, managing the bitmaps belongs to the UI. Maybe you can create a class Card in your Memory.Rules project that holds information about a card (position and e.g. a name such as "Cat", "Dog"). In your UI project, you could create a user control that represents a card/buttom. When you create the form with all the card buttons, pass each card button the Card object that it represents and have it load the bitmap based on the name of the card ("Cat"=> "Cat.jpg" or so). Of course that would cause all bitmaps to be loaded twice. So you could go a step further and create a "BitmapManager" class. You pass it the name of a card and it returns the appropriate bitmap (that it loads once the first time it is requested). This can be as simple as this:
public class BitmapManager : IDisposable {  private Dictionary<string, Bitmap> images = new Dictionary<string, Bitmap>();    public Bitmap GetBitmap(string name){    Bitmap bitmap;    if(!images.TryGetValue(name, out bitmap)){      bitmap = LoadBitmap(name);      images.Add(name, bitmap);    }    return bitmap;  }    Bitmap LoadBitmap(string name)[    string fileName = Path.Combine("images", string.Format("{0}.jpg", name));    return new Bitmap(fileName);  }  public void Dispose(){    foreach(var bmp in images.Values){      bmp.Dispose();    }    images.Clear();  }}


Now the BitmapManager is the owner of the bitmaps.

So, in general don't try to combine completely different concerns in the same class. Have a look at the Single Responsibility Principle (and the other OOP principles). Hope that helps :-)

Have fun!
Andre Loker | Personal blog on .NET
^^^ THIS. Totally this.
You can ignore that advice (and it is an AWESOME learning experience) but it will get painful to maintain in the long run.

For drawing in WinForm land I usually lay off the Controls (PictureBoxes, etc) and create a custom control where I draw everything via the GDI+ objects and an override of OnPaint and OnPaintBackground(){/*do nothing/*}.
This is probably because I like to have a bit more freedom in the long run.
However for something incredibly simple (like your memory game might be) just doing it all with WinForm controls might be the quickest option.
I choosed to walk the right way :P , separating game code from gui code. In a small game like this it wont mather but its a good thing to learn how to do this early, might be good experience for bigger projects.

And I´m done with the game :), only have 1 strange issue now; Memory wont be released when creating new games (in the same session). The game consumes a little bit of RAM every new game that is run and I dont really know where the problem is. I´ve implemented IDisposable and calls it from my objects. =/
You don't need to worry about it. The garbage collector will run when it needs to.

Former Microsoft XNA and Xbox MVP | Check out my blog for random ramblings on game development

Unless there is a "leak", is usually due to hanging events. Try constructing and disposing a bunch of game instances, then call GC.Collect(). If the memory usage continues to rise even after the GC runs, you probably have some references that need to be cleaned up.
NetGore - Open source multiplayer RPG engine

This topic is closed to new replies.

Advertisement