Granting a Custom Class/Object visibility (VB2010)

Posted 13 July 2012 - 02:43 PM

(Using VB2010)

I'm working on a programming exercise (very little practical programming experience) to create a chess game. Though I shudder at the logic required to verify a King's Move is legal, luckily I'm not at that point yet.

Currently I am trying to give life to the chess-board that only exists in memory. As designed, each 'Game' object creates an array of 'Square' objects with properties like color, piece, rank, file, etc. As far as I can tell, everything works like clockwork. Whenever I create a new 'Game' I also create a new Form to run the game (the visual component to the logical board).

While I could dynamically create an 8x8 series of buttons, each of which call appropriate methods in the 'Game' or 'Square' classes, I'd like to somehow give my own custom 'Square' class a visual component that can be clicked on. I may have the terminology wrong, but essentially I'd like to create 'image' or 'color/height/width/xpos/ypos' properties for the 'Square's.

I've tried to lookup the carious properties of pre-built controls in the MSDN knowledgebase, and various tutorials on creating classes and assigning properties. I know I can add controls dynamically (I could create a button for each 'Square') and I've come to the (true|false) conclusion that a control is nothing more than a pre-built class. If that's true, I should be able to do this. All of the tutorials, sadly, assume that all I am doing with my classes is behind-the-scenes logic.

In short (which I rarely do), how would I give a custom 'Square' class a 100x100 black image on a form?

I'm certainly not asking for the code (Eliminates half of the fun!), but a reference or keyword would be greatly appreciated.

Replies To: Granting a Custom Class/Object visibility (VB2010)

Re: Granting a Custom Class/Object visibility (VB2010)

Posted 13 July 2012 - 02:59 PM

hey i could be completely wrong here but i was doing reports in work where i want to click a bar in a bar graph then when i click the bar it would bring up the associated records (which worked really well) i use a method called hit test you could look into that for clicking on the squares.

Re: Granting a Custom Class/Object visibility (VB2010)

Posted 13 July 2012 - 03:19 PM

Thanks for your quick response!

The problem isn't so much the code to execute when the square is clicked on as the fact that there is nothing to click on in the first place! The Board (array of squares) only exists in memory at this point. I am trying to give them a visual component, without using a predefined class/control, so that the player has something to click on.

Re: Granting a Custom Class/Object visibility (VB2010)

Posted 13 July 2012 - 08:21 PM

I appreciate your sense of purity, and you have some very good ideas here so far. The thing is, a "control" is a class that has a visual aspect to it. That's what you are looking for, and you're suggesting, then, that you want to define your own control. You can do this, but I might suggest instead that you leverage the existing framework so far as to use the existing PIctureBox control, which is made to display images, and the ImageList control, which is made to hold a group of images in memory. Make a two-dimensional (8x8) array of pictureboxes. The ImageLIst control would contain a black square, a white square, and an image of each piece x 4, one for each permutation of piece and square color.

Now, I'd also consider having your Square object inherit from PictureBox. (Edit: this answers your boldface question.) That way, you can incorporate the specialized properties that you have for your square directly into your control. Then, taking this a bit further, you can create a CastleableSquare object that derives from square, that has an additional boolean CanCastle property. These would be (given that 0,0 is a1) 0,0; 0,4; 0,7; 7,0; 7,4; and 7,7. Once the rook or king moves from the square, then set the variable to false. You can still create an array of type Square, and instantiate a CastleableSquare object for these squares. (See "polymorphism" for more theory on this idea.)

I would also consider creating a Piece object. This one could have various properties general to all pieces such x and y coordinates (you could set the coordinates to -1,-1 for captured pieces if you want to avoid having a Captured property) and color. You can also add a Move method here, and implement any move logic that is common to all pieces. Then you can derive specific pieces and override the Move method, calling the base move method (i. e. Square.Move) when appropriate to do the general move logic, and also implementing specialized move logic for each piece. In particular, specialized move logic would throw an exception for an illegal move, and also handle queening in the case of pawns and castling in the case of kings. (Rooks don't need to implement any castling logic; since the standard rule to castle is to move the King 2 squares the rook can be moved as part of the King.Move method.)

Rank and file are inferrable by the position in the array. Square (0,0) is a1, for example, so I don't think you need these properties.

White is also inferrable by the position in the array. Even/even and odd/odd are black, even/odd and odd/even are white. So you can lose that property too, I do believe.

I don't think you need your threatenedby properties, either, given that there isn't any sort of behavior of a threatened piece that requires it to behave differently. The exception to this, is, of course, the king, which will need different logic when en pris than when not. But all this would be handled in the specialized Move method of the piece.

That's all I can think of offhand. Interesting problem! Although I've played chess for many more years than I've written code, I've never thought about how to put this together before. Maybe you'll take some of those ideas and see where they take you, and post back when you feel the need.

Re: Granting a Custom Class/Object visibility (VB2010)

Posted 14 July 2012 - 09:58 AM

Thank you, Bob and Adam!

I was unable to follow the link posted by Adam either.

Interestingly enough the ideas posted by Bob are nearly identical to the ones suggested by my dad last night. At the moment I am experimenting with the picturebox and imagelist controls inheriting the picturebox properties. The question I am wrestling with is how that affects the resources utilized by the program. My custom 'Square' doesn't take up much space because it only has a few parameters. If I inherit all of the parameters in the picturebox control, then my square would take up much more room (and I have to imagine that I will only be using a small fraction of the inherited parameters). A lot of that feels like waste. While I grant that many feel there are enough resources that it's ok to waste a few, I do take a more conservative approach. You can thank my dad for teaching me basic Assembly and how to read some old programs he wrote on Punch-Cards, back in the day.

My dad also mentioned a very short thought about using 'DRAW' and having the form itself handle the click-event, calling the appropriate object's method. Seems like it would work, especially since a puzzle sitting in the back of my mind is how to allow resizing the form to resize the squares themselves.

The rest is a little off-topic, perhaps, but I'm the OP so I suppose that's my call. Maybe I should start a chess-thread? It IS a fun exercise to figure out creative ways to validate moves and such.

I thought about creating a 'Piece' object early on, but chose instead to break from the intuitive and make piece a property of a 'Square' object. My thoughts, at the time, were that only one piece can be on a square at a time so I eliminate any possibility of errors during movement and that I really couldn't think of an advantage to using an object if a property works just as well. Perhaps an advantage to using a parameter and NOT an object is that memory consumption is constant throughout the game (from that perspective, anyway)? Promoting, taking pieces, even creating custom board layouts for puzzles like the 'Eight Queens Puzzle' doesn't require creating or destroying objects.

I'm using Rank and File because, at the moment, I haven't looked into how to determing an objects location in an array from within the array. I'm getting there! Jeez! :-)

White, as it turns out, was a much more challenging property to determine recursively than I expected. I realized rather recently (woke up with the idea...dream in code is true...never knew!) that the square itself really doesn't care what color it is. The squares alternating colors are part of the visual interface and help the player see the board but don't actually affect ANY of the game logic/rules, as I can tell. Yes, Queen gets her color and white to the right...but those can easily be programmed into a coordinate system without any color references. The White Queen starts on D1 and Black Queen starts on D8.

To share a little bit of fun code, though, a bit of the 'Game' Object:

Property Even As Boolean = True 'True if the board has an even number of files
Property MaxRank As Byte = 7
Property MaxFile As Byte = 7
Dim Board(Me.MaxRank, Me.MaxFile) As Square
Dim White As Boolean = Not Even 'Used to set the color of each square as it is created.
Public Sub New(ByVal Rank As Byte, ByVal File As Byte)
Me.MaxRank = Rank
Me.MaxFile = File
ReDim Board(Me.MaxRank, Me.MaxFile)
Dim ctrRank As Byte = 0
Dim ctrFile As Byte = 0
For ctrRank = 0 To Me.MaxRank
If Even Then
White = Not White
End If
For ctrFile = 0 To Me.MaxFile
Board(ctrRank, ctrFile) = New Square(ctrRank, ctrFile, White)
White = Not White
Next
Next
End Sub

I haven't tackled threated squares yet. I am dancing between the idea of tracking which squares are threatened (which might provide some interesting visual options in a later version) or simply determining if the King is threatened on demand. I'm always thinking from a resource useage perspective, and I get the gut feeling that tracking the threat (and updating it every time a piece moves) might be more wasteful in the long-run.

Anyway, I am going to seriously consider starting a chess thread, since it is a common game with set rules. I think it would be great fun to debate and puzzle carious aspects of writing a chess program. It's trickier than I thought. Is there an appropriate place to start something like that? In addition, I'd love for you to join me there for continued discussion. Will post a link here, if I do create/find something like that.

Re: Granting a Custom Class/Object visibility (VB2010)

Posted 14 July 2012 - 12:07 PM

A few more thoughts:

Start with using what's there. Then if you want to write something more lightweight, write it. Once you have a firm enough grasp of C++ to write controls in it. For now, use what's there to teach yourself more about OOAD. I appreciate your more conservative approach, however one may take it too far. A fishing purist will perhaps use one fly as bait, whereas someone who wants fish for dinner will have a somewhat less conservative approach to bait. So, start by wasting resources and not liking it, then use that perfectionistic streak to refine your programs once you have them working.

I would use the squares' click events. It's easier to know which square was clicked that way. Why add logic to figure out which square was clicked when you don't have to?

I would read up a bit on "cohesion" and "coupling". Cohesion means that an object is targeted to one purpose. Excessive decision logic in an object suggests that it is targeted to too many purposes, and has to spend extra time figuring out what it's doing. Objects should be loosely coupled, meaning that communication between them is minimal. Objects that spend too much time talking to each other might need to be merged.

Now, having a square determine the move logic of a piece lacks cohesion. Think about all the decision logic required to move a piece off of a square! If it's one piece, do one thing, if it's another, do another, if yet another...and so on. Rather, let the square have a Piece property, that itself is a reference to a piece object. Call that piece object's move method, which has move logic specific to that piece. This is more cohesive: square logic (such as what image goes on the square) is in the Square object, and Piece logic is in the piece. Loose coupling is evidenced by a simple reference to the piece object, and the ability to call the piece's move method.

To have constant memory consumption is not an advantage per se in terms of performance; to use memory when needed and not use it when not is. Also, the idea that "creating and destroying objects" is something to avoid to optimize performance doesn't strike me as entirely valid. True, there are more efficient ways in terms of space to maintain state. However, a lot of those ways require more time to work with. Imagine a closet with too many clothes in it. Is it better to have the smaller closet and not be able to move in it, just because a bigger closet takes up more space? Not if you can afford to use the space for a bigger closet. RAM cost about $5000 for 1k in 1972, about $35 for 1 mb in 1992, and now it costs about the same for 8 gig. Architectural considerations that were valid 40 years ago simply aren't now; to create a chess GUI in 1970 would cost millions of dollars and require all the computing power on the average high-end college campus. I'd think about being a bit less conservative. Experiment and learn from your mistakes.

Square color affects what image appears on the square. Black pawn on white square isn't the same as black pawn on black square, for example.