I am new to Java programming and would like to seek your help.
I'm trying to develop a simple minesweeper game using Java. However, I keep getting the error "Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1 at practice.week.pkg4.PracticeWeek4.main(PracticeWeek4.java:55)"
This occurs when I'm trying to place digits around the square which has a bomb. I understand that perhaps the 1 has went out of the array, causing the exception to occur. However, I'm not sure how to go about catching the error. Would appreciate any kind help.
Eg: Sample Output
1 1 1
1 B 1
1 1 1
Here is my code snippet:
public static void main(String[] args) {
// TODO code application logic here
int rows = 9;
int cols = 9;
char[][] map = new char[rows][cols];
int count = 0;
for(int i = 0; i<map.length; i++)
{
for(int j = 0; j<map[i].length; j++)
{
map[i][j] = '.';
}
}
Random rnd = new Random();
do
{
int x = rnd.nextInt(rows);
int y = rnd.nextInt(cols);
for(int i = 0; i<map.length; i++)
{
for(int j = 0; j<map[i].length; j++)
{
if(map[x][y] != 'B' && x > 0 & y > 0)
{
map[x][y] = 'B';
map[x-1][y-1] = '1';
map[x-1][y] = '1';
map[x-1][y+1] = '1';
map[x][y-1] = '1';
map[x][y+1] = '1';
map[x+1][y-1] = '1';
map[x+1][y] = '1';
map[x+1][y+1] = '1';
count++;
}
}
}
}
while(count < 10);
for(int x = 0; x<map.length; x++)
{
for(int y = 0; y <map[x].length; y++)
{
}
}
for(int x = 0; x<map.length; x++)
{
for(int y = 0; y<map[x].length; y++)
{
System.out.print(map[x][y] + " ");
}
System.out.println("");
}
}
The do-while loop for setting the mines is on the right track, but the way you are updating the counts for surrounding blocks is causing the IndexOutOfBoundsException. And these two loops
for(int i = 0; i < map.length; i++)
{
for(int j = 0; j < map[i].length; j++)
serve no purpose. You need to rearrange it to handle multiple mines, etc, so why not set all the mines first:
do
{
int x = rnd.nextInt(rows);
int y = rnd.nextInt(cols);
if (map[x][y] != 'B')
{
map[x][y] = 'B';
count++;
}
} while(count < 10);
Then go through the map, and count the number of mines surrounding each block:
for (int x = 0; x < map.length; x++)
{
for (int y = 0; y < map[x].length; y++)
{
if (map[x][y] == 'B')
continue;
// Count the number of mines around map[x][y]
int mines = 0;
for (int xOffset = -1; xOffset <= 1; xOffset++)
{
// This is an important step - without it, we will access elements off the edge of the map
if (x + xOffset < 0 || x + xOffset >= map.length)
continue;
for (int yOffset = -1; yOffset <= 1; yOffset++)
{
// Another check for the edge of the map
if (y + yOffset < 0 || y + yOffset >= map[x].length)
continue;
if (map[x + xOffset][y + yOffset] == 'B')
mines++;
}
}
map[x][y] = "012345678".charAt(mines); // Get the number as a character
}
}
Related
I have to create a Java program for Conway's Game Of Life in procedural manner and I'm only one step away from finishing - all I have left to do is figure out how to make the output change itself(something like a GIF). Instead, my program outputs all the results one by one. I'm figuring it should be some kind of a loop, but I'm not sure. Here's the code:
import java.util.Random;
import java.util.Scanner;
class gameOfLife {
public static void main(String[] args) {
//User input
Scanner in = new Scanner(System.in);
System.out.println("How many rows?");
int rows = in.nextInt();
System.out.println("How many columns?");
int cols = in.nextInt();
//Declaring variables and grids
int[][] grid = new int[rows][cols];
int[][] nextGrid = new int[rows][cols];
int[][] temp = new int [rows][cols];
//Initializing first generation
initiateGrid(grid);
printGameBoard(grid);
//Looping through 10 generations
for (int x = 0; x < 20; x++) {
applyTheRules(grid, rows, cols, nextGrid);
temp = nextGrid;
nextGrid = grid;
grid = temp;
printGameBoard(grid);
}
}
//Initiating first generation grid randomly
static void initiateGrid(int[][] grid) {
Random r = new Random();
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
grid[i][j] = r.nextInt(2);
}
}
}
//Printing out the game board
static void printGameBoard(int[][] grid) {
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
if (grid[i][j] == 0)
System.out.print(" . ");
else
System.out.print(" ■ ");
}
System.out.println();
}
System.out.println();
}
//Applying the rules of the game
static void applyTheRules(int [][] grid, int rows, int cols, int [][] nextGrid) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int count = 0;
if(i-1>=0 && i+1<grid.length && j-1>=0 && j+1<grid[i].length) {
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
count += grid[i + x][j + y];
}
}
count -= grid[i][j];
} else{
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
count += 0;
}
}
}
//Alive cell becomes dead, if there are more than
//3 or less than 2 neighbouring cells
if((grid[i][j]==1)&&(count<2)||(count>3))
nextGrid[i][j]=0;
//Dead cell becomes alive if there are exactly 3 neighbouring cells
else if((grid[i][j]==0)&&(count==3))
nextGrid[i][j]=1;
//State stays the same
else
nextGrid[i][j]=grid[i][j];
}
}
}
}
I have a project at school where I have to create a Sudoku Program. I have managed to get a Solver algorithm working but not a Generator. I spent a lot of time online to see if people had found ways to make a working one and I found a man named Mark Fredrick Graves, Jr. (https://www.youtube.com/user/mfgravesjr) who provided a very detailed code on the creation of a sudoku grid on his GitHub (https://github.com/mfgravesjr/finished-projects/tree/master/SudokuGridGenerator). However, I felt that using a one dimensional array was unnecessarily difficult in terms of finding the equations to access lines, columns and boxes. I therefore tried to translate his code into a two dimensional array but I am running into issues with some of his sorting methods and what some variables represent like "int step = (a%2==0? rowOrigin + j: colOrigin + j*9);". What I would like to know is how to translate the methods he uses from one dimensional arrays into two dimensional arrays. Below are the methods (code snippets) in question and my half attempt at translating it myself.
public int[] generateGrid(){
ArrayList<Integer> arr = new ArrayList<Integer>(9);
solvedGrid = new int[81];
for(int i = 1; i <= 9; i++) arr.add(i);
//loads all boxes with numbers 1 through 9
for(int i = 0; i < 81; i++){
if(i%9 == 0) {
Collections.shuffle(arr);
}
int perBox = ((i / 3) % 3) * 9 + ((i % 27) / 9) * 3 + (i / 27) * 27 + (i % 3);
solvedGrid[perBox] = arr.get(i%9);
}
//tracks rows and columns that have been sorted
boolean[] sorted = new boolean[81];
for(int i = 0; i < 9; i++){
boolean backtrack = false;
//0 is row, 1 is column
for(int a = 0; a<2; a++){
//every number 1-9 that is encountered is registered
boolean[] registered = new boolean[10]; //index 0 will intentionally be left empty since there are only number 1-9.
int rowOrigin = i * 9;
int colOrigin = i;
ROW_COL: for(int j = 0; j < 9; j++){
//row/column stepping - making sure numbers are only registered once and marking which cells have been sorted
int step = (a%2==0? rowOrigin + j: colOrigin + j*9);
int num = solvedGrid[step];
if(!registered[num]) {
registered[num] = true;
}else {
//if duplicate in row/column
//box and adjacent-cell swap (BAS method)
//checks for either unregistered and unsorted candidates in same box,
//or unregistered and sorted candidates in the adjacent cells
for(int y = j; y >= 0; y--){
int scan = (a%2==0? i * 9 + y: i + 9 * y);
if(solvedGrid[scan] == num){
//box stepping
for(int z = (a%2==0? (i%3 + 1) * 3: 0); z < 9; z++){
if(a%2 == 1 && z%3 <= i%3) {
continue;
}
int boxOrigin = ((scan % 9) / 3) * 3 + (scan / 27) * 27;
int boxStep = boxOrigin + (z / 3) * 9 + (z % 3);
int boxNum = solvedGrid[boxStep];
if((!sorted[scan] && !sorted[boxStep] && !registered[boxNum]) || (sorted[scan] && !registered[boxNum] && (a%2==0? boxStep%9==scan%9: boxStep/9==scan/9))){
solvedGrid[scan] = boxNum;
solvedGrid[boxStep] = num;
registered[boxNum] = true;
continue ROW_COL;
}else if(z == 8) {
//if z == 8, then break statement not reached: no candidates available
//Preferred adjacent swap (PAS)
//Swaps x for y (preference on unregistered numbers), finds occurence of y
//and swaps with z, etc. until an unregistered number has been found
int searchingNo = num;
//noting the location for the blindSwaps to prevent infinite loops.
boolean[] blindSwapIndex = new boolean[81];
//loop of size 18 to prevent infinite loops as well. Max of 18 swaps are possible.
//at the end of this loop, if continue or break statements are not reached, then
//fail-safe is executed called Advance and Backtrack Sort (ABS) which allows the
//algorithm to continue sorting the next row and column before coming back.
//Somehow, this fail-safe ensures success.
for(int q = 0; q < 18; q++){
SWAP: for(int b = 0; b <= j; b++){
int pacing = (a%2==0? rowOrigin+b: colOrigin+b*9);
if(solvedGrid[pacing] == searchingNo){
int adjacentCell = -1;
int adjacentNo = -1;
int decrement = (a%2==0? 9: 1);
for(int c = 1; c < 3 - (i % 3); c++){
adjacentCell = pacing + (a%2==0? (c + 1)*9: c + 1);
//this creates the preference for swapping with unregistered numbers
if((a%2==0 && adjacentCell >= 81)
|| (a%2==1 && adjacentCell % 9 == 0)) {
adjacentCell -= decrement;
}else {
adjacentNo = solvedGrid[adjacentCell];
if(i%3!=0
|| c!=1
|| blindSwapIndex[adjacentCell]
|| registered[adjacentNo]) {
adjacentCell -= decrement;
}
}
adjacentNo = solvedGrid[adjacentCell];
//as long as it hasn't been swapped before, swap it
if(!blindSwapIndex[adjacentCell]){
blindSwapIndex[adjacentCell] = true;
solvedGrid[pacing] = adjacentNo;
solvedGrid[adjacentCell] = searchingNo;
searchingNo = adjacentNo;
if(!registered[adjacentNo]){
registered[adjacentNo] = true;
continue ROW_COL;
}
break SWAP;
}
}
}
}
}
//begin Advance and Backtrack Sort (ABS)
backtrack = true;
break ROW_COL;
}
}
}
}
}
}
if(a%2==0) {
for(int j = 0; j < 9; j++) {
sorted[i*9+j] = true; //setting row as sorted
}
}else if(!backtrack) {
for(int j = 0; j < 9; j++) {
sorted[i+j*9] = true; //setting column as sorted
}
}else {//reseting sorted cells through to the last iteration
//backtrack = false;
for(int j = 0; j < 9; j++) {
sorted[i*9+j] = false;
}
for(int j = 0; j < 9; j++) {
sorted[(i-1)*9+j] = false;
}
for(int j = 0; j < 9; j++) {
sorted[i-1+j*9] = false;
}
for(int j = 0; j < 81; j++) {
sorted[j] = false;
}
i-=2;
}
}
}
if(!isPerfect(solvedGrid)) {
throw new RuntimeException("ERROR: Imperfect grid generated.");
}
return solvedGrid;
}
My code (unfinished)
public int[][] generateGrid(){
ArrayList<Integer> arr = new ArrayList<Integer>(9);
ArrayList<Integer> values = new ArrayList<Integer>(9);
solvedGrid = new int[9][9];
for(int i = 1 ; i <= 9; i++) {
arr.add(i);
values.add(i);
}
//Fill all boxes with number 1 to 9
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
if(j == 0) {
Collections.shuffle(arr);
}
solvedGrid[(i/3)*3+(j/3)][(i%3)*3+(j%3)] = arr.get(j);
}
}
//boolean[][] sorted = new boolean[9][9];
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
int[] rowColValues = new int[9];
rowColValues[j] = solvedGrid[0][j];
ArrayList<Integer> occurence = new ArrayList<Integer>();
for(int k = 0; k < rowColValues.length; k++) {
occurence.add((k+1), occurence.get(k+1)+1);
if(occurence.get(k+1) != 1) {
//swap with number in the box that isn't already in rowColValues
//Not sure how to do this...
//Create a method that takes the correct variables as parameters ?
break;
}
}
//Read the sudoku row then column wise and swap values that already exist in the column or row.
}
}
print2DGrid(solvedGrid);
return solvedGrid;
}
I wrote the following code to print a pyramid, but only one side is being printed.
int k = 7;
int m = 13;
int x = 6;
int y = x;
for (int i = 0; i < k; i++) {
for (int j = 0; j < m; j++) {
if (j < x) System.out.print(" ");
if ((j >= x) && (j <= y)) System.out.print("*");
}
System.out.println();
x++;
y++;
}
This code should print a pyramid starting with 1 asterisk at the top (first row containing the most spaces) and then increment by 2 each time until a pyramid with 7 rows is formed.
In your code x++; should be x--;
I'll summarize it for you:
int k = 7;
int m = 13;
int x = 6;
int y = x;
for (int i = 0; i < k; i++) {
for (int j = 0; j < m; j++) {
if (j<x)
System.out.print(" ");
if (j>=x && j<=y)
System.out.print("*");
}
System.out.println();
x--;
y++;
}
x needs to reduced each loop until the base of the triangle to maintain
the spaces amount.
your x and y are always the same, so this
if ((j >= x) && (j <= y))
will only be true once, when j is exactly = x = y.
I am trying to create a program that returns the maximum square submatrix of 1's from a square matrix of 0's and 1's. Right now I have figured out how to break the square up into a square submatrix starting at each number that equals 1. The problem is, as the program starts to get farther from the starting point of the matrix, it suddenly goes out of bounds, which I am suspecting has to do with how it calculates what part of the matrix to start from for each submatrix.
Here is my code:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter the number of rows and columns in the matrix (only one input, this is a square matrix): ");
int dimensions = input.nextInt();
int[][] matrix = new int[dimensions][dimensions];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
int n = input.nextInt();
if (n == 0 || n == 1)
matrix[i][j] = n;
else
System.out.print("Input only 0 or 1");
}
}
int[] largestBlock = findLargestBlock(matrix);
}
public static int[] findLargestBlock(int[][] m) {
int[] solution = new int[3];
//find rows with most consecutive 1's, then find columns with the same # of consecutive 1's
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
//"origin" for each iteration is (i, j)
if (m[i][j] == 1)
if (isSquare(m, i, j) == true) {
solution[0] = i; solution[1] = j; solution[2] = getSize(m, i, j);
}
}
}
return solution;
}
public static boolean isSquare(int[][] m, int i, int j) {
int k = m.length - i;
if (m[0].length - j < k)
k = m.length - j;
if (k < 2)
return false;
int[][] testSquare = new int[k][k];
for (int y = i; y < m.length - i; y++) {
for (int x = j; x < m[i].length - j; x++) {
testSquare[y - i][x - j] = m[y][x];
}
}
for (int y = 0; y < testSquare.length; y++) {
for (int x = 1; x < testSquare[y].length; x++) {
if (testSquare[y][x] != testSquare[y][x - 1])
return false;
}
}
for (int x = 0; x < testSquare[0].length; x++) {
for (int y = 1; y < testSquare.length; y++) {
if (testSquare[y][x] != testSquare[y - 1][x])
return false;
}
}
return true;
}
public static int getSize(int[][] m, int i, int j) {
int k = m.length - i;
if (m[0].length - j < k)
k = m.length - j;
return k;
}
I determined that this part of the program was causing the issue, apparently there is some flaw in it that sends the array x- or y- value out of bounds:
public static boolean isSquare(int[][] m, int i, int j) {
int k = m.length - i;
if (m[0].length - j < k)
k = m.length - j;
if (k < 2)
return false;
int[][] testSquare = new int[k][k];
for (int y = i; y < m.length - i; y++) {
for (int x = j; x < m[i].length - j; x++) {
**testSquare[y - i][x - j] = m[y][x];**
}
}
I'm very confused regarding the line in stars/in bold font, as I think this is the line causing the issue. However, I'm not sure how its causing the issue.
I think the loop you are looking for is this - since testSquare is square just start from it make sure its enumerated from 0 to k then find the other matrix indexes - m will never go more than k since k is the minimum so it starts from i and j and goes to i+k and j+k max.
if (m[i].length - j < k)
k = m[i].length - j;
for (int y = 0; y < k; y++) {
for (int x = 0; x < k; x++) {
testSquare[y][x] = m[i+y][j+x];
}
}
im stuck building a function that takes a given 2d-char array and a Point inside of it, that takes the given point coordinate and builds a new 2d-char array that surrounds the point.
for example if the original grid is:
a b c d e
z h a f c
g y z q x
r z x s a
k j h z z
the answer of point (0,0) should be:
? ? ?
? a b
? z h
the answer of point(2,2) should be:
h a f
y z q
z x s
public int numOfColors(Point p) {
char [][] neighbors = new char[3][3];
for(int i = 0; i < neighbors.length; i++){
for(int j = 0; j < neighbors.length; j++){
neighbors[i][j]='?';
}
}
int pX = p.getX(), pY = p.getY();
for(int i = pX - 1; (i < map.length) && (i < pX + 1) ; i++){ //runs on the original map and copy to neighbors
for (int j = pY - 1; (j < map.length) && (j < pY + 1); j++){
neighbors[i-pX+1][j-pY+1]=map[i][j];
}
}
for(int k = 0; k < neighbors.length; k++){ //runs on the neighbors array. if a point is an edge point.copy the given point color to the '?' cell
for(int l = 0; l < neighbors.length; l++){
if(neighbors[k][l]=='?')
neighbors[k][l]= map[pX][pY];
}
}
I've been sitting on this all day, the correct answer will be rewarded with a beer
I would like to begin from a helper method
private char getValue(int x, int y) {
if (x < 0 || x >= xSize || y < 0 || y >= ySize) {
return '?';
}
return neighbors[x][y];
}
public static void extract(char [][] arr, int row, int col){
char [][] ex = new char [3][3];
int rc = 0;
int cc = 0;
for(int i=row-1; i<row+2; i++){
for(int j=col-1; j<col+2; j++){
if(i < 0 || j < 0 || i >= arr.length || j >= arr[i].length){
ex[rc][cc] = '?';
} else {
ex[rc][cc] = arr[i][j];
}
cc++;
}
rc++;
cc = 0;
}
for(int i=0; i<3;i++){
for(int j=0; j<3; j++){
System.out.print (ex[i][j] +" ");
}
System.out.println();
}
}
Row, Col is Point(x,y).
I'm assuming the out of bounds exception is happened when using this bit of code, since you aren't checking if px - 1 is -1 and the same for py:
for(int i = px - 1; (i < map.length) && (i < px + 1) ; i++){ //runs on the original map and copy to neighbors
for (int j = py - 1; (j < map.length) && (j < py + 1); j++){
neighbors[i-pX+1][j-pY+1]=map[i][j];
}
}
You could change it to something like this:
int x1 = Math.max(p.getX() - 1, 0);
int x2 = Math.min(p.getX() + 1, map.length);
int y1 = Math.max(p.getY() - 1, 0);
int y2 = Math.min(p.getY() + 1, map[0].length);
int xCount = 0;
int yCount = 0;
and then:
for(int i = x1; i < x2; i++) { //runs on the original map and copy to neighbors
for (int j = y1; j < y2; j++) {
neighbors[xCount][yCount++]=map[i][j];
}
yCount = 0;
xCount++;
}