Tris MiniMax
This commit is contained in:
221
TrisMiniMax/src/TrisGame.java
Normal file
221
TrisMiniMax/src/TrisGame.java
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user