How can i validate the surroundings of a ship in Battleship game? - java

This is supposed to prevent ship edges from touching other ships, but for some reason it doesn't work. Specially for my T shaped ship.
I think this has to do with the condition in the for loops, probably the boat.getLength()+1 is not enough there, but i don't know what else to try.
My mainBoard length is 10x10 and the line and col parameters are supposed to be what we get from the user scanner. My board in its natural state is initialized with character '~'. Each boat when its positioned successfully it changes the '~' with the character appointed to that specific boat.
public boolean validateSurrounding(Boat boat, int line, int col) {
int i = line;
int j = col;
for (i = i - 1; i < boat.getLength()+1; i++) {
for (j = j - 1; j < boat.getLength()+1; j++) {
if (i < 0 || i >= mainBoard.length || j < 0 || j >= mainBoard[0].length) {
continue;
}
if (mainBoard[i][j] != '~') {
return false;
}
}
}
return true;
}

You are damaging your inner loop starting condition.
int i = line;
int j = col;
for (i = i - 1; i < boat.getLength()+1; i++) {
for (j = j - 1; j < boat.getLength()+1; j++) {
The second iteration of the outer loop, j will start at boat.getLength()+1, which is the last value it had during the outer loop's first execution.
Instead, use:
int i;
int j;
for (i = line - 1; i < boat.getLength()+1; i++) {
for (j = col - 1; j < boat.getLength()+1; j++) {

Related

for loop that cycles between 0 and 1 in a 2D Array

I am currently making a chessboard and I need to assign every other cell with 1 or 0 with a double for loop.
My code looks like this:
(Processing / Java)
int[][] board = new int [8][8];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
board[i][j] = ?;
println(board[i][j]);
}
}
int[][] board = new int[8][8];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
board[i][j] = (j+i) % 2;
System.out.println(board[i][j]);
}
}
Looks like you're trying to assign color to a chessBoard.
0 - Black
1 - White
what you can do is,
if((i + j) % 2 == 0)
arr[i][j] = 0;
else
arr[i][j] = 1;

Specific cell test understanding the game of life Function

I have game of life exercise, I wrote the whole game only remains for me to write the function that checks the cell and decides whether he lives or dies.
the code:
public class lifeGame1 {
public static void main(String[]args){
gameOfLife(4, 5, 0.3);
}
public static void gameOfLife(int n, int m, double p){
int[][] matrix = new int[n][n];
// Random each matrix[i][j]
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(Math.random() < p)
matrix[i][j] = 1;
else
matrix[i][j] = 0;
} // for j
} // for i
System.out.println("The board is: ");
printMatrix(matrix);
int steps = 0;
while(steps < m){
int[][] newMatrix = new int[n][n];
for(int i = 0; i < newMatrix.length; i++){
for(int j = 0; j < newMatrix[i].length; j++){
newMatrix[i][j] = checkTheNewValueOfCell(matrix, i, j);
}
}
matrix = newMatrix;
System.out.println("The new board: ");
printMatrix(matrix);
steps++;
} // while
}
public static void printMatrix(int[][] matrix){
// Random each matrix[i][j]
for(int i = 0; i < matrix.length; i++){ // for each row
for(int j = 0; j < matrix[i].length; j++){ // print one row
System.out.print(matrix[i][j] + " ");
} // for j
System.out.println();
} // for i
}
}
Cell can make the dead or make a life according to the following rules:
1. Live cell can become dead as a result of:
A. If it has a density of more than three live neighbors.
B. Solitude if it has fewer than two live neighbors.
Hence the cell life continues to be my life if and only if it has two or three live neighbors.
2 dead cell can turn the cheek if it has exactly three live neighbors.
While the volume chamber has five neighbors) if Angular three (but also for work the same rules.
Code that checks the cell:
private static int checkTheNewValueOfCell(int[][] matrix, int i, int j) {
// check how much active neighbors
int countActiveNeighbors = 0;
for(int k = i-1; k <= i+1; k++){
for(int m = j-1; m <= j+1; m++){
if(k >= 0 && k < matrix.length && m >= 0 && m < matrix[0].length){ // אם בתחום
if(k != i || m != j)
if(matrix[k][m] == 1)
countActiveNeighbors++;
} // if
} // for m
} // for k
if(matrix[i][j] == 1){ // pail
if(countActiveNeighbors == 2 || countActiveNeighbors == 3)
return 1;
else
return 0;
}else{ // savil
if(countActiveNeighbors == 3)
return 1;
else
return 0;
}
}
I was helped by a lecturer who register their function and indeed work, but I did not realize it until the end and it's really important for me to understand it.
I do not understand the loop Four run from i-1 to i + 1 and the loop Four which run from j-1 to j + 1.
If I am in the first cell so I should get an error that the i-1 is equal to -1 and it is beyond the scope of the array does not it?
Can help writing a simple function so we can understand it better?
thank's
You get an ArrayIndexOutOfBoundsException only when you try to ACCESS an non-valid array index. But in the nested for loops, you have the following if statements:
if(k >= 0 && k < matrix.length && m >= 0 && m < matrix[0].length){ // אם בתחום
if(k != i || m != j)
if(matrix[k][m] == 1)
countActiveNeighbors++;
} // if
the top if tests that k and m are within the matrix (they are both positive and less than the length/width of the matrix). The bottom if then actually accesses the array at index k,m. Since you check for valid indices before you access, you won't get an Exception
I've commented the function to try and make it clearer. Paired with my comment hopefully it helps you understand!
private static int checkTheNewValueOfCell(int[][] matrix, int i, int j) {
// check how much active neighbors
int countActiveNeighbors = 0; // Neighbor count starts at 0
for(int k = i-1; k <= i+1; k++){ // Loop from 1 before the cell to 1 after the cell
for(int m = j-1; m <= j+1; m++){ // Loop from 1 above the cell to 1 below it
if(k >= 0 && k < matrix.length && m >= 0 && m < matrix[0].length){ // אם בתחום // This if statement skips out of bounds in case we are on an edge cell
if(k != i || m != j) // This if statement skips the current cell we are looking at
if(matrix[k][m] == 1)
countActiveNeighbors++; // Finally we increment if we find a neighbor cell
} // if
} // for m
} // for k

Iterate through a matrix with openJML

I have a class with a matrix initialized with all 0 and 1 in a specific position:
public class MatrixTest {
/*# spec_public #*/ int[][] griglia;
//#requires true;
//#ensures griglia[2][3] == 1;
public MatrixTest() {
griglia = new int[6][6];
for (int i=0; i < 6; i++) {
for (int j=0; j < 6; j++){
griglia[i][j] = 0;
}
}
griglia[2][3] = 1;
}
}
I would like to add an invariant to check that i always have only one 1 cell with a value of 1 and 35 cells with a value of 0. I tried doing that:
//# public invariant (\num_of int i, j; i >= 0 && i < 6 && j >= 0 && j < 6; griglia[i][j] == 1) == 1;
But it gives me invariant error just after the constructor. How can i iterate through a matrix to check a property?
After a lot of research, it seems like you can only do it with \forall, other commands didn't work for me.
\forall int i; i >= 0 && i < matrix.length; (\forall int j; j >= 0 && j < matrix[i].length; /* your check here */)
So, just don't use openJML if you are working with multi-dimensional arrays

Move left if there is a zero

I am trying to create a program that will take an array of integers, say {2,0,32,0,0,8} that can be of any length, and make it so all of the nonzero numbers are to the left at the lower indexes, and all the zeros are moved to the end.
For example, {2,0,32,0,0,8} becomes {2,32,8,0,0,0}.
This array can be of any length and contain any nonnegative integers.
This is what I have so far:
public static int[] moveLeft(final int[] a) {
for (int i = 0; i < a.length; i++) {
if (a[i] != 0) {
for (int j = 0; j < a.length; j++) {
if (a[j] == 0) {
a[j] = a[i];
a[i] = 0;
}
}
}
}
return a;
}
However, when I do this, it doesn't work for the first and second characters. If I have {1,2,0,1} it will return {2,1,1,0} when it should return {1,2,1,0}. Any help?
Your inner loop should stop before index i. Change this
for (int j = 0; j < a.length; j++) {
to
for (int j = 0; j < i; j++) {
And then your code works for me.

TicTacToe resizable board, WIN method error

Hi just attempted a TicTacToe project and was stuck about an error. My error has to do with checking for win solutions specifically diagonals.
What I need:
Create nested loop to loop down the array diagonally, then incrementing it so it would scan diagonally under or to the size until eventually scanning the entire array.
What I did:
I tried to make a nested for loop that would loop through the rows and add the to the counter until the end of the row then check if the counter was equal to the inline (amount in a row needed to win). I believe it works for the rows and columns.
Problem:
But for diagonals, I get an array out of bounds exception and I think it's because my a or b is added to i which could be gameBoard[3][4] when speaking of a 3x3 game board.
Attempt to solve:
I attempted a solution which you can see is the oddly placed for loop with j. So that i would only go to j and not go past the array limits.
I'm wondering if the logic behind this would work?
Sorry if the code is messy especially with the added for loops contain j
/*
* Method winner will determine if the symbol (X or O) wins
*
* #param symbol will be either X or O
* #return will return true if the symbol has won from any of the methods
*/
public boolean winner(char symbol) {
int counter = 0;
/* Scan from ROWS for any symbols inline to win */
for (int i = 0; i < gameBoard.length; i++) { // loop through the rows
for (int j = 0; j < gameBoard.length; j++) { // Loop through the columns
if (gameBoard[i][j] == symbol) {
counter++;
}
if (gameBoard[i][j] != symbol) { // If the next one in the row is not equal then reset counter to 0
counter = 0;
}
if (counter == inline) { // Counter will only equal inline if there is amount of inliine in a row
return true;
}
}
}
/* Scan and search for winning conditions in COLUMNS */
for (int i = 0; i < gameBoard.length; i++) { // loop through the rows
for (int j = 0; j < gameBoard.length; j++) { // Loop through the columns
if (gameBoard[j][i] == symbol) {
counter++;
}
if (gameBoard[j][i] != symbol) { // Reset counter to 0 if not equal to symbol
counter = 0;
}
if (counter == inline) { // If counter reached amount of inline then it must have had amount of inline in a row to win
return true;
}
}
}
/* Scan for RIGHT DIAGONALS for winning conditions */
// a shifts the position of diagonal to the right by one
// after diagonally looping through the board
for (int a = 0; a < gameBoard.length; a++) {
// i loops diagonally through the board
for (int j = gameBoard.length; j < 0; j--) {
for (int i = 0; i < j; i++) {
if (gameBoard[i][i + a] == symbol) {
counter++;
}
if (gameBoard[i][i + a] != symbol) {
counter = 0;
}
if (counter == inline) {
return true;
}
}
}
}
// b shifts the position of the diagonal down by one
for (int b = 1; b < gameBoard.length; b++) {
for (int j = gameBoard.length - 1; j < 0; j--)
// i loops diagonally through the board
for (int i = 0; i < j; i++) {
if (gameBoard[i + b][i] == symbol) {
counter++;
}
if (gameBoard[i + b][i] != symbol) {
counter = 0;
}
if (counter == inline) {
return true;
}
}
}
/* Scan for LEFT DIAGONALS for winning conditions */
// a shifts the position of diagonal to the left by one
for (int a = gameBoard.length; a >= 0; a--) {
for (int j = gameBoard.length; j < 0; j--) {
// i loops diagonally through the board
for (int i = 0; i < j; i++) {
if (gameBoard[i][a - i] == symbol) {
counter++;
}
if (gameBoard[i][a - i] != symbol) {
counter = 0;
}
if (counter == inline) {
return true;
}
}
}
}
// b shifts the position of the diagonal down by one
for (int b = 0; b < gameBoard.length; b++) {
for (int j = gameBoard.length - 1; j < 0; j--) {
// i loops diagonally in the left direction of through the board
for (int i = 0; i < j; i++) {
if (gameBoard[i + b][gameBoard.length - i] == symbol) {
counter++;
}
if (gameBoard[i + b][gameBoard.length - i] != symbol) {
counter = 0;
}
if (counter == inline) {
return true;
}
}
}
}
return false; // If it reaches here then no one has won yet and the game is ongoing
}
As far as i see in your code you must get Array Index Out Of Bounds Exception. I assume you try to implement classic tic-tac-toe, so we are dealing with 3x3 matrix. Here is how your game board is indexed:
[0.0] [1.0] [2.0]
[0.1] [1.1] [2.1]
[0.2] [1.2] [2.2]
So this is what happens in your loop with Right Diagonals:
int a increments 0 --> 2
int j decrements 2 --> 0
int i increments 0 --> 2
So your loop goes like this:
[0.0+0] --> i++ [1.1+0] --> i++ [2.2+0] j--
[0.0+0] --> i++ [1.1+0] j--
[0.0+0] a++
[0.0+1] --> i++ [1.1+1] --> i++ [2.2+1] j-- <--Here you get out of Array.
Additionally after checking through main diagonal, you go through [0.0] [1.1] which is not diagonal at all and you already did this in loops for rows. Even shifting through bottom diagonal is not needed ([0.1][1.2]) as you already did this in loops before. So checking through [0.0] [1.1] [2.2] will do work for you.
I believe that this is ineffective way to check for win condition. You can get rid of 3 loops, just by storing position of found element.
Sorry couldn't get the format for the comments so I'll post what I got here
/* Scan for RIGHT DIAGONALS for winning conditions */
int j = gameBoard.length
for (int a = 0; a < gameBoard.length; a++) {
// i loops diagonally through the board
for (int i = 0; i < j; i++) {
if (gameBoard[i][i + a] == symbol) {
counter++;
}
if (gameBoard[i][i + a] != symbol) {
counter = 0;
}
if (counter == inline) {
return true;
}
} j--; // Incrementing after the i for loop.
}
output:
a:0 i:0 j:3
[0.0+0] --> i++ [1.1+0] --> i++ [2.2+0] /*end for loop. i:2 j:3 a: 0 */
j-- a++
[0.0+1] --> i++ [1.1+1] /*end for loop. i:1 j:2 a: 1*/
j-- a++
[0.0+2] /* end for loop. i:0 j: 1 a:2 */
and the array stays in bounds while checking the diagonals. So I think think can work on a larger scale.

Categories