trying to dilate a binary image, getting a full white image instead - java

public static Color[][] dilate(Color[][] array) {
boolean white = false;
boolean black = false;
Color[][] copy = new Color[array.length][array[0].length];
for(int i = 0; i<array.length; i++){
for(int j=0; j<array[i].length; j++){
int g = array[i][j].getGreen();
if( g>= 0 && g< 50){
black = true;
//System.out.println("black is true");
} else if(g> 200 && g < 300){
white = true;
//System.out.println("white is true");
} else {
System.out.println("Nothing");
}
if (white == true){
//System.out.println("who");
for(int x = i-3; x <= i + 3; x++){
//int rem = k - Math.abs(i - x);
for(int y = j- 3; y<= j + 3; y++){
if (x>=0 && y>=0 && x < array.length && y < array[0].length && black == true){
copy[x][y] = new Color(255, 255, 255);
}
}
}
}
}
}
return copy;
}
So i'm trying to dilate a binary image. I take a white pixel from the Color array, and create a threshold. If within that threshold I find any any black pixel, i make it white and store those into another array. I can't figure out why my resulting image is all white.

Related

Check if a char is in a 2D array in java

I have been working on my homework of creating a simple chess program.
The chessboard is a 2D array, named board. The pieces are all single chars like R,Q,K, and empty space is filled with a ' ' char, so a space.
public static char[][] board;
The method get should return the char or whatever is there on the coordinate (x,y).
public char get(int x, int y) {
if(x < board[0].length && x >= 0 && y < board.length && y >= 0){
return board[x][y];
}
else
return '\0';
}
And the problem is that my program of evaluating who is the winner is not working as expected.
This program checks whether the king of each team is still in the chessboard, so the board array.
It should return 0 if both are still alive, 1, if only the white king is alive, and 2 if only the black king is alive.
I have made a program, or at least tried to make one, that goes through each coordinate and checks if there is a character 'K', which represents the white king, and 'S', the black king.
I have set the boolean kingIsAlive to false, so that if there is no K or S found in the array, it remains false.
Though, my code at the bottom, with the if and else that returns 0,1 or2, has the error, that kingWhiteIsAlive is always false and kingBlackIsAlive is always false.
So, I think my program of turning the kingIsAlive boolean to true is not working at all....
The errors I got is:
White should have won => expected: <1> but was: <-1>
No one should have won => expected: <0> but was: <1>
And after a couple of hours trying, I gave up and decided to ask here.
public int decideWinner(){
boolean kingWhiteIsAlive = false;
boolean kingBlackIsAlive = false;
for(int y = 0; y < board.length;y++){
for(int x = 0;x < board[0].length;x++){
if(get(x,y) == 'K'){
kingWhiteIsAlive = true;
}
}
}
for(int j = 0; j < board.length;j++){
for(int i = 0;i < board[0].length;i++){
if(get(i,j) == 'S'){
kingBlackIsAlive = true;
}
}
}
if(kingWhiteIsAlive && kingBlackIsAlive){
return 0;
}
else if(kingWhiteIsAlive && !kingBlackIsAlive){
return 1;
}
else if(!kingWhiteIsAlive && kingBlackIsAlive){
return 2;
}
else
return -1;
}
return -1 is for a test case that there are no kings from both teams.
I've tested your code & it's running perfectly, perhaps the problem is in your board initialization?
Try to debug your code by showing the actual content of the array at the beginning of decideWinner function.
I've used this initialization for the board, if it might help.
public void initBoard() {
board = new char[8][8];
// Init pawns
for (int j = 0; j < board.length; j++) {
board[j][1] = 'P';
board[j][6] = 'P';
}
// Rooks
board[0][0] = 'R';
board[7][0] = 'R';
board[0][7] = 'R';
board[7][7] = 'R';
// Knights
board[1][0] = 'N';
board[6][0] = 'N';
board[1][7] = 'N';
board[6][7] = 'N';
// Bishops
board[2][0] = 'B';
board[5][0] = 'B';
board[2][7] = 'B';
board[5][7] = 'B';
// Queens
board[3][0] = 'Q';
board[4][7] = 'Q';
// Kings
board[4][0] = 'K'; // White
board[3][7] = 'S'; // Black
// Empty space
for (int y = 0; y < board.length; y++) {
for (int x = 2; x < 6; x++) {
board[y][x] = ' ';
}
}
}
If you find a king, you need to interrupt your search. You can do it by a break statement.
for(int y = 0; y < board.length;y++){
for(int x = 0;x < board[0].length;x++){
if(get(x,y) == 'K'){
kingWhiteIsAlive = true;
break;
}
}
}
for(int j = 0; j < board.length;j++){
for(int i = 0;i < board[0].length;i++){
if(get(i,j) == 'S'){
kingBlackIsAlive = true;
break;
}
}
}

how to fill every second rectangle / Java / acm / chessboard

I'm currently developing a simple chessboard with Java ACM and I want to fill every second rectangle with a color but I don't know how to.
for (i = 0; i < 400; i += 50) {
for (j = 0; j < 400; j += 50) {
GRect rect = new GRect(100, 100, i, j);
add(rect);
}
}
I tried it with a if statment, but i doesn't worked for me.
With your pretty minimal description, here is my solution.
Here is a tile-able representation. 1/2/3/4 represent "cases"
Assuming: i and j are dimensions of the chessboard, 50x50 is the size of a square.
Assuming: Constructor for GRect is (width, height, ipos, jpos), with top left rectangle coordinate system.
Assuming: Only making rectangles for black squares (cases 2 and 3)
Notice: cases 2 is when (i % 100 == 50) AND (
However, what you probably want is a checker board patter:
for (int i = 0; i < 400; i += 50) {
for (int j = 0; j < 400; j += 50) {
if (i % 100 == 0) {
if (j % 100 == 50) {//case 3
add(new GRect(50,50, i, j));
}
} else if (i % 100 == 50) {
if (j % 100 == 0) { //case 2
add (new GRect(50,50, i, j));
}
}
}
}
Note: no one has any idea what the constructor of GRect is, so i've made my best guess as to what to do.
You could hold an ever switching running condition:
boolean white = true;
for (int i = 0; i < 400; i += 50) {
for (int j = 0; j < 400; j += 50) {
...
white = !white;
Or derive the color from i and j, which then better be [0, 8) indices:
for (i = 0; i < 8; ++i) {
for (j = 0; j < 8; ++j) {
boolean white = (i + j) % 2 == 0;
GRect rect = new GRect(100, 100, i*50, j*50);
rect.setFillColor(white ? Color.WHITE : Color.BLACK);
add(rect);
}
}

Programming a battleships ship placing algorithm(java)

So im programming a battleships game, and im trying to place ships on a board. I can get it to place the ship going left and going down from the starting point but cant get it going down or left. I understand my method overall is in-effeicient.
public static int[][] SetUserBoard(int[][] board) {
int x;
int y;
y = 0;
for (int z = 0; z < 10; z++) {
String gridv;
gridv = "";
int direction;
System.out.println("Set the Position for Ship no. " + (z+1));
Scanner s1 = new Scanner(System.in);
System.out.println("Enter the grid column(A-H):");
gridv = s1.nextLine();
if (gridv.equals("A")) {
y = 0;
}
if (gridv.equals("B")) {
y = 1;
}
if (gridv.equals("C")) {
y = 2;
}
if (gridv.equals("D")) {
y = 3;
}
if (gridv.equals("E")) {
y = 4;
}
if (gridv.equals("F")) {
y = 5;
}
if (gridv.equals("G")) {
y = 6;
}
if (gridv.equals("H")) {
y = 7;
}
System.out.println("Enter the y co=ordinate: ");
x = s1.nextInt();
x -= 1;
System.out.println("Enter the direction of the ship 0-3(0=down,1=right,2=up,3=left): ");
direction = s1.nextInt();
if(z == 0) { //placing 4 unit ship in first increment
if(direction == 0 && x < 5){ //vertical placement - down
for(int i=0; i < 4; i++) {
board[x][y] = 0;
x += 1;
}
}
if(direction == 1 && y < 5) { //horizontal placement - right
for(int i=0; i < 4; i++) {
board[x][y] = 0;
y += 1;
}
}
if(direction == 2 && x > 3 ) { //vertical placement - up
for(int i=0; i < 4; i++) {
board[x][y] = 0;
x -= 1;
}
}
if(direction == 3 && y > 3) { //horizontal placement - left
for(int i=0; i < 4; i++) {
board[x][y] = 0;
y -= 1;
}
}
}
...if(z > 0 && z < 3) { //placing 3 unit ships in 2nd and 3rd increment....
return board;
}
if you ignore the bottom part, and focus on the if z=0 part as that's which part i'm using to test this with my most updated try. Originally I had an indexing error which I managed to solve but now all the program does is run as usual except when moving onto the next one the board isn't updated and is still empty. So im stumped as to what logic to use for up/left.
For diagonal changes, you need to alter both i and j as you traverse the ship. For instance:
UP_LEFT = 4
...
ship_len = 4
...
if(direction == UP_LEFT &&
y > ship_len-1 &&
x > ship_len-1) { // SE-NW placement
for(int i=0; i < ship_len; i++) {
board[x][y] = 0;
y -= 1;
x -= 1;
}
}

How to keep track of winner in Connect Four Java game

This is a class that creates the game connect four in console and drawing panel, and I am having trouble in the connectedFour method where it determines if someone has gotten 4 discs in a row. The problem is, is that I am not sure how to set up my for loops to check through the array for four discs in a row
Here is my code:
import java.util.*;
import java.awt.*;
public class ConnectFour{
public static void main(String[] args){
//board
DrawingPanel panel = new DrawingPanel(550,550);
int rowAvailable;
Graphics g = panel.getGraphics();
g.drawLine(0,0,0,500);
g.drawLine(0,0,500,0);
g.drawLine(500,0,500,427);
g.drawLine(0,427,500,427);
for(int i = 0; i< 6; i++){
for(int j= 0; j<= 6; j++){
g.setColor(Color.YELLOW);
g.fillRect(j*71,i*71,71,71);
g.setColor(Color.WHITE);
g.fillOval(j*71,i*71,71,71);
}
}
//setBlankArray
Scanner console = new Scanner(System.in);
char[][] board = new char[6][7];
for(int j = 0;j <= 6; j++){
for(int i= 0; i < 6; i++){
board[i][j] = ' ';
}
}
boolean isBlack = true;
boolean isRed = false;
int column = 0;
boolean playersTurn = true;
boolean rightNum = false;
//oneTurn
while(getWinner(board, playersTurn)){
//while(playersTurn == true){
rightNum = false;
if(isBlack == true){
// displayCurrentPlayer
System.out.println("Black's Turn");
g.setColor(Color.WHITE);
g.drawString("Red Disc's Turn",200, 450);
g.setColor(Color.BLACK);
g.drawString("Black Disc's Turn",200, 450);
}
else{
// displayCurrentPlayer
System.out.println("Red's Turn");
g.setColor(Color.WHITE);
g.drawString("Black Disc's Turn",200, 450);
g.setColor(Color.RED);
g.drawString("Red Disc's Turn",200, 450);
}
System.out.print("Choose a column to place your disk (1-7): ");
while(rightNum == false){
column = (console.nextInt()) -1;
if(column >= 0 && column < 7 && board[0][column] == ' '){
rightNum = true;
}
else{
System.out.print("Try again: ");
}
}
drawBoard(column, board, isBlack, isRed, board, g);
isBlack = !isBlack;
}
if(isBlack == false){System.out.println("Congratulations Black Player");}
else{System.out.println("Congratulations Red Player");}
// use the while loop to say try again if the column is filled.
}
public static void drawBoard(int column, char[][] board, boolean isBlack, boolean isRed, char[][] availability,Graphics g){
char player = ' ';
if(isBlack == true){
g.setColor(Color.BLACK);
player = 'b';
}
else{
g.setColor(Color.RED);
player = 'r';
}
int x = 0;
int row = 5;
while(board[row-x][column] != ' '){
x++;
}
row = row-x;
g.fillOval((column * 71),(row * 71), 71,71);
board[row][column] = player;
}
public static boolean getWinner(char[][] board, boolean playersTurn){
int verticalCount = 0;
boolean isVertical = false;
for(int i = 6; i >= 0; i--){
verticalCount = 0;
for(int j = 5; j > 0; j--){
if(board[j][i] == board[j-1][i] && board[j][i] != ' '){
verticalCount++;
}
if(verticalCount == 4){
isVertical = true;
}
}
}
int horizontalCount = 0;
boolean isHorizontal = false;
for(int i =1; i <= 5; i++){
for(int j =1; j<6; j++){
if(board[j][i] == board[j][i+1] && board[j][i] != ' '){
horizontalCount++;
}
if(horizontalCount == 3){
isHorizontal = true;
}
}
}
int diagonalCount = 0;
boolean isDiagonal = false;
// for(int i = 0; i<=6; i++){
// for(int j =0; j<6; j++){
// if(board[i][j-1] == board[i][j]){
// diagonalCount++;
// }
// }
// }
if(isVertical || isHorizontal || isDiagonal){
playersTurn = false;
}
else{
playersTurn = true;}
return playersTurn;
}
}
I would implement this by checking if the game-winning condition is met after a disc has been placed. This way you aren't iterating over the entire board after each move.
Regardless, try this:
replace
while (gameWon == false ){
with
while (!connectedFour(board, playersTurn)) {
I don't think this will completely fix your problems as it looks like there are a handful of other things wrong with the code you've posted.

Calculating next frame in conways game of life using java

trying to create a Conways Game of life, but apparently the shapes are not like they have to be. Perhaps someone can help me find the issue.
For example the glider :
- X - - - -
- - X X - -
- X X - - -
- - - - - -
becomes this
- - X X - -
- X - - - -
X X X - - -
- X X X - -
but should be like this :
- - X - - -
- - - X - -
- X X X - -
- - - - - -
And my code looks like this
public Frame(int x, int y) {
setWidth(x);
setHeight(y);
if (x<1)
frame = null;
else if (y<1)
frame = null;
else {
frame = new String [x][y];
for (int i=0; i<frame.length; i++) {
for (int j=0; j<frame[i].length; j++) {
frame [i][j] = DEAD;
}
}
} // else
} // construktor
public Integer getNeighbourCount(int x, int y) {
Frame cell = new Frame(getHeight(), getWidth());
int counter = 0;
if(frame[x][y].equals(ALIVE))
{
counter = counter - 1;
}
for(int i=x-1; i<=x+1;i++){
if(i<frame.length && i>0){
for(int j=y-1; j<=y+1;j++){
if(j<frame[i].length && j>0){
if (frame[i][j]==ALIVE) {
counter++;
}
}
}
}
}
return counter;
}
public Frame nextFrame() {
// Returns next frame
Frame cell = new Frame(getWidth(), getHeight());
//cell.frame = new String[getWidth()][getHeight()];
for(int i = 0; i < frame.length; i++){
for(int j =0; j <frame[i].length;j++){
int n = getNeighbourCount(i,j);
if(cell.frame[i][j]==null) {
cell.frame[i][j] = DEAD;
}
if (isAlive(i, j) && n < 2 || n > 3) {
cell.frame[i][j] = DEAD;
}
if (isAlive(i, j) && n == 3 || n == 2){
cell.frame[i][j] = ALIVE;
}
if(!isAlive(i, j) && n == 3) {
cell.frame[i][j] = ALIVE;
}
if(isAlive(i, j) && n > 3){
cell.frame[i][j] = DEAD;
}
frame[i][j] = cell.frame[i][j];
}
}
cell.toString();
return cell;
}
`
Full code http://pastebin.com/LMwz724H
Here's a solution that works - using an enum for each cell and getting the i/j and x/y stuff right (I think). It certainly generates the correct first iteration:
static class GameOfLife {
final int w;
final int h;
State[][] frame;
enum State {
Dead, Alive;
}
public GameOfLife(int w, int h) {
this.w = w;
this.h = h;
frame = new State[h][w];
}
public void alive(int x, int y) {
frame[y][x] = State.Alive;
}
public void tick() {
frame = nextGeneration();
}
private int surroundingPopulation(int x, int y) {
int pop = 0;
for (int i = y - 1; i <= y + 1; i++) {
for (int j = x - 1; j <= x + 1; j++) {
// On frame - vertically.
if ((i >= 0 && i < h)
// On frame horizontally.
&& (j >= 0 && j < w)
// Alive
&& (frame[i][j] == State.Alive)
// Not the center.
&& (i != y || j != x)) {
pop += 1;
}
}
}
return pop;
}
private State[][] nextGeneration() {
State[][] next = new State[h][w];
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int pop = surroundingPopulation(x, y);
// Any live cell
if (frame[y][x] == State.Alive) {
if (pop < 2) {
// ... with fewer than two live neighbours dies, as if caused by under-population.
next[y][x] = State.Dead;
} else if (pop > 3) {
// ... with more than three live neighbours dies, as if by overcrowding.
next[y][x] = State.Dead;
} else {
// ... with two or three live neighbours lives on to the next generation.
next[y][x] = State.Alive;
}
} else {
// Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
if (pop == 3) {
next[y][x] = State.Alive;
}
}
}
}
return next;
}
#Override
public String toString() {
StringBuilder s = new StringBuilder();
for (State[] row : frame) {
for (State c : row) {
s.append(c == State.Alive ? "X" : " ");
}
s.append("\r\n");
}
return s.toString();
}
}
public void test() {
GameOfLife g = new GameOfLife(6, 6);
g.alive(1, 0);
g.alive(2, 1);
g.alive(3, 1);
g.alive(1, 2);
g.alive(2, 2);
System.out.println("Before:\r\n" + g);
g.tick();
System.out.println("After:\r\n" + g);
}
I believe the problem is that you are copying the new value as you iterate through the loop. This means neighbours are using the value from the next tick rather than the current one.
You can fix this by waiting until you calculated all new values in your new frame: cell.frame and then iterate through the frame again and copy from cell.frame to frame.
An alternative (better in my view) is to have away of cloning a frame during construction. Then you could change your nextFrame method to create a clone of frame and use the clone to set the new values in frame.
You are changing the DEAD and ALIVE frames while you iterate through the grid. You need to store the coordinates which should die or become alive and perform that afterwards.
Store the coordinates in two ArrayLists (dead, alive). The first and second position is the x and y axis, and change those coordinates according to whether they should become alive or not.
Here's a snippet from a simple test I wrote a while back. As others have mentioned, don't change values on an active board while still reading them. Instead, clone the board and make changes to the copy while reading the current board.
Another problem I bumped into a few times was iterating over y, then x for each y, but referring to x,y when accessing a point. It feels back to front :)
// Rules:
// 1) Any live cell with fewer than two live neighbours dies, as if caused by under-population.
// 2) Any live cell with two or three live neighbours lives on to the next generation.
// 3) Any live cell with more than three live neighbours dies, as if by overcrowding.
// 4) Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
void mutateGrid() {
// Copy existing grid into the next generation's grid
boolean[][] mutatedGrid = new boolean[gridXWidth][gridYHeight];
for (int i = 0; i < gridXWidth; i++) {
System.arraycopy(grid[i], 0, mutatedGrid[i], 0, gridYHeight);
}
// Start mutation rules
for (int y = 0; y < gridYHeight; y++) {
for (int x = 0; x < gridXWidth; x++) {
int liveNeighbours = countLiveNeighbours(x,y);
if (liveNeighbours < 2 || liveNeighbours > 3) {
mutatedGrid[x][y] = false;
}
else if (liveNeighbours == 3) {
mutatedGrid[x][y] = true;
}
}
}
grid = mutatedGrid;
}
int countLiveNeighbours(int x, int y) {
int count = 0;
for (int j = y-1; j <= y+1; j++) {
for (int i = x-1; i <= x+1; i++) {
if (i < 0 || j < 0 || i >= gridXWidth || j >= gridYHeight){
continue;
}
if (grid[i][j]) {
count++;
}
}
}
count -= grid[x][y]?1:0; // remove self from count
return count;
}

Categories