Lights Out Game (in C#)

This is a fun little game that you might be familiar with. When you click a light (button), it switches from "on" to "off." It also switches the buttons to the right, left, above, and below. To win the game, you have to change all the lights from being on to being off. Once you win, you should then try to do it in fewer moves.

This program was created by using C# in Visual Studio 2005. Most of the code should be easy to follow for the average C# developer. There are just a few things worth noting.

Using an Array of Buttons

The main game form is a grid of buttons as shown in Figure 1. The size of this grid can be adjusted within the code by changing the value stored in GridSize. In general, you want this to be from 3 to 9; however, you technically could go as large as you want. The code is written to place the buttons dynamically and to resize the form based on the value you place in GridSize.

Figure 1: The Lights Out game form

The grid of buttons is stored in an array called btnLights declared as:

private System.Windows.Forms.Button [,] btnLights;

This array then is instantiated with the following:

this.btnLights = new System.Windows.Forms.Button[GridSize,GridSize];
for (int row = 0; row < GridSize; row++)
   for( int col = 0; col < GridSize; col++)
   this.btnLights[row,col] = new System.Windows.Forms.Button();

Note that after instantiating the array using the GridSize variable mentioned earlier, each element within the array then is instantiated with a button. You must instantiate the individual buttons into the array. Once the above code is completed, you will have an array of valid buttons.

Caution: The Visual Studio 2005 Editor design editor can't deal with the array of buttons. As such, if you use Visual Studio 2005, you won't be able to view the form in design mode.

Once the buttons are created, you then can configure the properties for each and add them to the form. This is done again using a couple of for loops:

for (int y = 0; y < GridSize; y++)
  for(int x = 0; x < GridSize; x++ )
     this.btnLights[x,y].Location = new System.Drawing.Point(13+(35*x),
     this.btnLights[x,y].Name = "btnLights" + x.ToString() + y.ToString();
     this.btnLights[x,y].Size = new System.Drawing.Size(30, 30);
     this.btnLights[x,y].TabIndex = x + (y*GridSize) + 1;
     this.btnLights[x,y].BackColor = onColor;
     this.btnLights[x,y].Click +=
        new System.EventHandler(this.LightsClickHandler);

There are a couple of important things that might not be clear in this code. In setting the location, a 13 pixel buffer is used for the edge of the form. Then, 35 pixels are added for each button placed on the form. As such, the first button will be at 13+(35*0), or thus at 13 pixels over. The second button (indexed 1) will be at 13+(35*1), or 48 pixels over. Each button is 30 pixels wide, so this gives a nice buffer of 5 pixels between each.

Also worth noting is that each button is set a tab index value. The Restart button is set earlier in the program to be the first tab position (0). Thus, the buttons are set to a tab index starting at 1. Later, the tab index will be used to determine where in the grid a button is located.

The code also adds a Click event handler to each button. You should notice that the same handler, LightsClickHandler, is added to each button. Before discussing this handler, it is worth looking at one last bit of code in the form layout:

this.ClientSize = new System.Drawing.Size(
            ( GridSize < 7 ? 240 : ((35*GridSize)+20)),
            ((35*GridSize) + 65));

This code sets the size of the form. The minimum size of the form will be 240 pixels. If the Gridsize is 7 or larger, the form size will be increased to make room. If you set Gridsize to less than 7, you will get a warning when you compile that the code to the right is unreachable. Should you decide to make the form dynamic when the program is running, this code would be more useful.

Handling the Button Clicks

A single event handler is used for all the buttons on the grid. This is the LightsClickHandler. Within this handler, the sender parameter is cast and assigned to a temporary button control, tempButton. This button then is used throughout the event.

Once cast to a button, it is easy to change the current button's color. You simply change the button's color. This is done by changing the BackColor to either the offColor or onColor, depending on what it was before.

Where things get trickier is in figuring out whether there are buttons to the left or right as well above or below. To determine this, the following two lines determine the coordinates of the current button in the grid of buttons.

int btnX = ((tempButton.TabIndex-1) % GridSize);
int btnY = (int)((tempButton.TabIndex-1) / GridSize);

As mentioned earlier, the buttons are in the tab order staring in position 1. Each button is then sequentially numbered. Using the size of the grid, the above two lines convert this linear value into the coordinate system that is used in the array. Once you have the coordinates, it is a much easier task to determine whether there are surrounding buttons and then toggling their colors if there are:

// Toggle button to the left
if(btnX > 0 )
   ToggleButtonColor(btnLights[(btnX-1), btnY]);
// Toggle button to the right
if(btnX < (GridSize-1) )
   ToggleButtonColor(btnLights[(btnX+1), btnY]);
// Toggle button above
if(btnY > 0 )
// Toggle button below
if(btnY < (GridSize-1))

Winning the Game

After each move, a check is done to see whether the game has been won. The game has not been won if any of the buttons still has a BackColor that is on. If all of the BackColors are the offColor, a message is displayed saying the game has been won. The game board then is reset back to a grid with the buttons all on.

The Code

Attached is a zip file containing the entire Visual Studio 2005 project for this program. The key files are Form1.Designer.cs and Form1.cs. You'll find the code described in this article in primarily these two files.

This is really just the beginning of a good game. Although the game is playable in its current form, you can make a number of enhancements to greatly improve it. You could add the ability for the user to configure the on and off colors at runtime. You also could allow the user to set the grid size at run time. Other improvements could include better functionality when the game is won. Right now, the game simply pops up a message and resets. You obviously could add a lot more to that as well.

This game was written quickly for fun, while I also was watching American Idol. The article was written while watching Grey's Anatomy. As such, I might have goofed here and there. If so, feel free to comment or drop me an email. In the mean time, feel free to play Lights Out. I'm terrible at the game. It likely took me less time to write the game than it would take me to win in the 7x7 grid!

# # #

About the Author

Bradley Jones

Bradley Jones, in addition to managing CodeGuru, Brad! oversees the Newtwork of sites including Codeguru,, DevX, VBForums, and over a dozen more with a focus on software development and database technologies. His experience includes development in C, C++, VB, some Java, C#, ASP, COBOL, and more as well as having been a developer, consultant, analyst, lead, and much more. His recent books include Teach Yourself the C# Language in 21 Days, Web 2.0 Heroes, and Windows Live Essentials and Services.
Google+ Profile | Linked-In Profile | Facebook Page



  • Form not being displayed with controls on it.

    Posted by Raj on 06/05/2012 10:50pm

    Hello Sir, after conversion, I am not able to find the controls on the form.I am able to see only the Designer.cs file but not the actual form instead it is displaying some errors onto the Visual Studio 2008. please help me Sir.....

  • error

    Posted by ashu@inno on 08/23/2010 04:36am

    error occured while opening the solution... its asked for conversion.. got an error

  • Web Browser page

    Posted by vinojkumar on 03/03/2007 12:35am

    Can your game appear in a web page and if so how? Can you explain how to make a web browser like IE run your code?

  • Error opening the resource

    Posted by vinojkumar on 03/01/2007 01:17am

    "One or more errors encountered while loading the designer. The errors are listed below. Some errors can be fixed by rebuilding your project, while others may require code changes. The designer cannot process the code at line 32: this.btnLights = new System.Windows.Forms.Button[GridSize,GridSize]; The code within the method 'InitializeComponent' is generated by the designer and should not be manually modified. Please remove any changes and try opening the designer again. " This is the error thrown by the VS2005 Designer.

    • Error is correct

      Posted by Brad Jones on 03/01/2007 08:31am

      This error is mentioned in the article. Because an array of buttons is being used, the Visual Studio Designer will not be able to display the form. You can use Visual Studio to edit and compiler the application, but not to do any more with the GUI. I know of no way for the Designer to handle the array of buttons that is dynamically generated.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • 10 Rules that Make or Break Enterprise App Development Projects In today's app-driven world, application development is a top priority. Even so, 68% of enterprise application delivery projects fail. Designing and building applications that pay for themselves and adapt to future needs is incredibly difficult. Executing one successful project is lucky, but making it a repeatable process and strategic advantage? That's where the money is. With help from our most experienced project leads and software engineers, …

  • A global data storage provider whose business is booming needed a best-in-class data center to serve as the backbone of its technical operations going forward—and it needed it delivered within a year.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds