diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9f97022
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+target/
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..f453be4
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+
+ berack96
+ Minefield
+ 1.0.1
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.9.0
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 2.2
+
+
+ jar-with-dependencies
+
+
+
+ berack96.games.minefield.Game
+
+
+
+
+
+ package
+
+ single
+
+
+
+
+
+
+
+ 17
+ 17
+
+
+
\ No newline at end of file
diff --git a/src/main/java/berack96/games/minefield/Game.java b/src/main/java/berack96/games/minefield/Game.java
new file mode 100644
index 0000000..2c9b71e
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/Game.java
@@ -0,0 +1,201 @@
+package berack96.games.minefield;
+
+import berack96.games.minefield.frame.MenuFrame;
+import berack96.games.minefield.object.Decisor;
+import berack96.games.minefield.object.Field;
+import berack96.games.minefield.object.view.FieldView;
+import berack96.games.minefield.runexception.OutOfBoundsException;
+import jbook.util.Input;
+
+/**
+ * Classe che utilizza {@link Field} e {@link Decisor} per creare una interazione con l'utente.
+ * Il gioco puo' esser fatto partire per console o come finestra.
+ * Senza argomenti il gioco partira' in finestra.
+ *
+ * Lista dei possibili argomenti da passare al programma:
+ * -nogui indica che il gioco partira' su console.
+ * -safe=(true/false)
+ * -mode=(EASY/MEDIUM/HARD/CUSTOM)
+ * -dim=(colonne),(righe)
+ * -mines=(num)
+ *
+ * Questi argomenti per ora funzionano solo con il gioco in console
+ * ovvero solo se si usa anche -nogui
+ *
+ * @author Jack
+ *
+ */
+public class Game {
+
+ private static Field field;
+ private static boolean graphic = true;
+
+ private static Boolean safe = null;
+ private static Mode mode = null;
+ private static Integer columns = null;
+ private static Integer lines = null;
+ private static Integer mines = null;
+
+ public static void main(String[] arg) {
+ for(String s: arg) // looking for arguments
+ try {
+
+ if(s.matches("-nogui"))
+ graphic = false;
+ else if(s.matches("-safe=(.*)")) {
+ String temp[] = s.split("=");
+ safe = Boolean.getBoolean(temp[1]);
+ }
+ else if(s.matches("-mode=(.*)")) {
+ String temp2[] = s.split("=");
+ mode = Mode.valueOf(temp2[1]);
+ }
+ else if(s.matches("-dim=(.*)")) {
+ String temp3[] = s.split("=");
+ String t[] = temp3[1].split(",");
+ columns = Integer.valueOf(t[0]);
+ lines = Integer.valueOf(t[1]);
+ }
+ else if(s.matches("-mines=(.*)")) {
+ String temp5[] = s.split("=");
+ mines = Integer.valueOf(temp5[1]);
+ }
+ } catch(Exception e) {}
+
+ if(mode == null && (columns != null || lines != null || mines != null))
+ mode = Mode.CUSTOM;
+
+ if(graphic)
+ Game.startGraphic();
+ else
+ Game.startConsole();
+ }
+
+ private static void startConsole() {
+ String str;
+
+ // PARTENZA PROTETTA O MENO
+ if(safe == null) {
+ System.out.println("Vuoi la partenza protetta? (non troverai mine intorno alla prima cella scoperta)");
+ do {
+ System.out.print("[s/N] ");
+
+ str = Input.readString();
+ } while(!str.matches("(s|S|N|n)"));
+
+ safe = str.matches("(s|S)");
+ }
+
+ // DIFFICOLTA DEL GIOCO
+ if(mode == null) {
+ System.out.println("A che difficolta' vuoi giocare? ");
+ do {
+ System.out.println("1 - Facile.");
+ System.out.println("2 - Medio.");
+ System.out.println("3 - Difficile.");
+ System.out.println("4 - Personalizzata.");
+
+ str = Input.readString();
+ } while(!str.matches("(1|2|3|4)"));
+
+ if(str.matches("1"))
+ mode = Mode.EASY;
+ else if(str.matches("2"))
+ mode = Mode.MEDIUM;
+ else if(str.matches("3"))
+ mode = Mode.HARD;
+ else if(str.matches("4"))
+ mode = Mode.CUSTOM;
+ }
+
+ // DIFFICOLTA PERSONALIZATA
+ if(mode == Mode.CUSTOM) do {
+
+ if(columns == null)
+ columns = getNum("Inserisci quante colonne deve avere il campo: ", "Colonne = ", 1, Field.MAX_VAL);
+ if(lines == null)
+ lines = getNum("Inserisci quante righe deve avere il campo; ", "Righe = ", 1, Field.MAX_VAL);
+ if(mines == null)
+ mines = getNum("Inserisci le mine presenti nel campo: ", "Mine = ", 1, Field.MAX_VAL);
+
+ try {
+ field = Decisor.getNewField(safe, columns, lines, mines);
+ } catch(Exception e) {
+ System.out.println(e.getMessage());
+ mines = null;
+ }
+
+ } while(field == null);
+ else
+ field = Decisor.getNewField(safe, mode);
+
+ // code game
+ do {
+ System.out.println(FieldView.toString(field));
+
+ // coordinates used for interacting with user
+ int x = getNum(null, "X = ", 0, Integer.MAX_VALUE);
+ int y = getNum(null, "Y = ", 0, Integer.MAX_VALUE);;
+
+ System.out.println("Vuoi Scoprire la cella(S),\nSettarla come pericolosa(P),\nO rimuoverla dallo stato di pericolosa(R)?");
+ str = null;
+
+ do {
+ System.out.print("Inserisci scelta: ");
+
+ str = Input.readString();
+ } while(str.matches("(S|s|P|p|R|r)") == false);
+
+ try {
+ if(str.matches("(s|S)"))
+ field.cellUncover(x, y);
+ else if(str.matches("(P|p)"))
+ field.cellSetDangerous(x, y);
+ else
+ field.cellSetNotDangerous(x, y);
+ } catch (OutOfBoundsException e) {
+ System.out.println("Inserisci delle coordinate valide...");
+ }
+ } while(!Decisor.isALoose(field) && !Decisor.isAWin(field));
+
+ Decisor.uncoverAllMinesCells(field);
+ Decisor.uncoverAllDangerousCells(field);
+
+ System.out.println(FieldView.toString(field));
+
+ if(Decisor.isALoose(field))
+ System.out.println("Hai perso. SCARSO AHAHAHHA!");
+ else
+ System.out.println("Hai vinto.");
+ }
+
+ private static void startGraphic() {
+ MenuFrame menuFr = new MenuFrame();
+ menuFr.setVisible(true);
+ }
+
+
+ private static int getNum(String messaggio, String campo, int min, int max) {
+ if(messaggio != null)
+ System.out.println(messaggio);
+
+ int num = min - 1;
+ do {
+ try {
+ num = Input.readInt(campo);
+ if(nummax) {
+ System.out.println("Inserire un numero minore di " + max);
+ num = -1;
+ }
+ } catch(java.lang.NumberFormatException e) {
+ System.out.println("Inserire un numero.");
+ }
+ } while(num < min);
+
+ return num;
+ }
+}
diff --git a/src/main/java/berack96/games/minefield/Mode.java b/src/main/java/berack96/games/minefield/Mode.java
new file mode 100644
index 0000000..42e5b18
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/Mode.java
@@ -0,0 +1,34 @@
+package berack96.games.minefield;
+
+import berack96.games.minefield.object.Decisor;
+
+/**
+ * Serve a scegliere una delle modalita' di gioco senza inserire ogni singolo parametro.
+ * Insomma serve a velocizzare la partenza del gioco.
+ * Da usare con {@link Decisor}
+ *
+ * @author Jack
+ *
+ */
+public enum Mode {
+
+ /**
+ * Modalita' di gioco facile
+ */
+ EASY,
+
+ /**
+ * Modalita' di gioco media
+ */
+ MEDIUM,
+
+ /**
+ * Modalita' di gioco difficile
+ */
+ HARD,
+
+ /**
+ * Modalita' di gioco personalizzata
+ */
+ CUSTOM
+}
diff --git a/src/main/java/berack96/games/minefield/assets/icons/1one.png b/src/main/java/berack96/games/minefield/assets/icons/1one.png
new file mode 100644
index 0000000..4949a06
Binary files /dev/null and b/src/main/java/berack96/games/minefield/assets/icons/1one.png differ
diff --git a/src/main/java/berack96/games/minefield/assets/icons/2two.png b/src/main/java/berack96/games/minefield/assets/icons/2two.png
new file mode 100644
index 0000000..0628f66
Binary files /dev/null and b/src/main/java/berack96/games/minefield/assets/icons/2two.png differ
diff --git a/src/main/java/berack96/games/minefield/assets/icons/3three.png b/src/main/java/berack96/games/minefield/assets/icons/3three.png
new file mode 100644
index 0000000..6958d0b
Binary files /dev/null and b/src/main/java/berack96/games/minefield/assets/icons/3three.png differ
diff --git a/src/main/java/berack96/games/minefield/assets/icons/4four.png b/src/main/java/berack96/games/minefield/assets/icons/4four.png
new file mode 100644
index 0000000..5a75960
Binary files /dev/null and b/src/main/java/berack96/games/minefield/assets/icons/4four.png differ
diff --git a/src/main/java/berack96/games/minefield/assets/icons/5five.png b/src/main/java/berack96/games/minefield/assets/icons/5five.png
new file mode 100644
index 0000000..7c4d189
Binary files /dev/null and b/src/main/java/berack96/games/minefield/assets/icons/5five.png differ
diff --git a/src/main/java/berack96/games/minefield/assets/icons/6six.png b/src/main/java/berack96/games/minefield/assets/icons/6six.png
new file mode 100644
index 0000000..aba78eb
Binary files /dev/null and b/src/main/java/berack96/games/minefield/assets/icons/6six.png differ
diff --git a/src/main/java/berack96/games/minefield/assets/icons/7seven.png b/src/main/java/berack96/games/minefield/assets/icons/7seven.png
new file mode 100644
index 0000000..6100a02
Binary files /dev/null and b/src/main/java/berack96/games/minefield/assets/icons/7seven.png differ
diff --git a/src/main/java/berack96/games/minefield/assets/icons/8eight.png b/src/main/java/berack96/games/minefield/assets/icons/8eight.png
new file mode 100644
index 0000000..36d9056
Binary files /dev/null and b/src/main/java/berack96/games/minefield/assets/icons/8eight.png differ
diff --git a/src/main/java/berack96/games/minefield/assets/icons/flag.png b/src/main/java/berack96/games/minefield/assets/icons/flag.png
new file mode 100644
index 0000000..4b53d0f
Binary files /dev/null and b/src/main/java/berack96/games/minefield/assets/icons/flag.png differ
diff --git a/src/main/java/berack96/games/minefield/assets/icons/flagRight.png b/src/main/java/berack96/games/minefield/assets/icons/flagRight.png
new file mode 100644
index 0000000..7707ade
Binary files /dev/null and b/src/main/java/berack96/games/minefield/assets/icons/flagRight.png differ
diff --git a/src/main/java/berack96/games/minefield/assets/icons/flagWrong.png b/src/main/java/berack96/games/minefield/assets/icons/flagWrong.png
new file mode 100644
index 0000000..79366fc
Binary files /dev/null and b/src/main/java/berack96/games/minefield/assets/icons/flagWrong.png differ
diff --git a/src/main/java/berack96/games/minefield/assets/icons/mine.png b/src/main/java/berack96/games/minefield/assets/icons/mine.png
new file mode 100644
index 0000000..c692270
Binary files /dev/null and b/src/main/java/berack96/games/minefield/assets/icons/mine.png differ
diff --git a/src/main/java/berack96/games/minefield/frame/EndFrame.java b/src/main/java/berack96/games/minefield/frame/EndFrame.java
new file mode 100644
index 0000000..bd29743
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/frame/EndFrame.java
@@ -0,0 +1,84 @@
+package berack96.games.minefield.frame;
+
+import java.awt.Dimension;
+import java.awt.GridLayout;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import berack96.games.minefield.listener.EndFrameListener;
+
+/**
+ * Classe che estende i {@link JPanel} in modo da creare una piccola finestra che appare alla fine del gioco.
+ *
+ * Essa contiene tre bottoni:
+ * Menu che fa tornare ad un {@link MenuFrame},
+ * Retry che fa riprovare la modalita' di gioco che era nel pannello {@link GameFrame},
+ * Exit che serve a chiudere il gioco.
+ *
+ * @author Jack
+ *
+ */
+public class EndFrame extends JFrame{
+
+ private static final long serialVersionUID = 1L;
+
+ private JLabel labelMsg;
+
+ /**
+ * Costruttore: bisogna passargli la finestra di gioco corrente e una finestra menu.
+ *
+ * @param game Il gioco corrente che e' finito
+ * @param menu Il menu' che si vuole mostrare alla fine
+ */
+ public EndFrame(GameFrame game, MenuFrame menu)
+ {
+ setTitle("MINEFIELD");
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ setResizable(false);
+
+ getContentPane().setLayout(new GridLayout(2,1));
+
+ JPanel labelPanel = new JPanel();
+ labelMsg = new JLabel();
+ JPanel buttons = new JPanel();
+ JButton toMenu = new JButton("MENU");
+ JButton retry = new JButton("RETRY");
+ JButton quit = new JButton("EXIT");
+
+ EndFrameListener controller = new EndFrameListener(this, game, menu);
+ toMenu.addActionListener(controller);
+ retry.addActionListener(controller);
+ quit.addActionListener(controller);
+
+ labelPanel.add(labelMsg);
+
+ buttons.add(toMenu);
+ buttons.add(retry);
+ buttons.add(quit);
+
+ add(labelPanel);
+ add(buttons);
+
+ // centering window
+ Dimension size = new Dimension(240, 110);
+ int x = game.getLocation().x + game.getWidth()/2 - size.width/2;
+ int y = game.getLocation().y + game.getHeight()/2 - size.height/2;
+
+ setLocation(x, y);
+ setSize(size);
+ setVisible(true);
+ }
+
+ /**
+ * Setta il messaggio che si vuole mostrare nel pannello
+ *
+ * @param msg La stringa da mostrare
+ */
+ public void setEndMsg(String msg)
+ {
+ labelMsg.setText(""+msg+"");
+ }
+}
diff --git a/src/main/java/berack96/games/minefield/frame/GameFrame.java b/src/main/java/berack96/games/minefield/frame/GameFrame.java
new file mode 100644
index 0000000..b61f031
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/frame/GameFrame.java
@@ -0,0 +1,120 @@
+package berack96.games.minefield.frame;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Toolkit;
+
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import berack96.games.minefield.listener.CellInFieldListener;
+import berack96.games.minefield.object.Decisor;
+import berack96.games.minefield.object.Field;
+import berack96.games.minefield.object.FieldSafe;
+import berack96.games.minefield.object.view.FieldView;
+
+//TODO remove log lines
+/**
+ * Classe che estende i {@link JPanel} in modo da creare una finestra del gioco.
+ * Essa si serve di un {@link MenuFrame} per la finestra finale {@link EndFrame}
+ * e anche di un {@link Field} gia' creato, in modo da creare una rappresentazione
+ * grafica del gioco.
+ *
+ * @author Jack
+ *
+ */
+public class GameFrame extends JFrame {
+
+ private static final long serialVersionUID = 1L;
+
+ final private MenuFrame menu;
+
+ private Field field;
+ private JPanel gamePanel;
+ private JLabel label;
+
+ /**
+ * Costruttore: crea una finestra di gioco a partire dal parametro field.
+ *
+ * @param menu Il menu' che si vuole mostrare eventualmente alla fine del gioco
+ * @param field Il campo di gioco
+ */
+ public GameFrame(MenuFrame menu, Field field)
+ {
+ this.field = field;
+ this.menu = menu;
+
+ setTitle("MINEFIELD");
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ setResizable(false);
+
+ Container c = getContentPane();
+ c.setLayout(new FlowLayout());
+
+ label = new JLabel(String.valueOf(field.getNumMines()-field.getNumDagerousCell()));
+ label.setVisible(true);
+
+ gamePanel = new FieldView(field, new CellInFieldListener(this, field)).toJPanel();
+ gamePanel.setVisible(true);
+
+ add(label);
+ add(gamePanel);
+
+ // centering window
+ Dimension dim = gamePanel.getPreferredSize();
+ dim.height += 57; // doing this for the flowlayout & for the label
+ dim.width += 10; // same here
+
+ Dimension dimScreen = Toolkit.getDefaultToolkit().getScreenSize();
+ int x = (dimScreen.width - dim.width)/2;
+ int y = (dimScreen.height - dim.height)/2;
+ setLocation(x, y);
+
+ setSize(dim);
+ setVisible(true);
+ }
+
+ public void updateView()
+ {
+ label.setText(String.valueOf(field.getNumMines()-field.getNumDagerousCell()));
+ }
+
+ /**
+ * Crea una nuova finestra {@link EndFrame} settata con endMsg.
+ *
+ * @param endMsg Il messaggio che si vuole mostrare
+ */
+ public void launchEndFrame(String endMsg)
+ {
+ Decisor.uncoverAllMinesCells(field);
+ Decisor.uncoverAllDangerousCells(field);
+
+ EndFrame end = new EndFrame(this, menu);
+ end.setEndMsg(endMsg);
+ }
+
+ /**
+ * Resetta la griglia di gioco.
+ * In questo modo si puo' giocare alla stessa difficolta' senza passare dal menu'.
+ */
+ public void retryGame()
+ {
+ field = Decisor.getNewField(field.getClass() == FieldSafe.class, field.columns, field.lines, field.getNumMines());
+
+ gamePanel.setVisible(false);
+ remove(gamePanel); // remove all the component in the Frame
+
+ gamePanel = new FieldView(field, new CellInFieldListener(this, field)).toJPanel();
+
+ gamePanel.setVisible(true);
+ add(gamePanel);
+
+ updateView();
+ setVisible(true);
+
+ System.out.println("\n---New game started---"); // log line
+
+ }
+}
diff --git a/src/main/java/berack96/games/minefield/frame/MenuFrame.java b/src/main/java/berack96/games/minefield/frame/MenuFrame.java
new file mode 100644
index 0000000..2892c8c
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/frame/MenuFrame.java
@@ -0,0 +1,366 @@
+package berack96.games.minefield.frame;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.GridLayout;
+import java.awt.Toolkit;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+
+import berack96.games.minefield.Mode;
+import berack96.games.minefield.frame.strings.StringMode;
+import berack96.games.minefield.frame.strings.StringSafe;
+import berack96.games.minefield.listener.MenuFrameListener;
+import berack96.games.minefield.object.Field;
+
+/**
+ * Classe che estende i {@link JPanel} in modo da creare una finestra per il menu' del gioco.
+ * Essa e' formata in modo da avere 4 zone: in ognuna di esse l'utente deve fare delle scelte.
+ *
+ * @author Jack
+ *
+ */
+public class MenuFrame extends JFrame {
+
+ private static final long serialVersionUID = 1L;
+
+ private MenuFrameListener listener;
+
+ // TOP
+ final private JPanel panelTop;
+ final private JRadioButton easy;
+ final private JRadioButton medi;
+ final private JRadioButton hard;
+ final private JRadioButton cust;
+ final private JLabel modeMsg;
+ private Mode mode;
+
+ // MID TOP
+ final private JPanel panelMidTop;
+ final private JTextField textColumns;
+ final private JTextField textLines;
+ final private JTextField textMines;
+ final private JPanel customPanel;
+
+ // MID BOT
+ final private JPanel panelMidBot;
+ final private JRadioButton yes;
+ final private JRadioButton no;
+ final private JLabel safeMsg;
+ private boolean safe;
+
+ // BOT
+ final private JPanel panelBot;
+ final private JLabel error;
+
+ /**
+ * Costruttore: crea la finestra menu'
+ */
+ public MenuFrame()
+ {
+ // set initial value for variable of JRadioButton
+ this.mode = Mode.EASY;
+ this.safe = true;
+
+ // add the listener
+ listener = new MenuFrameListener(this);
+
+ // basic things for the frame
+ setTitle("MINEFIELD");
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ setResizable(false);
+ getContentPane().setLayout( new GridLayout(4, 1));
+ Dimension dim = new Dimension(350, 400);
+
+ // TOP frame
+ panelTop = new JPanel();
+ JPanel panelTopLabel = new JPanel();
+ JPanel panelTopButtons = new JPanel();
+ JLabel labelTop = new JLabel("Scegli una difficolta'");
+ easy = new JRadioButton("EASY", true);
+ medi = new JRadioButton("MEDIUM", false);
+ hard = new JRadioButton("HARD", false);
+ cust = new JRadioButton("CUSTOM", false);
+ ButtonGroup groupTop = new ButtonGroup();
+
+ easy.addActionListener(this.listener);
+ medi.addActionListener(this.listener);
+ hard.addActionListener(this.listener);
+ cust.addActionListener(this.listener);
+
+ groupTop.add(easy);
+ groupTop.add(medi);
+ groupTop.add(hard);
+ groupTop.add(cust);
+
+ panelTopButtons.add(easy);
+ panelTopButtons.add(medi);
+ panelTopButtons.add(hard);
+ panelTopButtons.add(cust);
+
+ panelTopLabel.add(labelTop);
+
+ panelTop.setLayout(new BoxLayout(this.panelTop, BoxLayout.Y_AXIS));
+ panelTop.setBorder(BorderFactory.createLineBorder(Color.black));
+ panelTop.add(panelTopLabel);
+ panelTop.add(panelTopButtons);
+
+ add(panelTop);
+
+ // MID TOP frame
+ panelMidTop = new JPanel();
+ modeMsg = new JLabel(StringMode.easy);
+ customPanel = new JPanel();
+ JLabel labelLength = new JLabel("Colonne:");
+ JLabel labelHeight = new JLabel("Righe:");
+ JLabel labelMines = new JLabel("Numero di mine:");
+ textColumns = new JTextField();
+ textLines = new JTextField();
+ textMines = new JTextField();
+
+ customPanel.setLayout(new GridLayout(3, 3));
+
+ customPanel.add(labelLength);
+ customPanel.add(textColumns);
+ customPanel.add(labelHeight);
+ customPanel.add(textLines);
+ customPanel.add(labelMines);
+ customPanel.add(textMines);
+
+ panelMidTop.setLayout(new FlowLayout());
+ panelMidTop.setBorder(BorderFactory.createLineBorder(Color.black));
+ panelMidTop.add(modeMsg);
+ // not adding custom panel 'cause there is the private function when needed.
+
+ add(panelMidTop);
+
+ // MID BOT frame
+ panelMidBot = new JPanel();
+ JPanel panelMidBotButtons = new JPanel();
+ JPanel panelMidBotMsg = new JPanel();
+ JLabel labelMidBot = new JLabel("Vuoi la partenza safe?");
+ yes = new JRadioButton("YES", true);
+ no = new JRadioButton("NO", false);
+ safeMsg = new JLabel(StringSafe.yes);
+ ButtonGroup groupMid = new ButtonGroup();
+
+ yes.addActionListener(listener);
+ no.addActionListener(listener);
+
+ groupMid.add(yes);
+ groupMid.add(no);
+
+ panelMidBotButtons.add(yes);
+ panelMidBotButtons.add(no);
+
+ panelMidBotMsg.add(safeMsg);
+
+ panelMidBot.setLayout(new BoxLayout(panelMidBot, BoxLayout.Y_AXIS));
+ panelMidBot.setBorder(BorderFactory.createLineBorder(Color.black));
+ panelMidBot.add(labelMidBot);
+ panelMidBot.add(panelMidBotButtons);
+ panelMidBot.add(panelMidBotMsg);
+
+ add(panelMidBot);
+
+ // BOT frame
+ panelBot = new JPanel();
+ JPanel panelBotLabel = new JPanel();
+ JPanel panelBotButton = new JPanel();
+ error = new JLabel();
+ JButton next = new JButton("NEXT");
+
+ next.addActionListener(listener);
+
+ panelBotLabel.add(error);
+
+ panelBotButton.add(next);
+
+ panelBot.setLayout(new BorderLayout());
+ panelBot.setBorder(BorderFactory.createLineBorder(Color.black));
+
+ panelBot.add(panelBotLabel, BorderLayout.CENTER);
+ panelBot.add(panelBotButton, BorderLayout.EAST);
+
+ add(panelBot);
+
+ // last things to do for the frame
+ setSize(dim);
+
+ // centering window
+ Dimension dimScreen = Toolkit.getDefaultToolkit().getScreenSize();
+ int x = (dimScreen.width - dim.width)/2;
+ int y = (dimScreen.height - dim.height)/2;
+ setLocation(x, y);
+
+ setVisible(true);
+ }
+
+ /**
+ * Funzione che serve al listener di questo frame {@link MenuFrameListener}
+ * per aggiornare le frasi dei label e le varie variabili del menu'
+ */
+ public void updateView()
+ {
+ if(easy.isSelected())
+ {
+ if(mode == Mode.CUSTOM)
+ removeCustomPanel();
+ mode = Mode.EASY;
+ modeMsg.setText(StringMode.easy);
+ }
+ else if(medi.isSelected())
+ {
+ if(mode == Mode.CUSTOM)
+ removeCustomPanel();
+ mode = Mode.MEDIUM;
+ modeMsg.setText(StringMode.medium);
+ }
+ else if(hard.isSelected())
+ {
+ if(mode == Mode.CUSTOM)
+ removeCustomPanel();
+ mode = Mode.HARD;
+ modeMsg.setText(StringMode.hard);
+ }
+ else
+ {
+ if(mode != Mode.CUSTOM)
+ addCustomPanel();
+ mode = Mode.CUSTOM;
+ modeMsg.setText(StringMode.custom);
+ }
+
+ if(yes.isSelected())
+ {
+ safe = true;
+ safeMsg.setText(StringSafe.yes);
+ }
+ else
+ {
+ safe = false;
+ safeMsg.setText(StringSafe.no);
+ }
+ }
+
+ /**
+ * Restituisce la stringa che si trova nel pannello delle colonne.
+ *
+ * @return La stringa inserita dall'utente
+ */
+ public String getStringColumnsTextPanel()
+ {
+ return textColumns.getText();
+ }
+
+ /**
+ * Restituisce la stringa che si trova nel pannello delle linee.
+ *
+ * @return La stringa inserita dall'utente
+ */
+ public String getStringLinesTextPanel()
+ {
+ return textLines.getText();
+ }
+
+ /**
+ * Restituisce la stringa che si trova nel pannello delle mine.
+ *
+ * @return La stringa inserita dall'utente
+ */
+ public String getStringMinesTextPanel()
+ {
+ return textMines.getText();
+ }
+
+ /**
+ * Restituisce il valore attuale del parametro safe.
+ *
+ * @return true/false
+ */
+ public boolean getSafeValue()
+ {
+ return safe;
+ }
+
+ /**
+ * Restituisce il valore attuale della modalita' di gioco.
+ *
+ * @return {@link Mode}
+ */
+ public Mode getModeValue()
+ {
+ return mode;
+ }
+
+ /**
+ * Se inserita una stinga verra' mostrata di colore rosso nel pannello.
+ *
+ * @param error La stringa da mettere in evidenza
+ */
+ public void setError(String error)
+ {
+ this.error.setText(""+error+"");
+ }
+
+ /**
+ * Se inserito un campo, verra' creata una finestra di gioco {@link GameFrame}
+ * e questa finestra menu' verra' nascosta tramite {@link #setVisible(boolean)}.
+ *
+ * @param field Il campo del gioco che si vuole giocare
+ */
+ public void startNewGameFrame(Field field)
+ {
+ setVisible(false);
+ GameFrame gameFrame = new GameFrame(this, field);
+ gameFrame.setVisible(true);
+ }
+
+ /**
+ * Resetta ogni variabile del pannello e ogni oggetto grafico.
+ */
+ public void resetVariablePanel()
+ {
+ easy.setSelected(true);
+ medi.setSelected(false);
+ hard.setSelected(false);
+ cust.setSelected(false);
+
+ yes.setSelected(true);
+ no.setSelected(false);
+
+ updateView();
+
+ setError("");
+
+ }
+
+ /**
+ * Mostra il pannello per la personalizzazione della partita.
+ */
+ private void addCustomPanel()
+ {
+ panelMidTop.add(customPanel);
+ customPanel.setVisible(true);
+ }
+
+ /**
+ * Nasconde il pannello per la personalizzazione della partita.
+ */
+ private void removeCustomPanel()
+ {
+ customPanel.setVisible(false);
+ panelMidTop.remove(customPanel);
+ //panelMidTop.validate();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/berack96/games/minefield/frame/strings/StringError.java b/src/main/java/berack96/games/minefield/frame/strings/StringError.java
new file mode 100644
index 0000000..65baaf2
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/frame/strings/StringError.java
@@ -0,0 +1,26 @@
+package berack96.games.minefield.frame.strings;
+
+public class StringError {
+
+ public static final String noValue = "Inserisci dei numeri nei campi indicati";
+
+ public static final String noPositiveValue = "Inserisci dei valori positivi
"
+ + "per la grandezza del campo";
+
+ public static final String minesLessThanZero = "Inserisci dei valori positivi
"
+ + "per le mine";
+
+ public static final String minesGreaterThanField = "Inserisci un valore minore per le mine
"
+ + "siccome non possono essere maggiori
"
+ + "della grandezza del campo";
+
+ public static final String minesGreaterThanFieldSafe = "Inserisci un valore minore per le mine
"
+ + "siccome non possono essere maggiori
"
+ + "della grandezza del campo-8
"
+ + "(perche' la prima cella non
"
+ + "puo avere mine intorno)";
+
+ public static final String valueTooHigh = "Inserisci un valore minore per le grandezze
"
+ + "siccome entrambe devono avere un valore
"
+ + "minore di 100";
+}
diff --git a/src/main/java/berack96/games/minefield/frame/strings/StringMode.java b/src/main/java/berack96/games/minefield/frame/strings/StringMode.java
new file mode 100644
index 0000000..73c108f
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/frame/strings/StringMode.java
@@ -0,0 +1,19 @@
+package berack96.games.minefield.frame.strings;
+
+public class StringMode {
+
+ public static final String easy = "MODALITA' FACILE:
"
+ + "Il campo non e' molto grande (8x8)
"
+ + "e le mine non sono molte (10)";
+
+ public static final String medium = "MODALITA' MEDIA:
"
+ + "Il campo e' di medie dimensioni (16x16)
"
+ + "e le mine sono numerose (40)";
+
+ public static final String hard = "MODALITA' DIFFICILE:
"
+ + "Il campo e' molto grande (16x32)
"
+ + "e le mine sono molto numerose (80)";
+
+ public static final String custom = "MODALITA' PERSONALIZZATA:";
+
+}
diff --git a/src/main/java/berack96/games/minefield/frame/strings/StringSafe.java b/src/main/java/berack96/games/minefield/frame/strings/StringSafe.java
new file mode 100644
index 0000000..85be077
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/frame/strings/StringSafe.java
@@ -0,0 +1,10 @@
+package berack96.games.minefield.frame.strings;
+
+public final class StringSafe {
+
+ public static final String yes = "La prima cella che viene scoperta
"
+ + "non avra' nessuna mina intorno.";
+
+ public static final String no = "La prima cella che viene scoperta
"
+ + "potra' avere mine intorno, o esserla.";
+}
diff --git a/src/main/java/berack96/games/minefield/listener/CellInFieldListener.java b/src/main/java/berack96/games/minefield/listener/CellInFieldListener.java
new file mode 100644
index 0000000..0d31f47
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/listener/CellInFieldListener.java
@@ -0,0 +1,112 @@
+package berack96.games.minefield.listener;
+
+import java.awt.Color;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+
+import javax.swing.JLabel;
+
+import berack96.games.minefield.frame.GameFrame;
+import berack96.games.minefield.object.Decisor;
+import berack96.games.minefield.object.Field;
+
+//TODO remove log lines
+/**
+ * Classe che serve a controllare un {@link Field} generato in un {@link GameFrame}.
+ * Questa classe modifica la cella in base all'azione dell'utente tramite i movimenti
+ * e i pulsanti generati dal mouse.
+ *
+ * @author Jack
+ *
+ */
+public class CellInFieldListener implements MouseListener {
+
+ private GameFrame frame;
+ private Field field;
+
+ public CellInFieldListener(GameFrame frame, Field field)
+ {
+ this.frame = frame;
+ this.field = field;
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent arg0)
+ {
+ if(Decisor.isALoose(field) == false && Decisor.isAWin(field) == false)
+ {
+ JLabel label = (JLabel) arg0.getSource();
+ String[] str = label.getName().split("-");
+
+ int x = Integer.parseInt(str[0]);
+ int y = Integer.parseInt(str[1]);
+
+ System.out.println("User clicked on cell ("+label.getName()+")"); // log line
+
+ if(field.cellIsUncovered(x, y) == false)
+ {
+ if(arg0.getButton() == MouseEvent.BUTTON1)
+ field.cellUncover(x, y);
+ else if(arg0.getButton() == MouseEvent.BUTTON3)
+ {
+ if(field.cellIsDangerous(x, y) == false)
+ field.cellSetDangerous(x, y);
+ else
+ field.cellSetNotDangerous(x, y);
+ }
+
+ if(Decisor.isALoose(field))
+ {
+ frame.launchEndFrame("HAI PERSO");
+ System.out.println("---Game Lost---"); // log line
+ }
+ else if(Decisor.isAWin(field))
+ {
+ frame.launchEndFrame("HAI VINTO");
+ System.out.println("---Game Won---"); // log line
+ }
+
+ frame.updateView();
+ }
+ }
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent arg0)
+ {
+ JLabel label = (JLabel) arg0.getSource();
+ String[] str = label.getName().split("-");
+
+ int x = Integer.parseInt(str[0]);
+ int y = Integer.parseInt(str[1]);
+
+ if(field.cellIsUncovered(x, y) == false && field.cellIsDangerous(x, y) == false)
+ label.setBackground(Color.GRAY);
+ }
+
+ @Override
+ public void mouseExited(MouseEvent arg0)
+ {
+ JLabel label = (JLabel) arg0.getSource();
+ String[] str = label.getName().split("-");
+
+ int x = Integer.parseInt(str[0]);
+ int y = Integer.parseInt(str[1]);
+
+ if(field.cellIsUncovered(x, y) == false && field.cellIsDangerous(x, y) == false)
+ label.setBackground(Color.LIGHT_GRAY);
+ }
+
+ @Override
+ public void mousePressed(MouseEvent arg0)
+ {
+ // do nothing
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent arg0)
+ {
+ // do nothing
+ }
+
+}
diff --git a/src/main/java/berack96/games/minefield/listener/EndFrameListener.java b/src/main/java/berack96/games/minefield/listener/EndFrameListener.java
new file mode 100644
index 0000000..e527a13
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/listener/EndFrameListener.java
@@ -0,0 +1,60 @@
+package berack96.games.minefield.listener;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+
+import berack96.games.minefield.frame.EndFrame;
+import berack96.games.minefield.frame.GameFrame;
+import berack96.games.minefield.frame.MenuFrame;
+
+/**
+ * Classe che contolla la finestra {@link EndFrame} e in base a che bottone
+ * viene premuto viene effettuata una scelta.
+ *
+ * @author Jack
+ *
+ */
+public class EndFrameListener implements ActionListener {
+
+ private EndFrame end;
+ private GameFrame game;
+ private MenuFrame menu;
+
+ public EndFrameListener(EndFrame end, GameFrame game, MenuFrame menu)
+ {
+ this.end = end;
+ this.game = game;
+ this.menu = menu;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ JButton button = (JButton) e.getSource();
+ String s = button.getText();
+
+ if(s.matches("EXIT"))
+ {
+ System.exit(0);
+ }
+ else if(s.matches("RETRY"))
+ {
+ game.retryGame();
+ }
+ else if(s.matches("MENU"))
+ {
+ game.setVisible(false);
+
+ menu.resetVariablePanel();
+ menu.setVisible(true);
+
+ game.dispose();
+ }
+
+ end.setVisible(false);
+ end.dispose();
+ }
+
+}
diff --git a/src/main/java/berack96/games/minefield/listener/MenuFrameListener.java b/src/main/java/berack96/games/minefield/listener/MenuFrameListener.java
new file mode 100644
index 0000000..40bb9c9
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/listener/MenuFrameListener.java
@@ -0,0 +1,89 @@
+package berack96.games.minefield.listener;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+
+import berack96.games.minefield.Mode;
+import berack96.games.minefield.frame.MenuFrame;
+import berack96.games.minefield.frame.strings.StringError;
+import berack96.games.minefield.object.Decisor;
+import berack96.games.minefield.object.Field;
+import berack96.games.minefield.runexception.TooHighValueException;
+
+/**
+ * Classe che contolla la finestra {@link MenuFrame} e in base a che bottone
+ * viene premuto o a che pulsante Radio viene scelto, viene effettuata una scelta.
+ *
+ * @author Jack
+ *
+ */
+public class MenuFrameListener implements ActionListener {
+
+ private MenuFrame frame;
+
+ public MenuFrameListener(MenuFrame frame)
+ {
+ this.frame = frame;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent arg0)
+ {
+ frame.updateView();
+ if(frame.getModeValue() != Mode.CUSTOM)
+ frame.setError("");
+
+ int columns = 0,
+ lines = 0,
+ mines = 0;
+
+ try{
+ JButton button = (JButton) arg0.getSource();
+
+ if(button.getText().matches("NEXT"))
+ {
+ Field field;
+
+ if(frame.getModeValue() == Mode.CUSTOM)
+ {
+ columns = Integer.parseInt(this.frame.getStringColumnsTextPanel());
+ lines = Integer.parseInt(this.frame.getStringLinesTextPanel());
+ mines = Integer.parseInt(this.frame.getStringMinesTextPanel());
+
+ field = Decisor.getNewField(frame.getSafeValue(), columns, lines, mines);
+ }
+ else
+ field = Decisor.getNewField(frame.getSafeValue(), frame.getModeValue());
+
+ frame.startNewGameFrame(field);
+ }
+
+ }
+ catch(ClassCastException e) // not a JButton generated the action (in this case a JRadioButton have)
+ {
+ // DO NOTHING
+ }
+ catch(NumberFormatException e) // not a number is inserted in the text
+ {
+ frame.setError(StringError.noValue);
+ }
+ catch(IllegalArgumentException e) // the numbers inserted is not valid
+ {
+ if(columns<=0 || lines<=0)
+ frame.setError(StringError.noPositiveValue);
+ else if(mines<=0)
+ frame.setError(StringError.minesLessThanZero);
+ else if(frame.getSafeValue() && mines>=lines*columns-8)
+ frame.setError(StringError.minesGreaterThanFieldSafe);
+ else if(mines>= lines*columns)
+ frame.setError(StringError.minesGreaterThanField);
+ }
+ catch(TooHighValueException e)
+ {
+ frame.setError(StringError.valueTooHigh);
+ }
+ }
+
+}
diff --git a/src/main/java/berack96/games/minefield/object/Cell.java b/src/main/java/berack96/games/minefield/object/Cell.java
new file mode 100644
index 0000000..c9d8ee5
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/object/Cell.java
@@ -0,0 +1,139 @@
+package berack96.games.minefield.object;
+
+import java.util.Observable;
+
+/**
+ * Classe che serve a creare una cella per il campo.
+ * Tramite le funzioni principali della cella si
+ * possono sapere 4 cose:
+ * - il numero di mine vicine {@link #nearMine}
+ * - se la cella e' una mina {@link #isMine()}
+ * - lo stato della cella {@link #getStatus()}
+ *
+ * @author Jack
+ *
+ */
+public class Cell extends Observable {
+
+ /**
+ * Indica le mine che si trovano vicino a questa cella
+ */
+ public int nearMine;
+
+ private boolean isMine;
+ private boolean uncovered;
+ private CellStatus status;
+
+ /**
+ * Costruttore: serve creare una nuova cella coperta con 0 mine intorno.
+ */
+ public Cell() {
+ nearMine = 0;
+ isMine = false;
+ uncovered = false;
+ status = CellStatus.COVERED;
+ }
+
+ /**
+ * Serve a mettere la cella nello stato di "scoperta"
+ * Una volta fatto la cella non potra' esser piu cambiata.
+ * Essa potra' avere i seguenti valori:
+ * - EXPLODED
+ * - UNCOVERED
+ * - GOTRIGHT
+ * - GOTWRONG
+ *
+ * Per altro vedere {@link CellStatus}
+ */
+ public void uncover() {
+ if(!this.uncovered) {
+ if(isMine) {
+ if(status == CellStatus.DANGEROUS)
+ status = CellStatus.GOTRIGHT;
+ else
+ status = CellStatus.EXPLODED;
+ }
+ else {
+ if(status == CellStatus.DANGEROUS)
+ status = CellStatus.GOTWRONG;
+ else
+ status = CellStatus.UNCOVERED;
+ }
+ uncovered = true;
+
+ setChanged();
+ notifyObservers();
+ clearChanged();
+ }
+ }
+
+ /**
+ * Serve ad avere lo stato della cella.
+ * Vedi {@link CellStatus} per i possibili valori.
+ *
+ * @return CellStatus
+ */
+ public CellStatus getStatus() {
+ return status;
+ }
+
+ /**
+ * Setta la cella come una mina solamente se
+ * quest'ultima non e' stata scoperta.
+ * Questa azione e' irreversibile.
+ */
+ public void setMine() {
+ if(!uncovered)
+ isMine = true;
+ }
+
+ /**
+ * Setta la cella nello stato di {@link CellStatus}.DANGEROUS
+ * Se La funzione {@link #uncover()} e' gia stata chiamata
+ * la cella non verra' settata come pericolosa.
+ */
+ public void setDangerous() {
+ if(status == CellStatus.COVERED) {
+ status = CellStatus.DANGEROUS;
+
+ setChanged();
+ notifyObservers();
+ clearChanged();
+ }
+ }
+
+ /**
+ * Toglie la cella dallo stato {@link CellStatus}.DANGEROUS
+ * e la mette come COVERED.
+ * Se la cella non e' in stato DANGEROUS, la funzione
+ * non fa nulla.
+ */
+ public void setNotDangerous() {
+ if(status == CellStatus.DANGEROUS) {
+ status = CellStatus.COVERED;
+
+ setChanged();
+ notifyObservers();
+ clearChanged();
+ }
+ }
+
+ /**
+ * Dice se la cella e' una mina o meno.
+ *
+ * @return true se lo e'
+ */
+ public boolean isMine() {
+ return isMine;
+ }
+
+ /**
+ * Dice se la cella e' gia stata scoperta.
+ * AKA se la funzione {@link #uncover()} e' gia stata chiamata.
+ *
+ * @return true se non e' piu {@link CellStatus#COVERED}
+ */
+ public boolean isUncovered() {
+ return uncovered;
+ }
+}
diff --git a/src/main/java/berack96/games/minefield/object/CellStatus.java b/src/main/java/berack96/games/minefield/object/CellStatus.java
new file mode 100644
index 0000000..603948e
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/object/CellStatus.java
@@ -0,0 +1,41 @@
+package berack96.games.minefield.object;
+
+/**
+ * Serve a comunicare lo stato della cella.
+ * Essa puo' assumere questi stati in base al
+ * fatto di essere o meno stata scoperrta.
+ *
+ * @author Jack
+ *
+ */
+public enum CellStatus {
+ /**
+ * Se la cella non e' ancora stata scoperta.
+ */
+ COVERED,
+
+ /**
+ * Se la cella e' marchiata pericolosa.
+ */
+ DANGEROUS,
+
+ /**
+ * Dopo aver scoperto la cella: se essa e' una mina.
+ */
+ EXPLODED,
+
+ /**
+ * Dopo aver scoperto la cella, se essa non e' una mina
+ */
+ UNCOVERED,
+
+ /**
+ * Dopo aver scoperto la cella: se essa, marchiata precedentemente come pericolosa, e' effettivamente una mina.
+ */
+ GOTRIGHT,
+
+ /**
+ * Dopo aver scoperto la cella: se essa, marchiata precedentemente cvome pericolosa, non e' una mina.
+ */
+ GOTWRONG
+}
diff --git a/src/main/java/berack96/games/minefield/object/Decisor.java b/src/main/java/berack96/games/minefield/object/Decisor.java
new file mode 100644
index 0000000..0628f20
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/object/Decisor.java
@@ -0,0 +1,160 @@
+package berack96.games.minefield.object;
+
+import berack96.games.minefield.Mode;
+
+/**
+ * Classe utile ad automatizzare alcuni meccanismi di gioco, come per esempio
+ * {@link #getNewField(boolean, Mode)} che crea un nuovo campo data la modalita'.
+ *
+ * @author Jack
+ *
+ */
+public class Decisor {
+
+ /**
+ * Crea un nuovo campo di gioco data la modalita' {@link Mode}.
+ *
+ * @param safe Se si vuole che il campo sia {@link FieldSafe}
+ * @param mode La modalita' di gioco
+ * @return Un nuovo campo
+ */
+ public static Field getNewField(boolean safe, Mode mode) {
+ if(mode == Mode.EASY)
+ return getNewFieldEasy(safe);
+ else if(mode == Mode.MEDIUM)
+ return getNewFieldMedium(safe);
+ else if(mode == Mode.HARD)
+ return getNewFieldHard(safe);
+ else
+ throw new java.lang.IllegalArgumentException("mode must be Easy, Medium or Hard");
+ }
+
+ /**
+ * Serve a creare un nuovo campo dati i parametri richiesti.
+ *
+ * @param safe Se si vuole che il campo sia {@link FieldSafe}
+ * @param columns Una grandezza del campo (larghezza)
+ * @param lines Una grandezza del campo (altezza)
+ * @param mines Quante mine ci sono nel campo
+ * @return Un nuovo campo
+ */
+ public static Field getNewField(boolean safe, int columns, int lines, int mines) {
+ if(safe)
+ return new FieldSafe(columns, lines, mines);
+ return new FieldNoSafe(columns, lines, mines);
+ }
+
+ /**
+ * Serve a creare un campo in modalita' facile
+ *
+ * @param safe Se si vuole che il campo sia {@link FieldSafe}
+ * @return Un nuovo campo
+ */
+ public static Field getNewFieldEasy(boolean safe) {
+ return getNewField(safe, 8, 8, 10);
+ }
+
+ /**
+ * Serve a creare un campo in modalita' media
+ *
+ * @param safe Se si vuole che il campo sia {@link FieldSafe}
+ * @return Un nuovo campo
+ */
+ public static Field getNewFieldMedium(boolean safe) {
+ return getNewField(safe, 16, 16, 40);
+ }
+
+ /**
+ * Serve a creare un campo in modalita' difficile
+ *
+ * @param safe Se si vuole che il campo sia {@link FieldSafe}
+ * @return Un nuovo campo
+ */
+ public static Field getNewFieldHard(boolean safe) {
+ return getNewField(safe, 32, 16, 80);
+ }
+
+ /**
+ * Indica se nel campo inserito si e' riusciti a vincere.
+ *
+ * @param field Il campo da controllare
+ * @return true se si ha vinto
+ */
+ public static boolean isAWin(Field field) {
+ // Basic
+ if(!field.isGenerated)
+ return false;
+
+ // First Condition
+ if(field.getNumMines() == field.getNumCoveredCell())
+ return true;
+
+ // Second Condition
+ int minesGot = 0;
+ for(Cell cell : field)
+ if(cell.isMine() && cell.getStatus() == CellStatus.DANGEROUS)
+ minesGot++;
+
+ if(minesGot == field.getNumMines())
+ return true;
+
+ // Else
+ return false;
+ }
+
+ /**
+ * Indica se nel campo inserito si ha perso.
+ *
+ * @param field Il campo da controllare
+ * @return true se si ha perso
+ */
+ public static boolean isALoose(Field field) {
+ for(Cell cell : field)
+ if(cell.isUncovered() && cell.isMine())
+ return true;
+ return false;
+ }
+
+ /**
+ * Scopre tutte le celle del campo.
+ *
+ * @param field Il campo da scoprire
+ */
+ public static void uncoverAllCells(Field field) {
+ for(Cell cell : field)
+ cell.uncover();
+ }
+
+ /**
+ * Scopre tutte celle pericolose del campo.
+ *
+ * @param field Il campo da scoprire
+ */
+ public static void uncoverAllDangerousCells(Field field) {
+ for(Cell cell : field)
+ if(cell.getStatus() == CellStatus.DANGEROUS)
+ cell.uncover();
+ }
+
+ /**
+ * Scopre tutte le mine del campo.
+ *
+ * @param field Il campo da scoprire
+ */
+ public static void uncoverAllMinesCells(Field field) {
+ for(Cell cell : field)
+ if(cell.isMine())
+ cell.uncover();
+ }
+
+ /**
+ * Scopre tutte le celle che non sono mine del campo.
+ *
+ * @param field Il campo da scoprire
+ */
+ public static void uncoverAllNotMinesCells(Field field) {
+ for(Cell cell : field)
+ if(!cell.isMine())
+ cell.uncover();
+ }
+}
diff --git a/src/main/java/berack96/games/minefield/object/Field.java b/src/main/java/berack96/games/minefield/object/Field.java
new file mode 100644
index 0000000..a2d2822
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/object/Field.java
@@ -0,0 +1,415 @@
+package berack96.games.minefield.object;
+
+import java.util.Iterator;
+
+import berack96.games.minefield.runexception.OutOfBoundsException;
+import berack96.games.minefield.runexception.TooHighValueException;
+
+/**
+ * Classe astratta in cui manca la funzione che genera il campo.
+ * Essa contiene un tot numero di celle della classe {@link Cell}
+ *
+ * @author Jack
+ *
+ */
+public abstract class Field implements Iterable {
+
+ /**
+ * Valore massimo del capo
+ */
+ public static final int MAX_VAL = 100;
+
+ /**
+ * Una delle grandezze del campo
+ */
+ public final int lines;
+
+ /**
+ * Una delle grandezze del campo
+ */
+ public final int columns;
+
+ /**
+ * Valore che inizialmente e' settato a false e che
+ * se messo a true, non fara' piu richiamare la funzione
+ * {@link #generateField(int, int)} quando la funzione
+ * {@link #cellUncover(int, int)} e' usata.
+ */
+ protected boolean isGenerated;
+
+ private int numMines;
+ private Cell [][]matrix;
+
+ private int numCoveredCell;
+ private int numDangerousCell;
+
+ /**
+ * Costruttore che crea un campo senza mine o altro.
+ * Genera solamente la base per futuri cambiamenti in esso.
+ *
+ * @param columns Una delle grandezze del campo (larghezza)
+ * @param lines Una delle grandezze del campo (altezza)
+ * @throws IllegalArgumentException nel caso in cui si inseriscano parametri sbagliati
+ * @throws TooHighValueException nel caso in cui i parametri siano maggiori di 100
+ */
+ public Field(int columns, int lines) {
+ if(lines<0 || columns<0)
+ throw new java.lang.IllegalArgumentException("columns and lines must be greater than 0.");
+ if(lines>MAX_VAL || columns>MAX_VAL)
+ throw new TooHighValueException("columns and lines must be less than 100.");
+
+ this.isGenerated = false;
+
+ this.lines = lines;
+ this.columns = columns;
+
+ numMines = 0;
+ numDangerousCell = 0;
+ numCoveredCell = lines*columns;
+
+ matrix = new Cell[lines][columns];
+
+ for(int i=0; i
+ * Se la cella e' in uno stato di {@link CellStatus}.DANGEROUS,
+ * essa non verra' scoperta e la funzione terminara'.
+ * Se il campo non e' ancora stato creato, viene automaticamente creato.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ public void cellUncover(int x, int y) {
+ checkCoordinates(x, y);
+
+ if(!isGenerated)
+ generateField(x, y);
+
+ if(!cellIsUncovered(x, y) && matrix[x][y].getStatus() != CellStatus.DANGEROUS) {
+ matrix[x][y].uncover();
+ numCoveredCell--;
+ if(matrix[x][y].nearMine == 0 && !matrix[x][y].isMine())
+ cellUncoverNeighbors(x, y);
+ }
+ }
+
+ /**
+ * Scopre la cella dalle coordinate selezionate.
+ * Se la cella e' in uno stato di {@link CellStatus}.DANGEROUS,
+ * essa VERRA' comunque scoperta.
+ * Se il campo non e' ancora stato creato, viene automaticamente creato.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ public void cellUncoverIngnoringDangerousState(int x, int y) {
+ checkCoordinates(x, y);
+
+ if(!isGenerated)
+ generateField(x, y);
+
+ if(!cellIsUncovered(x, y)) {
+ matrix[x][y].uncover();
+ numCoveredCell--;
+ if(matrix[x][y].nearMine == 0 && matrix[x][y].isMine() == false)
+ cellUncoverNeighbors(x, y);
+ }
+ }
+
+ /**
+ * Setta una determinata cella come {@link CellStatus}.DANGEROUS
+ * Se la cella e' gia stata scoperta non succedera' nulla.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ public void cellSetDangerous(int x, int y) {
+ checkCoordinates(x, y);
+
+ if(numMines != numDangerousCell && matrix[x][y].getStatus() == CellStatus.COVERED) {
+ matrix[x][y].setDangerous();
+ numDangerousCell++;
+ }
+ }
+
+ /**
+ * Toglie alla cella lo status di {@link CellStatus}.DANGEROUS
+ * Se la cella non e' in stato di DANGEROUS, la funzione non fa nulla.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ public void cellSetNotDangerous(int x, int y) {
+ checkCoordinates(x, y);
+
+ if(matrix[x][y].getStatus() == CellStatus.DANGEROUS) {
+ matrix[x][y].setNotDangerous();
+ numDangerousCell--;
+ }
+ }
+
+ /**
+ * Dice se la cella e' stata scoperta o meno.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @return true se e' stata scoperta
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ public boolean cellIsUncovered(int x, int y) {
+ checkCoordinates(x, y);
+ return matrix[x][y].isUncovered();
+ }
+
+ /**
+ * Indica se la cella e' nello stato pericoloso.
+ * Per info: {@link CellStatus}.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @return true se lo e'
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ public boolean cellIsDangerous(int x, int y) {
+ return matrix[x][y].getStatus() == CellStatus.DANGEROUS;
+ }
+
+ /**
+ * Indica se la cella e' esplosa.
+ * Per info: {@link CellStatus}.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @return true se lo e'
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ public boolean cellIsExploded(int x, int y) {
+ return matrix[x][y].getStatus() == CellStatus.EXPLODED;
+ }
+
+ /**
+ * Indica se la cella e' stata marchiata come pericolosa,
+ * e alla fine del gioco e' risultata essere una mina.
+ * Per info: {@link CellStatus}.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @return true se lo e'
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ public boolean cellIsGotRight(int x, int y) {
+ return matrix[x][y].getStatus() == CellStatus.GOTRIGHT;
+ }
+
+ /**
+ * Indica se la cella e' una mina o meno.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @return true se e' una mina
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ public boolean cellIsMine(int x, int y) {
+ checkCoordinates(x, y);
+ return matrix[x][y].isMine();
+ }
+
+ /**
+ * Serve ad avere lo stato della cella.
+ * Vedi {@link CellStatus} per i possibili valori.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @return lo stato della cella
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ public CellStatus cellGetStatus(int x, int y) {
+ checkCoordinates(x, y);
+ return matrix[x][y].getStatus();
+ }
+
+ /**
+ * Indica il numero di mine vicine alla cella richiesta.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @return il numero di mine vicine alla cella
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ public int cellGetNumNearMines(int x, int y) {
+ checkCoordinates(x, y);
+ return matrix[x][y].nearMine;
+ }
+
+ /**
+ * @return il numero delle mine che il campo contiene
+ */
+ public int getNumMines() {
+ return numMines;
+ }
+
+ /**
+ * @return il numero di celle ancora da scoprire
+ */
+ public int getNumCoveredCell() {
+ return numCoveredCell;
+ }
+
+ /**
+ * @return il numero delle celle gia scoperto
+ */
+ public int getNumUncoveredCell() {
+ return ( lines * columns ) - numCoveredCell;
+ }
+
+ /**
+ * @return il numero delle celle segnate pericolose
+ */
+ public int getNumDagerousCell() {
+ return numDangerousCell;
+ }
+
+ /**
+ * Restituisce la cella desiderata. Restituendo la cella
+ * questa funzione puo' esser considerata un modo per
+ * rendere le cose piu' facili.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @return la cella desiderata
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ public Cell getCell(int x, int y) {
+ checkCoordinates(x, y);
+ return matrix[x][y];
+ }
+
+ /**
+ * Funzione che inserisce nel campo gia creato mine e numeri.
+ * La funzione DEVE aggiornare il campo {@link #isGenerated},
+ * in modo che sia generato una sola volta il campo.
+ * Per creare il campo si possono usare le funzioni
+ * {@link #insertMine(int, int)} e {@link #updateNumNearMines(int, int)} gia fornite.
+ * Nel caso non si usasse questa funzione nel costruttore,
+ * essa viene richiamata nella funzione {@link #cellUncover(int, int)}.
+ * Il campo isGenerated evita che venga ripetuta l'operazione piu' volte,
+ * quindi e' necessario che venga aggiornata in questa funzione.
+ * Le coordinate sono fornite per passare, per esempio,
+ * il punto della cella da cui l'utente ha iniziato a giocare.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ */
+ protected abstract void generateField(int x, int y);
+
+ /**
+ * Marchia la cella come mina se non lo e' gia
+ * Aaggiorna inoltre quante mine ci sono nel campo
+ * reperibili tramite {@link #getNumMines()}.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @return true se la mina e' stata piazzata, false se la mina era gia presente
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ protected boolean insertMine(int x, int y) {
+ checkCoordinates(x, y);
+
+ if(!matrix[x][y].isMine()) {
+ matrix[x][y].setMine();
+ numMines++;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Aggiorna il numero di mine che si trovano vicino alla cella richiesta.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @return Il numero di mine che la cella ha intorno
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ protected int updateNumNearMines(int x, int y) {
+ checkCoordinates(x, y);
+
+ for(int i=x-1; i<=x+1; i++)
+ for(int j=y-1; j<=y+1; j++) try {
+ checkCoordinates(i, j);
+
+ if(matrix[i][j].isMine() && (i!=x || j!=y))
+ matrix[x][y].nearMine++;
+ } catch(OutOfBoundsException e) { /* do nothing and go on */ }
+
+ return matrix[x][y].nearMine;
+ }
+
+ /**
+ * Funzione che serve a controllare se le coordinate sono consone al campo.
+ * Nel caso non lo siano, il programma lancera' una eccezione.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ * @throws OutOfBoundsException nel caso in cui si inseriscano coordinate sbagliate
+ */
+ private void checkCoordinates(int x, int y) {
+ if(x<0 || y<0 || x>=lines || y>=columns)
+ throw new OutOfBoundsException("coordinates must be inside the field x(0-"+lines+"), y(0-"+columns+").\tX = "+x+" Y = "+y);
+ }
+
+ /**
+ * Scopre i vicini della cella che si passa.
+ *
+ * @param x Una coordinata della cella
+ * @param y Una coordinata della cella
+ */
+ private void cellUncoverNeighbors(int x, int y) {
+ for(int i=x-1; i<=x+1; i++)
+ for(int j=y-1; j<=y+1; j++)
+ if(!(i==x && j==y)) try {
+ this.cellUncover(i, j);
+ } catch(OutOfBoundsException e) { /* do nothing and go on */ }
+ }
+
+ @Override
+ public Iterator iterator() {
+ return new FieldIter(this);
+ }
+
+
+ private class FieldIter implements Iterator {
+
+ private final Field field;
+ private int x = 0;
+ private int y = 0;
+
+ private FieldIter(Field field) {
+ this.field = field;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return y + 1 < field.columns;
+ }
+
+ @Override
+ public Cell next() {
+ if(x + 1 == field.lines) {
+ x = 0;
+ y++;
+ }
+ else
+ x++;
+ return field.getCell(x, y);
+ }
+ }
+}
diff --git a/src/main/java/berack96/games/minefield/object/FieldNoSafe.java b/src/main/java/berack96/games/minefield/object/FieldNoSafe.java
new file mode 100644
index 0000000..ac53077
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/object/FieldNoSafe.java
@@ -0,0 +1,61 @@
+package berack96.games.minefield.object;
+
+import berack96.games.minefield.runexception.TooHighValueException;
+
+/**
+ * Classe che crea un campo di celle {@link Cell}.
+ * Quando l'utente scopre la prima cella, essa puo essere anche una mina.
+ *
+ * @author Jack
+ *
+ */
+public class FieldNoSafe extends Field{
+
+ private final int numMines;
+
+ /**
+ * Costruisce il campo, contenente le mine e quante mine ogni cella ha intorno.
+ *
+ * @param columns Una delle grandezze del campo (lunghezza)
+ * @param lines Una delle grandezze del campo (altezza)
+ * @param numMines Quante mine deve contenere il campo
+ * @throws IllegalArgumentException nel caso in cui si inseriscano parametri sbagliati
+ * @throws TooHighValueException nel caso in cui i parametri siano maggiori di 100
+ */
+ public FieldNoSafe(int columns, int lines, int numMines)
+ {
+ super(columns, lines);
+
+ if(numMines<=0)
+ throw new java.lang.IllegalArgumentException("the mines must be greater than 0.");
+ if(numMines>=columns*lines)
+ throw new java.lang.IllegalArgumentException("the mines must be less than the size of the whole field.");
+
+ this.numMines = numMines;
+ generateField(0, 0); // use of this function here because don't need safe start
+ }
+
+ /**
+ * Genera il campo senza considerare le due coordinate in entrata
+ */
+ @Override
+ protected void generateField(int x, int y)
+ {
+
+ // i will not use the argument, don't need it
+
+ super.isGenerated = true;
+
+ while(getNumMines()
+ * Quando l'utente scopre la prima cella, essa NON puo essere una mina,
+ * e non puo avere mine intorno.
+ *
+ * @author Jack
+ *
+ */
+public class FieldSafe extends Field{
+
+ private final int numMines;
+
+ /**
+ * Crea il campo vouto. Esso si riempira' non appena verra'
+ * scoperta la prima cella con al funzione {@link #cellUncover(int, int)}
+ * @param columns Una delle grandezze del campo.
+ *
+ * @param lines Una delle grandezze del campo
+ * @param numMines Quante mine deve contenere il campo
+ * @throws IllegalArgumentException nel caso in cui si inseriscano parametri sbagliati
+ * @throws TooHighValueException nel caso in cui i parametri siano maggiori di 100
+ */
+ public FieldSafe(int columns, int lines, int numMines) {
+ super(columns, lines);
+
+ if(numMines<=0)
+ throw new java.lang.IllegalArgumentException("the mines must be greater than 0.");
+ if(numMines>=columns*lines-8)
+ throw new java.lang.IllegalArgumentException("the mines must be less than the size of the whole field -8 (for the safe start).");
+
+ this.numMines = numMines;
+ }
+
+ /**
+ * Genera il campo non creando mine vicino alla cella indicata dalle due coordinate
+ */
+ @Override
+ protected void generateField(int x, int y) {
+
+ isGenerated = true;
+
+ while(this.getNumMines()=x-1 && randX<=x+1 && randY>=y-1 && randY<=y+1) == false)
+ this.insertMine(randX, randY);
+ }
+
+ for(int i=0; i
+ * [ ] - {@link CellStatus#UNCOVERED} 0 mine vicine
+ * [n] - {@link CellStatus#UNCOVERED} con "n" mine vicine
+ * [D] - {@link CellStatus#DANGEROUS}
+ * [*] - {@link CellStatus#EXPLODED}
+ * [V] - {@link CellStatus#GOTRIGHT}
+ * [X] - {@link CellStatus#GOTWRONG}
+ * [#] - {@link CellStatus#COVERED}
+ *
+ * @return String
+ */
+ public String toString()
+ {
+ return string;
+ }
+
+ /**
+ * Ritorna la rappresentazione della cella sottoforma di JLabel:
+ * {@link CellStatus#UNCOVERED} bianco con eventuale numero
+ * {@link CellStatus#DANGEROUS} con icona di una bandiera
+ * {@link CellStatus#EXPLODED} con una icona di una mina
+ * {@link CellStatus#GOTRIGHT} con una icona di una bandierina cerchiata di verde
+ * {@link CellStatus#GOTWRONG} - con una icona di una bandierina crociata di rosso
+ * {@link CellStatus#COVERED} - grigio chiaro
+ *
+ * @return JLabel
+ */
+ public JLabel toJLabel()
+ {
+ return label;
+ }
+
+ @Override
+ public void update(Observable arg0, Object arg1)
+ {
+ CellStatus status = cell.getStatus();
+
+ if(status == CellStatus.UNCOVERED)
+ {
+ label.setBackground(Color.WHITE);
+ label.setIcon(null);
+
+ if(cell.nearMine == 0)
+ string = "[ ]";
+ else
+ {
+ string = "["+cell.nearMine+"]";
+ switch(cell.nearMine)
+ {
+ case 1:
+ label.setIcon(CellIcons.one);
+ break;
+ case 2:
+ label.setIcon(CellIcons.two);
+ break;
+ case 3:
+ label.setIcon(CellIcons.three);
+ break;
+ case 4:
+ label.setIcon(CellIcons.four);
+ break;
+ case 5:
+ label.setIcon(CellIcons.five);
+ break;
+ case 6:
+ label.setIcon(CellIcons.six);
+ break;
+ case 7:
+ label.setIcon(CellIcons.seven);
+ break;
+ case 8:
+ label.setIcon(CellIcons.eight);
+ break;
+ }
+ }
+ }
+ else if(status == CellStatus.DANGEROUS)
+ {
+ string = "[D]";
+ label.setBackground(Color.LIGHT_GRAY);
+ label.setIcon(CellIcons.flag);
+ }
+ else if(status == CellStatus.EXPLODED)
+ {
+ string = "[*]";
+ label.setBackground(Color.LIGHT_GRAY);
+ label.setIcon(CellIcons.mine);
+ }
+ else if(status == CellStatus.GOTRIGHT)
+ {
+ string = "[V]";
+ label.setBackground(Color.LIGHT_GRAY);
+ label.setIcon(CellIcons.flagRight);
+ }
+ else if(status == CellStatus.GOTWRONG)
+ {
+ string = "[X]";
+ label.setBackground(Color.LIGHT_GRAY);
+ label.setIcon(CellIcons.flagWrong);
+ }
+ else
+ {
+ string = "[#]";
+ label.setBackground(Color.LIGHT_GRAY);
+ label.setIcon(null);
+ }
+ }
+
+ /**
+ * Metodo statico che serve, passata una cella, a trasformarla in stringa
+ * secondo {@link #toString()}.
+ *
+ * @param cell La cella da vedere
+ * @return String
+ */
+ public static String toString(Cell cell)
+ {
+ CellStatus status = cell.getStatus();
+
+ if(status == CellStatus.UNCOVERED)
+ {
+ if(cell.nearMine == 0)
+ return "[ ]";
+ else
+ return "["+cell.nearMine+"]";
+ }
+ else if(status == CellStatus.DANGEROUS)
+ return "[D]";
+ else if(status == CellStatus.EXPLODED)
+ return "[*]";
+ else if(status == CellStatus.GOTRIGHT)
+ return "[V]";
+ else
+ return "[#]";
+ }
+
+ /**
+ * Metodo statico che serve, passata una cella, a trasformarla in jpanel
+ * secondo {@link #toJLabel()}.
+ *
+ * @param cell La cella da vedere
+ * @return JLabel
+ */
+ public static JLabel toJLabel(Cell cell)
+ {
+ CellStatus status = cell.getStatus();
+ JLabel label = new JLabel();
+
+ label.setOpaque(true);
+ label.setBorder(BorderFactory.createLineBorder(Color.BLACK));
+ label.setPreferredSize(new Dimension(25, 25));
+ label.setSize(label.getPreferredSize());
+ label.setVisible(true);
+
+ if(status == CellStatus.UNCOVERED)
+ {
+ label.setBackground(Color.WHITE);
+ if(cell.nearMine != 0)
+ label.setText("["+cell.nearMine+"]");
+ }
+ else if(status == CellStatus.DANGEROUS)
+ label.setBackground(Color.BLACK);
+ else if(status == CellStatus.EXPLODED)
+ label.setBackground(Color.RED);
+ else if(status == CellStatus.GOTRIGHT)
+ label.setBackground(Color.GREEN);
+ else
+ label.setBackground(Color.LIGHT_GRAY);
+
+ return label;
+ }
+}
diff --git a/src/main/java/berack96/games/minefield/object/view/FieldView.java b/src/main/java/berack96/games/minefield/object/view/FieldView.java
new file mode 100644
index 0000000..bd161a1
--- /dev/null
+++ b/src/main/java/berack96/games/minefield/object/view/FieldView.java
@@ -0,0 +1,119 @@
+package berack96.games.minefield.object.view;
+
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import berack96.games.minefield.listener.CellInFieldListener;
+import berack96.games.minefield.object.Field;
+
+/**
+ * Classe che mostra il campo da gioco in modo grafico (tramite stringhe o jpanel).
+ *
+ * @author Jack
+ *
+ */
+public class FieldView {
+
+ private final Field field;
+
+ private String string;
+ private JPanel panel;
+
+ /**
+ * Costruttore in cui si inserisce il campo e un eventuale listener
+ * su ogni cella del campo
+ *
+ * @param field Il campo da vedere
+ * @param listener il controllore delle celle
+ */
+ public FieldView(Field field, CellInFieldListener listener)
+ {
+ this.field = field;
+
+ string = toString(field);
+ panel = toJPanel(field, listener);
+ }
+
+ /**
+ * Restituisce il campo sottoforma di stringa.
+ * Per valori celle vedi {@link CellView#toString()}.
+ *
+ * @return String
+ */
+ public String toString()
+ {
+ string = toString(field);
+ return string;
+ }
+
+ /**
+ * Restituisce il campo sottoforma di jpanel.
+ * Per valori celle vedi {@link CellView#toJLabel()}.
+ *
+ * @return JPanel
+ */
+ public JPanel toJPanel()
+ {
+ return panel;
+ }
+
+ /**
+ * Metodo statico che serve, passato un campo, a trasformarlo in stringa
+ * secondo {@link #toString()}.
+ *
+ * @param field il campo da vedere
+ * @return String
+ */
+ public static String toString(Field field)
+ {
+ String string = new String();
+
+ for(int i=0; i
+ * secondo {@link #toJPanel()}.
+ *
+ * @param field il campo da vedere
+ * @param listener eventuale controller da applicare ad ogni cella
+ * @return JPanel
+ */
+ public static JPanel toJPanel(Field field, CellInFieldListener listener)
+ {
+ JPanel panel = new JPanel();
+
+ panel.setLayout(new GridLayout(field.lines, field.columns));
+ panel.setVisible(true);
+
+ for(int i=0; i seqTemp = new Vector();
+ System.out.print(prompt);
+ String inputString = readString();
+ while (inputString.length()>0) {
+ seqTemp.add(inputString);
+ System.out.print(prompt);
+ inputString = readString();
+ }
+ String[] seq = new String[seqTemp.size()];
+ return seqTemp.toArray(seq);
+ }
+
+ public static String[] readSeq(String msg, String prompt){
+ System.out.println(msg);
+ String[] seq = readSeq(prompt);
+ return seq;
+ }
+
+}
diff --git a/src/test/java/berack96/test/games/minefield/TestCell.java b/src/test/java/berack96/test/games/minefield/TestCell.java
new file mode 100644
index 0000000..c5e2fe3
--- /dev/null
+++ b/src/test/java/berack96/test/games/minefield/TestCell.java
@@ -0,0 +1,59 @@
+package berack96.test.games.minefield;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import berack96.games.minefield.object.Cell;
+import berack96.games.minefield.object.CellStatus;
+
+public class TestCell {
+
+ public Cell cell;
+
+ @BeforeAll
+ public void initialize() {
+ cell = new Cell();
+ assertEquals(cell.getStatus(), CellStatus.COVERED);
+ }
+
+ @Test
+ public void cellUncover() {
+ assertFalse(cell.isUncovered());
+ cell.uncover();
+ assertTrue(cell.isUncovered());
+ assertEquals(cell.getStatus(), CellStatus.UNCOVERED);
+ }
+
+ @Test
+ public void cellMine() {
+ assertFalse(cell.isMine());
+ cell.setMine();
+ assertFalse(cell.isUncovered());
+ assertTrue(cell.isMine());
+ }
+
+ @Test
+ public void cellDangerous() {
+ cell.setDangerous();
+ assertFalse(cell.isUncovered());
+ assertEquals(cell.getStatus(), CellStatus.DANGEROUS);
+ }
+
+ @Test
+ public void cellUncoveredMine() {
+ cell.setMine();
+ cell.uncover();
+ assertEquals(cell.getStatus(), CellStatus.EXPLODED);
+ }
+
+ @Test
+ public void cellUncoveredMineDangerous() {
+ cell.setMine();
+ cell.setDangerous();
+ cell.uncover();
+
+ assertEquals(cell.getStatus(), CellStatus.GOTRIGHT);
+ }
+}
diff --git a/src/test/java/berack96/test/games/minefield/TestFieldNoSafe.java b/src/test/java/berack96/test/games/minefield/TestFieldNoSafe.java
new file mode 100644
index 0000000..4a4fc81
--- /dev/null
+++ b/src/test/java/berack96/test/games/minefield/TestFieldNoSafe.java
@@ -0,0 +1,31 @@
+package berack96.test.games.minefield;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import berack96.games.minefield.object.FieldNoSafe;
+
+public class TestFieldNoSafe {
+
+ public FieldNoSafe field;
+ public final int height = 10;
+ public final int length = 20;
+ public final int mines = 10;
+
+ @BeforeAll
+ public void initialize() {
+ field = new FieldNoSafe(this.length, this.height, this.mines);
+ }
+
+ @Test
+ public void fieldStart() {
+ assertEquals(field.lines, this.height);
+ assertEquals(field.lines, this.length);
+ assertEquals(field.getNumCoveredCell(), this.height*this.length);
+ assertEquals(field.getNumDagerousCell(), 0);
+ assertEquals(field.getNumUncoveredCell(), 0);
+ assertEquals(field.getNumMines(), this.mines);
+ }
+}
diff --git a/src/test/java/berack96/test/games/minefield/TestFieldSafe.java b/src/test/java/berack96/test/games/minefield/TestFieldSafe.java
new file mode 100644
index 0000000..3d54f65
--- /dev/null
+++ b/src/test/java/berack96/test/games/minefield/TestFieldSafe.java
@@ -0,0 +1,7 @@
+package berack96.test.games.minefield;
+
+
+
+public class TestFieldSafe {
+
+}
| | |