Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Programming Challenge: Noughts and Crosses

Name: Anonymous 2009-08-11 16:23

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: Anonymous 2009-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;
    }
}

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List