Stack overflow on recursive method when the counter begins at 1 [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I've written a program to read in a text file containing a matrix of 1s and 0s that will loop recursively to identify all unique four-connected regions (regions connected by moving up, down, left, right). I then replace the 1s in each region with an identifier number, however when I begin the counter for the replacement values at 1 I get a stack overflow error. I've worked around this while building my recursive method by just starting at 2 and then going back after everything is finished and decrementing all the region values by 1 so that the region counters start at 1 in the output. This works and my output is correct, but this feels like a lazy solution.
I know I need a way to identify if a 1 has already been identified, this would allow me to replace an area with 1s and still be able to properly read through the grid, but I am unsure of any way to see if an element is a member of an object. I've attempted to build a series of if-else statements to identify the very first 1 encountered and to loop from there, but when I hit that region again I either get a stack overflow error or bizarre outputs such as every number in the first region (which should be replaced by new 1s) being a different number. Would it be smarter to write a second recursive method to handle the very first 1 encountered, or does the fact I start at 2 and then later decrement all values really make the program so ugly?
/**
* Scans the grid for 1s, calling the designateRegions method when unique
* 1s are found.
*/
public static void findRegions() {
int region = 2;//the counter variable in question
for (int i = 0; i < nRows; i++) {
for (int j = 0; j < nCols; j++) {
if (grid[i][j] == 1) {
//Ensure the value isn't part of a known region
if (j-1 >= 0 && grid[i][j-1] >= 1) {
grid[i][j] = grid[i][j-1];
} else if (i-1 >= 0 && grid[i-1][j] >= 1) {
grid[i][j] = grid[i-1][j];
} else {//if 1 is unique
Regions regionObject = new Regions(region);//instantiate a Regions object
regionCountList.add(regionObject);//add new Regions object to arraylist
designateRegions(grid, i, j, region, regionObject);//call recursive method designateRegions
region++;
}//end nested if-else block
}//end outer if statement
}//end inner for loop
}//end outer for loop
//this is stupid
for (int i = 0; i < nRows; i++) {
for (int j = 0; j < nCols; j++) {
if (grid[i][j] > 1) {
grid[i][j] = grid[i][j] - 1;//drop the value of each region by 1
}//end if statement
}//end inner for loop
}//end outer for loop
}//end findRegions method
/**
* Loops recursively to identify four-connected regions of 1s and change the
* value of the elements in the newly identified region.
* #param grid the 2d integer array containing the grid to be scanned
* #param r the row position
* #param c the column position
* #param region the identifier value for the region
* #param regionObject the object associated with each region
*/
private static void designateRegions(Integer[][] grid, int r, int c, int region, Regions regionObject) {
if (grid[r][c] == 0) { //base case
} else if (grid[r][c] == 1) {
grid[r][c] = region;//switch value of the 1 with appropriate region identifier
regionObject.regionCount++;
if (r - 1 >= 0) {
designateRegions(grid, r - 1, c, region, regionObject);//move up
}
if ((r + 1) < nRows) {
designateRegions(grid, r + 1, c, region, regionObject);//move down
}
if ((c + 1) < nCols) {
designateRegions(grid, r, c + 1, region, regionObject);//move right
}
if (c - 1 >= 0) {
designateRegions(grid, r, c - 1, region, regionObject);//move left
}
}
}//end findRegions method

You correctly identified the problem: the recursive code needs to mark each grid element that has been visited to prevent the program from chasing its own tail.
Marking the visited cells with a different value (2) is a valid strategy. Another possibility would be passing around a separate grid of boolean[nRows][nCols]s with cells that have a true in them identify the visited cells.
I think that your solution is cleaner, because it does not require allocating any additional memory.

Related

How to squeeze an Array so no consective two or more values appear and is replace by that one value

/**
* squeeze() takes an array of ints. On completion the array contains the
* same numbers, but wherever the array had two or more consecutive
* duplicate numbers, they are replaced by one copy of the number. Hence,
* after squeeze() is done, no two consecutive numbers in the array are the
* same.
*
* Any unused elements at the end of the array are set to -1.
*
* For example, if the input array is [ 4 , 1 , 1 , 3 , 3 , 3 , 1 , 1 ], it
* reads [ 4 , 1 , 3 , 1 , -1 , -1 , -1 , -1 ] after squeeze() completes.
* #param ints
* the input array.
*/
public static void squeeze(int[] ints) {
// TODO: Fill in your solution here. Ours takes linear time and is less than 10 lines long,
// not counting blank/comment lines or lines already present in this file.
// ArrayList<Integer> k = new ArrayList<Integer>();
below is my code but for some reason the logic is not right, it returns the same array passed into the function and not the modified one, I believe most of the logic to be correct unless there is an error in the continue statement. Every time a consecutive same index appears in the array, it should be replaced by that one index
int deleted = 0;
int i = 0;
for(int j = 1; j < ints.length; j++) { ?
if(ints[i] == ints[j]) {
deleted++;
continue;
}else {
//k.add(ints[i]);
i++;
}
}
ints = new int[ints.length + deleted];
for(int s = 0; s < ints.length; s++) {
if(ints[s] == 0) {
ints[s] = -1;
}
}
}
/**
* main() runs test cases on your squeeze() method. Prints summary
* information on basic operations and halts with an error (and a stack
* trace) if any of the tests fail.
*/
continue simply jumps to the end of your for loop skipping any code. that is, it starts the next interation.
as pointed out in the comments, you need to modify the array that was passed in since there is no return value in the defined method.
Consider the following....
int deleted = 0;
for(int j = 0; j < (ints.length-1); j++) {
if (ints[j] == -1) // if -1 then we've reached the end of the original list
break; // this breaks out of the loop even if the constraint is not met
if(ints[j] == ints[j+1]) { // if consecutive entries are equal
// shift all values down in the list
for (int k = j+1; k < (ints.length-1); k++){
ints[k] = ints[k+1];
} // end loop k
// set the last entry in the array to -1 since we moved everything down
ints[ints.length-1] = -1;
//back our loop up one so that we stay where we were in case there was
// more than two consecutive numbers that were the same
j--;
}
} // end loop j
// display the result
for (int i = 0; i < ints.length; i++)
System.out.print(ints[i] + ", " );

4 queens algorithm - can't understand code

public boolean canPlaceQueen(int r, int c) {
/**
* Returns TRUE if a queen can be placed in row r and column c.
* Otherwise it returns FALSE. x[] is a global array whose first (r-1)
* values have been set.
*/
// System.out.println("r======"+r);
// System.out.println("c="+c);
for (int i = 0; i < r; i++) {
System.out.println("iiiiiiiiiii="+i);
if (x[i] == c || (i - r) == (x[i] - c) ||(i - r) == (c - x[i]))
{
System.out.println("try c="+c);
System.out.println("try="+r);
return false;
}
}
return true;
}
public void placeNqueens(int r, int n) {
/**
* Using backtracking this method prints all possible placements of n
* queens on an n x n chessboard so that they are non-attacking.
*/
//System.out.println("r="+r);
for (int c = 0; c < n; c++) {
//System.out.println("c=="+c);
if (canPlaceQueen(r, c)) {
x[r] = c;
// System.out.println("2nd==="+r);
if (r == n - 1) {
printQueens(x);
} else {
placeNqueens(r + 1, n);
}
}
}
}
My question is: If c = 0, then c = 1, but then c=0. I cant understand that logic, why not c=2,please describe it or describe how c increment in this program
Okay, I'll take a crack at this. You enter the method placeNqueens with r=0 and n=whatever (let's say 5). We loop through each column and check if we can fit a queen in that column for row . If we CAN place it, we set the x[0] = c (which will probably be 0 for the first attempt) and then recursively call into placeNqueens with r=1 and n=5. At this point we're checking the next row.
Inside this call, we now start again and check all the columns. We won't be able to place it in the first column, because that's where the first queen is, so we loop until we find a column we can place it. Inside this loop, you might check column 0 and fail, and then check column 1 and fail, and then check column 2 and find a spot, so you set x[1] = 2 and then call placeNqueens(6, 5).
Eventually you've placed enough queens that your row == queens -1, so then you print the solution. If you don't ever find a solution, then the call stack ends and falls back to the previous call, which keeps looping until it finds ANOTHER possible place to put the queen in that row. When it does, it then calls placeNqueens to try the next row again. If a solution is present, eventually the algorithm will try all the permutations needed to find it.
So, to summarize, in each execution of placeNqueens, you loop only as long as you need to loop until you find a spot to place your queen, and then you call placeNqueens again, reducing your current row position by 1. If you reach a point where you cannot place any queens, your program will finish the entire for-loop and then return, which takes you to wherever you left off in the loop on the previous call.

Confused about writing a program for placing some modified queen-type pieces on an 8 x 8 board

To this question:
The superqueen is a chess piece that can move like a queen, but also like a knight. What is the maximal number of superqueens on an 8X8 chessboard such that no one can capture an other?
I want to write a brute force algorithm to find the maximum. Here's what I wrote:
public class Main {
public static boolean chess[][];
public static void main(String[] args) throws java.lang.Exception {
chess = new boolean[8][8];
chess[0][0] = true;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
/*Loop to check various possibilities*/
if (!checkrow(i) && !checkcolumn(j) && !checkdiagonals(i, j) && !checkknight(i, j)) {
if (i != 0 || j != 0) {
chess[i][j] = true;
}
}
}
}/*printing the array*/
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
System.out.print(((chess[i][j]) ? "T" : "x") + "|");
}
System.out.println();
}
}
/*All working fine here*/
public static boolean checkrow(int a) {
for (int i = 0; i < 8; i++) {
if (chess[a][i]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkcolumn(int a) {
for (int i = 0; i < 8; i++) {
if (chess[i][a]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkdiagonals(int pi, int pj) {
int i = pi - Math.min(pi, pj);
int j = pj - Math.min(pi, pj);
for (int k = i, l = j; k < 8 && l < 8; k++, l++) {
if (chess[k][l]) {
return true;
}
}
int i_2 = pi - Math.min(pi, pj);
int j_2 = pj + Math.min(pi, pj);
for (int k = i_2, l = j_2; k < 8 && l > 1; k++, l--) {
if (chess[k][l]) {
return true;
}
}
return false;
}
/*Not All working fine here try commenting out this method above so that that it doesn't run during the check*/
public static boolean checkknight(int pi, int pj) {
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (0 <= pi + 2 * i && pi + 2 * i <= 8 && 0 <= pj + j && pj + j <= 8) {
if (chess[pi + 2 * i][pj + j]) {
return true;
}
}
if (0 <= pi + i && pi + i <= 8 && 0 <= pj + 2 * j && pj + 2 * j <= 8) {
if (chess[pi + i][pj + 2 * i]) {
return true;
}
}
}
}
return false;
}
}
I have two questions:
My algorithm for checkknight looks for all knight positions, is it wrong? or there is some coding error.Everything is working fine when I comment out it and I get a nice solution.
Secondly it'll result only in one solution.For other solutions I have to offset(or change position) of other pieces bit by bit after each mega-loop of this, I am confused about implementing it. My instincts guide me that I need to change whole of the code. Is there a modification or a way to do it?
Additional Thoughts: I think we would add to a counter each time we place a piece and add to a long array and output the maximum and array after storing the relevant data.
Code Location: You may view/edit/fork/download it at http://ideone.com/gChD8a
This a rough brute-force method starting from the opposite direction, i.e. from the solved eight-queens puzzle. This will allow us to find a bunch of viable solutions.
The brute-force technique for going from a single superqueen to potentially 8 seems to be especially complex due to the knight's traversal. Based on the runs, about 60% of the viable paths for normal queens are invalid with superqueens. So if we were to instead brute force normal queens, and then work backwards, that is potential time saved for finding a solution, and we can better determine the run-time. Because we know normal queens is easier.
We start off with the 12 fundamental solutions, we would then use these as inputs. Solving normal queens is outside this, but the wiki page has a fantastic article describing everything.
In my case, I stored them as Strings representing the coordinate of the queen (the rows are indices).
So: "17468253" = A1, B7, C4, D6, E8, F2, G5, H3
By brute-forcing the opposite direction from solved queens, we only have to test at most 12 x 8! possible solutions. Because order doesn't matter, additional optimization could occur by eliminating duplicate boards and solutions for processing.
First up, checkKnight, which appears to be your source of confusion. Using absolute values, you can reasonably determine whether or not a piece is within knight's range by checking whether the X offset is 2 and Y offset is 1, or vice versa. You've made a complex checkKnight function to check each individual location and whether or not a piece is on the border. Working the other way by hitscanning each queen to each other queen is logically simpler and less of a nightmare to debug.
Queen class
public class Queen {
int i, j;
public Queen(int i, int j) {
this.i = i;
this.j = j;
}
public boolean checkKnight(Queen queen) { // if any queen meets another
// queen at 2 and 1 offset, we
// eliminate it.
return (Math.abs(i - queen.i) == 2 && Math.abs(j - queen.j) == 1)
|| (Math.abs(i - queen.i) == 1 && Math.abs(j - queen.j) == 2);
}
}
This board has been modified since I originally posted. It takes a String input and converts it to a full chessboard. It has some minor work towards the potential any-size board, but right now it handles child board creation. When a child board is created, the queens are passed by reference rather than making a whole new set of queens. A total of 96 queens are stored in memory, 1 for each one on the original 12-board solution. Not perfectly optimized, but better than 96 -> 672 -> 4032 -> ...
Board class
public class Board {
static int boardSize = 8;
ArrayList<Queen> queens = new ArrayList<Queen>();
public Board(String s) {
for (int i = 0; i < s.length(); i++) {
queens.add(new Queen(i, s.charAt(i) - 49)); // you could implement
// base 16 here, for
// example, for a 15x15
// board
}
}
public Board(Board b) { // duplicates the board, but keeps references to
// queens to conserve memory, only 96 total queens
// in existence through search!
for (Queen q : b.queens) {
queens.add(q);
}
}
public boolean checkForImpact() {
for (int i = 0; i < queens.size(); i++) {
for (int j = i + 1; j < queens.size(); j++) {
if (queens.get(i).checkKnight(queens.get(j))) { // just check
// for any
// queens
// intersecting,
// one hit is
// enough
return true;
}
}
}
return false;
}
public ArrayList<Board> getChildBoards() { // create child boards with a
// single queen removed
ArrayList<Board> boards = new ArrayList<Board>();
for (int i = 0; i < queens.size(); i++) {
boards.add(new Board(this));
}
int i = 0;
for (Board b : boards) {
b.queens.remove(i);
i++;
}
return boards;
}
public String drawBoard() {
String s = "";
char[][] printableBoard = new char[boardSize][boardSize];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
printableBoard[i][j] = '_';
}
}
for (Queen q : queens) {
printableBoard[q.i][q.j] = 'Q';
}
s += " A B C D E F G H\n";
for (int i = 0; i < 8; i++) {
s += (8 - i) + "|";
for (int j = 0; j < boardSize; j++) {
s += printableBoard[i][j];
s += "|";
}
s += "\n";
}
return s;
}
}
Test class
import java.util.ArrayList;
public class Test {
static String[] boards = { "24683175", "17468253", "17582463", "41582736",
"51842736", "31758246", "51468273", "71386425", "51863724",
"57142863", "63184275", "53172864" }; // all 12 solutions for the 8
// queens problem
static ArrayList<Board> boardObjects = new ArrayList<Board>();
public static void main(String[] args) {
for (String queens : boards) { // create starter boards
boardObjects.add(new Board(queens));
}
int i;
ArrayList<Board> foundBoards = null;
for (i = 8; i > 0; i--) {
ArrayList<Board> newBoards = new ArrayList<Board>();
foundBoards = new ArrayList<Board>();
for (Board b : boardObjects) {
if (b.checkForImpact()) { // if any queen intercepts we get
// children
ArrayList<Board> boardsToBeAdded = b.getChildBoards(); // pass
// all
// permutations
// of
// queens
// once
// removed
for (Board bo : boardsToBeAdded) {
newBoards.add(bo); // add it in to the next list
}
} else {
foundBoards.add(b); // if we have no impact, we have a
// solution
}
}
if (!foundBoards.isEmpty())
break;
boardObjects.clear();
boardObjects = newBoards;
}
System.out.println("The maximum number of super-queens is: " + i);
ArrayList<String> winningCombinations = new ArrayList<String>();
for (Board board : foundBoards) {
String createdBoard = board.drawBoard();
boolean found = false;
for (String storedBoard : winningCombinations) {
if (storedBoard.equals(createdBoard))
found = true;
}
if (!found)
winningCombinations.add(createdBoard);
}
for (String board : winningCombinations) {
System.out.println(board);
}
}
}
The end output is:
The maximum number of super-queens is: 6
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|Q|_|
6|_|_|_|Q|_|_|_|_|
5|_|_|_|_|_|_|_|_|
4|_|_|_|_|_|_|_|Q|
3|_|Q|_|_|_|_|_|_|
2|_|_|_|_|Q|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|_|_|
6|_|_|_|_|Q|_|_|_|
5|_|_|_|_|_|_|_|Q|
4|_|Q|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|_|_|_|Q|_|_|
1|_|_|Q|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|Q|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|_|_|_|_|_|
4|_|_|Q|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|_|_|_|_|_|_|
1|_|_|_|Q|_|_|_|_|
I've removed the duplicates and made a nice board printing method. don't remember the exact math, but this highlights 40 possible locations. There are others, just by looking, but we've found a fair chunk of them already! From here, we can gently shift individual queens around. From a cursory look, each board has a single piece that can be moved to 3 additional spaces, so now we know there are probably about 160 solutions.
Conclusions
With this application, the run-time on my machine was less than a second, meaning that if we attached this to a standard queens application, the additional knight's brute-forcing would have no impact on that process and have almost the same run-time. In addition, because only 6-piece puzzles are possible, we know that your eventual application run will finish its finding at the 6th piece being placed, as no more solutions are possible, since there are no viable 7-piece and 8-piece solutions.
In other words, finding the maximum super-queen layout is likely actually shorter than the maximum queen layout due to the additional restrictions!
Trying to brute-force such a question is a good way to get a feel for it. So I won't suggest looking up pre-cooked solutions at first.
One little remark though: I don't see the reason for the condition if (i != 0 || j != 0) { that you have there. You are working on Java arrays. Instead of 1 through 8, they go 0 through 7, but the 0 is the first column, you should not eliminate it, otherwise it's only a 7x7 board.
First, let me address your technical question: how to calculate the knight positions.
Take a sheet of quad paper, put a queen somewhere not less than two squares away from the edge. Then mark the end positions of a knight-move from it.
You'll end up with just 8 squares that need to be considered. There is no point in doing a 3x3 loop to find them. A better idea would be to prepare a static array with the relative coordinates of the knight moves - an array of 8 pairs of numbers - and loop on that. So you have only an 8-step loop. In each step of the loop, check for bounds (0 ≤ X + Xoffset < 8, 0 ≤ Y + Yoffset < 8 ), and you have the knight coordinates.
Second, there is no point checking the part of the board that's ahead of you. Since you have not covered the next row and those below it, there is no point in looking for queens there. The implications of this:
You'll never put another queen in the same row where you have just marked a queen position (because you threaten it horizontally). This means that if you mark a queen, you should use continue to break out of the inner loop to the next row.
You don't need checkrow(). When you start a row, there is no queen ahead of you. And if you followed the above bullet point, there is no queen on your back, either.
When you use checkcolumn, you start at row 0, but you can finish at the row before the one you are on (i-1). There are still no queens in the rows below you! The same is true for the diagonal checks.
Earlier I said that you need to prepare and check 8 knight positions. But now you know there is no queen at the knight positions ahead of you. So you only need to prepare an array with four knight positions - the ones above your position.
But most importantly... once you have finished and you have your queens in positions and print the board: you have a single solved board. You have proved that this number of queens is possible. But is it the highest number possible? You have not checked what happens if you don't put a queen on the first square of the first row, but on the second. Perhaps this will allow you to put in an extra queen later. And what about the queen in the second row? Maybe if you moved that, you would be able to put a queen somewhere below where you couldn't before?
So, now you have to actually do the same thing over again, changing one decision every time and working from there. In effect, you have many potential boards. Why? Because there may be more than one valid position on each row where you put that row's queen. So you have decided to put it in the first valid position. But what if you decide to put it in the second valid position? Or leave that row empty? Each such decision is followed by another set of decisions on the next row.
The different boards created by different decisions form a decision tree. The problem for you to consider, therefore, is how to work such a tree out. How to write your decision trail and then backtrack, change, fill another board and count the queens at each level. People here suggested recursion, because it lends itself nicely to such problems. Or you can keep a stack of decisions if you want. You can eliminate some of the potential boards based on symmetries.
I suggest you first make sure you understand your single board well, and then consider how to represent your decision tree and how to traverse it.
There are several questions here.
The first is: how many knight-queens can be placed on an nxn chessboard? Since a k-piece solution can trivially be reduced to a k-1 piece solution, it makes sense to start from the upper bound. That is, look for an n-piece solution, if that fails look for an n-1 piece solution, and so forth.
The second question is: how should I look for a k-piece solution? There are two classic strategies: depth-first and breadth-first. In the former, you consider one vertex of the search tree at a time and use backtracking on failure. In the latter, you consider one complete level of the search tree at a time.
Something that can make a great deal of difference to your search is to account for symmetry (in this case, rotations and reflections).
The third (implicit) question is: what is a good representation here? If your chess-boards are less than 8x8 in size then a 64-bit bit-pattern will do very nicely!
In practical terms, try to separate the three levels of your problem as far as you can. If you don't, you'll find that a choice in one level will severely limit your options at another level.

Strings - Number guessing game [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
This is a game that generates a random 4 digit number and then lets the user input 5 chances to guess the game and returns a hint as to how many numbers were in the correct place and how many matched but were in the wrong place.
I am having a problem comparing two strings. One of the strings holds the correct answer to the game, the other string holds the most recent 4 digit guess.
aCount needs to be the number of characters that are in correct position.
bCount needs to be the number of characters that are in the correct answer, but not in correct position.
bCount is the part I'm having trouble with (it's not working as I expect). I thought I might try a double for loop, but I'm not sure.
static String getHint(String guess, String answer){
int aCount=0;
int bCount=0;
String hintString="";
for (int i =0; i<answer.length(); i++){
char guessAChar = guess.charAt(i);
char ansAChar = answer.charAt(i);
if(guessAChar == ansAChar){
aCount++;
}
}
for (int indexOfGuess = 0; indexOfGuess < answer.length(); indexOfGuess++)
{
for (int indexOfActualNumber = 0; indexOfActualNumber < answer.length(); indexOfActualNumber++)
{
if (guess.charAt(indexOfGuess) == (answer.charAt(indexOfActualNumber)))
{
bCount++;
}
}
}
bCount = bCount - aCount;
hintString =("Your hint is: \n"+aCount+"A" + bCount + "B");
return hintString;
}
}
EDIT: This problem has been solved: This method now searches and outputs how many numbers in each string match, and how many in each position are the same!
Variable bCount is the amount of numbers in the final string, but not in the right spot. You need a double loop for this to check each character in each string to see if they match. This might point you in the right direction.
int outer_counter = 0;
for(char g : guess.toCharArray())
{
int inner_counter = 0;
for(char a : answer.toCharArray())
{
if(g == a && inner_counter != outer_counter)
{
bCount++;
}
inner_counter++;
}
outer_counter++;
}
The counters make sure these are NOT in the same position.
So bCount is determining the number of digits that are in the answer, but not in the right place. So let's try this:
public string bCount()
{
for (int indexOfGuess = 0; indexOfGuess < answer.length(); indexOfGuess++)
{
for (int indexOfActualNumber = 0; indexOfActualNumber < answer.length(); indexOfActualNumber++)
{
if (guess.charAt(indexOfGuess).equals(answer.charAt(indexOfActualNumber))
{
bCount++;
}
}
}
}
This method does:
Creates an outer loop that loops through each index of the "guess" array
Creates an inner loop that, while the "guess" array is at an index, the inner loop will loop through each index (so while "guess" is at index 0, "answer" will go through all indexes before "guess" goes to 1, and then the inner loop runs again)
Check to see if the number at the guess index = number at the actual index.
If it is, increment bCount.
The only issue which I haven't taken care of for you is if the number is entered twice. Example: if the number is 1900, and you guess 1909, you number for bCount will be higher than it should be. However, I'll leave that to you as this is a homework assignment after all.

Java : Sudoku Game : Checking 3x3 grids for repeated values

What this program does :
This program takes values from a class and uses those as the starting values for a Sudoku puzzle. We are to print these out in a typical Sudoku 9x9 grid. The program then prompts the user to give a coordinate point on the grid and a value to put in there. Currently what I am working on is making sure that the values put in by the user are valid to solve this puzzle. Once the puzzle is filled out and there are no longer any repeated values in each column, row, and 3x3 square, the game should end and the output should be "Puzzle Complete".
As of right now, my program checks for repeated values in columns and rows successfully, but I have no idea where to begin for checking each 3x3 square.
The numbers for this puzzle are saved in a 9x9 array.
Basicly : Any tips for how to check for repeated values in each 3x3 part of the array?
What I'd do instead of a big 9x9 array is storing a 3x3 array of 3x3 arrays of numbers. Or do both, for ease of computation (storing 81 more bytes of data (you do use bytes for the fields I hope?) isn't going to cause memory problems in all but the most memory starved devices and I doubt you'd want to play games on such anyway).
It depends on how you are storing the sudoku board. If you are storing it as a 2D array, you could have your logic identify the 3x3 box the user has chosen to enter the new value and use the code you already have to check a row and column sections.
What you could also have would be to have a collection of 9 sets. Each set would correspond to a specific 3x3 block. So, when the user selects the coordinates of where he/she would like to add the value, you would select the given set and perform an add operation in the set.
Since sets do not allow repetition, the add method will return false if the number already exists in the set. This will also allow you to identify any duplicate values (however, unlike the array option, you would also need to update the set should the user opt to remove values from the 3x3 grid).
I wrote the following code about 4 years ago in C to solve the exact same problem, it's as brute-force-y as it looks, though. The int array was a 9x9 grid. The "index" specifies the 0...8th line, 0...8th column, and 0...8th box.
int checkBox(int a[][9], int index)
{
int i, j, isValid = 1;
int m, n;
for(i = 3*(index%3) ; isValid && (i < (3*(index%3) + 3)); i++)
{
for(j = 3*(index/3); isValid && (j < (3*(index/3) + 3)); j++)
{
for(m = (3*(index%3)) ; isValid && (m < (3*(index%3) + 3)); m++)
{
for(n = 3*(index/3); isValid && (n < (3*(index/3) + 3)); n++)
{
if(isValid && (a[m][n] == 0) || ((i != m) || (j != n)) && (a[i][j] == a[m][n])) //select given element and compare others to it
{ //if any element is the same that is not itself then the sudoku is not valid
isValid = 0; //this checks for 3x3 box
}
}
}
}
}
return isValid;
}
Basically what I did was just manipulate the index until it selected a specific box, and in that box I checked all numbers to see if there's any kind of match. If there is a match, the sudoku is invalid.
In the end, I checked the validity like this:
int checkSudoku(int a[][9]) //check every row, column and box
{ //if there is no contradiction then it is valid
int i, isValid = 1;
for(i = 0; isValid && (i < 9); i++)
{
isValid = (checkLine(a, i) && checkColumn(a, i) && checkBox(a, i));
}
return isValid;
}
Of course, the same concept can be applied to Java, considering it's just array management.

Categories