Peg Solitaire can't always find a path - java

I develope a software that should solve some types of Peg Solitaire and print the steps to solve it like that:
[3,3,"^"],[4,5,"<"]
I'm using a Backtracking algorithm and most of times(not always) it's work on the "original" board, the france one and another one that is 5x6, but when i try to solve a new one that look like that:
XXXXXXXXX
XXXXXXXXX
XX     XX
XX     XX
XXXXXXXXX
XXXXXXXXX
the program can't find the answer, I try some basic board and this work but after 3 or 4 steps the program can't find the path.
I Try to debbug the code but can't find why he can't find the path
my PegSolver:
package com.company;
public class PegSolver {
public int peg=0;
String answer[];
public boolean superLevel=false;
public void start(){
boolean makefrance=false;
boolean lastLevel = false;
//france
String end,start;
//the starting board
start="OOOOOOOOO\", \"OOOOOOOOO\", \"OO OO\", \"OO O.\", \"OO OO\", \"OOOOOOOOO\", \"OOOOOOOOO\"";
//the wanted board
end = " OOOOOOOOO\", \"OOOOOOOO.\", \"OO OO\", \"OO O.\", \"OO OO\", \"OOOOOOOO.\", \"OOOOOOOO.\"] ";
//clean the Strings, let only 'O' or '.'
start = removeUnwanted(start);
end = removeUnwanted(end);
//adapt the board to normal, france, or other by the number of char in the string after remove the unwanted chars
if(start.length()==33)
{
makefrance=false;
lastLevel=false;
}
else if(start.length()==37)
{
makefrance = true;
lastLevel = false;
}
else if(start.length()==30){
makefrance=false;
lastLevel=true;
}
else if(start.length()==48){
superLevel=true;
}
int startDots=0;
int endDots=0;
Board board;
Board destinationBoard;
if(lastLevel)
{
board = new Board(start,true,true,superLevel);//The start of my board
destinationBoard = new Board(end,true,true,superLevel);//the wanted destination board, '.' for no peg and O for peg.
}
else{
board = new Board(start,makefrance,lastLevel,superLevel);//The start of my board
destinationBoard = new Board(end,makefrance,lastLevel,superLevel);//the wanted destination board, '.' for no peg and O for peg.
}
//count the pegs from the begining and ending board
for(int i=0;i<start.length()-1;i++) {
if (start.charAt(i) == '.') {
startDots++;
}
}
for(int i=0;i<end.length()-1;i++) {
if (end.charAt(i) == '.') {
endDots++;
}
}
//calculate the number of turns to the destination, every turn only one peg is disapear so finally there is:
//pegs at the end - pegs at the begining = number of turns
peg=endDots-startDots;
//create a string for save the steps.
answer = new String[peg];
//if we have a result, return the answer and print a text
if(Solve(board,destinationBoard,0))
{
System.out.println("The best day of my life");
for(int i=0;i<answer.length;i++)
{
System.out.println(answer[i]);
}
}
//if don't find path, print WTF
else{
System.out.println("WTFFFFF");
}
}
//recurse method that solve the peg solitaire
public boolean Solve(Board board, Board destination, int turn)
{
int rows=0;
//if we are on the end of the game
if(turn==peg)
{
//check if the current board is like the destination board.
if(board.isFinished(destination))
{
System.out.println("found the path");
return true;//this board is the same as the desitnation
}
else
{
return false;//this board is not the same as the desitnation
}
}
else {
if (superLevel)//if its a bigger board, need to check the board on more rows and lines
{
rows=9;
}
else{
rows=7;
}
for(int i=0;i<rows;i++){
for(int j=0;j<rows;j++)
{
if(board.isLegal(j,i))
{
if(board.canTurn(j,i,"right"))//test if it's possible to turn right
{
if(Solve(board.turn(board,j,i,"right"),destination,turn+1))//create a new board after changment of direction and recurse
{
answer[turn]= "["+j+","+i+",\">\"],";//add this step to the answer
return true;
}
}
if(board.canTurn(j,i,"up"))//test if it's possible to turn up
{
if(Solve(board.turn(board,j,i,"up"),destination,turn+1))//create a new board after changment of direction and recurse
{
answer[turn]= "["+j+","+i+",\"^\"],";//add this step to the answer
return true;
}
}
if(board.canTurn(j,i,"down"))//test if it's possible to turn down
{
if(Solve(board.turn(board,j,i,"down"),destination,turn+1))//create a new board after changment of direction and recurse
{
answer[turn]= "["+j+","+i+",\"v\"],";//add this step to the answer
return true;
}
}
if(board.canTurn(j,i,"left"))//test if it's possible to turn left
{
if(Solve(board.turn(board,j,i,"left"),destination,turn+1))//create a new board after changment of direction and recurse
{
answer[turn]= "["+j+","+i+",\"<\"],";//add this step to the answer
return true;
}
}
}
}
}
return false;//if don't find any path return.
}
}
public String removeUnwanted(String boardText)
{
String returnBoard="";
for(int i=0; i<boardText.length();i++)
{
if(boardText.charAt(i) == '.' || boardText.charAt(i)== 'O')//remove all the char that are not '.' or 'O'
{
returnBoard += boardText.charAt(i);
}
}
System.out.println(returnBoard);
return returnBoard;
}
}
and my board class:
package com.company;
import java.security.PublicKey;
public class Board {
//the array that storage the board data
private int[][] board = new int[9][9];;
public boolean superLvl=false;
int pegs = 0;
public Board(String place, boolean makefrance,boolean lastLevel,boolean superlevel) {
int boardx,boardy;
//add 2 to make the board compatible to the string
if(superlevel) {
superLvl=true;
boardx = 9;
boardy = 9;
int[][] temp = new int[][]{{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,2,2,2,2,2,0,0},{0,0,2,2,2,2,2,0,0},{0,0,2,2,2,2,2,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{2,2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2,2}};
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
board[j][i]=temp[i][j];
}
}
}
else {
if (!lastLevel) {
boardx = 7;
boardy = 7;
board[0][0] = 2;
board[1][0] = 2;
board[5][0] = 2;
board[6][0] = 2;
board[0][1] = 2;
board[1][1] = 2;
board[5][1] = 2;
board[6][1] = 2;
board[0][5] = 2;
board[1][5] = 2;
board[5][5] = 2;
board[6][5] = 2;
board[0][6] = 2;
board[1][6] = 2;
board[5][6] = 2;
board[6][6] = 2;
if (makefrance) {
board[1][1] = 1;
board[1][5] = 1;
board[5][1] = 1;
board[5][5] = 1;
}
} else {
boardx = 6;
boardy = 6;
board[0][6] = 2;
board[1][6] = 2;
board[2][6] = 2;
board[3][6] = 2;
board[4][6] = 2;
board[5][6] = 2;
board[6][6] = 2;
board[0][5] = 2;
board[1][5] = 2;
board[2][5] = 2;
board[3][5] = 2;
board[4][5] = 2;
board[5][5] = 2;
board[6][5] = 2;
board[6][0] = 2;
board[6][1] = 2;
board[6][2] = 2;
board[6][3] = 2;
board[6][4] = 2;
}
}
int loca = 0;//location on the string of place
//add 0 or 1 to the table
for (int i = 0; i < boardy; i++) {
for (int j = 0; j < boardx; j++) {
if (board[j][i] != 2) {
if (place.charAt(loca) == 'O') {
loca++;
board[j][i] = 1;
pegs++;
} else if (place.charAt(loca) == '.') {
loca++;
board[j][i] = 0;
}
}
}
}
System.out.println();
this.printBoard();
}
public Board(Board newone)
{
int placement=7;
if(superLvl)
{
placement=9;
}
for(int i=0;i<placement;i++)
{
for(int j=0;j<placement;j++)
{
board[i][j]= newone.getValue(i,j);
}
}
}
//test if this board is like the other board at the end of the game
public boolean isFinished(Board destination) {
int placement=7;
if(superLvl)
{
placement=9;
}
for (int i = 0; i < placement; i++) {
for (int j = 0; j < placement; j++) {
if (this.getValue(j,i)!=destination.getValue(j,i))
{
return false;
}
}
}
return true;
}
//get the value of this coordinate.
public int getValue(int x, int y)
{
return board[x][y];
}
//test if this cooardiante is a place on the board(not 2)
public boolean isLegal(int x,int y)
{
if(board[x][y]!=2)
{
return true;
}
else{
return false;
}
}
//test if can turn- if this place is 1 and the next is 1 and the second next is 0
//also protect from stack overflow
public boolean canTurn(int x,int y,String direction)
{
if(direction.equals("right"))
{
if(x<5){
if(this.getValue(x,y)==1 && this.getValue(x+1,y)==1 && this.getValue(x+2,y)==0)
{
return true;
}
else {
return false;
}
}
else
{
return false;
}
}
else if(direction.equals("left"))
{
if(x>1){
if(this.getValue(x,y)==1 && this.getValue(x-1,y)==1 && this.getValue(x-2,y)==0)
{
return true;
}
else {
return false;
}
}
else
{
return false;
}
}
else if(direction.equals("up"))
{
if(y>1){
if(this.getValue(x,y)==1 && this.getValue(x,y-1)==1 && this.getValue(x,y-2)==0)
{
return true;
}
else {
return false;
}
}
else
{
return false;
}
}
else if(direction.equals("down"))
{
if(y<5){
if(this.getValue(x,y)==1 && this.getValue(x,y+1)==1 && this.getValue(x,y+2)==0)
{
return true;
}
else {
return false;
}
}
else
{
return false;
}
}
else{
System.out.println("method canTurn on board get a wrong direction string");
return false;
}
}
//make the move and return a "new" board for saving the originial one.
public Board turn(Board oldBoard,int x, int y ,String direction)
{
Board board = new Board(oldBoard);
if(direction.equals("right"))
{
board.setValue(x,y,0);
board.setValue(x+1,y,0);
board.setValue(x+2,y,1);
return board;
}
else if(direction.equals("left"))
{
board.setValue(x,y,0);
board.setValue(x-1,y,0);
board.setValue(x-2,y,1);
return board;
}
else if(direction.equals("up"))
{
board.setValue(x,y,0);
board.setValue(x,y-1,0);
board.setValue(x,y-2,1);
return board;
}
else if(direction.equals("down"))
{
board.setValue(x,y,0);
board.setValue(x,y+1,0);
board.setValue(x,y+2,1);
return board;
}
else{
System.out.println("method Turn on board get a wrong direction string");
return null;
}
}
//change the value of the wanted board.
public void setValue(int x,int y,int value)
{
board[x][y]=value;
}
//print the board, made for tests.
public void printBoard()
{
int placement=7;
if(superLvl)
{
placement=9;
}
for(int i=0;i<placement;i++)
{
for(int j=0;j<placement;j++)
{
System.err.print(board[j][i]);
}
System.err.println();
}
System.err.println("------------------");
}
}

Related

Tic tac toe game loop stops when it is a draw - Java

According to the requirements from my learning platform works fine apart from when the input command is "start easy easy" and the result is draw program doesn't stop and nothing happens after that and I have to force end the program. In all other cases program continues to run unless user types in "exit". Please help and also if you can suggest how to improve my code and in terms of OOP that will be great. Thank you.
import java.util.Arrays;
import java.util.Scanner;
import java.util.Random;
public class Main {
public final static Scanner scan = new Scanner(System.in);
public static Random random = new Random();
public static char[][] gameBoard;
public static String level = "";
public static void main(String[] args) {
// write your code here
menu();
}
public static String[] getParams() {
String[] params = scan.nextLine().split(" ");
return params;
}
public static void menu() {
while (true) {
System.out.println("Input command: ");
String[] params = getParams();
if (params.length == 3) {
if ("start".equals(params[0])) {
level = params[1].equals("easy") ? params[1] : params[2];
start(params[1], params[2]);
continue;
}
} else if (params.length == 1) {
if ("exit".equals(params[0])) {
break;
} else {
System.out.println("Bad parameters!");
continue;
}
} else {
System.out.println("Bad parameters!");
continue;
}
break;
}
}
public static void start(String str1, String str2) {
gameBoard = to2dArray("_________");
drawBoard(gameBoard);
char player1 = 'X';
char player2 = 'O';
if ("user".equals(str1)) {
while (!gameFinished(gameBoard)) {
drawBoard(playerMove(gameBoard, player1));
gameState(gameBoard);
drawBoard(computerMove(gameBoard, player2));
gameState(gameBoard);
}
} else if ("user".equals(str2)) {
while (!gameFinished(gameBoard)) {
gameState(computerMove(gameBoard, player2));
drawBoard(gameBoard);
gameState(playerMove(gameBoard, player1));
drawBoard(gameBoard);
}
} else if ("user".equals(str1) && "user".equals(str2)) {
while (!gameFinished(gameBoard)) {
drawBoard(playerMove(gameBoard, player1));
gameState(gameBoard);
drawBoard(playerMove(gameBoard, player2));
gameState(gameBoard);
}
} else {
while (!gameFinished(gameBoard)) {
drawBoard(computerMove(gameBoard, player1));
gameState(gameBoard);
drawBoard(computerMove(gameBoard, player2));
gameState(gameBoard);
}
}
}//startGame method
public static int[] getRandomNumber() {
int[] computerCoords = new int[2];
while (true) {
int a = random.nextInt((3 - 1) + 1) + 1;
int b = random.nextInt((3 - 1) + 1) + 1;
if (gameBoard[a - 1][b - 1] == 'X' || gameBoard[a - 1][b - 1] == 'O') {
continue;
} else {
computerCoords[0] = a;
computerCoords[1] = b;
break;
}
}
return computerCoords;
}
public static char[][] computerMove(char[][] gameBoard, char computer) {
int[] arr = getRandomNumber();
int row = arr[0] - 1;
int col = arr[1] - 1;
if (!gameFinished(gameBoard)) {
System.out.println("Making move level \"" + level + "\"");
gameBoard[row][col] = computer;
}
return gameBoard;
}
public static char[][] playerMove(char[][] gameBoard, char player) {
int index = 0;
int row, column;
while (true) {
System.out.println("Enter the coordinates: ");
String[] coordinates = scan.nextLine().split(" ");
try {
row = Integer.parseInt(coordinates[0]);
column = Integer.parseInt(coordinates[1]);
if ((row < 1 || column < 1) || (row > 3 || column > 3)) {
System.out.println("Coordinates should be from 1 to 3!");
continue;
}
row -= 1;
column -= 1;
if (gameBoard[row][column] != '_') {
System.out.println("This cell is occupied! Choose another one!");
continue;
}
gameBoard[row][column] = player;
return gameBoard;
} catch (NumberFormatException e) {
System.out.println("You should enter numbers!");
continue;
}
}//while loop ends here
}// playerMove() ends
public static char[][] to2dArray(String s) {
char[][] twoDArray = new char[3][3];
int index = 0;
for (int i = 0; i < twoDArray.length; i++) {
for (int j = 0; j < twoDArray[i].length; j++) {
twoDArray[i][j] = s.charAt(index);
index++;
}
}
return twoDArray;
}// to2dArray method
public static void drawBoard(char[][] arr) {
System.out.println("---------");
for (int i = 0; i < arr.length; i++) {
System.out.print("| ");
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j] == '_') {
System.out.print(" " + " ");
} else {
System.out.print(arr[i][j] + " ");
}
}
System.out.println("|");
}
System.out.println("---------");
}//end drawBoard method
public static boolean xWon (char[][] gameBoard) {
char[] xWins = {'X', 'X', 'X'};
char[][] winningCombos = {
{gameBoard[0][0], gameBoard[0][1], gameBoard[0][2]}, //horizontal
{gameBoard[1][0], gameBoard[1][1], gameBoard[1][2]}, //horizontal
{gameBoard[2][0], gameBoard[2][1], gameBoard[2][2]}, //horizontal
{gameBoard[0][0], gameBoard[1][0], gameBoard[2][0]}, //vertical
{gameBoard[0][1], gameBoard[1][1], gameBoard[2][1]}, //vertical
{gameBoard[0][2], gameBoard[1][2], gameBoard[2][2]}, //vertical
{gameBoard[0][0], gameBoard[1][1], gameBoard[2][2]}, //diagonal
{gameBoard[0][2], gameBoard[1][1], gameBoard[2][0]} //diagonal
};
for (char[] charArray : winningCombos) {
if (Arrays.equals(xWins, charArray)) {
return true;
}
}
return false;
}// end xWon method
public static boolean oWon (char[][] gameBoard) {
char[] oWins = {'O', 'O', 'O'};
char[][] winningCombos = {
{gameBoard[0][0], gameBoard[0][1], gameBoard[0][2]}, //horizontal
{gameBoard[1][0], gameBoard[1][1], gameBoard[1][2]}, //horizontal
{gameBoard[2][0], gameBoard[2][1], gameBoard[2][2]}, //horizontal
{gameBoard[0][0], gameBoard[1][0], gameBoard[2][0]}, //vertical
{gameBoard[0][1], gameBoard[1][1], gameBoard[2][1]}, //vertical
{gameBoard[0][2], gameBoard[1][2], gameBoard[2][2]}, //vertical
{gameBoard[0][0], gameBoard[1][1], gameBoard[2][2]}, //diagonal
{gameBoard[0][2], gameBoard[1][1], gameBoard[2][0]} //diagonal
};
for (char[] charArray : winningCombos) {
if (Arrays.equals(oWins, charArray)) {
return true;
}
}
return false;
}// end oWon method
public static boolean hasEmptyCells(char[][] gameBoard) {
for (char[] arr : gameBoard) {
for (char ch : arr) {
if (ch == '_') {
return true;
}
}
}
return false;
} //end of hasEmptyCells method;
public static boolean gameFinished(char[][] gameBoard) {
if (xWon(gameBoard) || oWon(gameBoard) || draw(gameBoard)) {
return true;
}
return false;
} //end of gameFinished method.
public static boolean draw(char[][] gameBoard) {
if(!xWon(gameBoard) && !oWon(gameBoard) && !hasEmptyCells(gameBoard)) {
return true;
}
return false;
}
public static char[][] gameState(char[][] gameBoard) {
if (xWon(gameBoard)) {
System.out.println("X wins");
return gameBoard;
} else if (oWon(gameBoard)) {
System.out.println("O wins");
return gameBoard;
} else if (draw(gameBoard)) {
System.out.println("Draw");
return gameBoard;
}
return gameBoard;
}//gameState method
}// Main class
The draw happens halfway into this:
while (!gameFinished(gameBoard)) {
drawBoard(computerMove(gameBoard, player1));
gameState(gameBoard);
// Result is now Draw
drawBoard(computerMove(gameBoard, player2));
gameState(gameBoard);
}
You try to generate another computerMove after the first one, but that is impossible, because the board is already full.
A possible solution woud be to check gameFinished before attempting another move

2 same-class objects being instantiated by another same-class object error

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();

need help on my tic tac toe demo invalid top level statement

public class TicTacToe
{
private char currentPlayer;
private char[][] board;
public TicTacToe()
{
board = new char [3][3];
currentPlayer = 'x';
startBoard();
}
public void startBoard()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
board[i][j] = '-';
}
}
}
public void makeBoard()
{
System.out.println("---------------");
for (int i = 0; i < 3; i++)
{
System.out.print("| ");
for (int j = 0; j < 3; j++)
{
System.out.print(board[i][j] + " | ");
}
System.out.println();
System.out.println("---------------");
}
}
public boolean fullBoard()
{
boolean full = true;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (board[i][j] == '-')
{
full = false;
}
}
}
return full;
}
public boolean win()
{
return (rowWin() || columnWin() || diagWin());
}
private boolean rowWin()
{
for (int i = 0; i < 3; i++)
{
if (rowColumn(board[i][0], board[i][1], board[i][2]) == true)
{
return true;
}
}
return false;
}
private boolean columnWin()
{
for (int i = 0; i < 3; i++)
{
if (rowColumn(board[0][i], board[1][i], board[2][i]) == true)
{
return true;
}
}
return false;
}
private boolean diagWin()
{
return ((rowColumn(board[0][0], board[1][1], board[2][2]) == true) ||
(rowColumn(board[0][2], board[1][1], board[2][0]) == true));
}
private boolean rowColumn(char rc1, char rc2, char rc3)
{
return ((rc1 != '-') && (rc1 == rc2) && (rc2 == rc3));
}
public void playerChange()
{
if (currentPlayer == 'x')
{
currentPlayer = 'o';
}
else
{
currentPlayer = 'x';
}
}
public boolean placeMark(int row, int column)
{
if ((row >= 0) && (row < 3))
{
if ((column >= 0) && (column < 3))
{
if (board[row][column] == '-')
{
board[row][column] = currentPlayer;
return true;
}
}
}
return false;
}
}
public class TicTacToedemo
{
public static void main(String[] args)
{
TicTacToe demo = new TicTacToe();
demo.makeBoard();
if (demo.win())
System.out.println("Winner! Hooray!");
else if (demo.fullBoard())
System.out.println("Cat Scratch, Draw.");
demo.playerChange();
}
}
I am not sure how to play the game right, every time I input numbers when I run it, I get the error code. What have I done wrong with this? The code can be compiled and runs and displays the board but when I go to put in the place I want the x or the o to go I get the error code " invalid Top level statement "
You have to use the Scanner class to make a player input using import java.util.Scanner then storing the input. After the import it going to look like this:
Scanner sc = new Scanner(System.in);
int input = sc.nextInt();
And you have to manage the sc.nextInt() result, in this example the input variable.

Java connect four victory check

I am a beginner at programming and I have been teaching myself as much as I can. I need help in a simpler way of checking for a victory instead of hard coding every possible combination.
I have no idea what to do.
here is my current code:
import java.awt.*;
import javax.swing.event.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class connectfour extends JFrame implements ActionListener
{
JLabel board[][] = new JLabel[8][7];
//JLabel board[] = new JLabel[64];
JButton action[] = new JButton[8];
JButton start;
JButton clear;
JFrame Frame = new JFrame();
ImageIcon red = new ImageIcon("red piece.jpeg");
ImageIcon black = new ImageIcon("blackpiece.jpeg");
boolean players = true;
//Integer[] numclick = new Integer[8];
int x;
int numclick1 = 7;
int numclick2 = 7;
int numclick3 = 7;
int numclick4 = 7;
int numclick5 = 7;
int numclick6 = 7;
int numclick7 = 7;
int numclick0 = 7;
public connectfour()
{
Frame.setSize(100,120);
Frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
Frame.setLayout(null);
Frame.setVisible(true);
start = new JButton("Start");
start.setBounds(0,0,100,100);
start.setVisible(true);
start.addActionListener(this);
Frame.add(start);
}
public void game()
{
for(int x = 0; x < 8 ; x++)
{
action[x] = new JButton();
action[x].setSize(100,40);
action[x].setLocation((x*100) + 50, 0);
action[x].addActionListener(this);
action[x].setVisible(true);
Frame.add(action[x]);
}
/**
board[1][1] = new JLabel();
board[1][1].setBounds(50,40,100,100);
board[1][1].setVisible(true);
board[1][1].setOpaque(true);
board[1][1].setBorder(BorderFactory.createLineBorder(Color.black));
Frame.add(board[1][1]);
**/
for(int i = 0; i < 8; i++)
{
for(int j = 0; j < 7; j++)
{
board[i][j] = new JLabel();
board[i][j].setSize(100,100);
board[i][j].setLocation((i*100)+50,(j*100)+40);
board[i][j].setOpaque(true);
board[i][j].setVisible(true);
board[i][j].setBorder(BorderFactory.createLineBorder(Color.black));
Frame.add(board[i][j]);
}
}
clear = new JButton("Clear");
clear.setBounds(850,100,100,50);
clear.addActionListener(this);
clear.setVisible(true);
Frame.add(clear);
}
public void boardsize()
{
Frame.setSize(950,800);
}
public static void main(String args[])
{
new connectfour();
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == start)
{
boardsize();
start.setVisible(false);
game();
}
for(x = 0;x < 8 ;x ++)
{
if(e.getSource() == action[x])
{
//numclick[x]++;
if(x == 0)
{
numclick0--;
if(players == true)
{
board[x][numclick0].setIcon(red);
players = false;
break;
}
if(players == false)
{
board[x][numclick0].setIcon(black);
players = true;
break;
}
}
if(x == 1)
{
numclick1--;
if(players == true)
{
board[x][numclick1].setIcon(red);
players = false;
break;
}
if(players == false)
{
board[x][numclick1].setIcon(black);
players = true;
break;
}
}
if(x == 2)
{
numclick2--;
if(players == true)
{
board[x][numclick2].setIcon(red);
players = false;
break;
}
if(players == false)
{
board[x][numclick2].setIcon(black);
players = true;
break;
}
}
if(x == 3)
{
numclick3--;
if(players == true)
{
board[x][numclick3].setIcon(red);
players = false;
break;
}
if(players == false)
{
board[x][numclick3].setIcon(black);
players = true;
break;
}
}
if(x == 4)
{
numclick4--;
if(players == true)
{
board[x][numclick4].setIcon(red);
players = false;
break;
}
if(players == false)
{
board[x][numclick4].setIcon(black);
players = true;
break;
}
}
if(x == 5)
{
numclick5--;
if(players == true)
{
board[x][numclick5].setIcon(red);
players = false;
break;
}
if(players == false)
{
board[x][numclick5].setIcon(black);
players = true;
break;
}
}
if(x == 6)
{
numclick6--;
if(players == true)
{
board[x][numclick6].setIcon(red);
players = false;
break;
}
if(players == false)
{
board[x][numclick6].setIcon(black);
players = true;
break;
}
}
if(x == 7)
{
numclick7--;
if(players == true)
{
board[x][numclick7].setIcon(red);
players = false;
break;
}
if(players == false)
{
board[x][numclick7].setIcon(black);
players = true;
break;
}
}
System.out.println(x);
System.out.println();
}
}
if(e.getSource() == clear)
{
for(int x = 0; x < 8; x++)
{
for(int y = 0; y < 7; y++)
{
board[x][y].setIcon(null);
numclick1 = 7;
numclick2 = 7;
numclick3 = 7;
numclick4 = 7;
numclick5 = 7;
numclick6 = 7;
numclick7 = 7;
numclick0 = 7;
players = true;
for(int j = 0; j < 8 ; j++)
{
action[j].setEnabled(true);
}
}
}
}
if(numclick0 == 0)
{
action[0].setEnabled(false);
}
if(numclick1 == 0)
{
action[1].setEnabled(false);
}
if(numclick2 == 0)
{
action[2].setEnabled(false);
}
if(numclick3 == 0)
{
action[3].setEnabled(false);
}
if(numclick4 == 0)
{
action[4].setEnabled(false);
}
if(numclick5 == 0)
{
action[5].setEnabled(false);
}
if(numclick6 == 0)
{
action[6].setEnabled(false);
}
if(numclick7 == 0)
{
action[7].setEnabled(false);
}
}
public void winner()
{
}
}
I would use a recursive method that checks the horizontal, vertical, and both diagonals.
As i was reading your code I realized you don't keep track(may have missed it) of where players are.. I recommend and array for this called grid[][] Mapping an array to your JLabels will go a long way.
Ill give an example of negative vertical check..
public Boolean checkVertical(Boolean player, int x, int y){
if(solveHelper(player, x, y, -1, 0) => 4) return true;
return false;
}
public int solveHelper(Boolean player, int x, int y, int addX, int addY){
if(x == 0 || x == size || y == 0 || y == size || grid[x][y].player != player)
return 0;
return solverHelper(player, x+addX, y+addY, addX, addY) + 1);
}
Now how can you create and use these methods for yourself?
you need to create a new methods for each of the horizontal, vertical, and both diagonals to check for all of them you call solveHelper with different properties in addX and addY that correspond with the direction you want to go. For instance, if you want to check the horizontal you need do make addY == 1 and addY == -1 with both values for addX == 0 by doing a solveHelper + solverHelper with these two values changed.
Other notes...
Some things you need to need to keep in mind is that how connect four actually runs. When you click on a row a piece falls down to the smallest unoccupied element in that particular column. Just something you should keep in mind when writing your game logic.
Cheers.

recursively creating a tree

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.

Categories