Fun with Towers of Hanoi

  • DNS Benchmark v2 Release 5 with Consultant License
    Guest:
    If you own any earlier release of our DNS Benchmark you may immediately download its release #5 replacement. Running an earlier release will detect the new release and help you upgrade.

    Although this release is cosmetic, appearance matters and affects ease of use. The biggest change, as seen in the image above, is that the DNS Benchmark now has a traditional Windows application menu to more fully expose its many features. This release is also "Consultant License Aware" and GRC will now issue a Consultant version when owners have previously purchased four "Personal Use" licenses. If you have previously purchased four DNSB licenses, or if you wish to upgrade your "Personal Use" license to Consultant, GRC's purchase process will direct you through that process.
    /Steve.
  • Be sure to checkout “Tips & Tricks”
    Dear Guest Visitor → Once you register and log-in please checkout the “Tips & Tricks” page for some very handy tips!

    /Steve.
  • BootAble – FreeDOS boot testing freeware

    To obtain direct, low-level access to a system's mass storage drives, SpinRite runs under a GRC-customized version of FreeDOS which has been modified to add compatibility with all file systems. In order to run SpinRite it must first be possible to boot FreeDOS.

    GRC's “BootAble” freeware allows anyone to easily create BIOS-bootable media in order to workout and confirm the details of getting a machine to boot FreeDOS through a BIOS. Once the means of doing that has been determined, the media created by SpinRite can be booted and run in the same way.

    The participants here, who have taken the time to share their knowledge and experience, their successes and some frustrations with booting their computers into FreeDOS, have created a valuable knowledgebase which will benefit everyone who follows.

    You may click on the image to the right to obtain your own copy of BootAble. Then use the knowledge and experience documented here to boot your computer(s) into FreeDOS. And please do not hesitate to ask questions – nowhere else can better answers be found.

    (You may permanently close this reminder with the 'X' in the upper right.)

Lapidary

New member
Mar 10, 2024
3
2
Hello all,

Back when Steve recommended the game, I have been tinkering with it. I find the patters to be relaxing. I kept thinking about how to describe the method to solve it. Then how to find any state of the game. Eventually I figured out that equation. After getting the answer, I wanted to see it go forward and backward a move. Below is the Python code for anyone who has pygame installed. I only program as a hobby, for me this was something cool; and I was proud of figuring out the position function. Once I added the Graphics, and the left and right arrow for forward and backward moves; I wanted to share it! Steve was right; it was a worthy goal to tackle.
Python:
import pygame
import sys

# Initialize Pygame
pygame.init()
pygame.font.init()

# Initial Values
ring_count = 13
current_move = 1023

# Constants
WIDTH, HEIGHT = 600, 400
TOWER_WIDTH = 10
TOWER_HEIGHT = (2/3) * HEIGHT
TOWER_SPACING = WIDTH / 3
font = pygame.font.SysFont('Arial', 12)  # Choose a small font size

# Colors
ODD_COLOR = (27, 48, 183)
EVEN_COLOR = (20, 110, 183)
TOWER_COLOR = (255, 255, 0)
BACKGROUND_COLOR = (0, 0, 0)

# Set up the screen
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Towers of Hanoi")

def tower_of_hanoi_state(num_disks, move_count):
    state = [[], [], []]
    def position(disk, move_count):
        period = 2 ** (disk+1)
        first = period // 2
        return (((move_count - first) // (period))+1) % 3
    for disk in range(num_disks):
        my_disk = disk + 1
        move_over = position(disk, move_count)
        if move_over == 0:
            state[0].append(my_disk)
        elif disk % 2 + num_disks % 2 != 1:
            state[move_over].append(my_disk)
        else:
            if move_over == 1:
                state[2].append(my_disk)
            else:
                state[1].append(my_disk)
    return state

# Function to draw towers
def draw_towers():
    for i in range(3):
        x = (i * TOWER_SPACING) + (TOWER_SPACING - TOWER_WIDTH) / 2
        pygame.draw.rect(screen, TOWER_COLOR, (x, HEIGHT - TOWER_HEIGHT, TOWER_WIDTH, TOWER_HEIGHT))

# Function to create rings
def create_rings(num_rings):
    rings = []
    smallest_ring_width = 20
    largest_ring_width = TOWER_SPACING
    increment = (largest_ring_width - smallest_ring_width) / num_rings
    for i in range(1, num_rings + 1):
        width = smallest_ring_width + (increment * i)
        color = ODD_COLOR if i % 2 == 1 else EVEN_COLOR
        rings.append((width, color))
    return rings

# Function to draw rings based on game state
def draw_rings(game_state, rings):
    for tower_index, rings_in_tower in enumerate(game_state):
        # Draw rings from bottom to top
        for i in range(len(rings_in_tower) - 1, -1, -1):
            ring_number = rings_in_tower[i]
            width, color = rings[ring_number - 1]
            tower_x = (tower_index * TOWER_SPACING) + (TOWER_SPACING - TOWER_WIDTH) / 2  # Center the rings on the peg
            x = tower_x + (TOWER_WIDTH - width) / 2  # Center the ring on the tower
            y = HEIGHT - (len(rings_in_tower) * 15) + (i * 15)
            pygame.draw.rect(screen, color, (x, y, width, 15))
            text_surface = font.render(str(ring_number), True, (200, 200, 200))  # White color
            text_rect = text_surface.get_rect(center=(x + width / 2, y + 7.5))  # Center the text
            screen.blit(text_surface, text_rect)

# Create rings
rings = create_rings(ring_count)
# Main loop
while True:
    game_state = tower_of_hanoi_state(ring_count, current_move)
    screen.fill(BACKGROUND_COLOR)  # Clear screen
    draw_towers()                   # Draw towers
    draw_rings(game_state, rings)   # Draw rings based on game state
    pygame.display.flip()           # Update display
    event = pygame.event.wait()  # Wait for an event
    if event.type == pygame.QUIT:
        pygame.quit()
        sys.exit()
    # Check for key down events
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_LEFT:
            current_move -= 1
            print(f"Current move {current_move}     ", end='\r')
        if event.key == pygame.K_RIGHT:
            current_move += 1
            print(f"Current move {current_move}     ", end='\r')