La Torre de Hanoi

En esta oportunidad les presento el famoso problema de la torre de Hanoi, pero con la particularidad que se maneja como un juego donde debemos hacer click sobre los anillos que conforman la torre para moverla de un lugar a otro. Este programa es bastante completo e incorpora elementos que hasta ahora no habiamos estudiado en este blog, como por ejemplo, slider, LCDnumber, DrawingArea, etc. Este programa no es de mi propiedad, fue enviado por un visitante de este foro a mi correo electronico. Muy agradecido por su aporte.

El formulario: Torre de Hanoi

El codigo del Formulario:

myHanoi AS Chanoi
myTower AS Integer[]
myTowerDep AS Integer
myTowerArr AS Integer
turn AS Integer
start AS Boolean
starttxt AS String
stoptxt AS String
movetxt AS String
towdeptxt AS String

PUBLIC SUB form_open()

myHanoi = NEW Chanoi

start = FALSE
turn = 1
myTowerDep = 0
myTowerArr = 0

slider1_change()

END

PUBLIC SUB Slider1_change()

DIM i AS Integer
DIM j AS Integer

LCDNumber1.Value = slider1.Value
drawTowers()

j = slider1.Value – 2

FOR i = 0 TO (slider1.Value) – 1
drawdisk(1, i + 1, (slider1.Value) – i)
NEXT

END

PUBLIC SUB Quit_Click()

DIM choice AS Integer

choice = Message.Question((“Are you sure ?”), (“&Yes”), (“&No”))

IF choice = 1 THEN
ME.Close
ENDIF

END

PUBLIC SUB Button1_Click()

IF start = TRUE THEN
start = FALSE
turn = 1
button1.Text = (“Start”)
TextLabel1.text = (“Choose the number of disks then press Start”)
slider1.Enabled = TRUE
slider1_change
RETURN
ENDIF

start = TRUE
button1.Text = (“Stop”)
TextLabel1.text = (“Move”) & ” ” & turn & ” ” & (“: choose the starting tower”)
slider1.Enabled = FALSE
myHanoi.init(slider1.value)

END

PUBLIC SUB DrawingArea1_MouseDown()

DIM X AS Integer
DIM y AS Integer
DIM Bckgd AS Integer

IF start = FALSE THEN
RETURN
ENDIF

X = (Mouse.X / 210) + 1

IF myTowerDep = 0 THEN
myTowerDep = X
TextLabel1.text = (“Move”) & ” ” & turn & ” ” & (“: choose the destination tower”)
RETURN
ENDIF

IF myTowerDep = X THEN
myTowerDep = 0
TextLabel1.text = (“Move”) & ” ” & turn & ” ” & (“: choose the starting tower”)
RETURN
ENDIF

myTowerArr = X

IF NOT myHanoi.moveDisk(myTowerDep, myTowerArr) THEN
Bckgd = DrawingArea1.Background
TextLabel1.Background = color.Red
TextLabel1.text = (“Move”) & ” ” & turn & ” ” & (“: illegal move !”)
WAIT 2
TextLabel1.Background = Bckgd
TextLabel1.text = (“Move”) & ” ” & turn & ” ” & (“: choose the starting tower”)
myTowerDep = 0
myTowerArr = 0
RETURN
ENDIF

moveTowers()

IF ((myHanoi.getTower(3)).length = slider1.Value) THEN
win()
RETURN
ENDIF

myTowerDep = 0
myTowerArr = 0
INC (turn)

TextLabel1.text = (“Move”) & ” ” & turn & ” ” & (“: choose the starting tower”)

END

PRIVATE PROCEDURE moveTowers()

DIM i AS Integer
DIM j AS Integer
DIM k AS Integer

drawTowers()

FOR i = 1 TO 3
myTower = myHanoi.getTower(i)

IF myTower.length THEN
FOR j = 1 TO myTower.length
drawDisk(i, j, myTower[j - 1])
NEXT
ENDIF
NEXT

END

PRIVATE PROCEDURE win()

message.Info((“Congratulation !\nYou have win in”) & ” ” & turn & ” ” & (“moves.”), (“&Ok”))
button1_click()

END

PRIVATE PROCEDURE drawTowers()

‘ the three empty towers

DIM i AS Integer

DrawingArea1.clear
DrawingArea1.Border = Border.Sunken
DRAW.Begin(DrawingArea1)
DRAW.ForeColor = color.Black
DRAW.FillStyle = fill.Solid
DRAW.FillColor = color.DarkRed

FOR i = 0 TO 2
DRAW.rect(5 + (i * 205), 160, 200, 20)
DRAW.Rect(102 + (i * 205), 5, 6, 155)
NEXT

DRAW.End

END

PRIVATE PROCEDURE drawDisk(tower AS Integer, pos AS Integer, size AS Integer)

DIM myX AS Integer
DIM myY AS Integer
DIM myL AS Integer
DIM myEp AS Integer
DIM mySpace AS Integer
DIM tower2tower AS Integer

tower2tower = 205
mySpace = 2
myEp = 13
myX = 100 – ((size – 1) * 10) + tower2tower * (tower – 1)
myY = 160 – ((mySpace + myEp) * pos)
myL = 10 + ((size – 1) * 20)

DRAW.Begin(DrawingArea1)
DRAW.ForeColor = color.Black
DRAW.FillStyle = fill.Solid
DRAW.FillColor = color.Blue
DRAW.rect(myX, myY, myL, myEp)
DRAW.End

END

El codigo de la Clase que llamaremos Chanoi (si… aqui vamos a crear una clase… fantastico no?)

PRIVATE tower1 AS NEW Integer[]
PRIVATE tower2 AS NEW Integer[]
PRIVATE tower3 AS NEW Integer[]
PRIVATE height AS Integer

PUBLIC SUB init(h AS Integer)

DIM i AS Integer

tower1.Clear
tower2.Clear
tower3.Clear
height = h

FOR i = h TO 1 STEP -1
tower1.Push(i)
NEXT

END

PUBLIC FUNCTION getTower(t AS Integer) AS Integer[]

SELECT t
CASE 1
RETURN tower1
CASE 2
RETURN tower2
CASE 3
RETURN tower3
END SELECT

END

PUBLIC FUNCTION moveDisk(st AS Integer, ar AS Integer) AS Boolean

DIM tw1 AS Integer[]
DIM tw2 AS Integer[]

SELECT st
CASE 1
tw1 = tower1
CASE 2
tw1 = tower2
CASE 3
tw1 = tower3
END SELECT

SELECT ar
CASE 1
tw2 = tower1
CASE 2
tw2 = tower2
CASE 3
tw2 = tower3
END SELECT

IF tw1.Length = 0 THEN
RETURN FALSE
ENDIF

IF tw2.Length = 0 THEN
tw2.Push(tw1.Pop())
RETURN TRUE
ENDIF

IF tw2[tw2.Length - 1] < tw1[tw1.Length - 1] THEN
RETURN FALSE
ENDIF

tw2.Push(tw1.Pop())
RETURN TRUE

END

About these ads

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s