I just got finished with my first program (that is, the first one I haven't just copied out of a book). It's a text based version of Noughts and Crosses (aka Tic-tac-toe) without an AI, and it looks pretty ugly to me. Commenting is half-assed, some variables are given nondescript names, and I can tell that my loop structure can use a little work. Still, it runs.
Show me up, /prog/. Write a more elegant version in the language of your choice. Surely it's not a difficult task for [o][u]EXPERT PROGRAMMERS[/o][/u] such as yourselves. If you've got any suggestions for me, those would be nice, too.
Name:
Anonymous2009-08-12 6:01
import java.util.Scanner;
import java.io.BufferedInputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Random;
public class NC {
private static final BigInteger WIDTH = BigInteger.valueOf(10);
private static final BigInteger HEIGHT = BigInteger.valueOf(10);
private static final BigInteger WINS = BigInteger.valueOf(3);
private static final BigInteger PLAYERS = BigInteger.valueOf(2);
public static Scanner sc;
public static void main(String[] args) {
BigInteger i;
sc = new Scanner(new BufferedInputStream(System.in));
ArrayList<Player> players = new ArrayList<Player>();
for(i = BigInteger.ZERO; i.compareTo(PLAYERS) < 0; i = i.add(BigInteger.ONE)) {
System.out.print("Please enter the name of player "+EnglishCounter.bigIntToEnglish(i.add(BigInteger.ONE)).trim()+": ");
players.add(new Player(sc.nextLine(), i));
}
Board b = new Board(players, WIDTH, HEIGHT, WINS);
}
}
class Board {
private BigInteger width, height, wins, moveCount;
private ArrayList<Player> players;
private ArrayList<ArrayList<Square>> squares;
private Player firstToMove;
public Board(ArrayList<Player> players, BigInteger width, BigInteger height, BigInteger wins) {
this.width = width;
this.height = height;
this.wins = wins;
this.players = players;
this.firstToMove = players.get(new Random().nextInt(players.size()));
this.moveCount = BigInteger.ZERO;
this.squares = new ArrayList<ArrayList<Square>>();
for(BigInteger i = BigInteger.ZERO; i.compareTo(width) < 0; i = i.add(BigInteger.ONE)) {
ArrayList<Square> temp = new ArrayList<Square>();
for(BigInteger j = BigInteger.ZERO; j.compareTo(height) < 0; j = j.add(BigInteger.ONE)) {
temp.add(new Square());
}
this.squares.add(temp);
}
playGame();
}
private void playGame() {
boolean moved;
drawBoard();
mainLoop:
for(;;) {
moved = false;
for(BigInteger i = BigInteger.valueOf(players.indexOf(firstToMove)); !i.equals(BigInteger.valueOf(players.indexOf(firstToMove))) || !moved;
i = i.add(BigInteger.ONE).mod(BigInteger.valueOf(players.size()))) {
moved = true;
doMove(players.get(i.intValue())); /* Narrowing conversion: TODO, reimplement java memory allocator to use a biginteger addressing scheme */
drawBoard();
if(checkWinner()) {
System.out.println("We have a winner!");
System.out.println("Congratulations: "+players.get(i.intValue()).getName());
break mainLoop;
}
else if(checkDraw()) {
System.out.println("It's a draw :(");
break mainLoop;
}
}
}
}
private boolean checkWinner() {
return checkheight() || checkwidth() || checkDiagDown() || checkDiagUp();
}
private boolean checkDraw() {
return moveCount.compareTo(width.multiply(height)) >= 0;
}
private boolean matchPlayers(ArrayList<Player> players) {
if(players.size() == 0) return false;
Player lastPlayer = players.get(0);
BigInteger count = BigInteger.ONE;
for(BigInteger i = BigInteger.ONE; i.compareTo(BigInteger.valueOf(players.size())) < 0; i = i.add(BigInteger.ONE)) {
Player current = players.get(i.intValue());
if(lastPlayer != null && lastPlayer.equals(current)) {
count = count.add(BigInteger.ONE);
if(count.equals(wins)) return true;
}
else {
lastPlayer = current;
count = current == null ? BigInteger.ZERO : BigInteger.ONE;
}
}
return false;
}
private boolean checkheight() {
ArrayList<Player> players = new ArrayList<Player>();
for(BigInteger i = BigInteger.ZERO; i.compareTo(height) < 0; i = i.add(BigInteger.ONE)) {
for(BigInteger j = BigInteger.ZERO; j.compareTo(width) < 0; j = j.add(BigInteger.ONE)) {
players.add(this.squares.get(i.intValue()).get(j.intValue()).getOwner());
}
if(matchPlayers(players)) return true;
players = new ArrayList<Player>();
}
return false;
}
private boolean checkwidth() {
ArrayList<Player> players = new ArrayList<Player>();
for(BigInteger i = BigInteger.ZERO; i.compareTo(height) < 0; i = i.add(BigInteger.ONE)) {
for(BigInteger j = BigInteger.ZERO; j.compareTo(width) < 0; j = j.add(BigInteger.ONE)) {
players.add(this.squares.get(j.intValue()).get(i.intValue()).getOwner());
}
if(matchPlayers(players)) return true;
players = new ArrayList<Player>();
}
return false;
}
private boolean checkDiagDown() {
for(BigInteger k = wins.subtract(BigInteger.ONE); k.compareTo(height.add(width).subtract(wins)) < 0; k = k.add(BigInteger.ONE)) {
BigInteger max = ((k.compareTo(width)>=0 && k.compareTo(height)<=0) ||
(width.subtract(BigInteger.ONE).subtract(k).compareTo(BigInteger.ZERO)<0) ?
height.subtract(BigInteger.ONE).subtract(k).add(width).subtract(BigInteger.ONE) : height.subtract(BigInteger.ONE));
BigInteger start = k.compareTo(height) >= 0 ? BigInteger.ZERO : height.subtract(BigInteger.ONE).subtract(k);
ArrayList<Player> players = new ArrayList<Player>();
for(BigInteger i = start; i.compareTo(max) <= 0; i = i.add(BigInteger.ONE)) {
BigInteger j = i.subtract(height.subtract(BigInteger.ONE).subtract(k));
players.add(this.squares.get(i.intValue()).get(j.intValue()).getOwner());
}
if(matchPlayers(players)) return true;
}
return false;
}
private boolean checkDiagUp() {
for(BigInteger k = wins.subtract(BigInteger.ONE); k.compareTo(height.add(width).subtract(wins).subtract(BigInteger.valueOf(2)))<=0; k = k.add(BigInteger.ONE)) {
BigInteger start = k.compareTo(height)>=0 ? height.subtract(BigInteger.ONE) : k;
BigInteger min = ((k.compareTo(width)>=0 && k.compareTo(height)<=0) || k.subtract(width.subtract(BigInteger.ONE)).compareTo(BigInteger.ZERO)>0) ?
k.subtract(width.subtract(BigInteger.ONE)) : BigInteger.ZERO;
ArrayList<Player> players = new ArrayList<Player>();
for(BigInteger i = start; i.compareTo(min)>=0; i = i.subtract(BigInteger.ONE)) {
BigInteger j = k.subtract(i);
players.add(this.squares.get(i.intValue()).get(j.intValue()).getOwner());
}
if(matchPlayers(players)) return true;
}
return false;
}
private void doMove(Player p) {
System.out.println(p.getName()+", it is your turn! Please enter a number to move: ");
BigInteger move;
for(;;) {
try {
move = new BigInteger(NC.sc.nextLine());
}
catch(NumberFormatException e) {
System.out.println("You must enter a valid number!");
continue;
}
if(move.compareTo(BigInteger.ZERO) < 0 || move.compareTo(width.multiply(height)) >= 0) {
System.out.println("You must enter a valid number!");
continue;
}
Square sq = squares.get(move.remainder(width).intValue()).get(move.divide(width).intValue());
if(sq.getOwner() != null) {
System.out.println(sq.getOwner().getName()+" has already moved in that square!");
continue;
}
else {
sq.setOwner(p);
moveCount = moveCount.add(BigInteger.ONE);
break;
}
}
}
private void drawBoard() {
System.out.println();
BigInteger length = Player.getMaxSymbolLength().compareTo(BigInteger.valueOf(width.multiply(height).subtract(BigInteger.ONE).toString().length())) < 0 ?
BigInteger.valueOf(width.multiply(height).subtract(BigInteger.ONE).toString().length()) : Player.getMaxSymbolLength();
String seperator = "";
for(BigInteger i = BigInteger.ZERO; i.compareTo(width) < 0; i = i.add(BigInteger.ONE)) {
if(!i.equals(BigInteger.ZERO)) seperator += "+";
for(BigInteger j = BigInteger.ZERO; j.compareTo(length.add(BigInteger.valueOf(2))) < 0; j = j.add(BigInteger.ONE)) {
seperator += "-";
}
}
for(BigInteger i = BigInteger.ZERO; i.compareTo(height) < 0; i = i.add(BigInteger.ONE)) {
if(!i.equals(BigInteger.ZERO)) System.out.println(seperator);
for(BigInteger j = BigInteger.ZERO; j.compareTo(width) < 0; j = j.add(BigInteger.ONE)) {
if(!j.equals(BigInteger.ZERO)) System.out.print("|");
Player owner = squares.get(j.intValue()).get(i.intValue()).getOwner();
BigInteger difference = length.subtract(BigInteger.valueOf(owner == null ? width.multiply(i).add(j).toString().length() : owner.getSymbol().length()));
String padding = "";
for(BigInteger k = BigInteger.ZERO; k.compareTo(difference.divide(BigInteger.valueOf(2))) < 0; k = k.add(BigInteger.ONE)) {
padding += " ";
}
System.out.print(" "+padding+(difference.mod(BigInteger.valueOf(2)).equals(BigInteger.ONE)?" ":""));
System.out.print(owner == null ? i.multiply(width).add(j).toString() : owner.getSymbol());
System.out.print(padding+" ");
}
System.out.println();
}
System.out.println();
}
}
class Square {
private Player owner;
public Square() {
this.owner = null;
}
public Player getOwner() {
return owner;
}
public void setOwner(Player o) {
owner = o;
}
}