Fun with Towers of Hanoi

  • DNS Benchmark v2 is Finished and Available!
    Guest:
    That's right. It took an entire year, but the result far more accurate and feature laden than we originally planned. The world now has a universal, multi-protocol, super-accurate, DNS resolver performance-measuring tool. This major second version is not free. But the deal is, purchase it once for $9.95 and you own it — and it's entire future — without ever being asked to pay anything more. For an overview list of features and more, please see The DNS Benchmark page at GRC. If you decide to make it your own, thanks in advance. It's a piece of work I'm proud to offer for sale. And if you should have any questions, many of the people who have been using and testing it throughout the past year often hang out here.
    /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')