Skip to content

Commit

Permalink
Merge branch 'master' into main
Browse files Browse the repository at this point in the history
Commit do projeto foi feito para a branch master, mas
a nomenclatura 'master' foi depreciada em favor da
nomenclatura 'main'.
  • Loading branch information
Pedro G committed Mar 9, 2021
2 parents d936736 + 5ee66d5 commit 78b0642
Show file tree
Hide file tree
Showing 8 changed files with 451 additions and 0 deletions.
Binary file added jar/campo-minado-swing.jar
Binary file not shown.
148 changes: 148 additions & 0 deletions src/com/yofiel/cm/modelo/Campo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* Campo possui alguns eventos. Eventos de Campo sao identificados pelo enum CampoEvent.
* Os observers de Campo implementam a Interface CampoObserver.
* CampoObserver e uma FunctionalInterface BiConsumer.
* Tabuleiro vai ser um Observer por controlar os campos
*/

package com.yofiel.cm.modelo;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Campo {

// ATRIBUTOS
private final int linha;
private final int coluna;

private boolean aberto;
private boolean minado;
private boolean marcado;

private List<Campo> vizinhos = new ArrayList<>();
private Set<CampoObserver> observers = new HashSet<>();

// CONSTRUTOR
Campo(int linha, int coluna) {
this.linha = linha;
this.coluna = coluna;
}

// SETTER E GETTERS
void setAberto(boolean aberto) {
this.aberto = aberto;

if (aberto) {
notificarObservers(CampoEvent.ABRIR);
}
}

public boolean isMarcado() {
return marcado;
}

public boolean isMinado() {
return minado;
}

public boolean isAberto() {
return aberto;
}

public int getLinha() {
return linha;
}

public int getColuna() {
return coluna;
}

// METODOS
public void addObserver(CampoObserver observer) {
observers.add(observer);
}

private void notificarObservers(CampoEvent evento) {
observers.forEach(o -> o.eventoOcorreu(this, evento));
}

boolean adicionarVizinho(Campo candidatoVizinho) {
boolean linhaDiferente = linha != candidatoVizinho.linha;
boolean colunaDiferente = coluna != candidatoVizinho.coluna;
boolean diagonal = linhaDiferente && colunaDiferente;

int deltaLinha = Math.abs(linha - candidatoVizinho.linha);
int deltaColuna = Math.abs(coluna - candidatoVizinho.coluna);
int deltaGeral = deltaColuna + deltaLinha;

if (deltaGeral == 1 && !diagonal) {
vizinhos.add(candidatoVizinho);
return true;
} else if (deltaGeral == 2 && diagonal) {
vizinhos.add(candidatoVizinho);
return true;
} else {
return false;
}
}

public void alternarMarcacao() {
if (!aberto) {
marcado = !marcado;

if (marcado) {
notificarObservers(CampoEvent.MARCAR);
} else {
notificarObservers(CampoEvent.DESMARCAR);
}
}
}

public boolean abrir() {
if (!aberto && !marcado) {
if (minado) {
notificarObservers(CampoEvent.EXPLODIR);
return true;
}

setAberto(true);

if (vizinhancaSegura()) {
vizinhos.forEach(v -> v.abrir());
}

return true;
} else {
return false;
}
}

public boolean vizinhancaSegura() {
return vizinhos.stream().noneMatch(v -> v.minado);
}

void minar() {
minado = true;
}

boolean objetivoAlcancado() {
boolean desvendado = !minado && aberto;
boolean protegido = minado && marcado;
return desvendado || protegido;
}

public int minasNaVizinhanca() {
return (int) vizinhos.stream().filter(v -> v.minado).count();
}

void reiniciar() {
aberto = false;
minado = false;
marcado = false;
notificarObservers(CampoEvent.REINICIAR);
}

}
6 changes: 6 additions & 0 deletions src/com/yofiel/cm/modelo/CampoEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.yofiel.cm.modelo;

public enum CampoEvent {

ABRIR, MARCAR, DESMARCAR, EXPLODIR, REINICIAR
}
7 changes: 7 additions & 0 deletions src/com/yofiel/cm/modelo/CampoObserver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.yofiel.cm.modelo;

@FunctionalInterface
public interface CampoObserver {
// ESSA INTERFACE PODERIA SER SUBSTITUIDA PELA INTERFACE BICONSUMER DO PROPRIO JAVA
public void eventoOcorreu(Campo campo, CampoEvent evento);
}
107 changes: 107 additions & 0 deletions src/com/yofiel/cm/modelo/Tabuleiro.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.yofiel.cm.modelo;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

public class Tabuleiro implements CampoObserver {

// ATRIBUTOS
private final int linhas;
private final int colunas;
private final int minas;

private final List<Campo> campos = new ArrayList<>();
private final Set<Consumer<Boolean>> observers = new HashSet<>();

// CONSTRUTOR
public Tabuleiro(int linhas, int colunas, int minas) {
this.linhas = linhas;
this.colunas = colunas;
this.minas = minas;

gerarCampos();
associarVizinhos();
sortearMinas();
}

// GETTERS
public int getLinhas() {
return linhas;
}

public int getColunas() {
return colunas;
}

public int getMinas() {
return minas;
}

public List<Campo> getCampos() {
return campos;
}

// METODOS
public void addObserver(Consumer<Boolean> observer) {
observers.add(observer);
}

public void notificarObservers(boolean resultado) {
observers.forEach(o -> o.accept(resultado));
}

private void gerarCampos() {
for (int linha = 0; linha < linhas; linha++) {
for (int coluna = 0; coluna < colunas; coluna++) {
Campo campo = new Campo(linha, coluna);
campo.addObserver(this);
campos.add(campo);
}
}
}

private void associarVizinhos() {
for (Campo c1 : campos) {
for (Campo c2 : campos) {
c1.adicionarVizinho(c2);
}
}
}

private void sortearMinas() {
long minasArmadas;

do {
int aleatorio = (int) (Math.random() * campos.size());
campos.get(aleatorio).minar();
minasArmadas = campos.stream().filter(c -> c.isMinado()).count();
} while (minasArmadas < minas);
}

public boolean objetivoAlcancado() {
return campos.stream().allMatch(c -> c.objetivoAlcancado());
}

public void reiniciar() {
campos.stream().forEach(c -> c.reiniciar());
sortearMinas();
}

private void mostrarMinas() {
campos.stream().filter(c -> c.isMinado()).filter(c -> !c.isMarcado()).forEach(c -> c.setAberto(true));
}

@Override
public void eventoOcorreu(Campo campo, CampoEvent evento) {
if (evento == CampoEvent.EXPLODIR) {
mostrarMinas();
notificarObservers(false);
} else if (objetivoAlcancado()) {
notificarObservers(true);
}
}

}
124 changes: 124 additions & 0 deletions src/com/yofiel/cm/visao/BotaoCampo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package com.yofiel.cm.visao;

import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;

import com.yofiel.cm.modelo.Campo;
import com.yofiel.cm.modelo.CampoEvent;
import com.yofiel.cm.modelo.CampoObserver;

@SuppressWarnings("serial")
public class BotaoCampo extends JButton implements CampoObserver, MouseListener {

// ATRIBUTOS
private static final Color BG_PADRAO = new Color(184, 184, 184);
private static final Color BG_MARCAR = new Color(8, 179, 247);
private static final Color BG_EXPLODIR = new Color(189, 66, 68);
private static final Color TEXTO_VERDE = new Color(0, 100, 0);

private Campo campo;

// CONSTRUTOR
public BotaoCampo(Campo campo) {
this.campo = campo;
setBackground(BG_PADRAO);
setBorder(BorderFactory.createBevelBorder(0));

campo.addObserver(this);
addMouseListener(this);
}

// METODOS
@Override
public void eventoOcorreu(Campo campo, CampoEvent evento) {
switch (evento) {
case ABRIR:
aplicarEstiloAbrir();
break;
case MARCAR:
aplicarEstiloMarcar();
break;
case EXPLODIR:
aplicarEstiloExplodir();
break;
default:
aplicarEstiloPadrao();
}
}

private void aplicarEstiloPadrao() {
setBackground(BG_PADRAO);
setBorder(BorderFactory.createBevelBorder(0));
setText("");
}

private void aplicarEstiloAbrir() {
setBorder(BorderFactory.createLineBorder(Color.GRAY));

if (campo.isMinado()) {
setBackground(BG_EXPLODIR);
return;
}

switch (campo.minasNaVizinhanca()) {
case 1:
setForeground(TEXTO_VERDE);
break;
case 2:
setForeground(Color.BLUE);
break;
case 3:
setForeground(Color.YELLOW);
break;
case 4:
case 5:
case 6:
setForeground(Color.RED);
break;
default:
setForeground(Color.PINK);
}

String valor = !campo.vizinhancaSegura() ? campo.minasNaVizinhanca() + "" : "";
setText(valor);
}

private void aplicarEstiloMarcar() {
setBackground(BG_MARCAR);
setForeground(Color.BLACK);
setText("M");
}

private void aplicarEstiloExplodir() {
setBackground(BG_EXPLODIR);
setForeground(Color.WHITE);
setText("*");
}

// METODOS DA INTERFACE DOS EVENTOS DO MOUSE
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() == 1) {
campo.abrir();
} else {
campo.alternarMarcacao();
}
}

public void mouseClicked(MouseEvent e) {
}

public void mouseReleased(MouseEvent e) {
}

public void mouseEntered(MouseEvent e) {
}

public void mouseExited(MouseEvent e) {
}

}
Loading

0 comments on commit 78b0642

Please sign in to comment.