Implementing an Array of Buttons: The
Shuffle Game
This article came out of the result of a forum of discussion on CodeGuru.com. When we tried to
implement an array of Windows buttons, we did not find any solution
using ClassWizard. Hence we discussed in the following forum: "Array of
buttons in VC++."
So, we tried to have a common
handler and control in the form of this game.
To Start
- Select New->Project from the
File menu. A dialog window will be displayed. Select "MFC
AppWizard(exe)" and give the project name as "Shuffle".
- When you give the OK, it will
ask for the type of application. Select Dialog, based on Step 1.
- Treat all other steps as
default and click Finish. This will create a dialog-based
application.
- Now, you see two buttons,
namely "Ok", "Cancel", and a text "TODO: Place dialog controls
here." Select and remove the Cancel button and the text "TODO..."
- Change the caption of the Ok
button to &Exit.
- Add one more button;
right-click on the button to go to Properties. Change the caption
to &About and ID to IDC_About.
Now, the dialog window should look
like Figure 1:

Compile the project by pressing
F7; then, to execute it, press Ctrl+F5. Make sure that there are no
errors.
- Double-click the About button
and click Ok to add your code as follows:
void CShuffleDlg::OnAbout()
{
CAboutDlg AboutDlg;
AboutDlg.DoModal();
} |
- Now, design the window by
adding 16 buttons and a Group box. Give the IDs for the buttons as
IDC_But1, IDC_But2...... IDC_But16. Then, the window should look
as in Figure 2.
- On the ClassView tab,
right-click the CShuffleDlg class (if your project name is
Shuffle), select to add a member variable, and give the variable
type as CButton and variable name as m_b. Keep Access as public.
Go to the DoDataExchange function and add the following code to
it:
void CShuffleDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_But1, m_b[0][0]);
DDX_Control(pDX, IDC_But2, m_b[0][1]);
DDX_Control(pDX, IDC_But3, m_b[0][2]);
DDX_Control(pDX, IDC_But4, m_b[0][3]);
DDX_Control(pDX, IDC_But5, m_b[1][0]);
DDX_Control(pDX, IDC_But6, m_b[1][1]);
DDX_Control(pDX, IDC_But7, m_b[1][2]);
DDX_Control(pDX, IDC_But8, m_b[1][3]);
DDX_Control(pDX, IDC_But9, m_b[2][0]);
DDX_Control(pDX, IDC_But10, m_b[2][1]);
DDX_Control(pDX, IDC_But11, m_b[2][2]);
DDX_Control(pDX, IDC_But12, m_b[2][3]);
DDX_Control(pDX, IDC_But13, m_b[3][0]);
DDX_Control(pDX, IDC_But14, m_b[3][1]);
DDX_Control(pDX, IDC_But15, m_b[3][2]);
DDX_Control(pDX, IDC_But16, m_b[3][3]);
}
|
This will assign the control
variable for each button in the array. Now, we have created an array
of 16 buttons. The thing we have to do now is to control these
buttons using a program.
To play the game, we have to
change the captions of the buttons to random numbers from 1 to 15.
To create random numbers, we have to write a function, name it
Randomize( ), and call it from OnInitDialog( ).
For that, in the ClassView tab,
right-click CShuffleDlg, select add member variable; name the type
as int and the variable name as m_x. Similarly, declare another
variable, m_y, of the same type. Later, we use these variables to
hold the position of the slider. Right-click the CShuffleDlg and
select add member function; give the type as int and the function
declaration as Randomize( ).
Write the following code in the
function:
int CShuffleDlg::Randomize()
{
int i=0,xx,yy;
int m[4][4];
CString temp;
srand(time(NULL));
for(xx=0;xx<=3;xx++)
for(yy=0;yy<=3;yy++)
m[xx][yy]=0;
while(i<16)
{
xx=rand()%4;
yy=rand()%4;
if(m[xx][yy]!=0)
continue;
m[xx][yy]=1;
temp.Format("%d",i);
m_b[xx][yy].SetWindowText(temp);
if(i==0)
{
m_x=xx;
m_y=yy;
}
i++;
}
m_b[m_x][m_y].SetButtonStyle(8);
return 1;
}
|
As explained above, to make the
numbers randomized, we used a rand( ) function. rand( )
will generate a random integer; we made it range between 0 to 3 to
select a random row and column using %4. Initial to this, we set the
numbers of all the boxes to zero. Taking the numbers from 1 to 15,
go on filling in the randomly selected boxes if they are not filled.
Now, hide the remaining button using
m_But[m_x][m_y].SetButtonStyle(8). This will set the
game.
To avoid repetition of the order
every time you run the program, make the seed of the random
time(NULL). srand(time(NULL)) makes the random numbers dependent of
time so that every time you run the program, the sequence will be
different.
Now, add the following code to the
OnInitDialog( ) function to randomize the number
initially.
BOOL CShuffleDlg::OnInitDialog()
{
Randomize();
} |
Change the caption of the Group
box to "Click On the Button to Move:".
If you compile and run, you should
get the window in Figure 3:

Now, let us start the game. To
move the button each time you click a button, you have to write a
common handler for all the buttons. Go to the position where you
find "BEGIN_MESSAGE_MAP(CShuffleDlg, CDialog)" (do not confuse
between CAboutDlg and CShuffleDlg), and then add following
code:
BEGIN_MESSAGE_MAP(CShuffleDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_About, OnAbout)
ON_COMMAND_RANGE(IDC_But1,IDC_But16,MoveButton)
END_MESSAGE_MAP()
|
If we press any button, the
"MoveButton" handler will be called with a parameter as the ID of
the corresponding button. Now, declare the MoveButton(int btn)
function of type BOOL by right-clicking the Class CShuffleDlg on the
ClassView tab.
To find the row and column of the
pressed button, subtract the ID of the first button from the empty
button call it btn. Now, btn%4 will give the column and btn/4 will
give the row.
Whenever we press a button, if the
adjacent button is empty, that button should be placed on that
position. For that to happen, we have to check whether the position
of the empty button is adjacent. If it is, we have to change the
caption of the empty button to the caption of the button pressed,
show that button, and hide the button that was pressed. This will
give the effect as if the desired button is moved. In m_x and m_y,
store the present position of the empty button.
Add the following code to the
MoveButton(int btn) function:
BOOL CShuffleDlg::MoveButton(int btn)
{
CString no,temp;
int bx,by=0;
btn = btn - IDC_But1 ;
by=(btn)%4;
bx=(btn)/4;
if(((m_x==bx) && ((m_y-by)==1)) || ((m_x==bx) && ((m_y-by)==-1))
|| ((m_y==by) && ((m_x-bx)==1))
|| ((m_y==by) && ((m_x-bx)==-1)))
{
m_b[m_x][m_y].SetButtonStyle(1,TRUE);
m_b[bx][by].GetWindowText(temp);
no.Format("0");
m_b[bx][by].SetWindowText(no);
m_b[m_x][m_y].SetWindowText(temp);
m_b[bx][by].SetButtonStyle(8,TRUE);
m_x=bx;
m_y=by;
}
return (TRUE);
}
|
Now the "Shuffle Game" is ready.
Play and enjoy
it! Another
possible way of designing a group of buttons is by using bitmap
buttons. For this we have to define it as an array in the
declaration. After trying above method of array implementation
you can go for loading bitmaps, I am sure you will be really
enthusiastic. |