Click here to Skip to main content
13,149,073 members (49,129 online)
Click here to Skip to main content
Add your own
alternative version


3 bookmarked
Posted 18 Oct 2013

Hanoi Tower

, 18 Oct 2013
Rate this:
Please Sign up or sign in to vote.
A full functional Hanoi Tower game base on WPF


From wiki

The Tower of Hanoi (also called the Tower of Brahma or Lucas' Tower,[1] and sometimes pluralised) is a mathematical game or puzzle. It consists of three rods, and a number of disks of different sizes which can slide onto any rod. The puzzle starts with the disks in a neat stack in ascending order of size on one rod, the smallest at the top, thus making a conical shape.

The objective of the puzzle is to move the entire stack to another rod, obeying the following rules:

  • Only one disk must be moved at a time.
  • Each move consists of taking the upper disk from one of the rods and sliding it onto another rod, on top of the other disks that may already be present on that rod.
  • No disk may be placed on top of a smaller disk.

With three disks, the puzzle can be solved in seven moves.

This article is not talking about the algorithm but the real game. This is WPF based and present a friendly GUI and control. You can use keyboard to move and drop disks. Let’s see how fast you can solve the Hanoi tower. I found that we already had some Hanoi projects here in past 8 years implemented by C++, VB.NET etc, however, this is the first WPF version and it even contains human voice! (TTS may not work in OS under Windows Vista) J Have fun.


I am interest in the 2D/Animation/Movie part. WPF structure is totally different from C# Winform, I encountered many problems when I try to apply my winform experience on WPF application. They are:

1. Where is the Left, Top properties? How can I move a form control in WPF?

We need to use Canvas.SetLeft/SetTop methods, Canvas is kind of root panel which supports absolutely location for controls (Elements).

2. How to add an image to an Image control programmingly?

In WPF, it calls uri. We need to set the image uri to Image.Source property.

3. Dispatcher Timer vs Timer

Dispatcher Timer, in a word, it can invoke UI Controls in the same thread. But original Timer can’t.

Using the code

The code has been refactored from the original mess up. So I will show some code points here since the source code is simple to read. I think...

I create a class to describe the Tower which contains disks. Here I use Stack<int> to simulate it. Int represents the disk size.

Stack<int> Tower1 = new Stack<int>();

To move the disk between two columns, I compare the int numbers and use Stack.Pop and Stack.Push to simulate the moving. Atually Stack is really suitable because it is FILO like the real Hanoi Disks moving policy.

public bool Move(Towers from, Towers to)
 int fromStep = 0;
 int toStep = 0;

 Stack<int> fromTower = GetTower(from); ;
 Stack<int> toTower = GetTower(to); ;

 if (fromTower.Count < 1) return false;

 fromStep = fromTower.Peek();

 if (toTower.Count < 1) toStep = 10;
 else toStep = toTower.Peek();

 if (fromStep < toStep)
  return true;
 else if (fromStep == toStep)
  return true;
  return false;

I try to decouple the logic from GUI, so I run the logic inside HanoiTowerClass and draw GUI everytime anything changes.

private void RedrawTower(List<int> tower, int columns)
 int j = 0;
 for (int i = tower.Count - 1; i >= 0; i--)
  Canvas.SetTop(rects[tower[i] - 1], Constant.BottomTop - Constant.StepThickness * ++j);
  Canvas.SetLeft(rects[tower[i] - 1], Constant.ColumnWidth * columns - rects[tower[i] - 1].Width / 2 + Constant.Offset);

private void RedrawEnvironment()
 List<int> towerLeft = tower.GetTowerLeft();
 List<int> towerMiddle = tower.GetTowerMiddle();
 List<int> towerRight = tower.GetTowerRight();

 RedrawTower(towerLeft, 1);
 RedrawTower(towerMiddle, 2);
 RedrawTower(towerRight, 3);

 Canvas.SetLeft(hand, Constant.ColumnWidth * (handPosition + 1));
 Canvas.SetTop(hand, Constant.HandTop);

 if (holdStep > 0)
  Canvas.SetTop(rects[holdStep - 1], Constant.HandTop);
  Canvas.SetLeft(rects[holdStep - 1], (handPosition + 1) * Constant.ColumnWidth - rects[holdStep - 1].Width / 2);

In Windows_KeyDown events, we can catch the user input and do some job:

if (e.Key == Key.A || e.Key == Key.Left) //move left
    if (handPosition > 0)
     handPosition = 2;
   else if (e.Key == Key.D || e.Key == Key.Right) //move right
    if (handPosition > 1)
     handPosition = 0;
   else if (e.Key == Key.J || e.Key == Key.S || e.Key == Key.Down) // hold/drop 
    if (!timer.IsEnabled)
    if (holdStep == 0)
     fromPosition = handPosition;
     holdStep = tower.GetStep(GetTowerFromPos(fromPosition));
    else if (holdStep > 0)
     bool successMove = tower.Move(GetTowerFromPos(fromPosition), GetTowerFromPos(handPosition));
     if (successMove)
      holdStep = 0;
      speaker.SpeakAsync("Can not drop there.");
   else if (e.Key == Key.D3)

The last point is the timer, I use it to calculate how fast the player complete the puzzle.

private void timer_Tick(object sender, EventArgs e)
 if (miliseconds == 100)
  if (seconds < 1000)
  miliseconds = 0;
 if (seconds > 999)
  lblTime.Content = "More than 999s";
  lblTime.Content = string.Format("TIME: {0}:{1}", seconds, miliseconds);

Points of Interest

Let your application speak! I invoke the TTS engine to say some words in this application, it's easy to use.   


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


About the Author

Software Developer (Senior) Aprimo
China China
I'm a dotnet developer who is interest in WPF, WCF base on C#.
I have worked for 11 years and have built different projects.
It is exciting working on code. Also management skill is an art which I am on it now.
Professional and efficient are always my goal.

You may also be interested in...

Comments and Discussions

Questiondon't know how can i open it Pin
Member 1276788129-Sep-16 15:32
memberMember 1276788129-Sep-16 15:32 
AnswerRe: don't know how can i open it Pin
ryowu18-Dec-16 21:53
professionalryowu18-Dec-16 21:53 
GeneralMy vote of 5 Pin
Gun Gun Febrianza16-Nov-13 7:16
member Gun Gun Febrianza16-Nov-13 7:16 
Generalremember me when i was child Pin
Gun Gun Febrianza16-Nov-13 7:16
member Gun Gun Febrianza16-Nov-13 7:16 
GeneralNostaligic... Pin
Bruno Tabbia19-Oct-13 5:52
memberBruno Tabbia19-Oct-13 5:52 
GeneralRe: Nostaligic... Pin
ryowu20-Oct-13 2:31
professionalryowu20-Oct-13 2:31 
Questionnice Pin
CIDev18-Oct-13 7:40
professionalCIDev18-Oct-13 7:40 
AnswerRe: nice Pin
ryowu20-Oct-13 2:33
professionalryowu20-Oct-13 2:33 
GeneralRe: nice Pin
CIDev20-Oct-13 4:59
professionalCIDev20-Oct-13 4:59 

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
Web01 | 2.8.170924.2 | Last Updated 18 Oct 2013
Article Copyright 2013 by ryowu
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid