RubiksCube / app.py
DHEIVER's picture
Update app.py
2eb8c3b verified
raw
history blame
7.47 kB
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()