diff --git a/TrisMiniMax/.gitignore b/TrisMiniMax/.gitignore
new file mode 100644
index 0000000..13275f1
--- /dev/null
+++ b/TrisMiniMax/.gitignore
@@ -0,0 +1,30 @@
+### IntelliJ IDEA ###
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+.kotlin
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/TrisMiniMax/.idea/.gitignore b/TrisMiniMax/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/TrisMiniMax/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/TrisMiniMax/.idea/misc.xml b/TrisMiniMax/.idea/misc.xml
new file mode 100644
index 0000000..07115cd
--- /dev/null
+++ b/TrisMiniMax/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TrisMiniMax/.idea/modules.xml b/TrisMiniMax/.idea/modules.xml
new file mode 100644
index 0000000..5d7e12e
--- /dev/null
+++ b/TrisMiniMax/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TrisMiniMax/.idea/vcs.xml b/TrisMiniMax/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/TrisMiniMax/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TrisMiniMax/TrisMiniMax.iml b/TrisMiniMax/TrisMiniMax.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/TrisMiniMax/TrisMiniMax.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TrisMiniMax/src/TrisGame.java b/TrisMiniMax/src/TrisGame.java
new file mode 100644
index 0000000..bf26f46
--- /dev/null
+++ b/TrisMiniMax/src/TrisGame.java
@@ -0,0 +1,221 @@
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+
+public class TrisGame extends JFrame {
+ private final JButton[][] buttons = new JButton[3][3];
+ private final char[][] board = new char[3][3];
+ private final char humanPlayer = 'X';
+ private final char aiPlayer = 'O';
+ private final JLabel statusLabel;
+ private boolean gameOver = false;
+
+ public TrisGame() {
+ setTitle("Tris - Minimax AI");
+ setSize(400, 450);
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ setLayout(new BorderLayout());
+
+ // Pannello di gioco
+ JPanel gamePanel = new JPanel(new GridLayout(3, 3, 5, 5));
+ gamePanel.setBackground(Color.BLACK);
+
+ // Inizializza la board e i bottoni
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ board[i][j] = ' ';
+ buttons[i][j] = new JButton("");
+ buttons[i][j].setFont(new Font("Arial", Font.BOLD, 60));
+ buttons[i][j].setFocusPainted(false);
+ buttons[i][j].setBackground(Color.WHITE);
+
+ final int row = i;
+ final int col = j;
+
+ buttons[i][j].addActionListener(e -> playerMove(row, col));
+ gamePanel.add(buttons[i][j]);
+ }
+ }
+
+ // Pannello di stato
+ JPanel statusPanel = new JPanel();
+ statusLabel = new JLabel("Il tuo turno! (X)");
+ statusLabel.setFont(new Font("Arial", Font.BOLD, 16));
+ statusPanel.add(statusLabel);
+
+ // Bottone reset
+ JButton resetButton = new JButton("Nuova Partita");
+ resetButton.addActionListener(e -> resetGame());
+ statusPanel.add(resetButton);
+
+ add(gamePanel, BorderLayout.CENTER);
+ add(statusPanel, BorderLayout.SOUTH);
+
+ setLocationRelativeTo(null);
+ setVisible(true);
+ }
+
+ private void playerMove(int row, int col) {
+ if (gameOver || board[row][col] != ' ') return;
+
+ // Mossa del giocatore
+ board[row][col] = humanPlayer;
+ buttons[row][col].setText("X");
+ buttons[row][col].setForeground(Color.BLUE);
+
+ if (checkWinner(humanPlayer)) {
+ statusLabel.setText("Hai vinto! 🎉");
+ gameOver = true;
+ highlightWinner(humanPlayer);
+ return;
+ }
+
+ if (isBoardFull()) {
+ statusLabel.setText("Pareggio!");
+ gameOver = true;
+ return;
+ }
+
+ // Mossa dell'AI
+ statusLabel.setText("L'AI sta pensando...");
+ Timer timer = new Timer(500, e -> {
+ aiMove();
+
+ if (checkWinner(aiPlayer)) {
+ statusLabel.setText("L'AI ha vinto!");
+ gameOver = true;
+ highlightWinner(aiPlayer);
+ } else if (isBoardFull()) {
+ statusLabel.setText("Pareggio!");
+ gameOver = true;
+ } else {
+ statusLabel.setText("Il tuo turno! (X)");
+ }
+ });
+ timer.setRepeats(false);
+ timer.start();
+ }
+
+ private void aiMove() {
+ int[] bestMove = findBestMove();
+ board[bestMove[0]][bestMove[1]] = aiPlayer;
+ buttons[bestMove[0]][bestMove[1]].setText("O");
+ buttons[bestMove[0]][bestMove[1]].setForeground(Color.RED);
+ }
+
+ private int[] findBestMove() {
+ int bestScore = Integer.MIN_VALUE;
+ int[] bestMove = new int[2];
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ if (board[i][j] == ' ') {
+ board[i][j] = aiPlayer;
+ int score = minimax(0, false);
+ board[i][j] = ' ';
+
+ if (score > bestScore) {
+ bestScore = score;
+ bestMove[0] = i;
+ bestMove[1] = j;
+ }
+ }
+ }
+ }
+ return bestMove;
+ }
+
+ private int minimax(int depth, boolean isMaximizing) {
+ if (checkWinner(aiPlayer)) return 10 - depth;
+ if (checkWinner(humanPlayer)) return depth - 10;
+ if (isBoardFull()) return 0;
+
+ int bestScore;
+ if (isMaximizing) {
+ bestScore = Integer.MIN_VALUE;
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ if (board[i][j] == ' ') {
+ board[i][j] = aiPlayer;
+ int score = minimax(depth + 1, false);
+ board[i][j] = ' ';
+ bestScore = Math.max(score, bestScore);
+ }
+ }
+ }
+ } else {
+ bestScore = Integer.MAX_VALUE;
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ if (board[i][j] == ' ') {
+ board[i][j] = humanPlayer;
+ int score = minimax(depth + 1, true);
+ board[i][j] = ' ';
+ bestScore = Math.min(score, bestScore);
+ }
+ }
+ }
+ }
+ return bestScore;
+ }
+
+ private boolean checkWinner(char player) {
+ // Righe e colonne
+ for (int i = 0; i < 3; i++) {
+ if (board[i][0] == player && board[i][1] == player && board[i][2] == player) return true;
+ if (board[0][i] == player && board[1][i] == player && board[2][i] == player) return true;
+ }
+ // Diagonali
+ if (board[0][0] == player && board[1][1] == player && board[2][2] == player) return true;
+ return board[0][2] == player && board[1][1] == player && board[2][0] == player;
+ }
+
+ private void highlightWinner(char player) {
+ Color winColor = new Color(144, 238, 144);
+
+ // Righe
+ for (int i = 0; i < 3; i++) {
+ if (board[i][0] == player && board[i][1] == player && board[i][2] == player) {
+ for (int j = 0; j < 3; j++) buttons[i][j].setBackground(winColor);
+ }
+ }
+ // Colonne
+ for (int i = 0; i < 3; i++) {
+ if (board[0][i] == player && board[1][i] == player && board[2][i] == player) {
+ for (int j = 0; j < 3; j++) buttons[j][i].setBackground(winColor);
+ }
+ }
+ // Diagonali
+ if (board[0][0] == player && board[1][1] == player && board[2][2] == player) {
+ for (int i = 0; i < 3; i++) buttons[i][i].setBackground(winColor);
+ }
+ if (board[0][2] == player && board[1][1] == player && board[2][0] == player) {
+ for (int i = 0; i < 3; i++) buttons[i][2-i].setBackground(winColor);
+ }
+ }
+
+ private boolean isBoardFull() {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ if (board[i][j] == ' ') return false;
+ }
+ }
+ return true;
+ }
+
+ private void resetGame() {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ board[i][j] = ' ';
+ buttons[i][j].setText("");
+ buttons[i][j].setBackground(Color.WHITE);
+ }
+ }
+ gameOver = false;
+ statusLabel.setText("Il tuo turno! (X)");
+ }
+
+ public static void main(String[] args) {
+ SwingUtilities.invokeLater(TrisGame::new);
+ }
+}
\ No newline at end of file