My connect four game program works when the GRID_HEIGHT and GRID_WIDTH is the same but my assignment requires the height to be 6 and the width to be 7. It doesn't work when I set it to 6 and 7 however for some reason it works when the width is 7 and the height is 6, though I need the opposite. For this version, the system instantly crashes when an input is entered, though it works perfectly on a square grid. Thanks for any help!
import java.util.Scanner;
public class WrittenStuff
{
public static final int GRID_HEIGHT=7;
public static final int GRID_WIDTH=7;
int totalMovesPlayed;
char[][] board;
public WrittenStuff()
{
board=new char[GRID_HEIGHT][GRID_WIDTH];
totalMovesPlayed=0;
}
public static void main(String args[])
{
Scanner input = new Scanner(System.in);
WrittenStuff c4=new WrittenStuff();
System.out.println("WELCOME TO CONNECT FOUR!!!");
c4.printBoard();
outer:
while(true)
{
int column=0;
//PLAYER 1.
while(true)
{
System.out.print("\n\nPlayer 1 play:");
column = input.nextInt();
column = column-1;
if(c4.isPlayable(column))
{
if(c4.playMove(column, 'X'))
{
c4.printBoard();
System.out.println("\n\nPlayer 1 wins!!!");
break outer;
}
break;
}
else{
System.out.println("Column "+column+" is already full!!");
}
}
c4.printBoard();
//PLAYER 2.
while(true)
{
System.out.print("\n\nPlayer 2 play:");
column = input.nextInt();
column = column-1;
if(c4.isPlayable(column))
{
if(c4.playMove(column, 'O'))
{
c4.printBoard();
System.out.println("\n\nPlayer 2 wins!!!");
break outer;
}
break;
}
else{
System.out.println("Column "+column+" is already full!!");
}
}
c4.printBoard();
if(c4.isFull())
{
System.out.print("Game drawn. Both of you suck at this!!! ");
break;
}
}
}
public void printBoard()
{
for(int vert=0;vert<board.length;vert++)
{
for(int hori=0;hori<board[0].length;hori++)
{
if(board[vert][hori] == 0)
{
System.out.print("|" + "_" + "|");
}
else
{
System.out.print("|" + board[vert][hori] + "|");
}
}
System.out.println();
}
for(int vert=0;vert<GRID_WIDTH;vert++)
System.out.print(" "+(vert+1)+" ");
System.out.println();
}
public boolean playMove(int column, char playerNum)
{
int vert=0;
for(vert=0;vert<GRID_HEIGHT;vert++)
{
if(board[vert][column] == 'X' || board[vert][column] == 'O')
{
board[vert-1][column]=playerNum;
break;
}
}
if(vert == GRID_HEIGHT)
{
board[vert-1][column]=playerNum;
}
totalMovesPlayed++;
return isConnected(vert-1,column);
}
public boolean isPlayable(int column)
{
return board[0][column] == 0;
}
public boolean isFull()
{
return totalMovesPlayed == GRID_HEIGHT*GRID_WIDTH;
}
public boolean isConnected(int x, int y)
{
int num=board[x][y];
int count=0;
int vert=y;
//HORIZONTAL.
while(vert<GRID_WIDTH && board[x][vert] == num)
{
count++; vert++;
}
vert=y-1;
while(vert>=0 && board[x][vert] == num)
{
count++; vert--;
}
if(count == 4){
return true;}
//VERTICAL.
count=0; int hori=x;
while(hori<GRID_HEIGHT && board[hori][y] == num)
{
count++; hori++;
}
if(count == 4){
return true;}
//SECONDARY DIAGONAL.
count=0; vert=x; hori=y;
while(vert<GRID_WIDTH && hori<GRID_HEIGHT && board[vert][hori] == num)
{
count++; vert++; hori++;
}
vert=x-1; hori=y-1;
while(vert>=0 && hori>=0 && board[vert][hori] == num)
{
count++; vert--; hori--;
}
if(count == 4){
return true;}
//LEADING DIAGONAL.
count=0; vert=x; hori=y;
while(vert<GRID_WIDTH && hori>=0 && board[vert][hori] == num)
{
count++; vert++; hori--;
}
vert=x-1; hori=y+1;
while(vert>=0 && hori<GRID_HEIGHT && board[vert][hori] == num)
{
count++; vert--; hori++;
}
if(count == 4){
return true;}
return false;
}
}
Looking at all your uses of board, I find:
board[vert][hori]
board[vert][hori]
board[vert][column]
board[vert][column]
board[vert-1][column]
board[vert-1][column]
board[0][column]
board[x][y]
board[x][vert]
board[x][vert]
board[hori][y]
board[vert][hori]
board[vert][hori]
board[vert][hori]
board[vert][hori]
So, if first dimension is indexed by vert, and second dimension is indexed by hori, why is second dimension variable sometimes named column, not hori? Consistent naming is important for the human understanding of your code, including your own, to prevent coding errors.
But more importantly, what's up with the [x][y], [x][vert], and [hori][y]? Assuming y is equivalent to vert, and that x is equivalent to hori (again, consistent naming, please), aren't those reversed?
I am doing an assignment for school. It is a towers of hanoi assignment. (I didn't add the larger-disk-over-smaller-disk code yet). When I set tower3 as 4, 3, 2, 1, it says I won, but when I do it while playing the game, nothing happens. Please help! This is due Monday 8:30pm EST.
import java.util.Scanner;
/**
* Simulates a tower that can hold disks.
* #author S. Camilleri
* #author <Hasan Zafar>
*/
public class Challenge {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// This array holds the disks. A 0 represents no disk.
int[] tower = {4,3,2,1};
int[] tower2 = {0,0,0,0};
int[] tower3 = {0,0,0,0};
// This index represents the first available empty spot for a disk.
int index = 0;
int towerCounter = 0;
int length = tower.length;
int length2 = tower2.length;
int length3 = tower3.length;
int diskChoice = 1;
int i;
int held = 0;
int placeChoice;
boolean playing = true;
while (playing)
{
//Check if Won
if (tower3[0] == 4 && tower3[1] == 3 && tower3[2] == 2 && tower[3] == 1) {
System.out.println("Congratulations! You win!");
playing = false;
break;
}
/********************
* Display the towers
********************/
System.out.println();
//Tower1
System.out.print("{ ");
for (int x=0; x<length; x++)
{
System.out.print(tower[x]);
}
System.out.println();
//Tower2
System.out.print("{ ");
towerCounter = 0;
for (int x=0; x<length2; x++)
{
System.out.print(tower2[x]);
}
System.out.println();
//Tower3
System.out.print("{ ");
towerCounter = 0;
for (int x=0; x<length3; x++)
{
System.out.print(tower3[x]);
}
/********************
* Select the highest disk from the tower
********************/
System.out.println();
System.out.println("Pick a tower (The disk highest on that tower will be chosen)");
diskChoice = input.nextInt();
// If user uses the first tower
if (diskChoice == 1) {
i = 3;
while (tower[i] == 0) {
i--;
}
held = tower[i];
tower[i] = 0;
} else if (diskChoice == 2) { // If user uses the second tower
i = 3;
while (tower2[i] == 0) {
i--;
}
held = tower2[i];
tower2[i] = 0;
} else if (diskChoice == 3) { // If user uses the third tower
i = 3;
while (tower3[i] == 0) {
i--;
}
held = tower3[i];
tower3[i] = 0;
}
/********************
* Place the disk
********************/
System.out.println("Where would you like to place" + " " + held + "?");
placeChoice = input.nextInt();
if (placeChoice == 1) {
i = 3;
if (tower[3] == 0){
while (tower[i] == 0) {
i--;
if (i == 0) {
break;
}
}
}
if (tower[i] == 0) {
tower[i] = held;
} else if (tower[i] != 0) {
tower[i+1] = held;
}
} else if (placeChoice == 2) {
i = 3;
if (tower2[3] == 0){
while (tower2[i] == 0) {
i--;
if (i == 0) {
break;
}
}
}
if (tower2[i] == 0) {
tower2[i] = held;
} else if (tower2[i] != 0) {
tower2[i+1] = held;
}
} else if (placeChoice == 3) {
i = 3;
if (tower3[3] == 0){
while (tower3[i] == 0) {
i--;
if (i == 0) {
break;
}
}
}
if (tower3[i] == 0) {
tower3[i] = held;
} else if (tower3[i] != 0) {
tower3[i+1] = held;
}
}
}
}
}
If I set tower3 as 4321 manually, it says I won.
If I set tower3 as 4321 in-game, it just keeps playing.
I figured it out. I forgot to write the 3 at the of win statement.
I am currently implementing Eight Puzzle problem using A* Algorithm (Hamming) method and have provided code :
public class Board
{
int board[][];
public Board()
{
board = new int[3][3];
}
public void initialise(int n1, int n2, int n3, int n4, int n5, int n6, int n7, int n8, int n9)
{
//first row
board[0][0] = n1;
board[0][1] = n2;
board[0][2] = n3;
//second row
board[1][0] = n4;
board[1][1] = n5;
board[1][2] = n6;
//third row
board[2][0] = n7;
board[2][1] = n8;
board[2][2] = n9;
}
public int states_out_of_order()
{
int count = 0;
for(int i = 0; i < 3; i++)
{
//Checking if first row is
//1 2 3
if(i==0)
{
if(board[i][0]!=1)
{
count++;
}
if(board[i][1]!=2)
{
count++;
}
if(board[i][2]!=3)
{
count++;
}
}
//Checking if second row is
//4 5 6
if(i==1)
{
if(board[i][0]!=4)
{
count++;
}
if(board[i][1]!=5)
{
count++;
}
if(board[i][2]!=6)
{
count++;
}
}
//Checking if second row is
//7 8 0
if(i==2)
{
if(board[i][0]!=7)
{
count++;
}
if(board[i][1]!=8)
{
count++;
}
if(board[i][2]!=9)
{
count++;
}
}
}
return count;
}
public boolean GoalStateCheck()
{
//Checking first row
if(board[0][0]!=1)
{
return false;
}
if(board[0][1]!=2)
{
return false;
}
if(board[0][2]!=3)
{
return false;
}
//Checking second row
if(board[1][0]!=4)
{
return false;
}
if(board[1][1]!=5)
{
return false;
}
if(board[1][2]!=6)
{
return false;
}
//Checking third row
if(board[2][0]!=7)
{
return false;
}
if(board[2][1]!=8)
{
return false;
}
if(board[2][2]!=0)
{
return false;
}
return true;
}
public void printBoard()
{
System.out.print(board[0][0] + " " + board[0][1] + " " + board[0][2]);
System.out.println();
System.out.print(board[1][0] + " " + board[1][1] + " " + board[1][2]);
System.out.println();
System.out.print(board[2][0] + " " + board[2][1] + " " + board[2][2]);
System.out.println();
}
}
And now the solver class
import java.util.ArrayList;
public class Solver
{
ArrayList<Board> list;
int steps;
public Solver()
{
list = new ArrayList<Board>();
steps = 0;
}
public Board SwapStates(Board b, int a[][], int r1, int c1, int r2, int c2)
{
int temp = a[r1][c1];
a[r1][c1] = a[r2][c2];
a[r2][c2] = temp;
return b;
}
//Find the board in ArrayList according the number of states out of order
public Board findBoard(int num)
{
for(int i = 0; i < list.size(); i++)
{
if(num == list.get(i).states_out_of_order())
{
return list.get(i);
}
}
return null;
}
//Choose the puzzle state with minimum states that are out of order
public int min()
{
int n = 10;
for(int i = 0; i < list.size(); i++)
{
if(list.get(i).states_out_of_order() < n)
{
n = list.get(i).states_out_of_order();
}
}
return n;
}
//Find the board in ArrayList and remove it
public void matchRemove(Board b)
{
for(int i = 0; i < list.size(); i++)
{
if(b == list.get(i))
{
list.remove(list.get(i));
break;
}
}
}
public void Hamming(Board b)
{
boolean solved = b.GoalStateCheck();
while(!solved)
{
if(b.board[0][0] == 0)
{
//Pointer to original board
final Board ptr = b;
Board b1 = ptr;
Board b2 = ptr;
//Check move #1 from original state
b1 = SwapStates(b1, b1.board,0,0,0,1);
//Check move #2 from original state
//Problem is that it is not swapping ptr but rather its swapping b1. why?
b2 = SwapStates(b2, b2.board,0,0,1,0);
//Add the moves to the Arraylist
list.add(b1);
list.add(b2);
//Find the board with minimum number of states out of order and remove it frm list
int n = min();
Board temp = findBoard(n);
matchRemove(temp);
//Assign removed board as optimum move
b = temp;
steps++;
b.printBoard();
}
else if(b.board[0][1] == 0)
{
}
else if(b.board[0][2] == 0)
{
}
else if(b.board[1][0] == 0)
{
}
else if(b.board[1][1] == 0)
{
}
else if(b.board[1][2] == 0)
{
}
else if(b.board[2][0] == 0)
{
}
else if(b.board[2][1] == 0)
{
}
else if(b.board[2][2] == 0)
{
}
else
{
System.out.println("Board is not in its proper form");
break;
}
}
/*System.out.println("Goal State has been achieved!!");
System.out.println("It took " + steps + " moves");
b.printBoard();*/
}
}
In the Hamming function of my Solver class at the first if statement i have this line
final Board ptr = b;
Board b1 = ptr;
Board b2 = ptr;
However when at these two lines:
//Check move #1 from original state
b1 = SwapStates(b1, b1.board,0,0,0,1);
//Check move #2 from original state
//Problem is that it is not swapping ptr but rather its swapping b1. why?
b2 = SwapStates(b2, b2.board,0,0,1,0);
b2 is using the swapped state of b1 instead of the original ptr which i want to use. why?
When you've written
final Board ptr = b;
Board b1 = ptr;
Board b2 = ptr;
You did not create an immutable copy of b called ptr and two mutable copies of ptr called b1 and b2.
You simply created 3 references to the same object. Any modification on the object using any of the 4 references will end up affecting the object in the same way and thus, change the visible state for all 4 references.
What you should do is add a public Board copy() method in your board class which would return another instance of Board (using a new Board() and copying values) and change your code by :
final Board ptr = b.copy(); // but is there any sense to use ptr rather than b ?
Board b1 = ptr.copy();
Board b2 = ptr.copy();
I'm building a program to play Connect Four. I have all my methods done and I'm just building my main method up to actually play the game. Is there a more efficient way to use my Play class than manually inputting the code the way I am? I was fine with doing this until I realized that I don't know how to find a winner doing it this way. Is there a loop I can use that'll properly go through my methods and make the main class tidier and more efficient?
Here is my code:
import java.util.Scanner;
public class Play {
public static void main(String[]args){
Scanner keyboard = new Scanner(System.in);
System.out.print("Welcome to Connect 4. Please enter your names. \nPlayer 1 Name: ");
String name1 = keyboard.nextLine();
System.out.print("Player 2 Name: ");
String name2 = keyboard.nextLine();
System.out.println(name1 + " - you have red chips \"R\" and you go first.");
Connect4Board game = new Connect4Board(6,7);
System.out.print(game);
System.out.println("Enter a column between 1-7: ");
int column = keyboard.nextInt();
game.add(column, "R");
System.out.print(game);
System.out.print(name2 + " - you have yellow chips \"Y\" and you go next.");
System.out.println("Enter a column between 1-7: ");
column = keyboard.nextInt();
game.add(column, "Y");
System.out.print(game);
}
}
class Chip { //Chip class determines the color of the chip
//Instance Variables
private String colour;
public Chip (String c) { //Constructor
colour = c;
}
public String getColour(){ //Get Method
return colour;
}
public void setColour(String c){ //Set Method
c = colour;
}
public boolean equals(Chip c){ //Checks if two colors are the same
return this.colour == c.getColour();
}
public String toString(){ //Converts to String
return colour;
}
}
class Board { //Creates a board with x rows and x columns.
//Instance Variables
private int rows;
private int cols;
public Board (int r, int c){ //Constructor
rows = r;
cols = c;
}
public int getRows(){ //Get Methods
return rows;
}
public int getCols(){
return cols;
}
public void setRows(int r){ //Set Methods
r = rows;
}
public void setCols(int c){
c = cols;
}
}
class Connect4Board extends Board {
//Instance Variable
private Chip [][] board;
private String colourOfWin = "";
public Connect4Board(int r, int c){
super(r, c);
board = new Chip[r][c];
}
public Chip[][] getBoard(){
return board;
}
public void setBoard(int r,int c){
setRows(r);
setCols(c);
}
public boolean add(int cols, String colour){
boolean result = true;
int counter = 0;
boolean testPlacement = false;
if(cols>=0 && cols<=6){
}
else
result = false;
if (board[5][cols] != null)
result = false;
for(int row = 5; row >= 0 && testPlacement == false; row--){
if(board[row][cols]==null){
counter += 1;
}
else
testPlacement = true;
}
if(result == true){
board[6-counter][cols] = new Chip(colour);
//
}
return result;
}
public String winType(){
String result;
if(rowWinner()){
result = "Row Winner";
}
else if(columnWinner()){
result = "Column Winner";
}
else if(rightDiagonalWinner() || leftDiagonalWinner()){
result = "Diagonal Winner";
}
else{
result = "No winner yet.";
}
return result;
}
public boolean rowWinner(){
boolean result = false;
boolean result1 = true; //Test the equals to see if true
for(int row=0; row<6 && result == false; row++){ //Nested for loops to proccess array. Row
for(int cols=0; cols<4 && result == false; cols++){ //Column
for(int win=0; win<4; win++){ //Check win
if(board[row][cols] != null && board[row][cols+win] != null){
if(board[row][cols+win].equals(board[row][cols])&& result1 == true ){ //result1 tests to see if the equals is true
}
else
result1 = false;
}
else
result1 = false;
}
if(result == true)
colourOfWin = board[row][cols].getColour();
result = result1;
}
}
return result;
}
public boolean columnWinner(){
boolean result = false;
boolean result1 = true; //Test the equals to see if true
for(int row=0; row<3 && result == false; row++){ //Nested for loops to proccess array. Row
for(int cols=0; cols<7 && result == false; cols++){ //Column
for(int win=0; win<4; win++){ //Check win
if(board[row][cols] != null && board[row+win][cols] != null){
if(board[row+win][cols].equals(board[row][cols])&& result1 == true ){ //result1 tests to see if the equals is true
}
else
result1 = false;
}
else
result1 = false;
}
if(result == true)
colourOfWin = board[row][cols].getColour();
result = result1;
}
}
return result;
}
public boolean rightDiagonalWinner(){
boolean result = false;
boolean result1 = true; //Test the equals to see if true
for(int row=0; row<3 && result == false; row++){ //Nested for loops to proccess array. Row
for(int cols=0; cols<4 && result == false; cols++){ //Column
for(int win=0; win<4; win++){ //Check win
if(board[row][cols] != null && board[row+win][cols+win] != null){
if(board[row+win][cols+win].equals(board[row][cols])&& result1 == true ){ //result1 tests to see if the equals is true
}
else
result1 = false;
}
else
result1 = false;
}
if(result == true)
colourOfWin = board[row][cols].getColour();
result = result1;
}
}
return result;
}
public boolean leftDiagonalWinner(){
boolean result = false;
boolean result1 = true; //Test the equals to see if true
for(int row=0; row<3 && result == false; row++){ //Nested for loops to proccess array. Row
for(int cols=6; cols<2 && result == false; cols--){ //Column
for(int win=0; win<4; win++){ //Check win
if(board[row][cols] != null && board[row+win][cols-win] != null){
if(board[row+win][cols-win].equals(board[row][cols])&& result1 == true ){ //result1 tests to see if the equals is true
}
else
result1 = false;
}
else
result1 = false;
}
if(result == true)
colourOfWin = board[row][cols].getColour();
result = result1;
}
}
return result;
}
public boolean winner(){
return rowWinner() || columnWinner() || rightDiagonalWinner() || leftDiagonalWinner();
}
public String toString(){
String b;
b="\tCol.\n";
for (int j=0;j<7;j++){
b=b+"\t"+(j+1);
}
b=b+"\n";
for (int i=0;i<6;i++){
b=b+(i+1)+"\t";
for(int j=0;j<7;j++){
if(board[5-i][j]==null){
b=b+" \t";
}
else{
b=b+board[5-i][j].getColour()+"\t";
}
}
b=b+"\n\n";
}
return b;
}
}
I am trying to recursively populate a tree, but my code is only only fill out one depth length, and then quiting. i.e. each node only has one child. Is there something am failing to take in to consideration?
public static void populate(Node n, int depth, String player){
System.out.println("Depth: " + depth);
if(player.equalsIgnoreCase("X"))
player = "O";
else
player = "X";
int j = 0;
System.out.println("empty spots: " + ((Board)n.getData()).noOfEmpty());
for(int i=0; i<((Board)n.getData()).noOfEmpty(); i++){
if(((Board)n.getData()).getSquare(j).equalsIgnoreCase("X")
|| ((Board)n.getData()).getSquare(j).equalsIgnoreCase("O"))
j++;
else{
Board tmp = new Board(((Board)n.getData()), j, player);
Node newNode = new Node(tmp);
tree.insert(n, newNode);
populate(newNode, depth-1, player);
}
}
}
P.S. and i check the noOfEmpty() return value, which should determine the number of children a node should have.
edit:#eznme the complete code as requested:
public class MinMax {
protected static Tree tree;
public static void createTree(Board b){
tree = new Tree();
tree.setRoot(new Node(b));
populate(tree.getRoot(), 5, "X");
//System.out.println("printing tree");
//tree.print(1);
}
public static void populate(Node n, int depth, String player){
System.out.println("Depth: " + depth);
if(player.equalsIgnoreCase("X"))
player = "O";
else
player = "X";
int j = 0;
System.out.println("empty spots: " + ((Board)n.getData()).noOfEmpty());
for(int i=0; i<((Board)n.getData()).noOfEmpty(); i++){
if(((Board)n.getData()).getSquare(j).equalsIgnoreCase("X")
|| ((Board)n.getData()).getSquare(j).equalsIgnoreCase("O"))
j++;
else{
Board tmp = new Board(((Board)n.getData()), j, player);
Node newNode = new Node(tmp);
tree.insert(n, newNode);
populate(newNode, depth-1, player);
}
}
}
}
import java.util.ArrayList;
/**
*
* #author Greg
*/
public class Node {
protected Object data;
protected int score; //fields to be used by the MaxMin class
protected ArrayList<Node> children;
//constructors
public Node(){
children = new ArrayList(0);
data = null;
}
public Node(Object obj){
children = new ArrayList(0);
data = obj;
}
public void setChild(Node n){
//EFFECT: set the ith child to node t
children.add(n);
}
public void setChildren(Node[] t){
//EFFECT: copy the array t, into the array children, effectively
// setting all the chidern of this node simultaneouly
int l = children.size();
for(int i=0; i<t.length; i++){
children.add(l, t[i]);
}
}
public void setData(Object obj){
//EFFECT: set the date of this node to obj, and also set the number of
// children this node has
data = obj;
}
public Node getChild(int i){
//EFFECT: returns the child at index i
return children.get(i);
}
public int noOfChildren(){
//EFFECT: return the length of this node
return children.size();
}
public Object getData(){
//EFFECT: returns the data of this node
return data;
}
#Override
public String toString(){
//EFFECT: returns the string form of this node
return "" + data.toString() + "\nwith " + noOfChildren()+ "\n";
}
public boolean isLeaf(){
if(children.size()==0)
return true;
return false;
}
public void setScore(int scr){
score = scr;
}
public int getScore(){
return score;
}
}
public class Tree {
private Node root;
public Tree(){
setRoot(null);
}
public Tree(Node n){
setRoot(n);
}
public Tree(Object obj){
setRoot(new Node(obj));
}
protected Node getRoot(){
return root;
}
protected void setRoot(Node n){
root = n;
}
public boolean isEmpty(){
return getRoot() == null;
}
public Object getData(){
if(!isEmpty())
return getRoot().getData();
return null;
}
public Object getChild(int i){
return root.getChild(i);
}
public void setData(Object obj){
if(!isEmpty())
getRoot().setData(obj);
}
public void insert(Node p,Node c){
if(p != null)
p.setChild(c);
}
public void print(int mode){
if(mode == 1) pretrav();
else if(mode == 2) postrav();
else
System.out.println("yeah... mode 1 or 2...nothing else, try agn");
}
public void pretrav(){
pretrav(getRoot());
}
protected void pretrav(Node t){
if(t == null)
return;
System.out.println(t.getData()+" \n");
for(int i=0; i<t.noOfChildren(); i++)
pretrav(t.getChild(i));
}
public void postrav(){
postrav(getRoot());
}
protected void postrav(Node t){
if(t == null)
return;
System.out.print(t.getData()+" ");
for(int i=0; i<t.noOfChildren(); i++)
pretrav(t.getChild(i));
System.out.print(t.getData()+" ");
}
}
public class Board {
boolean isFull = false; // a check to see if the board is full
String[] grid = new String[9]; //an array represting the 9 square on a board
int hV;
String MIN, MAX;
public Board(){
for(int i=0; i<grid.length;i++)
grid[i] = Integer.toString(i);
hV = heuristicValue(this);
}
public Board(Board b, int x, String player){
this.grid = b.getBoard();
if(!(grid[x].equalsIgnoreCase("X")|| grid[x].equalsIgnoreCase("X")))
grid[x] = player;
}
public boolean setSquare(String player, int position){
/*
EFFECT:set a square on the board to either a X or a O, debending on the player
PRECON: square (x,y) is empty
POATCON: square (x,y) has player 'symbol'
*/
boolean isValidPlay = false;
try{
//as a sanity
Integer.parseInt(grid[position]);
grid[position] = player;
isValidPlay = true;
}catch(NumberFormatException e){
System.out.println("positon " + position + "is already occupied");
}
return isValidPlay;
}
public boolean endGame(){
/*
* EFFECT: check to see if the game have been won or drawn
*/
if(ticTacToe(0,1,2)){
//System.out.println("Player " + grid[0] + " wins");
return true;
}
else if(ticTacToe(3,4,5)){
//System.out.println("Player " + grid[3] + " wins");
return true;
}
else if(ticTacToe(6,7,8)){
//System.out.println("Player " + grid[6] + " wins");
return true;
}
else if(ticTacToe(0,4,8)){
//System.out.println("Player " + grid[0]+ " wins");
return true;
}
else if(ticTacToe(0,3,6)){
//System.out.println("Player " + grid[0]+ " wins");
return true;
}
else if(ticTacToe(1,4,7)){
//System.out.println("Player " + grid[1] + " wins");
return true;
}
else if(ticTacToe(2,5,8)){
//System.out.println("Player " + grid[2] + " wins");
return true;
}else if(ticTacToe(2,4,6)){
//System.out.println("Player " + grid[2] + " wins");
return true;
}
else
return isDrawn();
}
public boolean ticTacToe(int x, int y, int z){
/*
* check is x, y and z has the same value
*/
try{
Integer.parseInt(grid[x]);
return false;
}catch(NumberFormatException e){
if( grid[x].equals(grid[y])
&& grid[x].equals(grid[z]))
return true;
else
return false;
}
}
public String getSquare(int i){
return grid[i];
}
#Override
public String toString(){
String msg = "";
for(int i=0; i<grid.length; i++){
msg = msg + grid[i] + " ";
if(i==2 || i==5)
msg = msg+ "\n";
}
return msg;
}
public boolean isDrawn(){
/*
* check to see if there are any 'free' spaces on the board, if there are any
* return false, else return true
*/
for(int i=0; i<grid.length; i++){
try{
Integer.parseInt(grid[i]);
return false;
}catch(NumberFormatException e){
}
}
System.out.println("Game drawn");
return true;
}
public String[] getBoard(){
return grid;
}
public int noOfEmpty(){
//EFFECT: returns the number of empty squares
int count = 0;
for(int i=0; i<grid.length; i++)
if (!(grid[i].equalsIgnoreCase("X") || grid[i].equalsIgnoreCase("O")))
count++;
return count;
}
public int heuristicValue(Board b){
String MAX = "X", MIN = "O";
/*
* calculate a value that will be used as a heuristic function
* the function works for ever X in a row WITHOUT O: 1 point,
* for two X in a row WITHOUT a O: 5 points
* and 3 X in a row: 100 points
*/
//System.out.println("Computing heuristic");
//System.out.println("Computing horizontals");
int hCount = 0;
//sum up the horizontals
for(int i=0; i<9; i=i+3){
int tmpMAX = playerCount(b, MAX,i,i+1,i+2);
int tmpMIN = playerCount(b, MIN,i,i+1,i+2);
//System.out.println(tmpMAX);
//System.out.println(tmpMIN);
if(tmpMIN > 0){
//System.out.println("Min was zero");
}
else if(tmpMAX==1){
//System.out.println("has one");
hCount = hCount + 1;
}
else if(tmpMAX==2){
//System.out.println("was tw0");
hCount = hCount + 5;
}
else if(tmpMAX==3){
//System.out.println("full 100");
hCount = hCount + 100;
}
}
//System.out.println("Computing verticals");
//sum up the verticals
for(int i=0; i<3; i++){
int tmpMAX = playerCount(b, MAX,i,i+3,i+6);
int tmpMIN = playerCount(b, MIN,i,i+3,i+6);
if(tmpMIN > 0){}
else if(tmpMAX==1){
hCount = hCount +1;
}
else if(tmpMAX==2){
hCount = hCount + 5;
}
else if(tmpMAX==3){
hCount = hCount + 100;
}
}
//System.out.println("Computing diagonals");
//sum up diagonals
if(playerCount(b, MIN,0,4,8)==0){
if(playerCount(b, MAX,0,4,8)==1){
hCount = hCount + 1;
}
if(playerCount(b, MAX,0,4,8)==2)
hCount = hCount + 5;
if(playerCount(b, MAX,0,4,8)==3)
hCount = hCount + 100;
}
if(playerCount(b, MIN,2,4,6)==0){
if(playerCount(b, MAX,2,4,6)==1){
hCount = hCount + 1;
}
if(playerCount(b, MAX,2,4,6)==2)
hCount = hCount + 5;
if(playerCount(b, MAX,2,4,6)==3)
hCount = hCount + 100;
}
//System.out.println("Computing completed");
int hV = hCount;
return hV;
}
int playerCount(Board b, String player, int x, int y, int z){
int count = 0;
if(b.getSquare(x).equals(player))
count = count + 1;
if(b.getSquare(y).equals(player))
count = count + 1;
if(b.getSquare(z).equals(player))
count = count + 1;
//System.out.println("playerCount; " + count);
return count;
}
}
import java.io.*;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException{
BufferedReader reader = new BufferedReader(new
InputStreamReader(System.in));
Board thisGame = new Board();
System.out.println("Start \n" + thisGame.toString());
MinMax.createTree(thisGame);
System.exit(0);
}
}
In order to recursively build a n-ary tree, I would do this:
public static void populate(Node n, int height){
if(height = 0){
n = new Node();
}else{
n = new Node();
for(int i = 0; i < n.nbChilds(); i++){
populate(n.getChildAt(i), height - 1);
}
}
}
I hope it helps.
Order of nodes creation with this algo (on a binary tree):
1
2 9
3 6 10 13
4 5 7 8 11 12 14 15
So here is what I would do in your case (minimax tic-tac-toe):
Terminology:
Height of a node: Distance from this node to it's further leaf.
Depth of a node: Distance from the root of the tree, to this node.
You have to keep trying all cases until: the board is full OR one player won. So, your tree's height is numberOfCells + 1.
If we simplify the problem and don't worry about symmetric duplicates:
Each node will have numberOfcells - nodeDepth childs.
public static void main(String[] args){
Tree t = new Tree();
int nbCells = 9;
t.setRoot(buildTree(new Board(nbCells), 0, -1));
}
public static Node buildTree(Board b, int player, int positionToPlay){
if(player != 0){
b.setCellAt(positionToPlay, player);
}
Node n = new Node(b, b.nbEmptyCells());
int j = 0;
for(int i = 0; i < b.nbCells(); i++){
if(b.getCellAt(i) == 0)
n.setChildAt(j++, buildTree(new Board(b), changePlayer(player), i));
}
return n;
}
public static int changePlayer(int p){
switch(p){
case 0:
return 1;
case 1:
return 2;
case 2:
return 1;
default:
return 0;
}
}
Node class:
public class Node {
private Board board;
private Node[] childs;
public Node(Board b, int nbChilds){
this.board = new Board(b);
this.childs = new Node[nbChilds];
}
public Node getChildAt(int i){
return childs[i];
}
public int nbChilds(){
return childs.length;
}
public void setChildAt(int i, Node n){
this.childs[i] = n;
}
public Board getBoard(){
return this.board;
}
I think you got a wrong approach.
First of all, you're doing a loop and recursion, besides using a depth variable that has no meaning since you never check it's value either to end the recursion, or to know something about what you want to do.
The use a a dynamic function within the loop itself is not quite good, since the iteration should be well defined from the beginning of the loop.
i is just useless in your context.
So if I understand your code, a problematic case would be a case where there is 3 empty squares and 4 non empty squares since you would iterate i from 0 to 3 and do nothing but incrementing j from 0 to 3 then exit because i would have reach 3.
Of course I may be mistaken on some points because I don't know what tree is, from where did it come from? is it related to n? What is a board.
I hope my contribution can help you and I encourage you to post more details to clarify the holes and enable me to help you a bit more.