Having trouble getting a vertical detection of connect 4 win - java

Right now I have a school assignment where I have to create a connect 4 game in java without a gui using arrays. So far I have been able to get the game to detect a horizontal four in a row but I can't seem to get a vertical four in a row. Originally my array was a 6x7 but I have changed it to a 5x5 just to test the concept of swapping the arrays dementions. Just to make less clutter, I only included the part of the code with the vertical detection.
for (column = 0; column < board.length; column++) {
count_piece = 0;
max = 0;
for (row = 0; row < board.length; row++) {
if (max < count_piece) {
max = count_piece;
}
if (board[column][row] == 'X') {
count_piece++;
} else {
count_piece = 0;
}
}
}
System.out.println(max);
if (max == 4) {
System.out.println("\nYou Win!");
break;
}
If you need more information or if anything is not clear please let me know and i'll be glad to provide some more info.
EDIT:
Here is the one with the inverted loop.
for (row = 0; row < board.length; row++) {
count_piece = 0;
max = 0;
for (column = 0; column < board.length; column++) {
if (max < count_piece) {
max = count_piece;
}
if (board[column][row] == 'X') {
count_piece++;
} else {
count_piece = 0;
}
}
}

How about inverting your loop that way your inner loop changing will be the column instead of the row?
Also make your inner loop take the length of the single array you are in.
So instead of using board.length use something like board[i].length
Edit
I think your logic inside your inner loop is wrong...
Try this:
if (board[row][column] == 'X') {
count_piece++;
if(count_piece == 4) {
System.out.println("you win");
return;
}
} else {
count_piece = 0;
}
Here is both checks Horizontal and Vertical with any size array
int count_piece = 0;
//Checking Vertical Win
for (int row = 0; row < board.length; row++) {
count_piece = 0;
for (int column = 0; column < board[row].length; column++) {
if (board[row][column] == 'X') {
count_piece++;
if (count_piece == 4) {
System.out.println("you win");
return;
}
} else {
count_piece = 0;
}
}
}
//Checking Horizontal Win
for (int column = 0; column < board.length; column++) {
count_piece = 0;
for (int row = 0; row < board[column].length; row++) {
if (board[row][column] == 'X') {
count_piece++;
if (count_piece == 4) {
System.out.println("you win");
return;
}
} else {
count_piece = 0;
}
}
}

The main issue I see is assigning max before incrementing count_piece (meaning you would have to get 5 in a row).
Also as others have said length might have issue (not familiar with java so you might get away with it as length would either be 5 or 25 depending if it takes all indices or just the first columns indices. regardless when you go back to 6x7 it will break.
Also what your code is currently doing is going through each column and checking if the row has 4 in a row. What you want is to check for 4 in a row on both axis (my solution would be to have a row count variable and a column count variable (unless you need diagonal)).
adding
count_piece_Col=0; max=0;
above the first for loop and incrementing it similarly to the row count
*lazy way
for(column=0;column<board.length;column++)
{
count_piece=0; max_r=0;
for(row=0;row<board.length;row++)
{
if(max_r<count_piece)
{
max_r=count_piece;
}
if(board[column][row]=='X')
{
count_piece++;
}
else
{
count_piece=0;
}
}
}
for(row=0;row<board.length;row++)
{
count_piece=0; max_c=0;
for(column=0;column<board.length;column++)
{
if(max_c<count_piece)
{
max_c=count_piece;
}
if(board[column][row]=='X')
{
count_piece++;
}
else
{
count_piece=0;
}
}
}

Related

Display the corresponding horizontal and vertical histograms in java

I just found a good question about arrays in java and I'd like to solve it
This is the question and expected output Example:
I've already written a correct way to print horizontally.
My approach to write vertically is:
public static void verticalHistogram(int[] array, int maximum) {
int one=0, two=0 , three=0, four=0, five=0;
for (int i=0; i< array.length; i++) {
if(array[i] < 20) {
one +=1;
}
else if (array[i] >= 20 && array[i] <= 39 ) {
two +=1;
}
else if (array[i] >= 40 && array[i] <= 59 ) {
three +=1;
}
else if (array[i] >= 60 && array[i] <= 79 ) {
four +=1;
}
else {
five +=1;
}
}
int arr[] = {one,two,three,four,five};
for (int i = 0; i < maximum; i++) {
for (int j = 0; j < 5; j++) {
if (arr[j] > i) {
System.out.print("* ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
System.out.println("00-19 20-39 40-59 60-79 80-100 \n");
}
Overally your approach is correct:
First you create a histogram array from the input array. (this is what you already have)
You get the maximum value of the histogram array to know how many rows to print (you need to write it)
For each row starting from the maximum row and for each element in histogram, print the * if the histogram of the adequate cell should be visible, e.g.
for (int row = maximum; row > 0; --row) {
for (int j = 0; j < 5; j++) {
// if value of hist[j] >= row then print a star else dont print it
}
}

Problem with ship overlapping in 2D-arrays for Battleships game, Java

I am creating a simple console-based Battleships in Java, for people who is unfamiliar with the game, it's played on a 2D-grid where you can put down different sized ships either horizontally or vertically. In my example it is a 10x10 grid created by using a 2D char-array. The ships are NOT allowed to overlap each other, they can't share the same 1x1 grid.
I have managed to fix so they can't overlap each other, but the problem I have is if a ship share the same column or row (depending on if the ship is placed vertically or horizontally) at the STARTING POSITION, I can't place it down.
See example picture below for better understanding.
'0' is "empty" slots, 'S' is current placed ships(3-sized). I can place (in this example) 4-sized ships at blue markers, but I can't place them like the red markers
public void placeShip(ShipType shipType, int posX, int posY, int shipSize, Placement placement) {
boolean success = true;
char tempChar = 'x';
if(shipType == ShipType.BATTLESHIP)
tempChar = 'B';
else if(shipType == ShipType.CARRIER)
tempChar = 'C';
else if(shipType == ShipType.DESTROYER)
tempChar = 'D';
else if(shipType == ShipType.SUBMARINE)
tempChar = 'S';
if(placement == Placement.HORIZONTAL) {
for(int i = 0; i < posX+shipSize; i++) {
for(int j = 0; j < posX+shipSize; j++) {
if(board[i][posX-1] != '0' || board[posY-1][i] != '0') {
System.out.println("Can't place down the ship ");
success = false;
break;
}
}
}
if(success) {
System.out.println("Got space");
for(int i = 0; i < shipSize; i++) {
board[posY-1][posX-1+i] = tempChar;
success = false;
}
}
}
if(placement == Placement.VERTICAL) {
for(int i = 0; i < posY+shipSize; i++) {
for(int j = 0; j < posX+shipSize; j++) {
if(board[posY-1][i] != '0' || board[i][posX-1] != '0') {
System.out.println("Can't place down the ship ");
success = false;
break;
}
}
}
if(success) {
System.out.println("Got space");
for(int i = 0; i < shipSize; i++) {
board[posY-1+i][posX-1] = tempChar;
success = false;
}
}
}
}
Above is the code I use to place ships, where I send in Position X and Y and the size of the ship, and the direction of the ship.
You need to re-think your loops for checking if a ship can be placed down. Let's break down one of them into plain English:
if(placement == Placement.HORIZONTAL) {
for(int i = 0; i < posX+shipSize; i++) {
for(int j = 0; j < posX+shipSize; j++) {
if(board[i][posX-1] != '0' || board[posY-1][i] != '0') {
System.out.println("Can't place down the ship ");
success = false;
break;
}
}
}
First issue:
for(int i = 0; i < posX+shipSize; i++)
Why are we iterating from 0 to posX+shipSize? we only need to check shipSize spaces. So you should be looping from posX to posX+shipSize, or from 0 to shipSize, not a combination.
Second issue:
Despite your position being horizontal or vertical, you are nesting your for loops. Which means you're doing your loop shipSize times for no reason. You only need to do it once.
Third issue:
if(board[i][posX-1] != '0' || board[posY-1][i] != '0')
The position board[i][posX-1] has no meaning in this context, and is not related to the position of your ship, because you always start at i = 0. So no matter where you're trying to place your ship, if you have one in the same row or col, we have a problem. This is what's causing the issue in your question. Instead, it should be something like: if(board[posY-1][posX-1] != '0').
Lastly, why not just set the position of posX and posY properly? So you don't have to subtract 1 and confuse yourself.
Ultimately, your new block should look something like this (but I can't be sure since you didn't post a minimum reproducible example):
if(placement == Placement.HORIZONTAL) {
for(int i = 0; i < shipSize; i++) {
if(board[posY-1][posX-1+i] != '0') {
System.out.println("Can't place down the ship ");
success = false;
break;
}
}
// your code

Sudoko grid conversion from 9*9 to all grid size

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;
}
}

8 Bishops to occupy whole board [Backtracking]

I have a task to write a program which sets up 8 bishops in chess board to occupy whole board. It should end up when first solution is found and print everything out. Here's my written code in Java, and I struggle with finishing it using backtracking ( that place is commented in the code).
/*
* 0 - not occupied square
* 1 - bishop standing square
* 2 - occupied square (diagonal)
*/
public class BishopsBT {
public int [][] solution;
final int N = 8; // number of squares in column and row (chess board)
final int solved = 120; //Sum of 1's and 2's in case of all occupied board
int sum; //current sum of board
public BishopsBT(){
solution = new int [N][N] ;
}
public void solve() {
if(placeBishops(0)){
//print the result
clear(); // clears all 2's
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print(" " + solution[i][j]);
}
System.out.println();
}
} else{
System.out.println("NO SOLUTION EXISTS");
}
}
public boolean placeBishops (int bishop){
for (int row = 0; row < N; row++) {
// check if bishop can be placed
if (canPlace(solution, row, bishop)) {
// place the bishop
solution[row][bishop] = 1;
}
}
if (allSpaceOccupied()) {
return true;
} else {
// SOME BACKTRACKING CODE HERE
return false;
}
}
// check if bishop can be placed at matrix[row][column]
public boolean canPlace(int[][] matrix, int row, int column) {
// we need to check all diagonals
// whether no bishop is standing there
for (int i = row, j = column; i >= 0 && j >= 0; i--, j--) {
if (matrix[i][j] == 1) {
return false;
}
}
for (int i = row, j = column; i >= 0 && j < matrix.length; i--, j++) {
if (matrix[i][j] == 1) {
return false;
}
}
for (int i = row, j = column; i < matrix.length && j >= 0; i++, j--) {
if (matrix[i][j] == 1) {
return false;
}
}
for (int i = row, j = column; i < matrix.length && j < matrix.length; i++, j++) {
if (matrix[i][j] == 1) {
return false;
}
}
// if we are here that means we are safe to place Bishop
return true;
}
public boolean allSpaceOccupied() {
// clears previously occupied space
clear();
// occupies new space
for (int i = 0; i < solution.length; i++) {
for ( int j = 0; j < solution.length; j++) {
if (solution[i][j] == 1) diagonalOccupy(i,j);
}
}
sum = 0;
// counts sum of occupied space
for (int i = 0; i < solution.length; i++) {
for ( int j = 0; j < solution.length; j++) {
sum += solution [i][j];
}
}
if (sum == solved) return true;
// else
return false;
}
public void diagonalOccupy(int row, int column) {
// writes 2 in each bishop's occupied square
for (int i = row, j = column; i >= 0 && j >= 0; i--, j--) {
if (solution[i][j] == 0) {
solution[i][j] = 2;
}
}
for (int i = row, j = column; i >= 0 && j < solution.length; i--, j++) {
if (solution[i][j] == 0) {
solution[i][j] = 2;
}
}
for (int i = row, j = column; i < solution.length && j >= 0; i++, j--) {
if (solution[i][j] == 0) {
solution[i][j] = 2;
}
}
for (int i = row, j = column; i < solution.length && j < solution.length; i++, j++) {
if (solution[i][j] == 0) {
solution[i][j] = 2;
}
}
}
// clears all 2's on the board
public void clear() {
for (int i = 0; i < solution.length; i++) {
for ( int j = 0; j < solution.length; j++) {
if (solution[i][j] == 2) solution[i][j] = 0;
}
}
}
public static void main(String[] args) {
BishopsBT q = new BishopsBT();
q.solve();
}
}
The thing is that at the moment my program puts bishops in first column and this layout does not occupy all space. Of course, I could simply put everything in third column and problem is solved. However, I have to use backtracking and have no idea how. If you have any ideas or tips, I would be really glad to hear them.
Your solution assumes that all bishops must be placed in different rows. This is not true for all solutions. (There is a solution where all bishops are in the third or fourth column. You are not looking for all solutions, but if you were, you'd be missing out on many solutions by this assumption.)
You also don't need the canPlace check: There is no restriction that the bishops can't threaten each other. (This might be a valid technique to speed up the search, but again, you'll miss out on some solutions when you apply it. If you want to use it, there's no need to check all diagonal cells for already placed bishops; it is enough to check whether the current cell has been marked as "occupied" or threatened.)
If you are going to use a brute force approach with backtracking, you could test all possible combinations of bishops. That's C(64, 8) or 4,426,165,368 combinations.
You can cut down on the possibilities drastically, but not by assuming that bishops must be in diferent rows. Instead, note that your solution consists of two independent solutions. A bishop on a white square can only threaten white squares and a bishop on a black square can only threaten black squares. So find a solution to place four bishops on the board that threaten all white squares. Then
(If you want to find all solutions, find all k sub-solutions and combine them to k² complete solutions.)
This separation of cases cuts down the possible arrangements to test to C(32, 8), or 35,960. Your strategy to consider only configurations where there is exaclty one bishop per row checks 8^8 (about 16 million) possibilities. It misses some solutions and checks meny configurations where not four bishops are on white squares and four on black squares.
The principle of backtracking was given in the other answer. If you label the 32 white squares like this:
01 02 03 04
05 06 07 08
09 10 11 12
13 14 15 16
17 18 19 20
21 22 23 24
25 26 27 28
29 30 31 32
you can use an recursive approach like this one (in pseudo-Java):
bool place(int i, int start) {
if (i == 8) {
if (allOccupied()) {
print();
return true;
}
} else {
for (int j = start, j < 32; j++) {
int row = j / 4;
int col = 2 * (j % 4) + row % 2;
// add bishop at (col, row)
// save occupancy matrix
// add threat by (col, row) to matrix
if (place(i + 1, j + 1)) return true;
// revert matrix to saved matrix
// remove bishop from (col, row)
}
}
return false;
}
and start it with
place(0, 0);
You should do something like this :
public boolean placeBishops (int bishop){
if(bishop == 8){
if(allSpaceOccupied()){
//Print the board here, i.e found the solution
//also check the indexing of the bishop,
//i have assumed that they start from 0
return true;
}else{
return false;
}
}
for (int row = 0; row < N; row++) {
// check if bishop can be placed
if (canPlace(solution, row, bishop)) {
// place the bishop
solution[row][bishop] = 1;
boolean found = placeBishops(bishop+1);
if(found == true) return true;
solution[row][bishop] = 0;
}
}
return false;
}
we can check if a place is good for a paticular bishop or not, and accordingly increment the bishop count, if we do not find the solution going down that path, we reset the solution array for the current bishop index and the corresponding row for that bishop, so that we can look for another possible solution.

Intro programming: Conways Game of Life

I have been working on this code for a long time and i can't seem to figure it out. The top portion of my code works to pre-populate the grid. but for some reason I cant get my image to move and to grow as its supposed to. Please Help Me!!
import java.util.Random;
public class Life {
public static void main(String []args){
//Declaring and initializing grid variables
int gridSize = 200;
int cellSize = 3;
Grid grid = new Grid(gridSize, cellSize, "The Game of Life");
grid.setDelay(10);
Random r = new Random();
int aliveColor = 1;
int deadColor= 0;
int aliveCells;
int row = 0;
int column = 0;
int val = grid.getPos(row,column);
int generation;
int aliveNeighbors;
int cell;
//loop statement pre-populating the grid
for (row = 0; row <= gridSize-1; row++){
for(column = 0; column <= gridSize-1; column++){
if (r.nextInt(100) > 49){
grid.setPos(row, column, aliveColor);
}
else
grid.setPos(row, column, deadColor);
}
}
grid.initialize();
//Loop executing the rules of the Game of Life
do
{
row = 0;
column = 0;
generation = 0;
while (row <= gridSize-1){
while (column <= gridSize-1){
cell = grid.getPos(row, column);
aliveNeighbors = grid.matchingNeighbors(row, column,aliveColor);
if (cell == aliveColor)
{
if (aliveNeighbors == 2 || aliveNeighbors == 3){
val =1;
grid.setPos(row, column,val);
}
}
else if (cell == deadColor)
{
if (aliveNeighbors == 3){
val =1;
grid.setPos(row, column,val);
}
}
else{
val = 0;
grid.setPos(row,column,val);
}
column++;
}
row++;
grid.update();
}
grid.update();
generation++;
} while (generation >= 0);
}
}
EDIT
//Loop executing the rules of the Game of Life
do
{
row = 0;
column = 0;
generation = 0;
while (row <= gridSize-1){
while (column <= gridSize-1){
cell = grid.getPos(row, column);
aliveNeighbors = grid.matchingNeighbors(row, column,aliveColor);
if (cell == aliveColor)
{
if (aliveNeighbors == 2 || aliveNeighbors == 3){
val =1;
grid.setPos(row, column,val);
}
if (aliveNeighbors ==1 || aliveNeighbors == 4){
val = 0;
grid.setPos(row,column,val);
}
}
else
{
if (cell == deadColor)
{
if (aliveNeighbors == 3){
val =1;
grid.setPos(row, column,val);
}
if (aliveNeighbors == 1 || aliveNeighbors == 2 || aliveNeighbors == 4){
val = 0;
grid.setPos(row, column, val);
}
}
}
column++;
}
row++;
}
grid.update();
generation++;
} while (generation >= 0);
}
EDIT****
do
{
row = 0;
column = 0;
generation = 0;
while (row <= gridSize-1){
while (column <= gridSize-1){
cell = grid.getPos(row, column);
aliveNeighbors = grid.matchingNeighbors(row, column,aliveColor);
if (cell == aliveColor)
{
if (aliveNeighbors == 2 || aliveNeighbors == 3){
grid.setPos(row, column, aliveColor);
} else {
grid.setPos(row,column, deadColor);
}
}
else
{
if (cell == deadColor){
if (aliveNeighbors == 3){
grid.setPos(row, column,aliveColor);
} else {
grid.setPos(row,column,deadColor);
}
}
}
column++;
}
row++;
}
grid.update();
generation++;
} while (generation >= 0);
}
Two problems that I have noticed:
You should only update the grid after you complete updating all the cells.
Your indentation was off, and there was a } misplaced. After re-formatting, it can clearly be seen that you are not covering all the cases, so there are cells that do not get a new value. For example, if a cell is alive, you only handle the case when it has 2 or 3 neighbors, but there is no else to that if, and so, a live cell with 1 or 4 or more neighbors is never updated.
You may think that somehow in that case the code falls through to the general "else", but in fact, it never gets there. All cell values are either "alive" or "dead". So a construct such as:
if ( cell == aliveColor ) {
// Handle alive cell
} else if ( cell == deadColor ) {
// Handle dead cell
} else {
// Handle all other cases - but there are none!
}
Is equivalent to:
if ( cell == aliveColor ) {
// Handle alive cell
} else {
// Handle dead cell
}
The original "else" is never reached because there is no other case than "aliveColor" and "deadColor".
Response to your edit:
if (cell == aliveColor)
{
if (aliveNeighbors == 2 || aliveNeighbors == 3){
val =1;
grid.setPos(row, column,val);
}
if (aliveNeighbors ==1 || aliveNeighbors == 4){
val = 0;
grid.setPos(row,column,val);
}
}
For some reason, you seem to think that there could be at most 4 neighbors to each cell. Look at the example cell in your lab document again:
⬜︎⬜︎⬛︎
⬛︎⬜︎⬛︎
⬛︎⬛︎⬜︎
This cell has 5 dead neighbors, and 3 live ones. In fact, each cell can have up to 8 neighbors - the diagonal neighbors also count!
But your rules were:
If x is alive and has exactly 2 or 3 live neighbors, then x survives to the next generation. Otherwise it dies.
If x is dead and has exactly 3 live neighbors, then x is alive in the next generation. Otherwise it remains dead
This otherwise translates directly to else in programming. So instead of having a second if with the complementary condition (if there are 1, 4,5,6,7 or 8 live neighbors...), just give the first if an else:
if (aliveNeighbors == 2 || aliveNeighbors == 3) {
grid.setPos(row, column, aliveColor);
} else {
grid.setPos(row, column, deadColor);
}
The same thing applies to the rules for a dead cell, of course.
(Note that I also removed the val=1 and just used the value directly, val is superfluous. Also I used the names that explain what the value is rather than 1 and 0 (what if you want to change the game to work with green and red)?).
One important thing that I didn't notice before:
do
{
row = 0;
column = 0;
generation = 0;
while (row <= gridSize-1){
while (column <= gridSize-1){
You initialize both the row and the column to zero before the row loop.
This means that at the end of the first row, column stays gridSize-1 and is not set to zero again. So in fact you are only updating one row and then only the last column of each of the other rows.
It should be:
do
{
row = 0;
generation = 0;
while (row <= gridSize-1){
column = 0;
while (column <= gridSize-1){
Or you could use a for loop:
for ( row = 0; row < gridSize; row++ ) {
for ( column = 0; column < gridSize; column++ ) {
...
If you choose to do so, don't forget to remove the row++ and column++ from inside the loop body so that they are not incremented twice.
It looks like you are using only one grid, you need a second grid where to put the cells next state ...

Categories

Resources