- Вы играете против ИИ (крестики-нолики)
- Вы целенаправленно заполняете всю доску и сравняйте/выиграйте игру.
- Вы играете в другую игру с ИИ.
- Выберите следующее (просто чтобы увидеть проблему), вы выбираете средний правый угол. , средний левый, затем центр, чтобы победить.
main.java
package alqashqish.u2l3_tictactoe;
public class main {
public static void main(String[] args) {
/**
* This is the main method in the program and invokes all the other methods required by your program.
*/
mainScreen frame = new mainScreen(); // Runs the screen layout class
}
}
mainScreen.java
package alqashqish.u2l3_tictactoe;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class mainScreen extends JFrame{
public mainScreen() {
super("Main Screen");
setMinimumSize(new Dimension(500, 300));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Sets the program to quit if the window is closed
setResizable(false);
FlowLayout layout = new FlowLayout();
layout.setAlignment(FlowLayout.CENTER);
setLayout(layout);
setLocationRelativeTo(null);
initComponents();
addActionListeners();
setVisible(true);
}
private void addActionListeners() {
twoPlayerButton.addActionListener(evt -> twoPlayerPerformed());
computerButton.addActionListener(evt -> computerPerformed());
}
private void computerPerformed() {
TicTac tictac = new TicTac(true);
// tictac.setVisible(true);
tictac.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
tictac.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent evt) {
setVisible(true);
}
});
setVisible(false);
}
private void twoPlayerPerformed() {
TicTac tictac = new TicTac(false);
// tictac.setVisible(true);
tictac.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
tictac.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent evt) {
setVisible(true);
}
});
setVisible(false);
}
private void initComponents() {
twoPlayerButton = new JButton("Play vs. Friend");
computerButton = new JButton("Play vs. AI");
twoPlayerButton.setSize(new Dimension(200, 100));
twoPlayerButton.setFont(new Font("Segoe UI", Font.BOLD, 50));
computerButton.setSize(new Dimension(200, 100));
computerButton.setFont(new Font("Segoe UI", Font.BOLD, 50));
JPanel mainPanel = new JPanel();
GridLayout layout1 = new GridLayout(2, 1, 50, 50);
mainPanel.setLayout(layout1);
mainPanel.add(twoPlayerButton);
mainPanel.add(computerButton);
add(mainPanel);
}
private JButton twoPlayerButton;
private JButton computerButton;
}
TicTac.java
package alqashqish.u2l3_tictactoe;
import java.awt.*; // Import the libraries needed in this app
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;
public class TicTac extends JFrame { // Sets up our TicTacToe class gets access to everything in the JFrame class
JPanel row1 = new JPanel();
JButton[][] boxes = new JButton[3][3];
public boolean aiPlayer;
public int xWon = 0;
public int oWon = 0;
/**
* Creates a 2D grid of arrays for the 9 buttons, sets aside memory spots for them
* but doesn't create them yet. The spaces have no context in them yet
*/
JOptionPane win = new JOptionPane("WINNER"); // Will pop-up and declare the winner
ImageIcon back = new ImageIcon("cardback.png"); // Loads the image to be used as the background of the buttons
public TicTac(boolean ai) { // Creates the method to draw the game board
super("Tic Tac Toe"); // Creates the title for the app
setSize(500, 770); // Sets the size of the outer frame
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Sets the program to quit if the window is closed
FlowLayout layout = new FlowLayout(); // Arranges components from left to right, centering components horizontally with a fivel pixel gap between them
setLayout(layout);
setLocationRelativeTo(null);
int name = 0; // Creates a variable to keep track of box number
String newName; // Will be used to hold button names
aiPlayer = ai;
TicTacEvent tictac = new TicTacEvent(this); // Joins the two programs (TicTac.java and TicTacEvent.java) to work with each other
GridLayout layout1 = new GridLayout(4, 3, 10, 10); // Arranges the components in a rectangular grid, where cells are of equal size
row1.setLayout(layout1);
for (int x = 0; x < 3; x++) { // Creates and adds the buttons to the GridLayout, goes up and down
for (int y = 0; y < 3; y++) { // Goes across the GridLayout
name += 1; // Adds one to the loop
newName = String.valueOf(name); // Names newName from number 1-9
boxes[x][y] = new JButton(); // Create a new box
boxes[x][y].setActionCommand(newName); // Set action command to number of box
int width = back.getIconWidth();
Map style = partialBorders(width / 10);
boxes[x][y].setContentAreaFilled(false); // Sets the colour of the button to transparent
boxes[x][y].setBorder(style.get(name)); // Sets border based off the location of button to draw the tictactoe board
boxes[x][y].setIcon(back); // Sets the images of the back of the buttons
row1.add(boxes[x][y]); // Adds remaining components to the GridLayout
}
}
// add(row1); // Adds the GridLayout to the FlowLayout
BorderLayout mainLayout = new BorderLayout();
JPanel main = new JPanel();
main.setLayout(mainLayout);
main.add(row1, BorderLayout.CENTER);
GridLayout grid = new GridLayout(3, 1, 10, 10);
GridLayout grid2 = new GridLayout(1, 2, 10, 100);
playAgain = new JButton("Play Again");
playAgain.setFont(new Font("Segoe UI", Font.BOLD, 40));
playAgain.setVisible(false);
playAgain.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
playAgain.setVisible(false);
tictac.reset();
for (int x = 0; x < 3; x++) { // Runs a loop to see which button was pressed
for (int y = 0; y < 3; y++) {
for (ActionListener al : boxes[x][y].getActionListeners()) {
boxes[x][y].removeActionListener(al); // Clear old listeners
}
boxes[x][y].addActionListener(tictac); // Reassign fresh listener
}
}
}
});
JPanel wins = new JPanel();
JPanel sub = new JPanel();
wins.setLayout(grid2);
xLabel = new JLabel("X: " + xWon);
oLabel = new JLabel("O: " + oWon);
xLabel.setFont(new Font("Segoe UI", Font.BOLD, 40));
oLabel.setFont(new Font("Segoe UI", Font.BOLD, 40));
xLabel.setForeground(new Color(236, 47, 47));
oLabel.setForeground(new Color(70, 154, 204));
xLabel.setHorizontalAlignment(WIDTH/2);
oLabel.setHorizontalAlignment(WIDTH/2);
wins.add(xLabel);
wins.add(oLabel);
JButton exitButton = new JButton("Exit");
exitButton.setFont(new Font("Segoe UI", Font.BOLD, 16));
exitButton.setSize(new Dimension(100, 50));
exitButton.addActionListener(evt -> exitScreen());
sub.setLayout(grid);
sub.add(playAgain);
sub.add(wins);
sub.add(exitButton);
main.add(sub, BorderLayout.SOUTH);
add(main);
for (int x = 0; x < 3; x++) { // Runs a loop to see which button was pressed
for (int y = 0; y < 3; y++) {
boxes[x][y].addActionListener(tictac); // Listens to button being clicked
}
}
setVisible(true); // Shows the FlowLayout on the screen
}
public void changeWinValues() {
xLabel.setText("X: " + xWon);
oLabel.setText("O: " + oWon);
}
private void exitScreen() {
dispose();
}
private static Map partialBorders(int pixels) {
/**
* This function will determine where the border of the buttons should be.
* For example, in the top left corner, the bottom and the right of the button
* should have a border in order to create the UI look of 3x3 grid layout
*/
Map result = new HashMap(); // Create a new hashmap
result.put(1, new MatteBorder(0, 0, pixels, pixels, Color.black)); // Add new border layout
result.put(2, new MatteBorder(0, pixels, pixels, pixels, Color.black)); // Add new border layout
result.put(3, new MatteBorder(0, pixels, pixels, 0, Color.black)); // Add new border layout
result.put(4, new MatteBorder(pixels, 0, pixels, pixels, Color.black)); // Add new border layout
result.put(5, new MatteBorder(pixels, pixels, pixels, pixels, Color.black)); // Add new border layout
result.put(6, new MatteBorder(pixels, pixels, pixels, 0, Color.black)); // Add new border layout
result.put(7, new MatteBorder(pixels, 0, 0, pixels, Color.black)); // Add new border layout
result.put(8, new MatteBorder(pixels, pixels, 0, pixels, Color.black)); // Add new border layout
result.put(9, new MatteBorder(pixels, pixels, 0, 0, Color.black)); // Add new border layout
return result; // Return map of border layouts based off button
}
private JLabel xLabel;
private JLabel oLabel;
public JButton playAgain;
}
TicTacEvent.java
package alqashqish.u2l3_tictactoe;
// Import needed libraries
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.Random;
/**
*
* @author Mohammad
*/
public class TicTacEvent implements ItemListener, ActionListener, Runnable { // Creates a class that responds to mouse and keyboard input by listening
TicTac gui; // Associates the game board with the event
ImageIcon a = new ImageIcon("x.png"); // Sets x.png to ImageIcon a
ImageIcon b = new ImageIcon("o.png"); // Sets o.png to ImageIcon b
int clicks = 0; // Checks for number of turns
int win = 0; // Created to check for a winner
public boolean computerPlaying;
int[][] check = new int[3][3]; // 2D array to check the value in each box
public TicTacEvent(TicTac in) { // Associates the two files to be used together
gui = in;
computerPlaying = gui.aiPlayer;
for (int row = 0; row < 3; row++) { // Initiates the winner check array
for (int col = 0; col < 3; col++) {
check[row][col] = 0;
}
}
}
public void reset() {
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
gui.boxes[row][col].setEnabled(true);
System.out.println("BEFORE: " + gui.boxes[row][col].getIcon());
gui.boxes[row][col].setIcon(gui.back);
System.out.println("AFTER: " + gui.boxes[row][col].getIcon());
check[row][col] = 0;
}
}
System.out.println("DONE\n");
win = 0;
clicks = 0;
}
public void actionPerformed (ActionEvent e) { // Tells the program what to do when a button is clicked
String command = e.getActionCommand(); // Takes the button name as input from the button that is clicked
switch (command) {
case "1" -> b1();
case "2" -> b2();
case "3" -> b3();
case "4" -> b4();
case "5" -> b5();
case "6" -> b6();
case "7" -> b7();
case "8" -> b8();
case "9" -> b9();
}
if (computerPlaying && win != 1) {
makeAiMove();
clicks++;
winner();
}
}
void b1() { // Creates method b1 to handle clicks on each game square
clicks ++; // Keeps track of the number of boxes chosen
if (clicks % 2 == 1) { // Put an X
check[0][0] = 1; // If box in top left corner is pressed
gui.boxes[0][0].setEnabled(false); // Disable the box
gui.boxes[0][0].setDisabledIcon(a); // Change icon to x
} else { // Put an O instead of X
check[0][0] = 2;
gui.boxes[0][0].setEnabled(false);
gui.boxes[0][0].setDisabledIcon(b);
}
winner();
}
void b2() { // Creates method b2 to handle clicks on each game square
clicks++; // Keeps track of the number of boxes chosen
if (clicks % 2 == 1) { // Put an X
check[0][1] = 1; // If box is pressed
gui.boxes[0][1].setEnabled(false); // Disable the box
gui.boxes[0][1].setDisabledIcon(a); // Change icon to x
} else { // Put an O instead of X
check[0][1] = 2;
gui.boxes[0][1].setEnabled(false);
gui.boxes[0][1].setDisabledIcon(b);
}
winner();
}
void b3() { // Creates method b3 to handle clicks on each game square
clicks++; // Keeps track of the number of boxes chosen
if (clicks % 2 == 1) { // Put an X
check[0][2] = 1; // If box is pressed
gui.boxes[0][2].setEnabled(false); // Disable the box
gui.boxes[0][2].setDisabledIcon(a); // Change icon to x
} else { // Put an O instead of X
check[0][2] = 2;
gui.boxes[0][2].setEnabled(false);
gui.boxes[0][2].setDisabledIcon(b);
}
winner();
}
void b4() { // Creates method b4 to handle clicks on each game square
clicks++; // Keeps track of the number of boxes chosen
if (clicks % 2 == 1) { // Put an X
check[1][0] = 1; // If box is pressed
gui.boxes[1][0].setEnabled(false); // Disable the box
gui.boxes[1][0].setDisabledIcon(a); // Change icon to x
} else { // Put an O instead of X
check[1][0] = 2;
gui.boxes[1][0].setEnabled(false);
gui.boxes[1][0].setDisabledIcon(b);
}
winner();
}
void b5() { // Creates method b5 to handle clicks on each game square
clicks++; // Keeps track of the number of boxes chosen
if (clicks % 2 == 1) { // Put an X
check[1][1] = 1; // If box is pressed
gui.boxes[1][1].setEnabled(false); // Disable the box
gui.boxes[1][1].setDisabledIcon(a); // Change icon to x
} else { // Put an O instead of X
check[1][1] = 2;
gui.boxes[1][1].setEnabled(false);
gui.boxes[1][1].setDisabledIcon(b);
}
winner();
}
void b6() { // Creates method b6 to handle clicks on each game square
clicks++; // Keeps track of the number of boxes chosen
if (clicks % 2 == 1) { // Put an X
check[1][2] = 1; // If box is pressed
gui.boxes[1][2].setEnabled(false); // Disable the box
gui.boxes[1][2].setDisabledIcon(a); // Change icon to x
} else { // Put an O instead of X
check[1][2] = 2;
gui.boxes[1][2].setEnabled(false);
gui.boxes[1][2].setDisabledIcon(b);
}
winner();
}
void b7() { // Creates method b7 to handle clicks on each game square
clicks++; // Keeps track of the number of boxes chosen
if (clicks % 2 == 1) { // Put an X
check[2][0] = 1; // If box is pressed
gui.boxes[2][0].setEnabled(false); // Disable the box
gui.boxes[2][0].setDisabledIcon(a); // Change icon to x
} else { // Put an O instead of X
check[2][0] = 2;
gui.boxes[2][0].setEnabled(false);
gui.boxes[2][0].setDisabledIcon(b);
}
winner();
}
void b8() { // Creates method b8 to handle clicks on each game square
clicks++; // Keeps track of the number of boxes chosen
if (clicks % 2 == 1) { // Put an X
check[2][1] = 1; // If box is pressed
gui.boxes[2][1].setEnabled(false); // Disable the box
gui.boxes[2][1].setDisabledIcon(a); // Change icon to x
} else { // Put an O instead of X
check[2][1] = 2;
gui.boxes[2][1].setEnabled(false);
gui.boxes[2][1].setDisabledIcon(b);
}
winner();
}
void b9() { // Creates method b9 to handle clicks on each game square
clicks++; // Keeps track of the number of boxes chosen
if (clicks % 2 == 1) { // Put an X
check[2][2] = 1; // If box is pressed
gui.boxes[2][2].setEnabled(false); // Disable the box
gui.boxes[2][2].setDisabledIcon(a); // Change icon to x
} else { // Put an O instead of X
check[2][2] = 2;
gui.boxes[2][2].setEnabled(false);
gui.boxes[2][2].setDisabledIcon(b);
}
winner();
}
void winner () {
int winner = 0;
for (int x = 0; x < 3; x++) { // Check rows for winner
if (check[x][0] == check[x][1] && check[x][0] == check[x][2]) {
if (check[x][0] == 1) {
JOptionPane.showMessageDialog(null, "X is the winner");
win = 1;
winner = 1;
} else if (check[x][0] == 2) {
JOptionPane.showMessageDialog(null, "O is the winner");
win = 1;
winner = 2;
}
}
}
for (int x = 0; x < 3; x++) {
if (check[0][x] == check[1][x] && check[0][x] == check[2][x]) {
if (check[0][x] == 1) {
JOptionPane.showMessageDialog(null, "X is the winner");
win = 1;
winner = 1;
} else if (check[0][x] == 2) {
JOptionPane.showMessageDialog(null, "O is the winner");
win = 1;
winner = 2;
}
}
}
boolean v1 = check[0][0] == check[1][1] && check[0][0] == check[2][2];
boolean v2 = check[2][0] == check[1][1] && check[2][0] == check[0][2];
if (v1 || v2) {
if (check[1][1] == 1) {
JOptionPane.showMessageDialog(null, "X is the winner");
win = 1;
winner = 1;
} else if (check[1][1] == 2) {
win = 1;
winner = 2;
}
}
if (clicks == 9 && win == 0) {
JOptionPane.showMessageDialog(null, "Tie game");
win = 1;
}
if (win == 1) {
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 3; y++) {
gui.boxes[x][y].setEnabled(false);
}
}
if (winner == 1) {
gui.xWon += 1;
} else if (winner == 2) {
gui.oWon += 1;
}
gui.changeWinValues();
gui.playAgain.setVisible(true);
}
}
public void itemStateChanged(ItemEvent evt) {
throw new UnsupportedOperationException("Not supported yet.");
}
private void makeAiMove() {
boolean mademove = false;
if (win == 1) {
return;
}
// check if you can take a win horizontally
for(int i = 0; i
Подробнее здесь: https://stackoverflow.com/questions/792 ... utton-icon
Мобильная версия