I recently had to complete this for a school assignment and I really enjoyed it, but was hoping someone with experience in OO design or maybe just Java in general could have a look and point out anything that's glaringly bad, or give me some pointers; I would appreciate it a lot. I hope it's not too much code.
This is BullsAndCowsServer.java
//-------------------------
// Multithreaded server program
//-------------------------
import java.net.*;
import java.io.*;
public class BullsAndCowsServer
{
public static void main(String[] args) throws IOException
{
final int PORT = (args.length > 0) ? Integer.parseInt(args[0]) : 1337;
ServerSocket s = new ServerSocket(PORT);
System.out.println("Started: " + s);
try
{
while (true)
{
Socket socket = s.accept();
System.out.println("New client connected: " + socket.getRemoteSocketAddress());
try
{
new ThreadWorker(socket);
} catch (IOException e)
{
socket.close();
} finally
{
//socket.close();
}
}
} finally
{
s.close();
}
}
}
This is ThreadWorker.java
//-------------------------
// Thread class for server use
//-------------------------
import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Random;
//this handles each game connection
class ThreadWorker extends Thread
{
public Socket socket;
public BufferedReader in;
public PrintWriter out;
public ThreadWorker(Socket s) throws IOException
{
socket = s;
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(s.getOutputStream())), true);
start();
}
public void run()
{
try
{
out.println("--------------------------------\nWelcome to the Bulls and Cows guessing game!\nType any of " +
"the following options:\n" +
"HELP\nNEWGAME\nRESUME <passcode>\n--------------------------------");
String str = in.readLine();
while (!str.equals("END"))
{
switch (str.split(" ", 10)[0])
{
case "HELP":
help();
break;
case "NEWGAME":
newgame();
break;
case "RESUME":
resume(str);
break;
default:
out.println("Sorry, that's not a valid option; please try again!");
break;
}
out.println("--------------------------------\nType any of the following options:\n" +
"HELP\nNEWGAME\nRESUME <passcode>\n--------------------------------");
str = in.readLine();
}
} catch (IOException | NullPointerException e){}
finally
{
try
{
System.out.println(socket.getRemoteSocketAddress() + " disconnected.");
socket.close();
} catch (IOException e)
{
}
}
}
private void newgame() throws IOException
{
bcGame game = new bcGame();
out.println("\n---------------------\nGreetings challenger.\nWhat is your name?");
String str = in.readLine();
str = str.replace(' ', '_');
game.name = str;
out.println("\n\n\n\n\n\n\nGreetings " + str + ". Play by typing 4 digit numbers where each digit is unique.\nYou can" +
" type PAUSE at any time to receive a passcode allowing you to return later.\nGoodluck!\n---------------------------");
playGame(game);
}
private void playGame(bcGame game) throws IOException
{
String str;
while (game.guesses < 6)
{
boolean guessed = false;
int bulls = 0, cows = 0;
out.println("\nYou have " + (6 - game.guesses) + " guesses remaining.\nPlease guess a number!");
str = in.readLine();
//pausing code
if (str.equals("PAUSE"))
{
pause(game);
return;
}
//check input is valid
if (!validate(str))
{
out.println("\nInvalid input; please enter a 4 digit number with no duplicate digits");
continue;
}
game.guesses++;
//calculate score
for (int i = 0; i < 4; i++)
{
if (str.charAt(i) == game.num.charAt(i))
bulls++;
else if (game.num.contains(str.charAt(i) + ""))
cows++;
}
//check win condition
if (bulls == 4)
{
out.println("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
out.println("Congratulations, you are correct!\nYou won after " + game.guesses + " guess" + ((game.guesses > 1) ? "es" : "") + "!");
out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
out.println("Press enter to return to the menu..");
in.readLine();
return;
} else
{
out.println("Bulls: " + bulls + "\nCows: " + cows);
}
}
out.println("\nSorry, you are out of guesses! The number was " + game.num + " \nBetter luck next time\n");
}
private synchronized void pause(bcGame game) throws IOException
{
out.println("\nPausing game...");
String dir = System.getProperty("user.dir");
File file = new File(dir + "/savedgames.txt");
file.createNewFile();
FileWriter writer = new FileWriter(file, true);
int key = new Random().nextInt(99999);
writer.append(key + " " + game.name + " " + game.num + " " + game.guesses + " ");
writer.close();
out.println("\nYour game has been saved.\nYou can resume at any time with the code " + key);
in.readLine();
return;
}
private void resume(String str) throws IOException
{
String gamekey = str.split(" ")[1];
out.println("\nReloading game <" + gamekey + ">");
String dir = System.getProperty("user.dir");
File file = new File(dir + "/savedgames.txt");
if (!file.exists())
{
out.println("Saved game not found, press enter to return to menu");
in.readLine();
return;
}
FileReader reader = new FileReader(file);
char[] a = new char[5000];
reader.read(a);
String s = new String(a);
String[] saved = s.split(" ");
for (int i = 0; i < saved.length; i += 4)
{
if (saved[i].equals(gamekey))
{
try
{
bcGame resumed = new bcGame(saved[i + 1], saved[i + 2], Integer.parseInt(saved[i + 3]));
out.println("Game found! Welcome back " + resumed.name);
playGame(resumed);
return;
} catch(NumberFormatException e)
{
System.out.println("Saved game is corrupt!");
break;
}
}
}
out.println("Saved game not found, press enter to return to menu");
in.readLine();
return;
}
private boolean validate(String str)
{
try
{
if (str.length() != 4) return false;
int num = Integer.parseInt(str);
boolean[] digs = new boolean[10];
for(int i = 0; i < 4; i++)
{
if (digs[num % 10]) return false;
digs[num % 10] = true;
num /= 10;
}
return true;
}
catch(NumberFormatException e) { return false;}
}
private void help() throws IOException
{
out.println("\nIn this game you must guess the secret 4 digit number.\nEach digit is unique; ie. no digit " +
"appears more than once." +
"\nAfter each guess you will be told a number of bulls and cows.\nYou get a bull if" +
" you guessed a digit in the correct place.\nYou get a cow if you guessed the digit correctly, but it " +
"was in the wrong place.\n" +
"Guess the number correctly in 6 attempts to win.\n Best of luck, challenger.");
out.println("\nPress enter to return to the menu");
in.readLine();
}
}
class bcGame
{
String num, name;
int guesses;
public bcGame()
{
guesses = 0;
num = generateNum();
name = "";
}
public bcGame(String namer, String numr, int guessesr)
{
guesses = guessesr;
num = numr;
name = namer;
}
//generates a 4 digit number in string form where all the digits are unique
String generateNum()
{
ArrayList arr = new ArrayList();// = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
for (int i = 0; i < 10; i++) arr.add(i);
String ret = "";
Random rand = new Random();
for (int i = 0; i < 4; i++)
{
int num = rand.nextInt(arr.size());
ret += arr.remove(num);
arr.trimToSize();
}
return ret;
}
}
And this is BullsAndCowsClient.java
//-------------------------
// Multithreaded client program
//-------------------------
import java.net.*;
import java.util.Scanner;
import java.io.*;
public class BullsAndCowsClient
{
public static void main(String args[]) throws IOException
{
//read in command line arguments
final String HOST = (args.length > 0) ? args[0] : "localhost";
final int PORT = (args.length > 1) ? Integer.parseInt(args[1]) : 1337;
try
{
Socket sock = new Socket(HOST, PORT);
Reader reader = new Reader(sock);
Writer writer = new Writer(sock);
while(reader.isAlive() && writer.isAlive() )
{
Thread.sleep(100);
}
//System.out.println("Quitting!");
if(reader.isAlive())
reader.kill();
else if(writer.isAlive())
writer.kill();
} catch (SocketException e)
{
System.out.println("Server not available! Is it running?");
System.out.println("Correct syntax is: java BullsAndCowsClient <hostname> <port>");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
class Writer extends Thread
{
//keep running while 'running' == true
private volatile boolean running = true;
private PrintWriter output;
private Scanner scanner = new Scanner(System.in);
public Writer(Socket sock) throws IOException
{
output = new PrintWriter(new BufferedWriter(new OutputStreamWriter(sock.getOutputStream())),true);
start();
}
public void kill()
{
running = false;
}
public void run()
{
String str;
while(running)
{
str = scanner.nextLine();
if(str.equals("QUIT")) running = false;
output.println(str);
}
output.close();
}
}
class Reader extends Thread
{
//keep running while 'running' == true
private volatile boolean running = true;
private BufferedReader input;
public Reader(Socket sock) throws IOException
{
input = new BufferedReader(new InputStreamReader(sock.getInputStream()));
start();
}
public void kill()
{
running = false;
}
public void run()
{
String str;
while(running)
{
try
{
str = input.readLine();
System.out.println(str);
}
catch (IOException ex)
{
running = false;
}
}
try
{
input.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
Hopefully it all formatted correctly and I'm not using any truly abhorrent programming styles. Look forward to any and all feedback, thanks!