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("------------------");
}
}
I am new to java and have an assignment which asks me to make a connect4 game. Everything in my code is working perfectly fine, other than the diagonals and for some reason I cannot enter a coin in column 6. Also, if any other error is found please point that out as well! Any help will be appreciated. Thanks!
public class Connect4 {
/**
* #param args the command line arguments
*/
public static void displayGrid(char [][]connectfourGrid){
for(int i=0;i<connectfourGrid.length;i++)
{
for(int j=0;j<connectfourGrid[i].length;j++)
System.out.print("|"+connectfourGrid[i][j]);
System.out.println("|");
}
for(int i=0;i<connectfourGrid.length-1;i++)
System.out.print("---");
System.out.println("");
}
public static void playConnect4(char[][]connectfourGrid){
Scanner input = new Scanner(System.in);
boolean gameOver=false;
boolean playersTurn = true;
int columnPos = 0;
char colour;
while(!gameOver){
if(playersTurn){
System.out.print("Drop a red coin at column 0-6:");
colour = 'R';
}
else{
System.out.print("Drop a yellow coin at column 0-6:");
colour = 'Y';
}
columnPos = input.nextByte();
while(columnPos<0||columnPos>6){
System.out.println("C'est out of bounds. "+colour+" please enter again mate");
columnPos=input.nextByte();
}
playersTurn = !playersTurn;
if(dropCoin(connectfourGrid, columnPos, colour))
playersTurn=!playersTurn;
else{
displayGrid(connectfourGrid);
if(gameStatus(connectfourGrid,columnPos,colour)){
gameOver=true;
System.out.println(colour+" won!");
}
else if(checkTie(connectfourGrid)){
gameOver = true;
System.out.println("C'est a tie!");
}
}
}
}
public static boolean checkTie(char[][]connectfourGrid){
for(int i=0;i<connectfourGrid[0].length;i++)
if(connectfourGrid[0][i]==0)
return false;
return true;
}
public static boolean gameStatus(char[][]connectfourGrid,int columnPos,char colour){
int rowPos=0;
for(int i=0;i<connectfourGrid.length;i++)
if(connectfourGrid[i][columnPos]!=0){
rowPos = i;
break;
}
if(checkCol(connectfourGrid,columnPos,colour,rowPos))
return true;
if(checkRow(connectfourGrid,columnPos,colour,rowPos))
return true;
if(checkMajorDiagonal(connectfourGrid,columnPos,colour,rowPos))
return true;
if(checkMinorDiagonal(connectfourGrid,columnPos,colour,rowPos))
return true;
return false;
}
public static boolean checkMajorDiagonal(char[][]connectfourGrid,int columnPos,char colour,int rowPos){
int count=1;
for(int i=rowPos-1,j=columnPos-1;i>=0&&j>=0;i--,j--)
if(colour==connectfourGrid[i][j])
return true;
else
break;
if(count>=4)
return true;
for(int i=rowPos+1,j=columnPos+1;i<connectfourGrid.length&&j<connectfourGrid[0].length;i++,j++)
if(colour==connectfourGrid[i][j])
return true;
else
break;
if(count>=4)
return true;
/* for(int i=rowPos-1;i>=0;i--)
for(int j=columnPos-1;j>=0;j--)
if(colour==connectfourGrid[i][j])
count++;
else
break;
if(count>=4)
return true;
for(int i=rowPos+1;i<connectfourGrid.length;i++)
for(int j=columnPos+1;j<connectfourGrid[0].length;j++)
if(colour==connectfourGrid[i][j])
return true;
else
break;
if(count>=4)
return true;*/
return false;
}
public static boolean checkMinorDiagonal(char[][]connectfourGrid,int columnPos,char colour,int rowPos){
int count=1;
for(int i=rowPos+1,j=columnPos-1;i<connectfourGrid.length&&j>=0;i++,j--)
if(colour==connectfourGrid[i][j])
count++;
else
break;
if(count>=4)
return true;
for(int i=rowPos-1,j=columnPos+1;i>=0&&j<connectfourGrid[0].length;i--,j++)
if(colour==connectfourGrid[i][j])
count++;
else
break;
if(count>=4)
return true;
/*for(int i=rowPos+1;i<connectfourGrid.length;i++)
for(int j=columnPos-1;j>=0;j--)
if(colour==connectfourGrid[i][j])
count++;
else
break;
if(count>=4)
return true;
for(int i=rowPos-1;i>=0;i--)
for(int j=columnPos+1;i<connectfourGrid[0].length;j++)
if(colour==connectfourGrid[i][j])
count++;
else
break;
if(count>=4)
return true;*/
return false;
}
public static boolean checkRow(char[][]connectfourGrid,int columnPos,char colour,int rowPos){
int count=1;
for(int i=columnPos-1;i>=0;i--)
if(colour==connectfourGrid[rowPos][i])
count++;
else
break;
if(count>=4)
return true;
for(int i=columnPos+1;i<connectfourGrid[0].length;i++)
if(colour==connectfourGrid[rowPos][i])
count++;
else
break;
if(count>=4)
return true;
return false;
}
public static boolean checkCol(char [][]connectfourGrid,int columnPos,char colour,int rowPos){
int count=1;
if((rowPos+4)<=6)
for(int i=rowPos+1;i<=(rowPos+3);i++)
if(colour==connectfourGrid[i][columnPos])
count++;
else
break;
if(count==4)
return true;
return false;
}
public static boolean dropCoin(char[][]connectfourGrid, int columnPos,char colour){
for(int i=connectfourGrid.length-1;i>=0;i--)
if(connectfourGrid[i][columnPos]==0){
connectfourGrid[i][columnPos]=colour;
return false;
}
System.out.println("C'est full. "+colour+" try again mate!");
return true;
}
public static void main(String[] args) {
// TODO code application logic here
Scanner input = new Scanner(System.in);
char[][]connectfourGrid = new char [6][7];
displayGrid(connectfourGrid);
playConnect4(connectfourGrid);
}
}
This doesn't seem to make sense...
public static boolean checkMajorDiagonal(char[][] connectfourGrid, int columnPos, char colour, int rowPos) {
int count = 1;
System.out.println(columnPos + "x" + rowPos);
for (int i = rowPos - 1, j = columnPos - 1; i >= 0 && j >= 0; i--, j--) {
if (colour == connectfourGrid[i][j]) {
return true;
} else {
break;
}
}
if (count >= 4) {
return true;
}
for (int i = rowPos + 1, j = columnPos + 1; i < connectfourGrid.length && j < connectfourGrid[0].length; i++, j++) {
if (colour == connectfourGrid[i][j]) {
return true;
} else {
break;
}
}
if (count >= 4) {
return true;
}
return false;
}
The moment you find a cell with a matching color you return true, which doesn't take into account if there are other matching coins, which would be required in order to form a winning condition.
What's even weirder is you've got code setup to check the number of "matches", but aren't using them.
So, when I changed it to...
public static boolean checkMajorDiagonal(char[][] connectfourGrid, int columnPos, char colour, int rowPos) {
int count = 1;
System.out.println(columnPos + "x" + rowPos);
for (int i = rowPos - 1, j = columnPos - 1; i >= 0 && j >= 0; i--, j--) {
if (colour == connectfourGrid[i][j]) {
//return true;
count++;
} else {
break;
}
}
if (count >= 4) {
return true;
}
for (int i = rowPos + 1, j = columnPos + 1; i < connectfourGrid.length && j < connectfourGrid[0].length; i++, j++) {
if (colour == connectfourGrid[i][j]) {
//return true;
count++;
} else {
break;
}
}
if (count >= 4) {
return true;
}
return false;
}
I got it to work (in my limited testing).
What's additional weird, you seem to do it correctly for checkMinorDiagonal.
I also had no issue getting coins in to column 6
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.