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.
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')
