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