Spaces:
Sleeping
Sleeping
import gradio as gr | |
import numpy as np | |
import matplotlib.pyplot as plt | |
import random | |
# Classe RubiksCube (mantém o mesmo código) | |
class RubiksCube: | |
def __init__(self): | |
self.cube = np.zeros((6, 3, 3), dtype=int) | |
for i in range(6): | |
self.cube[i] = np.full((3, 3), i) | |
self.color_names = { | |
0: "Branco", | |
1: "Amarelo", | |
2: "Verde", | |
3: "Azul", | |
4: "Vermelho", | |
5: "Laranja" | |
} | |
def rotate_face_clockwise(self, face_num): | |
if 0 <= face_num < 6: | |
self.cube[face_num] = np.rot90(self.cube[face_num], k=-1) | |
self._update_adjacent_faces(face_num, clockwise=True) | |
def rotate_face_counterclockwise(self, face_num): | |
if 0 <= face_num < 6: | |
self.cube[face_num] = np.rot90(self.cube[face_num], k=1) | |
self._update_adjacent_faces(face_num, clockwise=False) | |
def _update_adjacent_faces(self, face_num, clockwise=True): | |
adjacent_faces = { | |
0: [(2,0), (4,0), (3,0), (5,0)], # Topo | |
1: [(2,2), (5,2), (3,2), (4,2)], # Base | |
2: [(0,2), (4,3), (1,0), (5,1)], # Frente | |
3: [(0,0), (5,3), (1,2), (4,1)], # Traseira | |
4: [(0,1), (2,1), (1,1), (3,3)], # Direita | |
5: [(0,3), (3,1), (1,3), (2,3)] # Esquerda | |
} | |
affected = adjacent_faces[face_num] | |
temp_values = [] | |
for face, edge in affected: | |
if edge == 0: | |
temp_values.append(self.cube[face][0].copy()) | |
elif edge == 1: | |
temp_values.append(self.cube[face][:,2].copy()) | |
elif edge == 2: | |
temp_values.append(self.cube[face][2].copy()) | |
else: # edge == 3 | |
temp_values.append(self.cube[face][:,0].copy()) | |
if clockwise: | |
temp_values = [temp_values[-1]] + temp_values[:-1] | |
else: | |
temp_values = temp_values[1:] + [temp_values[0]] | |
for (face, edge), new_values in zip(affected, temp_values): | |
if edge == 0: | |
self.cube[face][0] = new_values | |
elif edge == 1: | |
self.cube[face][:,2] = new_values | |
elif edge == 2: | |
self.cube[face][2] = new_values | |
else: # edge == 3 | |
self.cube[face][:,0] = new_values | |
def is_solved(self): | |
return all(np.all(self.cube[face] == face) for face in range(6)) | |
def scramble(self, num_moves=20): | |
moves = [] | |
for _ in range(num_moves): | |
face = random.randint(0, 5) | |
direction = random.choice([True, False]) | |
if direction: | |
self.rotate_face_clockwise(face) | |
moves.append(f"Rotação horária da face {self.color_names[face]}") | |
else: | |
self.rotate_face_counterclockwise(face) | |
moves.append(f"Rotação anti-horária da face {self.color_names[face]}") | |
return moves | |
# Funções de interface | |
def num_to_color(num): | |
colors = { | |
0: "#FFFFFF", # Branco | |
1: "#FFFF00", # Amarelo | |
2: "#00FF00", # Verde | |
3: "#0000FF", # Azul | |
4: "#FF0000", # Vermelho | |
5: "#FFA500" # Laranja | |
} | |
return colors.get(num, "#CCCCCC") | |
def create_cube_visualization(cube_state): | |
fig, ax = plt.subplots(4, 3, figsize=(10, 12)) | |
plt.subplots_adjust(hspace=0.4, wspace=0.4) | |
for row in ax: | |
for col in row: | |
col.set_xticks([]) | |
col.set_yticks([]) | |
face_positions = [ | |
(1, 1), # Face superior (branco) | |
(2, 1), # Face frontal (verde) | |
(1, 2), # Face direita (vermelho) | |
(1, 0), # Face esquerda (laranja) | |
(3, 1), # Face inferior (amarelo) | |
(2, 2), # Face traseira (azul) | |
] | |
for face_idx, (row, col) in enumerate(face_positions): | |
if row < 4 and col < 3: | |
face = cube_state[face_idx] | |
for i in range(3): | |
for j in range(3): | |
color = num_to_color(face[i, j]) | |
ax[row, col].add_patch(plt.Rectangle((j/3, (2-i)/3), 1/3, 1/3, facecolor=color, edgecolor='black')) | |
ax[row, col].set_xlim(0, 1) | |
ax[row, col].set_ylim(0, 1) | |
ax[row, col].set_title(f'Face {cube.color_names[face_idx]}') | |
for row in range(4): | |
for col in range(3): | |
if (row, col) not in face_positions: | |
fig.delaxes(ax[row, col]) | |
return fig | |
def process_moves(moves, current_state): | |
moves_list = moves.strip().split('\n') | |
output_text = [] | |
for move in moves_list: | |
move = move.strip().lower() | |
try: | |
if move.startswith('r'): # rotação horária | |
face = int(move[1]) | |
cube.rotate_face_clockwise(face) | |
output_text.append(f"Rotação horária da face {cube.color_names[face]}") | |
elif move.startswith('l'): # rotação anti-horária | |
face = int(move[1]) | |
cube.rotate_face_counterclockwise(face) | |
output_text.append(f"Rotação anti-horária da face {cube.color_names[face]}") | |
except: | |
output_text.append(f"Movimento inválido: {move}") | |
fig = create_cube_visualization(cube.cube) | |
status = "Resolvido!" if cube.is_solved() else "Não resolvido" | |
return fig, "\n".join(output_text), status | |
def scramble_cube(n_moves): | |
moves = cube.scramble(int(n_moves)) | |
fig = create_cube_visualization(cube.cube) | |
status = "Resolvido!" if cube.is_solved() else "Não resolvido" | |
return fig, "\n".join(moves), status | |
def show_initial_state(): | |
fig = create_cube_visualization(cube.cube) | |
return fig, "", "Cubo inicial" | |
# Criar instância do cubo | |
cube = RubiksCube() | |
# Criar interface Gradio | |
with gr.Blocks(title="Cubo Mágico") as demo: | |
gr.Markdown("# Simulador de Cubo Mágico") | |
gr.Markdown(""" | |
### Como usar: | |
1. Use o botão 'Embaralhar' para misturar o cubo | |
2. Digite movimentos no formato: | |
- r0 (rotação horária da face 0) | |
- l0 (rotação anti-horária da face 0) | |
onde o número representa a face: | |
0: Branco, 1: Amarelo, 2: Verde, 3: Azul, 4: Vermelho, 5: Laranja | |
""") | |
with gr.Row(): | |
with gr.Column(): | |
n_moves = gr.Slider(minimum=1, maximum=20, value=5, step=1, label="Número de movimentos para embaralhar") | |
scramble_btn = gr.Button("Embaralhar") | |
moves_input = gr.Textbox(label="Digite os movimentos (um por linha)", lines=5) | |
move_btn = gr.Button("Executar Movimentos") | |
with gr.Column(): | |
cube_plot = gr.Plot() | |
output_text = gr.Textbox(label="Movimentos realizados", lines=5) | |
status_text = gr.Textbox(label="Status") | |
# Conectar os botões às funções | |
scramble_btn.click( | |
fn=scramble_cube, | |
inputs=[n_moves], | |
outputs=[cube_plot, output_text, status_text] | |
) | |
move_btn.click( | |
fn=process_moves, | |
inputs=[moves_input, status_text], | |
outputs=[cube_plot, output_text, status_text] | |
) | |
# Carregar estado inicial | |
demo.load( | |
fn=show_initial_state, | |
inputs=None, | |
outputs=[cube_plot, output_text, status_text] | |
) | |
# Iniciar a aplicação | |
demo.launch() |