Who is this Chatbot? Based off the coding puzzle: Who is this chatbot?

The code's purpose is to create an AI that the user can communicate with. Due to there being no hard-coded strings, the AI learns from what the user has said.

In my version of this AI, all messages said by the user are stored in an array and when it comes time for the computer to speak, a random message from the array is written to standard output.

The code

Main.java

public class Main {
    public static void main(String[] args) {
        String name;
        if(args.length &gt;= 1) {
            name = args[0];
        } else {
            name = "You";
        }
        Conversation c = new Conversation(new AI(), new User(name));
        while(true) {
            String input = c.getUser();
            if(input.equals(":exit")) {
                System.exit(0);
            }
            c.getAI();
        }
    }
}


Converstaion.java

public class Conversation {
    private AI ai;
    private User user;

    private DynamicArray saidStrings = new DynamicArray(1);
    private int saidCount = 0;

    public Conversation(AI a, User u) {
        ai = a;
        user = u;
    }

    public String getUser() {
        String input = user.getInput();
        saidStrings.push(input);
        saidCount++;
        return input;
    }
    public void getAI() {
        ai.saySomething(saidStrings, saidCount);
    }
}


AI.java

import java.util.Random;

public class AI {
    private Random rand = new Random();

    public void saySomething(DynamicArray saidStrings, int saidCount) {
        System.out.printf("Bot: %s\n", saidStrings.get(getRandom(saidCount)));
    }
    public int getRandom(int max) {
        return rand.nextInt(max);
    }
}


User.java

import java.util.Scanner;

public class User {
    private Scanner input = new Scanner(System.in);

    private String name;

    public User(String n) {
        name = n;
    }

    public String getInput() {
        System.out.printf("%s: ", name);
        return input.nextLine();
    }
}


DynamicArray.java

/*

Strongly based off of: http://stackoverflow.com/questions/3536153/c-dynamically-growing-array

*/

public class DynamicArray {
    private String[] array;
    private int used;
    private int size;

    public DynamicArray(int initialSize) {
        array = new String[initialSize];
        used = 0;
        size = initialSize;
    }

    public void push(String e) {
        if(used == size) { // if the limit has been reached
            size *= 2;

            String[] temp = array; //  a median for the trade
            array = new String[size];
            copy(temp, array);
        }
        array[used++] = e; // append the provided element
    }

    public String get(int i) {
        return array[i];
    }

    private void copy(String[] src, String[] dest) {
        System.arraycopy(src, 0, dest, 0, src.length);
    }
}


Concerns:


Am I following common OOP practices?
Am I following common Java practices
Do I have too many classes?
Do I have too few classes?
Am I handling input and output in the correct places?
Do I have too few/many comments?


Any other recommendations for improvement are welcome.
Your DynamicArray class is mimicking an ArrayList which is exactly that: a dynamic array. Use this instead of reinventing the wheel.



Use break; instead of System.exit(0) to exit a loop. It leaves room to add more instructions beyond the loop without having to change the implementation. It's also a more natural way to break out of a loop.



getUser() and getAI() indicate a return type of User and AI respectively. Choose naming that indicates you are receiving their input.



Write your parameter names in full (user instead of u, name instead of n).



Adhere to the single responsibility principle. Printing output and receiving input are two distinct tasks and shouldn't be done in the same method.



Concerning OO principles: perhaps create an interface Conversationist that defines a method String getSentence(). Now your User can implement this as receiving console input while the AI implements it by taking a random value from its stored text. This makes sure you can just call getSentence() for both objects and introduces some inheritance structure.