I'm in the middle of learning Java right now and a project peaked my interests, so I attempted to do it. The project was a tic-tac-toe AI, but I'm not quite there so I created a tic-tac-toe game where the bot plays randomly, making it very easy ![:)]()
I was wondering how I did, what you would have done differently, and what I could improve on.
There are 4 files:
tictactoe.java: The main file that handles inputs, starts games, and so on
Game.java: Controls the game, checks for wins, makes the bot play, etc
Board.java: Used for storing the position of plays
AI.java: The bot. It accepts a Board object, finds an empty spot, and places an X there and returns the board.
Thanks you for your time

I was wondering how I did, what you would have done differently, and what I could improve on.
There are 4 files:
tictactoe.java: The main file that handles inputs, starts games, and so on
Spoiler
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class tictactoe { public static boolean quit = false; public static Game game = new Game(); public static void main(String[] args){ System.out.println("Welcome to tic-tac-toe!"); // Start with an amazing message while(!quit){ System.out.print("> "); handleCmd(getInput()); // Keep on accepting input } } public static void handleCmd(String cmd){ if(cmd.equals("quit")){ quit = true; } if(!game.inProgress){ if(cmd.equals("start")){ game.start(); game.doLogic(); } } else { if(cmd.matches("[1-9],[1-9]")){ int y = Integer.parseInt(cmd.substring(0, 1)); int x = Integer.parseInt(cmd.substring(2, 3)); if(game.playMove(y-1, x-1)){ return; } } else { System.out.println("Incorrect move"); } } } public static String getInput(){ try { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); return in.readLine(); } catch (IOException e) { e.printStackTrace(); return "Error"; } } }
Game.java: Controls the game, checks for wins, makes the bot play, etc
Spoiler
import java.util.Arrays; public class Game { protected Board board; public boolean inProgress = false; private AI bot = new AI(0); private boolean won; private char winner; public void start(){ System.out.println("A new game has started!"); board = new Board(3, 3); inProgress = true; won = false; winner = ' '; } public boolean playMove(int y, int x){ if(board.board[y][x] != ' '){ return false; } board.putChar(y, x, 'O'); doLogic(); botPlayMove(); return true; } public void botPlayMove(){ if(inProgress){ board = bot.playMove(board); doLogic(); } } public void doLogic(){ if(inProgress){ System.out.println("---"); boardToScreen(); detectTie(); detectWin(); if(won){ inProgress = false; if(winner == 't'){ System.out.println("Tie game!"); } else { System.out.println(winner + " wins!"); } } } } public void detectTie(){ for(int y=0; y<3; y++){ for(int x=0; x<3; x++){ if(board.board[y][x] == ' '){ // return; } } } won = true; winner = 't'; } public void detectWin(){ // Check for straight across wins for(int y=0; y<3; y++){ for(int x=1; x<3; x++){ char prevChar = board.board[y][x-1]; if(prevChar != board.board[y][x] || prevChar == ' '){ // If our current char isn't the same as the last, or the last was an empty space, it ain't a win break; } if(x==2){ won = true; winner = prevChar; } } } // Check for straight down wins for(int x=0; x<3; x++){ char first = board.board[0][x]; char second = board.board[1][x]; char third = board.board[2][x]; if(first == second && second == third && third != ' '){ won = true; winner = third; } } // Check for 1,1->3,3 cross win for(int i=1; i<3; i++){ char prevChar = board.board[i-1][i-1]; if(prevChar != board.board[i][i] || prevChar == ' '){ break; } if(i==2){ won = true; winner = prevChar; } } } public void boardToScreen(){ char[][] b = new char[5][5]; // Line 1 b[0][0] = board.board[0][0]; b[0][1] = '|'; b[0][2] = board.board[0][1]; b[0][3] = '|'; b[0][4] = board.board[0][2]; // Line 2 b[1][0] = '-'; b[1][1] = '+'; b[1][2] = '-'; b[1][3] = '+'; b[1][4] = '-'; // Line 3 b[2][0] = board.board[1][0]; b[2][1] = '|'; b[2][2] = board.board[1][1]; b[2][3] = '|'; b[2][4] = board.board[1][2]; // Line 4 b[3][0] = '-'; b[3][1] = '+'; b[3][2] = '-'; b[3][3] = '+'; b[3][4] = '-'; // Line 5 b[4][0] = board.board[2][0]; b[4][1] = '|'; b[4][2] = board.board[2][1]; b[4][3] = '|'; b[4][4] = board.board[2][2]; // Draw to screen char c = '\n'; int length = 10; char[] chars = new char[length]; Arrays.fill(chars, c); System.out.print(String.valueOf(chars)); // I feel so unclean :(/>/>/>/> for(int x = 0; x < b.length; x++){ for(int y = 0; y < b[x].length; y++){ System.out.print(b[x][y]); if(y == b[x].length-1) System.out.println(); } } } }
Board.java: Used for storing the position of plays
Spoiler
import java.util.Arrays; public class Board { protected char[][] board; public Board(int height, int width){ board = new char[height][width]; for(int h = 0; h < height; h++){ for(int w = 0; w < width; w++){ board[h][w] = ' '; } } } public void putChar(int y, int x, char Char){ try { board[y][x] = Char; } catch (Exception ex){ System.out.println("There was a problem!"); ex.printStackTrace(); } } public void draw(){ char c = '\n'; int length = 10; char[] chars = new char[length]; Arrays.fill(chars, c); System.out.print(String.valueOf(chars)); // I feel so unclean :(/>/>/>/> for(int x = 0; x < board.length; x++){ for(int y = 0; y < board[x].length; y++){ System.out.print(board[x][y]); if(y == board[x].length-1) System.out.println(); } } } }
AI.java: The bot. It accepts a Board object, finds an empty spot, and places an X there and returns the board.
Spoiler
import java.util.Random; public class AI { public int smarts; public AI(int level){ smarts = level; } public Board playMove(Board board){ if(smarts == 0){ // Dumb mode: Plays randomly boolean found = false; Random random = new Random(); while(!found){ // That's right, we're going to keep searching for an empty spot. int h = random.nextInt(3); int w = random.nextInt(3); if(board.board[h][w] == ' '){ board.putChar(h, w, 'X'); // Found one, we're done. I hope this didn't take too long. found = true; } } } return board; } }
Thanks you for your time