move to a new instance in an 2d array randomly once - java

so i a player on a 2d array, when i do an action i want the player to move to one of the 8 available blocks around him, the code below moves him randomly but does it twice
Map Before Moving
GrassGrassGrassGrass
Grass Rek GrassGrass
GrassGrassGrassGrass
GrassGrassGrassGrass
Random Movement
0 0
0 0 //This shouldn't be happening
Map After Moving
GrassGrassGrassGrass
GrassGrassGrassGrass
GrassGrassGrassGrass
GrassGrassGrass Rek
import java.util.Random;
public class command_Movment implements command_Move {
inSwamp map = new inSwamp();
inSwamp rek = new Rek();
Random random = new Random();
int row = random.nextInt(3);
int col = random.nextInt(3);
#Override
public Command move() {
for (int i = 0; i < map.grid.length; i++) {
for (int j = 0; j < map.grid[i].length; j++) {
if (map.grid[i][j] == rek.getName()) {
try {
map.grid[i][j] = "Grass";
if (row == 0) {
i++;
}
if (row == 1) {
i--;
}
if (col == 0) {
j++;
}
if (col == 1) {
j--;
}
map.grid[i][j] = rek.getName();
System.out.println(col + " " + row);
break;
} catch (ArrayIndexOutOfBoundsException exception) {
if (row == 0) {
i--;
}
if (row == 1) {
i++;
}
if (col == 0) {
j--;
}
if (col == 1) {
j++;
}
map.grid[i][j] = rek.getName();
System.out.println("Error");
break;
}
}
}
}
return null;
}
}

Firstly, you shouldn't use == to compare strings, you should use equals method. so replace if (map.grid[i][j] == rek.getName()) with if (map.grid[i][j].equals(rek.getName())).
Edit: PLEASE don't use label to break the modularity of the program!
Please don't use catching ArrayIndexOutofBound exception to determine if an array index is correct or not. The exception should NOT happen. You should check the index first.
I updated my program for your random move: basically I thin you want to:
1) randomly move up or move down from the original position 2) if move up or move down exceeds the boundary of the matrix, don't move in that direction.
The following program should move rek to one of its 8 neighbors randomly without causing any ArrayIndexOutOfBoundException.
public Command move() {
// randomly determine the moving direction
// -1 means move left, 1 means move right
int horizontal_direction = Math.random() > 0.5 ? -1 : 1;
// -1 means move up, 1 mean move down
int vertical_direction = Math.random() > 0.5 ? -1 : 1;
for (int i = 0; i < map.grid.length; i++) {
for (int j = 0; j < map.grid[i].length; j++) {
if (map.grid[i][j].equals(rek.getName())) {
map.grid[i][j] = "Grass"; // replace rek's current position with Grass\
// if the newRow exceeds the boundaries, don't move in that direction
int newRow = i + horizontal_direction;
if (newRow < 0 || newRow == map.grid.length)
newRow = i;
// if the newCol exceeds the boundaries, don't move in that direction
int newCol = j + vertical_direction;
if (newCol < 0 || newCol == map.grid[i].length)
newCol = j;
map.grid[newRow][newCol] = rek.getName(); // move rek to the new position
System.out.println(newRow + " " + newCol);
break;
}
}
}
return null;
}

Add a label like this to your outer loop:
outer:
for (int i = 0; i < map.grid.length; i++) {
......
}
And in the try block, break the loop this way:
map.grid[i][j] = rek.getName();
System.out.println(col + " " + row);
break outer;

Related

Determining a winner on a grid of 8x8 tic tac toe

I'm trying to get the diagonals of a matrix that is at least 5x5; trying to loop through new columns in multiple rows. The example I have is 8x8. I can't get it to trigger the middle section as recorded "hits" in a sequence diagonally. Here is my code. This is regarding button presses that then register a persons choice, based on a player color. It loops through fine on the edges like this:
JButton[][] buttons = new JButton[8][8];
String red = "";
String green = "";
string blue = "";
int col = 0;
for (int row = 0; row < 8; row++, col++) {
if (buttons[row][col].getBackground() == Color.RED) {
red = red.concat("+");
} else if (buttons[row][col].getBackground() == Color.GREEN) {
green = green.concat("+");
} else if (buttons[row][col].getBackground() == Color.BLUE) {
blue = blue.concat("+");
} else {
red = red.concat(",");
green = green.concat(",");
blue = blue.concat(",");
}
}
I am trying to solve it like this:
JButton[][] buttons = new JButton[8][8];
String red = "";
String green = "";
string blue = "";
int col = 0;
for (int loop = 0; loop < 5; loop++) {
for (int row = (0 + loop); row < 8; row++, col++) {
if (buttons[row][col].getBackground() == Color.RED) {
red = red.concat("+");
} else if (buttons[row][col].getBackground() == Color.GREEN) {
green = green.concat("+");
} else if (buttons[row][col].getBackground() == Color.BLUE) {
blue = blue.concat("+");
} else {
red = red.concat(",");
green = green.concat(",");
blue = blue.concat(",");
}
}
}
What I came up with is that I am always checking only from top to bottom and
Only to the right
Only to the bottom
Bottom down diagonally
Bottom left diagonally
So in my opinion this covers all possible wining configurations if the search is done field by field from the top.
I use 1D array to represent the gameboard and I always check if any of those checks can be performed or not, and skipping the one that.
Running example tries to randomly fill the board of given dimensions step by step and stops execution when winning condition is met (or it is a tie).
For checking winning conditions I just define the "field index progression" for the next field so I can do the ckeck as simple for loop.
public class TheGame {
static int side = 8;
static int fieldsCount = side * side;
static int[] fields = new int[fieldsCount];
static int toWin = 5;
public static void main(String[] args) {
//generate list of random picks
List<Integer> fieldsToBet = IntStream.range(0, fields.length).boxed().collect(Collectors.toList());
Collections.shuffle(fieldsToBet);
Iterator<Integer> it = fieldsToBet.iterator();
Arrays.fill(fields, ' ');
//place bets using list above
char nextBet = 0;
while (it.hasNext()) {
nextBet = nextBet == 'o' ? 'x' : 'o';
Integer idx = it.next();
fields[idx] = nextBet;
char winner=(char) gameOver(idx); //check the condition, if game is done, return the winner
if (winner > 0) {
System.out.println();
System.out.println("Winner is: " + nextBet);
break;
}
}
printout();
}
private static int gameOver(Integer i) {
if (fields[i] == ' ') {
return 0;
}
int column = i % side; //this can be ommited if using nested for loops
int row = i / side;
boolean canCheckRight = column + toWin <= side;
boolean canCheckDown = row <= side - toWin;
boolean canCheckLeft = column + 1 - toWin >= 0;
boolean canCheckRightDownDiagonal = canCheckDown && canCheckRight;
boolean canCheckLeftDownDiagonal = canCheckDown && canCheckLeft;
boolean itsEnd =
canCheckRight && check(i, toWin, idx -> idx += 1) || //every field to check is just "next field"
canCheckDown && check(i, toWin, idx -> idx += side) || // every field to check is in next row
canCheckRightDownDiagonal && check(i, toWin, idx -> idx += side + 1) || // next field to check is in next row skewed by 1 to the right
canCheckLeftDownDiagonal && check(i, toWin, idx -> idx += side - 1);// next field to check is in next row skewed by 1 to the left
return itsEnd ? fields[i]:0;
}
private static boolean check(int idx, int iterations, Function<Integer, Integer> nextCoordinateProducer) {
int figure = fields[idx];
if (figure == ' ') {
return false;
}
for (int i = 1; i < iterations; i++) {
idx = nextCoordinateProducer.apply(idx);
if (figure != fields[idx]) {
return false;
}
}
return true;
}
public static void printout() {
for (int i = 0; i < fieldsCount; i += side) {
System.out.println(Arrays.stream(fields)
.skip(i)
.limit(side)
.boxed()
.map(v -> Character.valueOf((char) v.intValue()).toString())
.collect(Collectors.joining("|")));
}
}
}

TicTacToe.java issues with checkWinner method

So I created a checkWinner method, using 'row' and 'col' private variables so I can locate the 'curPlayer' position in the 2D array.
import java.util.Scanner;
public class TicTacBoard
{
private char[][] board; // 2-D array of characters
private char curPlayer; // the player whose turn it is (X or O)
// added so I can locate the current player location in the board
private int row;
private int col;
// Constructor: board will be size x size
public TicTacBoard(int size)
{
board = new char[size][size];
// initialize the board with all spaces:
for(row=0; row < board.length; row++)
for(col=0; col < board[row].length; col++)
board[row][col] = ' ';
curPlayer = 'X'; // X gets the first move
}
public void playGame()
{
display();
do
{
takeTurn();
display();
}while(!checkWinner(row, col));
}
/////// display ////////
// Display the current status of the board on the
// screen, using hyphens (-) for horizontal lines
// and pipes (|) for vertical lines.
public void display()
{
System.out.println();
dispRow(0);
System.out.println("-----");
dispRow(1);
System.out.println("-----");
dispRow(2);
System.out.println();
}
// Display the current status of row r of the board
// on the screen, using hyphens (-) for horizontal
// lines and pipes (|) for vertical lines.
private void dispRow(int r)
{
System.out.println(board[r][0] + "|" + board[r][1]
+ "|" + board[r][2]);
}
/////// takeTurn ////////
// Allow the curPlayer to take a turn.
// Send output to screen saying whose turn
// it is and specifying the format for input.
// Read user's input and verify that it is a
// valid move. If it's invalid, make them
// re-enter it. When a valid move is entered,
// put it on the board.
public void takeTurn()
{
Scanner scan = new Scanner(System.in);
int row, col;
boolean invalid;
do{
invalid = false; // assume correct entry
System.out.println("It is now " + curPlayer + "'s turn.");
System.out.println("Please enter your move in the form row column.");
System.out.println("So 0 0 would be the top left, and 0 2 would be the top right.");
row = scan.nextInt();
col = scan.nextInt();
if(row < 0 || col < 0 || row > 2 || col > 2)
{
System.out.println("Invalid entry: row and column must both be between 0 and 2 (inclusive).");
System.out.println("Please try again.");
invalid = true;
}
else if(board[row][col] != ' ')
{
System.out.println("Invalid entry: Row " + row + " at Column " + col
+ " already contains: " + board[row][col]);
System.out.println("Please try again.");
invalid = true;
}
}while(invalid);
// Now that input validation loop is finished, put the move on the board:
board[row][col] = curPlayer;
// Switch to the other player (take turns):
if(curPlayer == 'X')
curPlayer = 'O';
else
curPlayer = 'X';
}
// If the game is over, print who won (if anyone),
// and return true. If the game is not over, return false.
public boolean checkWinner(int row, int col)
{
// YOUR CODE GOES HERE
int x = row;
int y = col;
// board length is always 3 here
// check winner on column
for (int i = 0; i < board.length; i++) {
if (board[x][i] != curPlayer)
break;
if (i == board.length - 1)
System.out.println("Player " + curPlayer + " wins!");
return true;
}
//check winner on row
for (int i = 0; i < board.length; i++) {
if (board[i][y] != curPlayer)
break;
if (i == board.length - 1)
System.out.println("Player " + curPlayer + " wins!");
return true;
}
// checks winner on diagonal up
if (x == y) {
for (int i = 0; i < board.length; i++) {
if (board[i][i] != curPlayer)
break;
if (i == board.length - 1)
System.out.println("Player " + curPlayer + " wins!");
return true;
}
}
// check winner on diagonal down
if (x + y == board.length - 1){
for (int i = 0; i < board.length; i++) {
if (board[i][(board.length-1)-i] != curPlayer)
break;
if (i == board.length - 1)
System.out.println("Player " + curPlayer + " wins!");
return true;
}
}
// checks if board is full
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
if (board[i][j] == '-')
System.out.println("Nobody won, game ends in a draw!");
return true;
}
}
return false;
}
}
The code works but I while I was checking I got this:
| |
-----
| |
-----
| |
It is now X's turn.
Please enter your move in the form row column.
So 0 0 would be the top left, and 0 2 would be the top right.
2 0
| |
-----
| |
-----
X| |
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
at TicTacBoard.checkWinner(TicTacBoard.java:126)
at TicTacBoard.playGame(TicTacBoard.java:43)
at Main.main(Main.java:14)
I thought the board length is always 3 with the location ranging from 0 to 3. Any solutions to this error? Any more efficient ways to do this? Please let me know!
You have a "shadowing" problem - that is, you're shadowing the instance fields row and col with local variables in your takeTurn method.
In it's current state...
// Constructor: board will be size x size
public TicTacBoard(int size) {
board = new char[size][size];
// initialize the board with all spaces:
for (row = 0; row < board.length; row++) {
for (col = 0; col < board[row].length; col++) {
board[row][col] = ' ';
}
}
curPlayer = 'X'; // X gets the first move
}
after the constructor has run, row and col will be 3, but in takeTurn, you define row and col as local variables...
public void takeTurn() {
Scanner scan = new Scanner(System.in);
int row, col;
boolean invalid;
This means, that when you call checkWinner in the playGame method...
public void playGame() {
display();
do {
takeTurn();
display();
} while (!checkWinner(row, col));
}
You're passing the instance field values (of 3/3) and everything breaks.
So, the "quick" solution would be to remove the local declaration of row/col from takeTurn
public void takeTurn() {
Scanner scan = new Scanner(System.in);
//int row, col;
boolean invalid;
You could also fix this in the constructor, but making row/col local variables
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
board[row][col] = ' ';
}
}
but at some point, you need to update the row/col value for the player, but I might consider passing this information back from takeTurn rather than trying to use instance fields.
You also have a subtle, but common bug in your if statements. Without brackets, { and }, only the line IMMEDIATELY following the if statement will be executed when the conditional statement above is true. Your INDENTATION, however, indicates that you expected a different behavior.
For instance, your very first for loop is:
for (int i = 0; i < board.length; i++) {
if (board[x][i] != curPlayer)
break;
if (i == board.length - 1)
System.out.println("Player " + curPlayer + " wins!");
return true;
}
Here, only the System.out.println() line is executed when the if statement is true. The indentation of the return true; statement indicates that you expect it to only run with the println(), only when the conditional is true.
The return true; line is NOT dependent upon the preceding if statement, though, because it is not within brackets and the if statement only runs the line immediately following it. This means that the for loop is only ever running ONE ITERATION because the return line is STAND-ALONE and executes every single time, regardless of how those if statements evaluate.
You should ALWAYS, ALWAYS, ALWAYS add brackets to your if statements, even if they are "one-liners". With that in mind, I'd expect it to look more like:
for (int i = 0; i < board.length; i++) {
if (board[x][i] != curPlayer) {
break;
}
if (i == board.length - 1) {
System.out.println("Player " + curPlayer + " wins!");
return true;
}
}
Now the return line is only executed when the preceding if statement is true.

java iterating through index +1 and -1 for image errosion model

I have been given the task of writing a script to "erode" a binary image i.e. black and white photo.
This means that I must distinguish the parts that are white from black, where on an RGB scale, black is 0 and 1 is white.
Pixels are iterated over on a horizontal (i index) and vertical (j index). In order for a pixel to be considered a particular colour, it's immediate neighbours must be of that colour i.e. i+1 and i-1 and j+1 and j-1.
My attempt to code this is as follows:
public static BufferedImage getErodedImage(BufferedImage image) {
BufferedImage target = copyImage(image);
for (int i = 0; i < image.getRaster().getWidth(); i++) {
for (int j = 0; j < image.getRaster().getHeight(); j++) {
if (i + 1)||(i - 1) == 0 {
i = 0
}
else{
i = 1
}
}
if (j + 1)||(j - 1) == 0 {
j = 0
}
else{
j = 1
}
}
}
My attempt is very pythonic and returns lots of Errors and I'm guessing that I might need another for loop to iterate the -1, 0 and +1 values. and then set the value of the i-th pixel.
In your code a lot of syntax error, try to use this code:
public static BufferedImage getErodedImage(BufferedImage image) {
BufferedImage target = copyImage(image);
for (int i = 0; i < image.getRaster().getWidth(); i++) {
for (int j = 0; j < image.getRaster().getHeight(); j++) {
if (i + 1 == 0 || i - 1 == 0) { // not if (i + 1)||(i - 1) == 0
i = 0; // ;
}
else{
i = 1; // ;
}
if (j + 1 == 0 ||j - 1 == 0) { // not if (j + 1)||(j - 1) == 0 and this "if" should be in "for (int j..."
j = 0; // ;
}
else{
j = 1; // ;
}
}
}
}

Java 2D Array manipulation

I have to modify the below method:
private final static int NUM = 6;
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
if((grid[row][col] % 2) == 0) {
grid[row][col] = 0;
}
}
}
}
This method checks if it's a even number and if so it replaces its value with 0. Simple.
I now need to modify it so that it directs each cell to simultaneously replace its value with its number of diagonal neighbors that hold a value of 0.
I've thought about this for about an hour and tried many different solutions, most of which resulted in an out of bounds exception. I'm stumped and don't know how to accomplish this.
If the code is right, using the integers for the grid array below, it will reproduce the numbers shown in the bottom of the picture.
What is the problem, you just need to put if statements, like there can be maximum 4 possible neighbors so check that how many are equal to 0. But this is not enough you just need to add one more condition in each of the if statements. The condition would be that the neighbor you are trying to check is possible or not.
That is: Total 4 neighbors. If the coordinates of your main cell are x, y then:
1st Diagonal neighbor: x-1, y-1
2nd Diagonal neighbor: x-1, y+1
3rd Diagonal neighbor: x+1, y+1
4th Diagonal neighbor: x+1, y-1
These are all the 4 diagonal neighbors' coordinates but the last thing you need to check is whether they go out of bonds or not. For example for checking the 1st Diagonal neighbor I would do:
if((x-1)>0 && (y-1)>0){
//and then check here if that block is = `0`
}
and for other having say x+1 or y+1 you will need to check whether or not they are less than the NUM. Like if I want to check the 3rd Diagonal Neighbor:
if((x+1)<NUM && (y+1)<NUM){
//and then check here if that block is = `0`
}
Update: What do you mean by check here if that block is = 0?
If you want to check that is the diagonal neighboring blocks are equal to 0 or not then you will need to do it in a loop. Here is how:
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
if((grid[row][col] % 2) == 0) {
grid[row][col] = 0;
}
}
}
for(row = 0; row< NUM; row++){
for(int col = 0; col < NUM; col++) {
int count = 0;
// To check for the 1st Diagonal Neighbor
if((row-1)>0 && (col-1)>0){
if(grid[row-1][col-1]==0){
count++;
}
}
//Similarly for 2nd, 3rd and 4th Diagonal Neighbors
//and then
grid[row][col]=count;
}
}
}
Update 2:
For say the 3rd diagonal neighbor the code block would be like this:
if((row+1)<NUM && (col+1)<NUM){
if(grid[row+1][col+1]==0){
count++;
}
}
Answer
final private static int NUM = 6;
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
int counter = 0;
if((row - 1) > 0 && (col - 1) > 0) {
if(grid[row - 1][col - 1] == 0) {
counter++;
}
}
if((row - 1) > 0 && (col + 1) < NUM) {
if(grid[row - 1][col + 1] == 0) {
counter++;
}
}
if((row + 1) < NUM && (col - 1) > 0) {
if(grid[row + 1][col - 1] == 0) {
counter++;
}
}
if((row + 1) < NUM && (col + 1) < NUM) {
if(grid[row + 1][col + 1] == 0) {
counter++;
}
}
grid[row][col] = counter;
}
}
}

Creating a random colour grid with all adjacent colours different

So I have the following problem set to me: Write a program that takes an integer command-line argument N, and uses two nested for loops to print an N-by-N board that alternates between 6 colours randomly separated by spaces. The colours are denoted by letters (like 'r' for RED, 'b' for BLUE). You are not allowed to have two of the same colour next to eachother.
So, I know I probably need arrays to get around this problem. I tried several methods that all came up wrong. The following is one of my recent attempts, but I am unsure as how to now go through the grid and correct it. What the code does is make every row randomized with no colour left or right the same, but the columns are not fixed.
Note that I am a first year CS student with no programming history. I am guessing the solution to this problem isnt too complex, however, I cant see a simple solution...
int N = StdIn.readInt();
int array1[] = new int[N];
for (int column = 0; column < N; column++) {
int x = 0;
for (int row = 0; row < N; row++) {
int c = (int) (Math.random() * 6 + 1);
while (x == c) {
c = (int) (Math.random() * 6 + 1);
array1[row] = c;
}
if (c == 1) {
System.out.print("R ");
}
if (c == 2) {
System.out.print("O ");
}
if (c == 3) {
System.out.print("Y ");
}
if (c == 4) {
System.out.print("G ");
}
if (c == 5) {
System.out.print("B ");
}
if (c == 6) {
System.out.print("I ");
}
x = c;
}
System.out.println();
}
}
this was my solution for the problem. Quite convoluted though, but the logic behind it is straightforward. Each time you assign a new colour to your 2D array, you need only check the value of the array to the top and to the left of the position where you want to assign a new colour. You can only do this after you have assigned colours to the first row of the array however so you need to create separate conditions for the first row.
public class ColourGrid {
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
char[][] clrGrid = new char[N][N];
char colours[] = {'r','b','y','w','o','g'} ;
for (int counter = 0 ; counter < N; counter++) {
for (int counter2 = 0 ; counter2 < N; counter2++) {
if (counter == 0 && counter2 == 0) {
clrGrid[counter][counter2] = colours[(int)(Math.random()* 5 + 1)] ;
}
else if (counter != 0 && counter2 == 0) {
clrGrid[counter][counter2] = colours[(int)(Math.random()* 5 + 1)] ;
while (clrGrid[counter][counter2] == clrGrid[(counter)-1][counter2]) {
clrGrid[counter][counter2] = colours[(int)(Math.random()* 5 + 1)] ;
}
}
else if (counter == 0 && counter2 != 0) {
clrGrid[counter][counter2] = colours[(int)(Math.random()* 5 + 1)] ;
while (clrGrid[counter][counter2] == clrGrid[(counter)][counter2-1]) {
clrGrid[counter][counter2] = colours[(int)(Math.random()* 5 + 1)] ;
}
}
else if (counter != 0 && counter2 != 0) {
clrGrid[counter][counter2] = colours[(int)(Math.random()* 5 + 1)] ;
while (clrGrid[counter][counter2] == clrGrid[(counter)-1][counter2] || clrGrid[counter][counter2] == clrGrid[counter][(counter2)-1]) {
clrGrid[counter][counter2] = colours[(int)(Math.random()* 5 + 1)] ;
}
}
else {
clrGrid[counter][counter2] = colours[(int)(Math.random()* 5 + 1)] ;
}
}
}
for (int counter = 0 ; counter < N; counter++) {
System.out.println("");
for (int counter2 = 0 ; counter2 < N; counter2++) {
System.out.print(clrGrid[counter][counter2] + " ");
}
}
}
}

Categories