In my previous post, Coding a Game of Memory in Delphi – OOP Model, I’ve been developing the model, aka the back end, for the Memory (Match Up, Concentration, …) game. The idea was to separate the game logic from the user interface (aka the front end). As a result a few classes were introduced: TPlayer, TField and, of course, the main class/object TMemoryGame implementing all the code required to run the game.
Having only the model does not help us much if we actually want to play the game. Therefore, this time, we go into building the user interface in Delphi.
Since the TMemoryGame class is framework agnostic (and not platform specific), it is up for you to decide if you would like to do a classic Windows VCL application, a FireMonkey Android mobile game or something that works on a Mac. To make it quick and simple, I’ll go old-style VCL school.
Memory, Match Up, Concentration … there are many names for a simple card game I’m certain you’ve been playing with your friends at some point during your childhood. I’m also certain you are still playing it from time to time (at least I do with my kids). Just a few months ago, I’ve tried my “luck” against a robot in CosmoCaixa, Barcelona (image).
The rules of the game are simple: cards are laid face down on a surface and two, per turn, are flipped face up. If the flipped cards are a match pair (same looking, same rank, save value) the player claims (wins) the pair and plays again. If they are not a match, cards are flipped face down again, and the next player takes turn. The game ends when all the pairs have been claimed and the player with the most claimed pairs is the winner. If all players have the same number of claimed pairs we can agree to have a tie, or to have the last player be the winner.
I’ve always been a fan of such simple games – from my point of view they are a perfect pick if you want to start learning programming – have fun and sharpen your developer skills at the same time.
While there are Delphi implementations of the game you can find online – most of them have heavily mixed the visual presentation of the game (user interface) with the model (implementation of the game logic).
In my version of Memory, I’d like to separate the user interface (front end) from the game logic (back end) as much as possible. I want to create a game model in OOP style – where the game logic does not interact (or as less as possible) with the front end.
Have you ever needed for a specific Delphi control, like a TButton, to have just one more property or a method that is a “must have” for your current application?
Most Delphi developers, when they need a TMySuperButton, would either look for a third-party VCL solution or would try creating a derived control.
What if you do not want to have this MySuperButton permanently in the Component/Tool Palette – since it solves one problem only for this particular application you are developing?
What’s more … how about having a TButton with more properties and methods, some application specific extra behavior, and not TMySupperButton?
How about extending what TButton has without the need to create a derived class with a different name?
As the Help states, The TStatusBar Delphi control displays a row of panels, usually aligned at the bottom of a form. Each panel is represented by a TStatusPanel object listed in the Panels property.
Much like any other VCL control, the TStatusBar can be adopted and extended to offer greater functionality. A simple case would be to use the status bar to display long hints from other controls.
What does not come out of the box is the possibility to have each panel on a status bar display its own hint (tooltip) when the mouse “stops” over a panel.
Even though the TStatusBar provides the Hint and ShowHint properties to let you assign the tooltip text which appears when the user moves the mouse over the control – you cannot have each panel on a status bar have its own specific hint!
You cannot? You can! Here’s how to implement TStatusPanel.Hint for each panel on a status bar…
Tab set controls are commonly used to display tabbed pages within a dialog box.
The TTabControl control can be used to add a control with multiple tab settings to a form. The TTabSet control presents horizontal tabs users can click to initiate actions.
Both TTabSet and TTabControl are a single object (not made up of several pages hosting different controls, like the case is with TPageControl). When the current tab changes, the tab control must directly update its contents to reflect the change in an OnChange event handler.
To have a set of tabs for the tab set control you specify a list of strings as the value of the Tabs property. Ever wondered how to have specific hint for each tab?
Say you are developing a game like Chess, Go, Checkers, Tic-Tac-Toe or Memory. In each of those games the game board is a rectangle looking playfield of different size (rows x columns). Tic-Tac-Toe is 3×3, Checkers is 8×8, while Go can be 19×19 or 13×13 and similar.
In a game with an arbitrary number of game fields you might want to have the board look as closely to square as possible (rectangle where height and width are the same). Think of Memory. Let’s say we have 24 cards, that is 12 pairs. If you want to place them in a rectangular grid, most similar to square, you would go for 4 x 6 (or 6 x 4) board size (as it would look more square like than 3 x 8 and 2 x 12 or 1 x 24 would be too wide).
Delphi’s TGridPanel control is an ideal pick when you want to create grid-flow like user interface layout for your controls.
To place controls on a grid panel you specify the number of rows and columns (RowCollection and ColumnCollection properties) and simply drop a control on it. Unlike standard TPanel, when you drop a control on a GridPanel it will be placed in the next available empty cell in the grid. As you add more controls the grid will grow either by rows or columns being added automagically (or not, if the ExpandStyle poroperty is set to emFixedSize). What’s more you can even determine how each cell will be sized: will it have a fixed size, or a percentage of the grid size – so you can have controls nicely uniformly distributed in a grid.
That’s all great when you know the design at design-time – and you know what number of controls you want to be hosted by the grid panel.
The second law of thermodynamics, in short version and when read by a programmer, states that “any collection of objects tends not to be sorted” 🙂
We developers, we have a tendency of organizing objects into lists, collections, queues, stacks …
Since you’ll be using the for loop to iterate over elements – why not sort the elements first. What’s more, a sorted list is easier (read: faster) to be searched upon.
In one of my applications, a tab on the page control hosts a TWebBrowser displaying PDF (and other supported) documents. Having the “PDF View” tab active, other tabs of the page control are hidden from the user – as this is how the page control functions.
One users asked: “Can we undock this tab so that it floats and then activate other tabs on the page control? We would also want to dock the viewer tab back. Further, we have two monitors and would like to move the floating viewer to the second monitor.”