Click here to Skip to main content
13,197,271 members (48,942 online)
Click here to Skip to main content
Add your own
alternative version


23 bookmarked
Posted 22 Mar 2010

Let Me Out - A Simple Board Game

, 22 Mar 2010
Rate this:
Please Sign up or sign in to vote.
A simple board game



"Let Me Out" is a board game with the goal to move the magenta block, the biggest one, from the middle of the top to the middle of the bottom. You need to move other blocks and make room for the big guy. The game has 3 levels, beginner, intermediate, and expert. You can change the levels from the menu.

The amazing thing about this software is that it only has 2 main classes, Block and Board. And the code is very simple. So, I think it is good for beginners to learn Object-Oriented programming. Or, hopefully fall in love with game developing. :) Another interesting thing about it is the UI design. I saw a lot of board games in which the user needs to either drag-and-drop or use several steps to move an item. That's because to let an item move, the user needs to tell it to move and where to move. This game uses an arrow to show the direction that a block will be moved, which changes with the mouse movement. Since the user already has the direction, all she/he needs to do is just one click.

Before you continue reading, I suggest that you play the game and have fun. You may want to change the level to Beginner to get familiar with the user interface.


This is a Chinese game with a thousand years of history. It's about a great battle. The guy who lost the battle tried his best to escape, which was almost impossible. But he did it. The 2x2 square, the magenta one, represents the guy who tried to escape. If you have played the game, you will understand why it is "almost impossible".

Using the Code

Block class inherits from Button class, so that it can be clicked. Its style is changed to flat, so that it looks more like a block. Since we will add blocks to board in code, we decorate the class with the attribute ToolboxItem(false), which prevents it from showing in the Visual Studio Toolbox window.

public class Block : Button {

Block class is responsible for remembering its size and position. When mouse is over it, an arrow will be shown. And the arrow will change direction with the mouse movement. We will talk more about this in UI Design section.

Board is divided to 4 x 5 squares as shown below:


Board class is responsible for remembering the status of the squares, which can be either occupied or free. It is also responsible for moving blocks. To move a block, the Board class checks whether the Block can be moved. Board knows that because it has the record of each square. By asking Block class, it knows the position, and size of the Block, and the direct to move, so that it can decide whether the Block can be moved. If yes, the Block updates its position, and the Board updates its status. The following is the code to move a block to left. It's a method in Board class:

void MoveLeft(Block block) {
    int oldX = block.X;
    if (oldX == 0) return;
    int newX = oldX - 1;

    //Check whether we can move the block
    for (int i = block.Y; i < block.Y + block.YSpan; ++i) {
        if (_occupied[newX, i]) return;

    //Move it
    block.MoveBlock(newX, block.Y);

    //Change board status
    for (int i = block.Y; i < block.Y + block.YSpan; ++i) {
        _occupied[newX + block.XSpan, i] = false;
        _occupied[newX, i] = true;

    //Add step

The first 2 lines check whether block is already in the left most. If yes, it cannot be moved left further, and program returns. "newX" is the x position of the block if it has been moved. To understand the codes after, we need to make clear the properties of the Block class. Let's use an example. In the beginning of the game, the big guy is at (1, 0). In this case, block.X = 1, block.Y=0, block.YSpan=2, which is how many rows the block spans, and block.XSpan=2, which is how many columns the block spans.

In the first for loop, we check whether the squares left to the block are all free. If any of the squares is occupied, the block cannot be moved, and the program returns immediately. For the big guy example, If we want to move it left, we need to check the status of (0,0) and (1,0).

The second for loop changes the board status. If the big guy moved from (1,0) to (0,0), we need to change the status of (0,0), (1,0) to be occupied, and (2, 0), (2,1) to be free.

UI Design

In this program, we move the blocks by using an arrow to show directions and a click to trigger the movement. To achieve this, we divided the block into 4 regions, like the one below:

UI Design

When mouse is moved to the left region, the image for the block is changed to a Left arrow. Other regions all have corresponding images, and behave the same way.

To get the functions for each region needs some knowledge of geometry. Basically, you need to know the functions for 2 lines. One of them passes the point (0,0) and (w, h), so the line is y=(h/w)*x. The other one passes (w, 0) and (0, h), so the line is y=h-(h/w)*x.

The code is below, it is in Block class, for MouseMove event:

    void Block_MouseMove(object sender, MouseEventArgs e) {
        int x = e.X;
        int y = e.Y;
        int h = this.Height;
        int w = this.Width;
        double k = (double)h / (double)w;
        int newIndex = -2;
        int kx = (int)(k * x + 0.5);
        if (y < h - kx) {
            if (y < kx) {
                newIndex = Direction_Up;
            } else if (y > kx) {
                newIndex = Direction_Left;
        } else if (y > h - kx) {
            if (y < kx) {
                newIndex = Direction_Right;
            } else if (y > kx) {
                newIndex = Direction_Down;
        if (newIndex >= 0 && _direction != newIndex) {
            this.Image = Button_Images[newIndex];
            _direction = newIndex;

Button_Images is a static array of 4 images. The images come from project resource.

What's Next

This program can be improved by doing the following:

  • Save/Load Program
  • Game Solver

Save and load can be done by saving each block's position into an XML file. The total steps that the user has moved should also be saved. Board's status doesn't need to be saved because when loading, we can re-establish the board status.

Game Solver is possible because in each game state, there are not many possible moves. I'd like to write a game solver if I find that people like this game.


  • Version 1.0 on March 14, 2010
  • Added more documents on March 21, 2010


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Yangyong Qin
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionNice, Sweet and Simple Pin
Yang Kok Wah28-May-14 14:09
memberYang Kok Wah28-May-14 14:09 
GeneralMy vote of 5 Pin
jiangcaiyang2-Nov-10 22:26
memberjiangcaiyang2-Nov-10 22:26 
GeneralLet me out in console Pin
kimlanu28-Jul-10 0:05
memberkimlanu28-Jul-10 0:05 
GeneralJust a thought... Pin
Blubbo30-Mar-10 1:17
memberBlubbo30-Mar-10 1:17 
GeneralRe: Just a thought... Pin
Anurag Gandhi30-Mar-10 8:52
memberAnurag Gandhi30-Mar-10 8:52 
GeneralChess Version Pin
Norm .net23-Mar-10 0:07
groupNorm .net23-Mar-10 0:07 
GeneralNostalgia Pin
Luc Pattyn22-Mar-10 15:28
mvpLuc Pattyn22-Mar-10 15:28 
GeneralRe: Nostalgia Pin
Yangyong Qin23-Mar-10 16:46
memberYangyong Qin23-Mar-10 16:46 
GeneralRe: Nostalgia Pin
Luc Pattyn23-Mar-10 17:17
mvpLuc Pattyn23-Mar-10 17:17 
GeneralResponse to article Pin
Dalek Dave22-Mar-10 15:08
memberDalek Dave22-Mar-10 15:08 
GeneralNice to know that! Pin
Yangyong Qin23-Mar-10 17:53
memberYangyong Qin23-Mar-10 17:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.171020.1 | Last Updated 22 Mar 2010
Article Copyright 2010 by Yangyong Qin
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid