PC SOFT

FOROS PROFESIONALES
WINDEVWEBDEV y WINDEV Mobile

Inicio → WINDEV 25 → Jogo da velha (Tic-Tac-Toe) em WLanguage, utilizando Orientação a Objetos
Jogo da velha (Tic-Tac-Toe) em WLanguage, utilizando Orientação a Objetos
Iniciado por Boller, 17,mar. 2025 16:55 - No hay respuesta
Miembro registrado
4.520 mensajes
Publicado el 17,marzo 2025 - 16:55
Boa tarde

Vou criar uma implementação do jogo da velha (Tic-Tac-Toe) em WLanguage, utilizando Orientação a Objetos (OOP) e aplicando as melhores práticas possíveis, como encapsulamento, responsabilidade única (SOLID), modularidade e código limpo. O jogo será para dois jogadores (X e O), com um tabuleiro 3x3, e verificará vitórias ou empates.

---

### Estrutura do Projeto
Vamos dividir o código em classes com responsabilidades claras:
- **`Celula`**: Representa uma célula do tabuleiro.
- **`Tabuleiro`**: Gerencia o estado do jogo e a lógica de vitória.
- **`Jogo`**: Controla a interação com o usuário e o fluxo do jogo.

---

### Passo 1: Código das Classes

1. **Classe `Celula`**
Representa cada célula do tabuleiro, que pode estar vazia ou conter "X" ou "O".

```wlanguage
CLASS Celula
PRIVATE
sValor IS string = " " // Espaço vazio por padrão
PUBLIC
PROCEDURE Construtor()
sValor = " "
END
FUNCTION GetValor() IS string
RETURN sValor
END
PROCEDURE SetValor(sNovoValor IS string)
IF sValor = " " AND (sNovoValor = "X" OR sNovoValor = "O") THEN
sValor = sNovoValor
END
END
FUNCTION EstaVazia() IS boolean
RETURN sValor = " "
END
END
```
- **Encapsulamento**: O valor é privado e só pode ser alterado por `SetValor`, com validação.
- **Responsabilidade**: Gerencia apenas o estado de uma célula.

2. **Classe `Tabuleiro`**
Gerencia o estado do jogo, incluindo o tabuleiro e a lógica de vitória.

```wlanguage
CLASS Tabuleiro
PRIVATE
arrCelulas IS array of Celula[3,3] // Matriz 3x3
PUBLIC
PROCEDURE Construtor()
LOCAL
i, j IS int
FOR i = 0 TO 2
FOR j = 0 TO 2
arrCelulas[i,j] = NEW Celula()
END
END
END
FUNCTION Jogar(nLinha IS int, nColuna IS int, sJogador IS string) IS boolean
IF nLinha >= 0 AND nLinha <= 2 AND nColuna >= 0 AND nColuna <= 2 THEN
IF arrCelulas[nLinha, nColuna].EstaVazia() THEN
arrCelulas[nLinha, nColuna].SetValor(sJogador)
RETURN True
END
END
RETURN False
END
FUNCTION VerificarVitoria() IS string
LOCAL
i IS int
sLinha, sColuna, sDiag1, sDiag2 IS string
// Verifica linhas
FOR i = 0 TO 2
sLinha = arrCelulas[i,0].GetValor() + arrCelulas[i,1].GetValor() + arrCelulas[i,2].GetValor()
IF sLinha = "XXX" THEN RETURN "X"
IF sLinha = "OOO" THEN RETURN "O"
END
// Verifica colunas
FOR i = 0 TO 2
sColuna = arrCelulas[0,i].GetValor() + arrCelulas[1,i].GetValor() + arrCelulas[2,i].GetValor()
IF sColuna = "XXX" THEN RETURN "X"
IF sColuna = "OOO" THEN RETURN "O"
END
// Verifica diagonais
sDiag1 = arrCelulas[0,0].GetValor() + arrCelulas[1,1].GetValor() + arrCelulas[2,2].GetValor()
sDiag2 = arrCelulas[0,2].GetValor() + arrCelulas[1,1].GetValor() + arrCelulas[2,0].GetValor()
IF sDiag1 = "XXX" OR sDiag2 = "XXX" THEN RETURN "X"
IF sDiag1 = "OOO" OR sDiag2 = "OOO" THEN RETURN "O"
RETURN ""
END
FUNCTION EstaCheio() IS boolean
LOCAL
i, j IS int
FOR i = 0 TO 2
FOR j = 0 TO 2
IF arrCelulas[i,j].EstaVazia() THEN
RETURN False
END
END
END
RETURN True
END
FUNCTION ToString() IS string
LOCAL
sResultado IS string = ""
i, j IS int
FOR i = 0 TO 2
FOR j = 0 TO 2
sResultado += arrCelulas[i,j].GetValor() + " | "
END
sResultado = Left(sResultado, Length(sResultado)-3) + Charact(13)
IF i < 2 THEN sResultado += "---------" + Charact(13)
END
RETURN sResultado
END
END
```
- **Encapsulamento**: A matriz é privada, acessada apenas por métodos.
- **Responsabilidade Única**: Gerencia o tabuleiro e verifica o estado do jogo.
- **Métodos**: `Jogar` para marcar uma jogada, `VerificarVitoria` para checar ganhador, `EstaCheio` para empate, `ToString` para exibição.

3. **Classe `Jogo`**
Controla o fluxo do jogo e a interação com o usuário.

```wlanguage
CLASS Jogo
PRIVATE
oTabuleiro IS Tabuleiro
sJogadorAtual IS string = "X"
PUBLIC
PROCEDURE Iniciar()
oTabuleiro = NEW Tabuleiro()
Info("Bem-vindo ao Tic-Tac-Toe!")
LOOP
Info(oTabuleiro.ToString())
nLinha IS int = Val(Input("Jogador " + sJogadorAtual + " - Linha (0-2): "))
nColuna IS int = Val(Input("Jogador " + sJogadorAtual + " - Coluna (0-2): "))
IF oTabuleiro.Jogar(nLinha, nColuna, sJogadorAtual) THEN
sVencedor IS string = oTabuleiro.VerificarVitoria()
IF sVencedor <> "" THEN
Info(oTabuleiro.ToString())
Info("Jogador " + sVencedor + " venceu!")
BREAK
END
IF oTabuleiro.EstaCheio() THEN
Info(oTabuleiro.ToString())
Info("Empate!")
BREAK
END
sJogadorAtual = IIF(sJogadorAtual = "X", "O", "X")
ELSE
Info("Jogada inválida! Tente novamente.")
END
END
END
END
```
- **Separação de Camadas**: Interage com o usuário e delega a lógica ao `Tabuleiro`.
- **Estado**: Alterna entre jogadores "X" e "O".

---

### Passo 2: Implementação no WinDev
1. Crie um projeto no WinDev.
2. Adicione as classes em um arquivo `.wls`.
3. No evento principal (ex.: botão "Jogar"), chame:
```wlanguage
oJogo IS Jogo
oJogo = NEW Jogo()
oJogo.Iniciar()
```

4. **Interface Gráfica (opcional)**:
- Use uma tabela 3x3 ou 9 botões no formulário.
- Atualize a UI com `oTabuleiro.ToString()` ou crie um método para acessar a matriz diretamente.
- Adicione eventos de clique para capturar as jogadas.

---

### Melhores Práticas Aplicadas
- **SOLID**:
- **S**: Cada classe tem uma única responsabilidade (`Celula` para estado, `Tabuleiro` para lógica, `Jogo` para fluxo).
- **O**: Fácil de estender (ex.: para um tabuleiro 4x4, basta ajustar a matriz e a lógica de vitória).
- **L**: Não aplicável diretamente (sem herança), mas respeitado em design.
- **I**: Métodos públicos são específicos e mínimos.
- **D**: Dependências são claras e injetadas (`Jogo` usa `Tabuleiro`).

- **Código Limpo**:
- Nomes descritivos (`Jogar`, `VerificarVitoria`).
- Funções curtas e focadas.
- Validações para evitar erros (ex.: célula ocupada).

- **Reutilização**:
- As classes podem ser adaptadas para outros jogos de tabuleiro.

---

### Passo 3: Melhorias Possíveis
- **IA Oponente**: Adicione um método em `Jogo` para um jogador automático (ex.: usando Minimax).
- **Reiniciar Jogo**: Inclua uma opção para reiniciar após o fim.
- **Persistência**: Salve o estado com HFSQL do WinDev.
- **UI Avançada**: Use imagens ou cores para "X" e "O" no WinDev.

Se quiser alguma dessas melhorias ou ajustes, é só pedir!

--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/