- Rust 100%
| .woodpecker | ||
| src | ||
| tests | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
Lição 7: Decisões Táticas
Narrativa
O piloto toma decisões baseadas nas leituras dos sensores. "Se energia < 20%, recuar. Se não, avançar." Condicionais permitem que o mecha reaja ao ambiente.
Na cabine de batalha, cada segundo conta. Um piloto experiente avalia constantemente múltiplos fatores — energia restante, integridade dos escudos, distância do inimigo — e toma decisões instantâneas. Estas decisões táticas são o coração do combate efetivo. Sem a capacidade de avaliar condições e reagir adequadamente, mesmo o mecha mais avançado torna-se apenas uma máquina inerte.
A Academia Æther ensina que a verdadeira maestria vem não apenas da força bruta, mas da capacidade de escolher o momento certo para atacar, defender ou recuar. Cada decisão é um ramo no caminho da vitória.
Conceito
Em Rust, condicionais permitem que seu código execute diferentes caminhos baseados em condições booleanas. O if avalia uma condição e executa um bloco se for verdadeira:
if energia < 20 {
println!("Recuar!");
}
O if-else fornece um caminho alternativo quando a condição é falsa:
if energia < 20 {
println!("Recuar!");
} else {
println!("Avançar!");
}
Para múltiplas condições, use if-else if-else:
if energia < 20 {
println!("Crítico - Recuar!");
} else if energia < 50 {
println!("Cuidado - Defender!");
} else {
println!("Ótimo - Avançar!");
}
O match é uma alternativa poderosa para comparar um valor contra múltiplos padrões:
match nivel_alerta {
1 => println!("Informação"),
2 => println!("Atenção"),
3 => println!("Perigo"),
_ => println!("Desconhecido"),
}
Importante: Em Rust, if é uma expressão, não uma declaração. Isso significa que pode retornar um valor:
let estrategia = if energia > 50 { "ataque" } else { "defesa" };
Requisitos
- Entrada: Leituras de sensores (energia, velocidade, níveis de alerta)
- Processamento: Avaliar condições e decidir ações apropriadas
- Saída: Decisões táticas como strings ou valores booleanos
Design de Dados
Esta lição trabalha com funções que recebem valores primitivos (inteiros e strings) e retornam decisões baseadas em condições:
// Avaliação de energia com if-else
pub fn avaliar_nivel_energia(energia: u32) -> &'static str;
// Decisão baseada em tipo e velocidade
pub fn decidir_manobra(tipo: &str, velocidade: i32) -> &'static str;
// Processamento de alerta com match
pub fn processar_alerta(nivel: u8) -> String;
// Avaliação booleana de ameaça
pub fn avaliar_valor_ameaca(inimigo_forca: i32, minha_forca: i32) -> bool;
// Determinação de modo com múltiplas condições
pub fn determinar_modo_combate(energia: u32, escudos: u32) -> &'static str;
As funções demonstram diferentes padrões de condicionais: if simples, if-else chains, match básico, e condições compostas.
Diagrama Conceitual
flowchart TD
A[Leituras dos Sensores] --> B{Avaliação Condicional}
B -->|if| C[Decisão Binária]
B -->|if-else| D[Dois Caminhos]
B -->|if-else if-else| E[Múltiplos Caminhos]
B -->|match| F[Comparação por Padrões]
C --> G[Ação Tática]
D --> G
E --> G
F --> G
Funções e Módulos
//! Lição 7: Decisões Táticas
//!
//! Aprenda a tomar decisões baseadas em condições.
/// Avalia o nível de energia e retorna a ação recomendada
pub fn avaliar_nivel_energia(energia: u32) -> &'static str;
/// Decide a manobra baseada no tipo e velocidade
pub fn decidir_manobra(tipo: &str, velocidade: i32) -> &'static str;
/// Processa o nível de alerta e retorna mensagem
pub fn processar_alerta(nivel: u8) -> String;
/// Avalia se vale a pena atacar baseado nas forças
pub fn avaliar_valor_ameaca(inimigo_forca: i32, minha_forca: i32) -> bool;
/// Determina o modo de combate baseado em energia e escudos
pub fn determinar_modo_combate(energia: u32, escudos: u32) -> &'static str;
Exemplo do Conceito
// Exemplo if-else simples
let energia = 30;
if energia < 20 {
println!("Recuar");
} else {
println!("Avançar");
}
// Exemplo if-else if-else chain
let velocidade = 75;
if velocidade < 30 {
println!("Lento");
} else if velocidade < 70 {
println!("Médio");
} else {
println!("Rápido");
}
// Exemplo match básico
let nivel = 2;
match nivel {
1 => println!("Baixo"),
2 => println!("Médio"),
3 => println!("Alto"),
_ => println!("Desconhecido"),
}
// if como expressão
let status = if energia > 50 { "Bom" } else { "Ruim" };
// Condição composta
if energia > 50 && escudos > 30 {
println!("Pronto para combate");
}
Explicação:
- Linha 2-6: Estrutura if-else básica com dois caminhos
- Linha 9-15: Cadeia de if-else if-else para múltiplas condições
- Linha 18-24: Match para comparar valor contra padrões
- Linha 29: if como expressão que retorna valor
- Linha 30-32: Condição composta com operador &&
Missão
- Implementar
avaliar_nivel_energia: Retorne "Recuar" se energia < 20, senão "Avançar" - Implementar
decidir_manobra: Baseado no tipo ("ataque"/"defesa"/"evasiva") e velocidade, retorne a manobra adequada. Contrato verificado pelos testes:("ataque", 80)→"Investida Rápida"(velocidade alta)("ataque", 50)→"Ataque Padrão"(velocidade baixa)("defesa", 30)→"Escudos Ativos"- O limiar entre "Investida Rápida" e "Ataque Padrão" fica entre 50 e 80 — escolha um valor nesse intervalo e seja consistente
- Implementar
processar_alerta: Use match para converter nível (1-3) em mensagem descritiva - Implementar
avaliar_valor_ameaca: Retorne true se minha_forca for maior ou igual a inimigo_forca (minha_forca >= inimigo_forca) - Implementar
determinar_modo_combate: Combine energia e escudos para decidir entre "agressivo", "defensivo", ou "retirada". Contrato verificado pelos testes:(80, 60)→"Agressivo"(energia e escudos altos)(40, 70)→"Defensivo"(escudos altos, energia moderada)(10, 10)→"Retirada"(energia e escudos baixos)
Diagrama de Fluxo da Missão
flowchart TD
A[Tarefa: Decisões Táticas] --> B[Implementar avaliar_nivel_energia]
B --> C[Implementar decidir_manobra]
C --> D[Implementar processar_alerta]
D --> E[Implementar avaliar_valor_ameaca]
E --> F[Implementar determinar_modo_combate]
F --> G[Testes verificam]
G --> H{Clippy limpo?}
H -->|Sim| I[Concluído]
H -->|Não| J[Corrigir warnings] --> G
Como Executar
# Executar testes
cargo test
# Verificar lint
cargo clippy -- -D warnings
# Formatar código
cargo fmt --check
Dicas
- Lembre-se: Rust exige que todas as ramificações de um if retornem o mesmo tipo
- Use
matchquando tiver múltiplos valores discretos para comparar - A condição de um if deve ser explicitamente booleana (não há coerção automática)
- Para condições compostas, use
&&(E),||(OU), e!(NÃO) - O padrão
_em match captura qualquer valor não coberto pelos outros casos - Prefira match sobre longas cadeias de if-else if quando comparar valores exatos