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("------------------");
}
}
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?
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.
I have to create the yahtzee game and its methods like full house, small straight, big straight, 3 of kind, 4 of kind , and chance. Now this is what i have done so far and i would like to know if my methods are right and also i'm having a hard time trying to figure out how to check if its yahtzee , 3 of kind, 4 of kind , etc and this is in my main method. The program consists of seven rolls, where every roll can have up to two sub-rolls
static final int NUM_RERROLS_ = 2;
static final int NUM_OF_DICE = 5;
static final int NUM_ROLLS_ = 7;
static final int[] dice = new int[NUM_OF_DICE];
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
rollDice();
for (int i = 0; i < NUM_RERROLS_; i++) {
if (gotYatzee()) {
break;
}
System.out.println(diceToString());
askUser();
System.out.println("Which dice do you want to reroll: ");
secondReroll(convert(keyboard.nextLine()));
}
System.out.println(diceToString());
if (gotYatzee()) {
System.out.println("You got Yatzee & 50 points!");
} else if (largeStraight() == true) {
System.out.println("You got large straight");
} else {
System.out.println("Sorry no large straight");
}
if (smallStraight() == true) {
System.out.println("You got smallStraight");
} else {
System.out.println("Sorry no small straight");
}
if (fullHouse() == true) {
System.out.println("You got full house");
} else {
System.out.println("Sorry no full house");
}
{
System.out.println("SORRY NO YAHTZEE");
}
if (askUser() == false) {
if (largeStraight() == true) {
System.out.println("You got large straight");
} else {
System.out.println("Sorry no large straight");
}
if (smallStraight() == true) {
System.out.println("You got smallStraight");
} else {
System.out.println("Sorry no small straight");
}
if (fullHouse() == true) {
System.out.println("You got full house");
} else {
System.out.println("Sorry no full house");
}
}
}
public static void rollDice() {
for (int i = 0; i < NUM_OF_DICE; i++) {
dice[i] = randomValue();
}
}
public static int randomValue() {
return (int) (Math.random() * 6 + 1);
}
public static String diceToString() {
String dado = "Here are your dice: ";
for (int element : dice) {
dado = dado + element + " ";
}
return dado;
}
public static boolean gotYatzee() {
for (int element : dice) {
if (element != dice[0]) {
return false;
}
}
return true;
}
public static void secondReroll(int[] newValue) {
for (int element : newValue) {
dice[element - 1] = randomValue();
}
}
public static int[] convert(String s) {
StringTokenizer st = new StringTokenizer(s);
int[] a = new int[st.countTokens()];
int i = 0;
while (st.hasMoreTokens()) {
a[i++] = Integer.parseInt(st.nextToken());
}
return a;
}
public static boolean Chance() {
for (int element : dice) {
int i = 0;
if (element != dice[i]) {
i++;
return false;
}
}
return true;
}
public static boolean smallStraight() {
for (int i = 1; i <= NUM_OF_DICE; i++) {
boolean b = false;
for (int j = 0; j < NUM_OF_DICE; j++) {
b = b || (dice[j] == i);
}
if (!b) {
return false;
}
}
return true;
}
public static boolean largeStraight() {
int[] i = new int[5];
i = dice;
sortArray(i);
if (((i[0] == 1) && (i[1] == 2) && (i[2] == 3) && (i[3] == 4) && (i[4] == 5))
|| ((i[0] == 2) && (i[1] == 3) && (i[2] == 4) && (i[3] == 5) && (i[4] == 6))
|| ((i[1] == 1) && (i[2] == 2) && (i[3] == 3) && (i[4] == 4) && (i[5] == 5))
|| ((i[1] == 2) && (i[2] == 3) && (i[3] == 4) && (i[4] == 5) && (i[5] == 6))) {
return true;
} else {
return false;
}
}
public static boolean askUser() {
Scanner keyboard = new Scanner(System.in);
int a = 0;
String yes = "Yes";
String no = "No";
System.out.println("Do you want to reroll the dice again: Yes or No? ");
String userInput;
userInput = keyboard.next();
if (userInput.equals(yes)) {
System.out.println("ALRIGHTY!!");
return true;
} else if (userInput.equals(no)) {
}
return false;
}
public static boolean threeKind() {
int[] a = new int[5];
a = dice;
sortArray(a);
if ((((a[0] == a[1]) && (a[1] == a[2])) // Three of a Kind
|| ((a[1] == a[2]) && ((a[2] == a[3])
|| (((a[2] == a[3]) && (a[3] == a[4]))))))) {
return true;
} else {
return false;
}
}
/*public static boolean fourKind(int[] dice) {
}
*/
public static int[] sortArray(int[] numbers) {
int stop;
for (stop = 0; stop < numbers.length; stop++) {
for (int i = 0; i < numbers.length - 1; i++) {
if (numbers[i] > numbers[i + 1]) {
swap(numbers, i, i + 1);
}
}
}
return numbers;
}
public static void swap(int[] numbers, int pos1, int pos2) {
int temp = numbers[pos1];
numbers[pos1] = numbers[pos2];
numbers[pos2] = temp;
}
public static boolean fullHouse() {
int[] a = new int[5];
a = dice;
sortArray(a);
if ((((a[0] == a[1]) && (a[1] == a[2])) && // Three of a Kind
(a[3] == a[4]) && // Two of a Kind
(a[2] != a[3]))
|| ((a[0] == a[1]) && // Two of a Kind
((a[2] == a[3]) && (a[3] == a[4])) && // Three of a Kind
(a[1] != a[2]))) {
return true;
} else {
return false;
}
}
}
basically i want to figure out a way to check if its full house, 3 of kind, 4 of kind , etc
You have 6 dice after three rolls. Sort the array of user-retained dice after the 3 rolls.
Yahtzee: ((die[0] == die[4]) || (die[1] == die[5]))
4 of a kind: ((die[0] == die[3]) || (die[1] == die[4] || (die[2] == die[5]))
Small straight, 3 tests (x = 3,4,5): ((die[x] - die[x-3]) == 3)
Large straight, 2 tests (x = 4,5): ((die[x] - die[x-4]) == 4)
etc.
Chance: Up to the user, right?
Unless I'm missing something (I'm a little rusty on Yatzee), this should be fairly straightforward.