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