To clarify I only wanted one or two for loops to help me on my way, preferably in the same style as I had used in the vertical :)
I'm making a game using a 2D array, and I need a check that tests if at the current position (indicated by a green square) the character there is part of a diagonal sequence of "l" more of the character.
public static boolean diagonals(char[][] b, int row, int col, int l) {
int counter = 1; // because we start from the current position
char charAtPosition = b[row][col];
int numRows = b.length;
int numCols = b[0].length;
int topleft = 0;
int topright = 0;
int bottomleft = 0;
int bottomright = 0;
for (int i=row-1,j=col-1;i>=0 && j>=0;i--,j--) {
if (b[i][j]==charAtPosition) {
topleft++;
} else {
break;
}
}
for (int i=row-1,j=col+1;i>=0 && j<=numCols;i--,j++) {
if (b[i][j]==charAtPosition) {
topright++;
} else {
break;
}
}
for (int i=row+1,j=col-1;i<=numRows && j>=0;i++,j--) {
if (b[i][j]==charAtPosition) {
bottomleft++;
} else {
break;
}
}
for (int i=row+1,j=col+1;i<=numRows && j<=numCols;i++,j++) {
if (b[i][j]==charAtPosition) {
bottomright++;
} else {
break;
}
}
return topleft + bottomright + 1 >= l || topright + bottomleft + 1 >= l; //in this case l is 5
}
The idea is that we walk in four directions and count the steps. This may not be the most efficient implementation, but at least it looks neat and easy to understand.
Here's the function, it works. The explanation is in the comments in the code, but if you find anything confusing let me know and I'll explain it.
public static boolean diagonals(char[][] b, int row, int col, int l) {
int forwardCounter = 1; // this counts top right to bottom left
int backCounter = 1; // this counts top left to bottom right
int distance = 1;
// 0 = topleft, 1 = topright, 2 = bottomleft, 3 = bottomright
boolean[] checks = new boolean[]{true, true, true, true};
char charAtPosition = b[row][col];
while(checks[0] || checks[1] || checks[2] || checks[3]) {
for(int i = 0; i < 4; i++) {
if(checks[i]) {
// This looks confusing but it's simply just converting i into
// The four different directions
checks[i] = checkSquare(b, row + (i < 2 ? -distance : distance),
col + (i % 2 == 0 ? -distance : distance), charAtPosition);
if(checks[i]) {
// If top left or bottom right
if(i % 3 == 0) {
backCounter++;
} else {
forwardCounter++;
}
}
}
}
if (forwardCounter >= l || backCounter >= l) return true;
distance++;
}
return false;
}
private static boolean checkSquare(char[][] b, int row, int col, char check) {
if(row < 0 || row >= b.length) return false;
if(col < 0 || col >= b[0].length) return false;
return check == b[row][col];
}
Related
I have coded for Sudoku puzzle in Java. The thing is my code has limitation for giving inputs for 9*9 grid. How do I make my code adaptable for all the grids. Please have patience. I am new to java.
What changes do I need to make so that the code can run on all grid sizes?The grid is square not a rectangle.
class Solution {
public void solveSudoku(char[][] board) {
if(solveSudoku2(board)) {
return;
}
}
public boolean solveSudoku2(char[][] board) {
boolean isEmpty = true;
int row = -1;
int col = -1;
int n = board.length;
//this code is used to check if there exists any empty cell in sudoku board
//if there is any empty cell, that means we are not done yet and we need to solve it further,
// so we cannot return true at any point until all the cells are full
//by empty cell, I mean cells having '.' as the value
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[0].length; j++) {
if(board[i][j] == '.') {
row = i;
col = j;
isEmpty = false;
break;
}
}
if(!isEmpty) {
break;
}
}
if(isEmpty) {
return true;
}
//loop for all the numbers and start placing in the empty cells
//numbers start from 1 to n
for(int num = 1; num <= n; num++) {
//convert number to char
char char_num = (char)(num + '0');
//check if the number we are adding satisfies all the sudoku rules,
// if it does, then we place that number in the cell
if(checkSafe(board,char_num,row,col)) {
board[row][col] = (char)(num + '0');
//using this number in place row,col, we check for all the other empty places and see if the board is returning true or not
// if the board is not filled that means that we need to use other number in row,col place.
//hence backtrack.
if(solveSudoku2(board)) {
return true;
} else {
board[row][col] = '.';
}
}
}
return false;
}
public boolean checkSafe(char[][] board, char num, int row, int col) {
//checkk if num is present in the row
for(int i = 0; i< board.length; i++ ) {
if(board[row][i] == num) {
return false;
}
}
for(int j = 0; j < board[0].length; j++) {
if(board[j][col] == num) {
return false;
}
}
int checknum = (int)Math.sqrt(board.length);
//check for the current grid. grid will be basically checknum*checknum matrix. where every matrix will start from startrow to startrow + checknum having checknum length.
// so, we we have row = 0, then matrix will start from 0 to 2, i.e. the first 3x3 matrix.
// however, we have row = 2, then also the matrix will start from 0 to 2 - the first 3x3 matrix.
//however, if row = 3, then we will start our matrix from 3 and cotinute upto 5.
int startrow = row - row % checknum;
int startcol = col - col % checknum;
for(int k = startrow; k < startrow + checknum; k++) {
for(int l = startcol; l < startcol + checknum; l++) {
if(board[k][l] == num) {
return false;
}
}
}
return true;
}
}
I've been working on a Game of Life assignment and am nearing the stage of completion, but am struggling to figure out what I've messed up on such that the GOL rules (and Fredkin rules that the assignment requires us to implement as well) are not generating the proper result.
As I have little experience working with graphics I decided to output everything in the interactions window (using Dr.Java). (It's used to set up menu options like the scale, coordinates (you manually enter), generations, and output the final generation of whichever rule you choose to run (GOL or Fredkin).
The program nextGeneration takes a Boolean array map from the main method (where people input coordinates), and should change it to correspond to the next generation of the Game of Life. This happens by creating an entirely new 2D array, map2, which gets values loaded into it based on the number of neighbors which are turned on for each point. At the end of the program, map gets loaded into map2.(Note: this isn't original, this is required by the assignment)
The program living merely checks if a point in the map array is on or off. countNeighbors takes the 8 neighbors of a particular square, passes them each through the living method, and returns the number of neighbors which are currently on. Since countNeighbors sometimes demands either a negative number, or a number greater than the scale of the map, we implemented conditions in living to create that wraparound universe.
I think the problem(s) most likely arise in nextGeneration. I am somewhat tense about using the operand "or" (written as || ), and I think this may be where I screwed up. If you could just look through the code, and see if what I have said is true is written as true, that would be absolutely wonderful.
Below is the code for the program. It also utilizes a Keyboard.class file which I'm happy to post (however one would do that) if that helps (it's required to compile).
public class GameOfLife {
public static void main(String[] args) {
int r = 0; //rules set. Either 0 or 1, 0 for life game, 1 for Fredkin game
int i = 0; // looping variable
int j = 0; // looping variable
int b = 0; // used to read integer inputs from keyboard
int x = 0; // used during the stage where the player manually changes the board. Represents x coordinate.
int y = 0; // used during the stage where the player manually changes the board. Represents x coordinate.
int gen = 0; //number of generations to be skipped before printing out new map
int scale = 0;
boolean[][] map = new boolean[0][0];
System.out.println("Start game? y/n");
String a = Keyboard.readString();
if (a.equals("n")) {
return;
} else {
System.out.println("Do you wish to know the rules? y/n");
a = Keyboard.readString();
if (a.equals("y")) {
System.out.println("Each coordinate in the printed graph is represented by a 0 or a .");
System.out.println("0 represents a live cell, . represents a dead one.");
System.out.println("Each cell has 8 neighboring cells.");
System.out.println("There are two ways in which the game can be played.");
System.out.println("In the Life model, if a cell has 3 neighbors, if dead, it turns on.");
System.out.println("If it has 2 neighbors, it keeps its current condition.");
System.out.println("Else, it dies. Brutal.");
System.out.println("In the Fredkin Model, only non-diagnol neighbors count.");
System.out.println("If a cell has 1 or 3 neighbors, it is alive.");
System.out.println("If it has 0, 2 or 4, it dies. WAY more Brutal.");
}
System.out.println("Do you want to play by Fredkin or Life Rules? 0 for life, 1 for Fredkin");
while (i == 0) {
b = Keyboard.readInt();
if (b == 1) {
r = 1;
i = 1;
}
if (b == 0) {
r = 0;
i = 1;
}
}
while (j == 0) {
System.out.println("What scale would you like to use? Please enter an integer larger than 4");
b = Keyboard.readInt();
if (b >= 5) {
map = new boolean[b][b];
scale = b;
j = 1;
} else {
System.out.println("Come on, buddy, read the rules");
}
}
j = 0;
while (j == 0) {
System.out.println("Do you want to enter coordinates? y to continue entering coordinates, n to go to next option");
a = Keyboard.readString();
if (a.equals("y")) {
i = 0;
while (i == 0) {
System.out.println("Please enter a value for an X coordinate from 0 to " + (scale - 1));
b = Keyboard.readInt();
if (b >= 0) {
if (b < scale) {
i = 1;
x = b;
}
}
}
i = 0;
while (i == 0) {
System.out.println("Please enter a value for a Y coordinate from 0 to " + (scale - 1));
b = Keyboard.readInt();
if (b >= 0) {
if (b < scale) {
i = 1;
y = b;
}
}
}
map[y][x] = true;
printgame(map);
} else {
if (a.equals("n")) {
j = 1;
}
}
}
i = 0;
while (i == 0) {
System.out.println("How many generations would you like to skip ahead? Please enter a value greater than 0");
b = Keyboard.readInt();
if (b > 0) {
gen = b;
i = 1;
}
}
i = 0;
if (r == 0) {
for (i = 0; i <= gen; i++) {
nextGeneration(map);
}
printgame(map);
} else {
if (r == 1) {
for (i = 0; i <= gen; i++) {
FredGen(map);
}
printgame(map);
}
}
}
}
public static void printgame(boolean[][] map) {
int x = map[0].length;
int y = map[0].length;
int i = 0;
int j = 0;
char c;
String Printer = "";
for (j = 0; j < y; j++) {
for (i = 0; i < x; i++) {
if (map[j][i]) {
c = '0';
} else {
c = '.';
}
Printer = (Printer + " " + c);
}
System.out.println(Printer);
Printer = new String("");
}
}
private static void nextGeneration(boolean[][] map) {
int x = map[0].length;
int y = map[0].length;
int[][] neighborCount = new int[y][x];
boolean[][] map2 = new boolean[y][x];
for (int j = 0; j < y; j++)
for (int i = 0; i < x; i++)
neighborCount[j][i] = countNeighbors(j, i, map);
//this makes a new generation array
for (int j = 0; j < y; j++) {
for (int i = 0; i < x; i++) {
if (map[j][i] = true) { //assumes initial value of array is true (AKA "ALIVE")
if (neighborCount[j][i] == 3) { //check if alive AND meeting condition for life
map2[j][i] = true; //sets character array coordinate to ALIVE: "0"
} else if ((neighborCount[j][i] <= 2) || (neighborCount[j][i] > 3)) { //check if dead from isolation or overcrowding
map2[j][i] = false; //sets character array coordinate to DEAD: "."
}
}
}
}
map = map2;
}
private static int countNeighbors(int j, int i, boolean[][] map) { //counts all 8 elements living/dea of 3x3 space surrounding and including living/dead central coordinate)
return living(j - 1, j - 1, map) + living(j - 1, i, map) +
living(j - 1, i + 1, map) + living(j, i - 1, map) + living(j, i + 1, map) +
living(j + 1, i - 1, map) + living(j + 1, i, map) + living(j + 1, i + 1, map);
}
private static int living(int j, int i, boolean[][] map) {
int x = map[0].length - 1;
if (i < 0) {
i = i + x;
} else {
i = i % x;
}
if (j < 0) {
j = j + x;
} else {
j = j % x;
}
if (map[j][i] == true) {
return 1;
} else {
return 0;
}
}
private static void FredGen(boolean[][] map) {
int x = map[0].length;
int y = map[0].length;
int[][] neighborCount = new int[y][x];
for (int j = 0; j < y; j++)
for (int i = 0; i < x; i++)
neighborCount[j][i] = Freddysdeady(j, i, map);
//this makes a new generation array
for (int j = 0; j < y; j++)
for (int i = 0; i < x; i++)
if (map[j][i] = true) { //assumes initial value of array is true (AKA "ALIVE")
if ((neighborCount[j][i] < 1) || (neighborCount[j][i] == 2) || (neighborCount[j][i] > 3)) { //check if dead from isolation or overcrowding
map[j][i] = false; //sets chracter array coordinate to DEAD: "."
} else if ((neighborCount[j][i] == 1) || (neighborCount[j][i] == 3)) { //check if alive AND meeting condition for life
map[j][i] = true; //sets character array coordinate to ALIVE: "0"
}
}
}
private static int Freddysdeady(int j, int i, boolean[][] map) {
return living(j - 1, i, map) + living(j, i - 1, map) + living(j, i + 1, map) + living(j + 1, i, map);
}
}
There might be other problems, here are a few that I could spot by eye:
In the nextGeneration method, you handle cases where a cell should stay alive or die, but you do not have anything for when cells should be born. You should have something like this:
if(map[x][y]) {
//should this cell stay alive? if yes = live, else die
} else {
//should a cell be born in this slot? if yes = born, else nothing
}
This is a minor issue, still in nextGeneration, in if(count==3)live; else if(count <=2 || count > 3) die; is redundant, you only need if(count == 3) live; else die;
let us know, if you still have problems
I'm working on a program that picks a random location in a grid, checks its neighbors, and assigns the location the value of 1 if any of the neighbors are occupied. If none are occupied, the program picks a random neighbor and moves to it (switch case in diffuse()).
public class Frost {
int width;
int height;
int density;
int seed;
int[][] grid = new int[this.width][this.height];
Random randoma = new Random();
[Later...]
boolean diffuse(){
int steps = 0;
int diffusionSteps = this.height*this.width*2;
int indexA = (int) randoma.nextInt(width);
int indexB = (int) randoma.nextInt(height);
while (steps <= diffusionSteps)
{
if (grid[indexA][indexB] == 0) { //if empty
if (this.checkNorth(indexA, indexB) || this.checkSouth(indexA,indexB) || this.checkEast(indexA,indexB) || this.checkWest(indexA,indexB))
{
grid[indexA][indexB] = 1;
return true;
}
else {
steps++; //increase counter before moving and looping again
int ofFour = this.randoma.nextInt(4);
int tempA = indexA;
int tempB = indexB;
switch(ofFour)
{
case 1:
if (tempA+1 >= this.width)
indexA = (tempA+1)%this.width;
else indexA=tempA+1;
case 2:
if(tempB+1 >= this.height)
indexB = (tempB+1)%this.height;
else indexB = tempB+1;
case 3:
if ((tempB-1) <= 0)
indexB = (indexB-1)%this.height;
else indexB = tempB-1;
case 4:
if ((tempA-1) <= 0)
indexA = (tempA-1)%this.width;
else indexA = tempA-1;
}
}
}
}
if (steps>=diffusionSteps){
grid[indexA][indexB]=1;
return true;
}
return false;
}
I'm getting ArrayIndexOutofBounds: -1 errors for getSouth and getWest methods. I thought the problem might be the decrement operators, but I fiddled with them and nothing changed. Any insights would be appreciated.
boolean checkSouth(int indexA, int indexB)
{
--indexB;
if (indexB > 0)
{return grid[indexA][indexB-1] == 1;}
else
return grid[indexA][((indexB-1)%this.height)] == 1;
}
boolean checkWest(int indexA, int indexB)
{
--indexA;
if (indexA > 0)
return grid[indexA][indexB-1] == 1;
else
return grid[(indexA)%this.width][indexB] == 1;
}
The problem seems to be here
boolean checkSouth(int indexA, int indexB) {
System.out.println(indexA+" "+indexB);
--indexB;
if (indexB > 0) {
return grid[indexA][indexB - 1] == 1;
} else
return grid[indexA][((indexB - 1) % this.height)] == 1;
}
When it's executed with indexB equal to 1. In this case it is first decremented
--indexB; //now it's equal to 0
and then here
(indexB - 1) % this.height
the result is -1, and being it used as index for an array... well, out of bounds!
The problem is probably in the way you do modulo: if index is -1, then index % height will still be -1.
You need to do (index + height) % height to deal with the negative number (provided you want the grid to be cyclic).
I'm trying to generate a complete (ie, each cell filled with a number) Sudoku-like board. It's for something else that has nothing to do with sudokus, so I am not interested in reaching a sudoku with white squares that can be solved, or anything that has to do with sudokus. Don't know if you know what I mean.
I've done this in java:
private int sudokuNumberSelector(int x, int y, int[][] sudoku) {
boolean valid = true;
String validNumbers = new String();
int[] aValidNumbers;
int squarexstart = 0;
int squareystart = 0;
int b = 0; // For random numbers
Random randnum = new Random();
randnum.setSeed(new Date().getTime());
// Check numbers one by one
for(int n = 1; n < 10; n++) {
valid = true;
// Check column
for(int i = 0; i < 9; i++) {
if(sudoku[i][y] == n) {
valid = false;
}
}
// Check file
for(int j = 0; j < 9; j++) {
if(sudoku[x][j] == n) {
valid = false;
}
}
// Check square
switch (x) {
case 0: case 1: case 2: squarexstart = 0; break;
case 3: case 4: case 5: squarexstart = 3; break;
case 6: case 7: case 8: squarexstart = 6; break;
}
switch (y) {
case 0: case 1: case 2: squareystart = 0; break;
case 3: case 4: case 5: squareystart = 3; break;
case 6: case 7: case 8: squareystart = 6; break;
}
for(int i = squarexstart; i < (squarexstart + 3); i++ ) {
for(int j = squareystart; j < (squareystart + 3); j++ ) {
if(sudoku[i][j] == n) {
valid = false;
}
}
}
// If the number is valid, add it to the String
if(valid) {
validNumbers += n;
}
}
if(validNumbers.length() != 0) {
// String to int[]
aValidNumbers = fromPuzzleString(validNumbers);
// By this random number, return the valid number in its position
Log.d(TAG, "NUMBERS: " + validNumbers.length());
// Select a random number from the int[]
b = randnum.nextInt((aValidNumbers.length));
return aValidNumbers[b];
} else {
return 0;
}
}
This method is called from this piece of code:
int[][] sudoku = new int[9][9];
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
sudoku[i][j] = sudokuNumberSelector(i, j, sudoku);
}
}
But it is not as easy as it seemed! When the algorithm has generated a part of the board like this one, and the loop is on the cell on bold:
|||164527389|||
|||983416257|||
|||257938416|||
|||719352648|||
|||3256791**0**0|||
|||000000000|||
|||000000000|||
|||000000000|||
|||000000000|||
There are no numbers to put in this cell, because all the numbers according to the rules of sudoku are already on the column, row or square!
It is a nightmare for me. Is there any way to this to work? If not, i guess I have to redo everything as if I were making a Sudoku game.
The problem is that it is not possible to generate a complete board using random numbers in most cases, you have to use backtracking in cases when it is not possibe to fi the next cell.
I have once written a sudoku game, so here's the piece of code that generates filled board.
This is the Cell class.
public class SudokuCell implements Serializable {
private int value;
private boolean filled;
private HashSet<Integer> tried;
public SudokuCell() {
filled = false;
tried = new HashSet();
}
public boolean isFilled() {
return filled;
}
public int get() {
return value;
}
public void set(final int number) {
filled = true;
value = number;
tried.add(number);
}
public void clear() {
value = 0;
filled = false;
}
public void reset() {
clear();
tried.clear();
}
public void show() {
filled = true;
}
public void hide() {
filled = false;
}
public boolean isTried(final int number) {
return tried.contains(number);
}
public void tryNumber(final int number) {
tried.add(number);
}
public int numberOfTried() {
return tried.size();
}
}
Here's the Field class (it's really handy to keep all data in just one object).
public class SudokuField implements Serializable {
private final int blockSize;
private final int fieldSize;
private SudokuCell[][] field;
public SudokuField(final int blocks) {
blockSize = blocks;
fieldSize = blockSize * blockSize;
field = new SudokuCell[fieldSize][fieldSize];
for (int i = 0; i < fieldSize; ++i) {
for (int j = 0; j < fieldSize; ++j) {
field[i][j] = new SudokuCell();
}
}
}
public int blockSize() {
return blockSize;
}
public int fieldSize() {
return fieldSize;
}
public int variantsPerCell() {
return fieldSize;
}
public int numberOfCells() {
return fieldSize * fieldSize;
}
public void clear(final int row, final int column) {
field[row - 1][column - 1].clear();
}
public void clearAllCells() {
for (int i = 0; i < fieldSize; ++i) {
for (int j = 0; j < fieldSize; ++j) {
field[i][j].clear();
}
}
}
public void reset(final int row, final int column) {
field[row - 1][column - 1].reset();
}
public void resetAllCells() {
for (int i = 0; i < fieldSize; ++i) {
for (int j = 0; j < fieldSize; ++j) {
field[i][j].reset();
}
}
}
public boolean isFilled(final int row, final int column) {
return field[row - 1][column - 1].isFilled();
}
public boolean allCellsFilled() {
for (int i = 0; i < fieldSize; ++i) {
for (int j = 0; j < fieldSize; ++j) {
if (!field[i][j].isFilled()) {
return false;
}
}
}
return true;
}
public int numberOfFilledCells() {
int filled = 0;
for (int i = 1; i <= fieldSize; ++i) {
for (int j = 1; j <= fieldSize; ++j) {
if (isFilled(i, j)) {
++filled;
}
}
}
return filled;
}
public int numberOfHiddenCells() {
return numberOfCells() - numberOfFilledCells();
}
public int get(final int row, final int column) {
return field[row - 1][column - 1].get();
}
public void set(final int number, final int row, final int column) {
field[row - 1][column - 1].set(number);
}
public void hide(final int row, final int column) {
field[row - 1][column - 1].hide();
}
public void show(final int row, final int column) {
field[row - 1][column - 1].show();
}
public void tryNumber(final int number, final int row, final int column) {
field[row - 1][column - 1].tryNumber(number);
}
public boolean numberHasBeenTried(final int number, final int row, final int column) {
return field[row - 1][column - 1].isTried(number);
}
public int numberOfTriedNumbers(final int row, final int column) {
return field[row - 1][column - 1].numberOfTried();
}
public boolean checkNumberBox(final int number, final int row, final int column) {
int r = row, c = column;
if (r % blockSize == 0) {
r -= blockSize - 1;
} else {
r = (r / blockSize) * blockSize + 1;
}
if (c % blockSize == 0) {
c -= blockSize - 1;
} else {
c = (c / blockSize) * blockSize + 1;
}
for (int i = r; i < r + blockSize; ++i) {
for (int j = c; j < c + blockSize; ++j) {
if (field[i - 1][j - 1].isFilled() && (field[i - 1][j - 1].get() == number)) {
return false;
}
}
}
return true;
}
public boolean checkNumberRow(final int number, final int row) {
for (int i = 0; i < fieldSize; ++i) {
if (field[row - 1][i].isFilled() && field[row - 1][i].get() == number) {
return false;
}
}
return true;
}
public boolean checkNumberColumn(final int number, final int column) {
for (int i = 0; i < fieldSize; ++i) {
if (field[i][column - 1].isFilled() && field[i][column - 1].get() == number) {
return false;
}
}
return true;
}
public boolean checkNumberField(final int number, final int row, final int column) {
return (checkNumberBox(number, row, column)
&& checkNumberRow(number, row)
&& checkNumberColumn(number, column));
}
public int numberOfPossibleVariants(final int row, final int column) {
int result = 0;
for (int i = 1; i <= fieldSize; ++i) {
if (checkNumberField(i, row, column)) {
++result;
}
}
return result;
}
public boolean isCorrect() {
for (int i = 0; i < fieldSize; ++i) {
for (int j = 0; j < fieldSize; ++j) {
if (field[i][j].isFilled()) {
int value = field[i][j].get();
field[i][j].hide();
boolean correct = checkNumberField(value, i + 1, j + 1);
field[i][j].show();
if (!correct) {
return false;
}
}
}
}
return true;
}
public Index nextCell(final int row, final int column) {
int r = row, c = column;
if (c < fieldSize) {
++c;
} else {
c = 1;
++r;
}
return new Index(r, c);
}
public Index cellWithMinVariants() {
int r = 1, c = 1, min = 9;
for (int i = 1; i <= fieldSize; ++i) {
for (int j = 1; j <= fieldSize; ++j) {
if (!field[i - 1][j - 1].isFilled()) {
if (numberOfPossibleVariants(i, j) < min) {
min = numberOfPossibleVariants(i, j);
r = i;
c = j;
}
}
}
}
return new Index(r, c);
}
public int getRandomIndex() {
return (int) (Math.random() * 10) % fieldSize + 1;
}
}
And finally the function that fills the game board
private void generateFullField(final int row, final int column) {
if (!field.isFilled(field.fieldSize(), field.fieldSize())) {
while (field.numberOfTriedNumbers(row, column) < field.variantsPerCell()) {
int candidate = 0;
do {
candidate = field.getRandomIndex();
} while (field.numberHasBeenTried(candidate, row, column));
if (field.checkNumberField(candidate, row, column)) {
field.set(candidate, row, column);
Index nextCell = field.nextCell(row, column);
if (nextCell.i <= field.fieldSize()
&& nextCell.j <= field.fieldSize()) {
generateFullField(nextCell.i, nextCell.j);
}
} else {
field.tryNumber(candidate, row, column);
}
}
if (!field.isFilled(field.fieldSize(), field.fieldSize())) {
field.reset(row, column);
}
}
}
The point is that you save the numbers you've already tried for each cell before moving on. If you have to the dead end, you simply need to try another number for the previous cell. If none are possible, erase that cell and step one cell back. Sooner or later you will get it done. (It actuay takes tiny amount of time).
Start out with a solved Sudoko like this:
ABC DEF GHI
329 657 841 A
745 831 296 B
618 249 375 C
193 468 527 D
276 195 483 E
854 372 619 F
432 716 958 G
587 923 164 H
961 584 732 I
And then permutate it by switching columns and switching rows. If you only switch within the following groups ABC, DEF, GHI, the Sudoku is still solved.
A permutated version (switching columns):
BCA DFE IGH
293 675 184 A
457 813 629 B
186 294 537 C
931 486 752 D
762 159 348 E
548 327 961 F
324 761 895 G
875 932 416 H
619 548 273 I
And after some more permutation (switching rows):
BCA DFE IGH
293 675 184 A
186 294 537 C
457 813 629 B
931 486 752 D
548 327 961 F
762 159 348 E
875 932 416 H
619 548 273 I
324 761 895 G
Your problem is you are using Strings. Try a recursive algorithm using integers. This algorithm will be useful for a sudoku of any size. While choosing random numbers within each call does work, it'll take much longer. If you choose a set of random numbers to go through if the next cell doesnt work, then you will not use the same number again. This algorithm will create a unique puzzle every time.
public class Sudoku {
//box size, and game SIZE ==> e.g. size = 3, SIZE = 9
//game will be the game
private int size, SIZE;
private int[][] game;
public Sudoku(int _size) {
size = _size;
SIZE = size*size;
game = generateGame();
}
//This will return the game
private int[][] generateGame() {
//Set everything to -1 so that it cannot be a value
int[][] g = new int[SIZE][SIZE];
for(int i = 0; i < SIZE; i++)
for(int j = 0; j < SIZE; j++)
g[i][j] = -1;
if(createGame(0, 0, g))
return g;
return null;
}
//Create the game
private boolean createGame(int x, int y, int[][] g) {
//An array of integers
Rand r = new Rand(SIZE);
//for every random num in r
for(int NUM = 0; NUM < size; NUM++) {
int num = r.get(NUM);
//if num is valid
if(isValid(x, y, g, num)) {
//next cell coordinates
int nx = (x+1)%SIZE, ny = y;
if(nx == 0) ny++;
//set this cell to num
g[x][y] = num;
//if the next cell is valid return true
if(createGame(nx, ny, g)) return true;
//otherwise return false
g[x][y] = -1;
return false;
}
}
return false;
}
private boolean isValid(int x, int y, int[][] g, int num) {
//Rows&&Cols
for(int i = 0; i < SIZE; i++)
if(g[i][y] == num || g[x][i] == num) return false;
//Box
int bx = x - x%size;, by = y - y%size;
for(int i = bx; i < bx + size; i++) {
for(int j = by; j < by + size; j++) {
if(g[i][j] == num)return false;
}
}
return true;
}
}
public class Rand {
private int rSize;
private int[] r;
public Rand(int _size) {
rSize = _size;
r = new int[size];
for(int i = 0; i < rSize; r++)r[i] = i;
for(int i = 0; i < rSize*5; r++) {
int a = (int)(Math.random()*rSize);
int b = (int)(Math.random()*rSize);
int n = r[a];
r[a] = r[b];
r[b] = n;
}
public void get(int i) {
if(i >= 0 && i < rSize) return r[i]; return -1;
}
}
You're going to have to implement a backtracking algorithm.
For each of the 81 locations, generate the set 1 through 9.
Repeat until solved
Solve one location. Pick one number from the set.
Remove that number from all the sets in the same row, column, and square.
If a conflict arises, backtrack to a known good position, and solve a different location.
You will probably have to use recursive functions so that you can backtrack.
You have at least few ways to do that, but usually you will need recurrence / backtracking. It would be great to have the solver also, just to check if partly filled puzzle has solution (and the unique one - for stoping criteria - if you want the real sudoku).
While performing backtracking / recurrence you will need:
to randomly select available empty cell (you can optimize this step by measuring digidts still free on the given cell, and then sorting)
to randomly select still available digit in that cell
you fill the cell and check if the solution exists, if yes - go further, if not - perform the step back.
Starting points:
- starting with completely empty puzzle
- starting with partially filled puzzle
- starting with solved puzzle (there are a lot of transformations not changing the solution existence, but making the puzzle different - i.e.: reflection, rotation, transposition, segment swapping, columns / rows swapping within segments, permutation, etc.)
I was recently using the Janet Sudoku library which provides solver, generator and puzzle transformation methods.
Janet Sudoku website
Please refer to the below source codes available on the GitHub
Sudoku Solver
Sudoku Generator
Sudoku Transformations
Library usage is pretty simple, ie:
SudokuGenerator g = new SudokuGenerator();
int[][] puzzle = g.generate();
SudokuSolver s = new SudokuSolver(puzzle);
s.solve();
int[][] solvedPuzzle = s.getSolvedBoard();
Best regards,
Just generate some random number between 1 to 9 and see it it fits the given cell[i][j] it promises you a new set of numbers every time as every cell number is generated randomly based on the current system time .
public int sudokuNumberSelector(int i, int j, int[][] sudoku) {
while (true) {
int temp = (int) ((System.currentTimeMillis()) % 9) + 1;//Just getting some random number
while (temp < 10) {
boolean setRow = false, setColomn = false, setBlock = false;
for (int a = 0; a < 9; a++) {
if (sudoku[a][j] == temp) {
setRow = true;
break;
}
}
for (int a = 0; a < 9; a++) {
if (sudoku[i][a] == temp) {
setColomn = true;
break;
}
}
for (int a = i - (i % 3); a < i - (i % 3)+ 3; a++) {
for (int b = j - (j % 3); b < j - (j % 3)+3; b++) {
if (sudoku[a][b] == temp) {
setBlock = true;
a = 3;
b = 3;
}
}
}
if(setRow | setColomn | setBlock == false){
return temp;
}
temp++;
}
}
}
The problem is to find the shortest path on a grid from a start point to a finish point. the grid is a 2 dimensional array filled with 0's and 1's. 1's are the path. I have a method that checks the neighbors of a given coordinate to see if its a path. The problem im having is with the boundaries of the grid. The right and bottom boundary can just be checked using the arrays length and the length of a column. But how would i check to make sure that i dont try to check a point thats to the left of the grid or above the grid?
This is my method
public static void neighbors(coordinate current, int[][] grid, Queue q)
{
int row = current.getRow();
int col = current.getCol();
if(grid[row-1][col] == 1)
{
if(grid[row][col] == -1)
{
grid[row-1][col] = grid[row][col] + 2;
}
else
{
grid[row-1][col] = grid[row][col] + 1;
}
coordinate x = new coordinate(row-1,col);
q.enqueue(x);
}
else if(grid[row+1][col] == 1)
{
if(grid[row][col] == -1)
{
grid[row+1][col] = grid[row][col] + 2;
}
else
{
grid[row+1][col] = grid[row][col] + 1;
}
coordinate x = new coordinate(row+1,col);
q.enqueue(x);
}
else if(grid[row][col-1] == 1)
{
if(grid[row][col] == -1)
{
grid[row][col-1] = grid[row][col] + 2;
}
else
{
grid[row][col-1] = grid[row][col] + 1;
}
coordinate x = new coordinate(row, col - 1);
q.enqueue(x);
}
else if(grid[row][col+1] == 1)
{
if(grid[row][col+1] == -1)
{
grid[row][col+1] = grid[row][col] + 1;
}
else
{
grid[row][col+1] = grid[row][col] + 1;
}
coordinate x = new coordinate(row, col + 1);
q.enqueue(x);
}
else
{
}
q.dequeue();
}
I assume that the leftmost and topmost indexes are 0 in your arrays, so just make sure that index-1 >= 0 before indexing into the appropriate array.