How do you search around any index in a 2D array? - java

So I'm making a program that takes in a 2D array of 5x5, and lists all the characters around any given index of the array. For example, if I input list[1][1], it will give the indexes: [0][0], [0][1], [0][2], [1][0], [1][2], [2][0], [2][1] ,[2][2].
I can print out all the letters around the indexes except for the ones on the edges such as index [0][0]. I can't seem to figure out how to get past that.
private static void checkSurrounding(char[][] list, int x, int y) {
for(int dx = -1; dx <= 1; dx++) {
for(int dy = -1; dy <= 1; dy++) {
if(!(dx == 0 && dy == 0)) {
System.out.print(list[x + dx][y + dy]);
}
}
}
}

Your code is almost correct! You exclude the middle point here:
private static void checkSurrounding(char[][] list, int x, int y) {
for(int dx = -1; dx <= 1; dx++) {
for(int dy = -1; dy <= 1; dy++) {
if(!(dx == 0 && dy == 0)) {
System.out.print(list[x + dx][y + dy]);
}
}
}
}
The only thing you miss is to avoid getting out of bounds. Just make sure that you do not get out of bounds and it should work impeccably:
private static void checkSurrounding(char[][] list, int x, int y) {
for(int dx = -1; dx <= 1; dx++) {
if ((x + dx >= 0) && (x + dx < list.length)) {
for(int dy = -1; dy <= 1; dy++) {
if ((y + dy >= 0) && (y + yd < list[x + dx].length) && (!(dx == 0 && dy == 0))) {
System.out.print(list[x + dx][y + dy]);
}
}
}
}
}

Related

Recursive Longest Common Substring (LCS) problem optmization

I have the following code in Java:
public static int Secret(String a, String b, int x, int y){
if ((x == -1) || (y == -1)) {
return 0;
}
if (a.charAt(x) == b.charAt(y)) {
return Secret(a, b, x-1, y-1) + 1;
} else {
int left = Secret(a, b, x, y-1);
int up = Secret(a, b, x-1, y);
if (left > up) {
return left ;
} else {
return up;
}
}
return -1;
}
This code looks like the Longest Common Substring Problem but with a garbage complexity. I am supposed to opmitize it to O(mn) (space and time).
I tried following the algorithm on the wikipedia (https://en.wikipedia.org/wiki/Longest_common_substring_problem), that is O(mn) (space and time).
public static int iterativeLCS(String a, String b, int x, int y) {
int[][] L = new int[x+1][y+1];
int z = 0;
for (int i = 0; i <= x; i++) {
for (int j = 0; j <= y; j++) {
if (a.charAt(i) == b.charAt(j)) {
if ((i == 0) || (j == 0)) {
L[i][j] = 1;
} else {
L[i][j] = L[i-1][j-1] + 1;
}
if (L[i][j] > z) {
z = L[i][j];
}
} else {
L[i][j] = 0;
}
}
}
}
But the results don't match for some inputs. For example:
xalmandriatico
talcolaritriom
13
13
Expected output (using the recursive alg): 8
Actual output (using the iterative alg from wikipedia): 2
Any idea on what I have to do?

Heuristics for 3D tic-tac-toe

Currently I'm trying to implement heuristics for a 3D tic-tac-toe but it seems like my counter is way of it,f but I'm unsure where I've done wrong, I'm not gonna post all of the code since it's a lot, but here is a part:
public void countDiagonal(GameState gameState) {
/*
* yz-plane (negativ)
*/
int z;
for (int x = 0; x < GameState.BOARD_SIZE; x++) {
for (int y = 0; y < GameState.BOARD_SIZE; y++) {
z = y;
if (gameState.at(x, y, z) == myPlayer) {
myCounter++;
opponentCounter = 0;
}
if (gameState.at(x, y, z) == opponentPlayer) {
opponentCounter++;
myCounter = 0;
}
if (gameState.at(x, y, z) == Constants.CELL_EMPTY) {
emptyCells++;
}
}
evaluateBoard();
myCounter = 0;
opponentCounter = 0;
emptyCells = 0;
}
The evaluation is done here:
public void evaluateBoard() {
if (myCounter == 1 && emptyCells == 3) {
myScore = myScore + 5;
}
if (myCounter == 2 && emptyCells == 2) {
myScore = myScore + 10;
}
if (myCounter == 3 && emptyCells == 1) {
myScore = myScore + 20;
}
if (myCounter == 4) {
myScore = myScore + 1000;
}
if (opponentCounter == 1 && emptyCells == 3) {
opponentScore = opponentScore + 5;
}
if (opponentCounter == 2 && emptyCells == 2) {
opponentScore = opponentScore + 10;
}
if (opponentCounter == 3 && emptyCells == 1) {
opponentScore = opponentScore + 20;
}
if (opponentCounter == 4) {
opponentScore = opponentScore + 1000;
}
}
When I try to run it, I use alpha-beta prune, but it seems like the calculation are done horrbly wrong, when I use the value, I take myScore - opponentScore and I use an alpha-beta tree with depth 1, but even after only playing one move, I'm down -15 in points, as I'm a noob in java, im therefore asking for help, is there an obvious mistake in my way of trying to evaluate the board?

How to avoid StackOverflow Error in Recursive MazeSolver

Like many other java students in college, I need to develop a maze program that solves the maze. My solveMaze method that implements recursion returned a stackoverflow runtime error. How do I solve this problem please? Does this have to do with my algorithm? Thanks in advance.
A) I created a solution maze that array that's going to hold the path to the exit.
B) Then, I implemented a method solveMaze() that took a step toward the exit everytime it's called.
Note: The isWall() method checks if the position you're moving to is a wall or not.
public void showPath() {
int[][] sol = new int[m.length][m[0].length];
for (int j = 0; j < sol.length; j++) {
for (int i = 0; i < sol[0].length; i++) {
sol[j][i] = m[j][i];
}
}
if (solveMaze(sol, m.length - 1, 0, exitCords) == false)
System.out.println("Solution doesn't exist");
else {
for (int y = 0; y < sol.length; y++) {
for (int x = 0; x < sol[0].length; x++) {
if (sol[y][x] == exitCords[0] && sol[y][x] == exitCords[1]) {
System.out.print("E ");
} else {
if (sol[y][x] == 1) {
System.out.print(" ");
} else if (sol[y][x] == 3) {
System.out.print("~");
} else {
System.out.print("# ");
}
}
}
System.out.println();
}
}
}
public boolean solveMaze(int[][] sol, int y, int x, int[] exitCords) {
//exitCords[] is a one-dimensional array that holds the x and y coordinate of the exit point on a maze.
if (y == exitCords[1] && x == exitCords[0]) {//Base Case
return true;
}
//North
if (!isWall(x, y - 1) && sol[y - 1][x] != 3) {
sol[y][x] = 3;//3 is assigned to positions you already visited.
y--;
sol[y][x] = 3;
//Implement recursion to call the solveMaze again on this line.
solveMaze(sol, y, x, exitCords);
return true;
}
//South
else if (!isWall(x, y + 1) && sol[y + 1][x] != 3) {
sol[y][x] = 3;
y++;
sol[y][x] = 3;
solveMaze(sol, y, x, exitCords);
return true;
}
//East
else if (!isWall(x + 1, y) && sol[y][x + 1] != 3) {
sol[y][x] = 3;
x++;
sol[y][x] = 3;
solveMaze(sol, y, x, exitCords);
return true;
}
//West
else if (!isWall(x - 1, y) && sol[y][x - 1] != 3) {
sol[y][x] = 3;
x--;
sol[y][x] = 3;
solveMaze(sol, y, x, exitCords);
return true;
}
/*The following line of code are to get out of dead ends and replace every position near a dead end with a wall*/
else if ((isWall(x, y - 1) && isWall(x, y + 1) && isWall(x + 1, y)) || (isWall(x, y - 1) && isWall(x, y + 1) && isWall(x - 1, y))
|| (isWall(x - 1, y) && isWall(x, y + 1) && isWall(x + 1, y)) || (isWall(x - 1, y) && isWall(x, y - 1) && isWall(x + 1, y))) {
if (isWall(x, y - 1) && isWall(x, y + 1) && isWall(x + 1, y)) {
sol[y][x] = 0;
solveMaze(sol, y, x - 1, exitCords);
return true;
}
if (isWall(x, y - 1) && isWall(x, y + 1) && isWall(x - 1, y)) {
sol[y][x] = 0;
solveMaze(sol, y, x + 1, exitCords);
return true;
}
if (isWall(x - 1, y) && isWall(x, y + 1) && isWall(x + 1, y)) {
sol[y][x] = 0;
solveMaze(sol, y - 1, x, exitCords);
return true;
}
if (isWall(x - 1, y) && isWall(x, y - 1) && isWall(x + 1, y)) {
sol[y][x] = 0;
solveMaze(sol, y + 1, x, exitCords);
return true;
}
}
return false;
}
You have different ways to solve the problem:
The first one is to rewrite your code without using recursion (no luck for tail recursion - Java doesn't have optimization for it)
Another way is to increase stack size using -Xss option
Or you can add actual depth check to solveMaze method, e.g.:
public void showPath() {
// ...
if (solveMaze(sol, m.length - 1, 0, exitCords , 0) == false) {
// ...
}
public boolean solveMaze(int[][] sol, int y, int x, int[] exitCords, int depth) {
if (depth > 64) {
return false;
}
// ...
solveMaze(sol, y, x, exitCords, depth + 1);
// ...
}
A stack overflow error means that your recursion has gone deeper than the language allows. For a small maze, this shouldn't happen, unless you are revisiting locations in the maze. As your code does not seem to make any effort to avoid that, you might want to fix that.

StackOverflowError during recursive calls to find closest empty index in 2D array

I am trying to use a recursive approach to figure out the closest empty element in my 2D array if the input index already has an element. For example, I call my method tryPlant(int X, int Y) to put a symbol in my 2D (32x32) array:
ecoArray[X][Y] == "." (empty) then fill it with "~"
If there is an element besides ".", then recursively find the next empty spot in the same row first, then column.
The code for the method is:
public void tryPlant(int X, int Y){
if (this.ecoArray[X][Y] == ".") {
this.ecoArray[X][Y] = "~";
}else{
if((Y - 1) >= 0) {
tryPlant(X, Y - 1);
}
else if((Y + 1) <= 32){
tryPlant(X, Y + 1);
}else if((X - 1) >= 0 ) {
tryPlant(X - 1, Y);
}else if((X + 1) <= 32){
tryPlant(X + 1, Y);
}
}
}
I am calling the method in another class like this:
Plant p1;
private void initPlants(){
int size = p1.initPop;
for (int i = 0; i < size; i++) {
int randX = randGen();
int randY = randGen();
Plant plant = new Plant(randX, randY, this.ecoArray);
}
}
The randGen() method returns a random integer between 0-31.
Sometimes the random generator gives me indexes such that they do not collide with other objects. An example of this (the | are obstacles):
I want to know why I get a stackoverflow error and what I can do to fix it. If you need any other portions of my code, please ask. I am pretty new to Java.
Edit
public static int left = 0;
public static int right = 0;
public void tryPlant(int X, int Y){
if (this.ecoArray[X][Y] == ".") {
this.ecoArray[X][Y] = "~";
}else{
if((Y - 1) >= 0) {
this.left++;
tryPlant(X, Y - 1);
}
else if((Y + this.left + 1) <= 32){
tryPlant(X, Y + this.left + 1);
this.left = 0;
}else if((X - 1) >= 0 ) {
this.right++;
tryPlant(X - 1, Y);
}else if((X + this.right + 1) <= 32){
tryPlant(X + + this.right + 1, Y);
this.right = 0;
}
}
}
Approximately what happens is: Each time a function is called it is stored in a memory stack. When the function return, what was stored is cleared. But, if you call too many functions, you fullfil the memory and a stackoverflow error is sent.
You get a stackoverflow error because somewhere you have a loop in your algorithm. That cause too many call to tryPlant().
First, when you find a way where you already pass, return. (where char == '~')
Second, where there is an obstacle, return. (where char == '|')
Third, you don't try all directions:
if ((Y - 1) >= 0) {
this.left++;
tryPlant(X, Y - 1);
} else if ((Y + this.left + 1) <= 32){
tryPlant(X, Y + this.left + 1);
this.left = 0;
} else if ((X - 1) >= 0 ) {
this.right++;
tryPlant(X - 1, Y);
} else if ((X + this.right + 1) <= 32){
tryPlant(X + + this.right + 1, Y);
this.right = 0;
}
I tried this and it seems to work:
public class Test {
private char[][] ecoArray;
public Test() {
String[] stringArray = new String[] {
"||.|.||..|..||.|.||||||||..||.||",
"||||....||..|||..||....|.||..|||",
"||||||...|.|||...||.|..||..||||.",
"||...||.|.|||.||||.|||||.|...||.",
"|.|....|.|||||||||..||.|.|.||...",
"..|||.||||...|..||.||..|..||||.|",
"..|.||||||..||.||||..|||.|.|...|",
"|||||.||.|||...||...||..||.|||..",
"||||.|..||||||..|.|||...||.||.|.",
"|||.|||||.|||||.||||.|....||||||",
"||...||||||.|.|||||||||||.|.|.||",
"|.|.||||||||.||||....|.||||.||||",
"||..||.||||.|..||.|||..||.|.||||",
"..||..|..||.|.|||..|||..|||||.|.",
"||||.|.||.||||.|||||..|||.|.....",
"..|.|.|||..|||..||.||||.|||.|..|",
"||||.|..|||||||.|||||.||.|.|....",
"..|...||...|||||.|...|..|...|||.",
"..|||||||..||...||||||..|..|||||",
"||||..||.|.|||||.||||.|||||.||..",
"|||||.||||.|....||||....||.||...",
"||..||.|||||.||||||..||..|....||",
"|.||||.||..|...|.|..|||.|.|||.||",
"...||||.|..|||.|||..|.||...|.|||",
".||||.|..|.|..||..||..||..||||||",
"|||.|||..|||..||||.||||.|.||.|||",
"|||||.||...|.|.|.||...|||..|.|||",
".||||.|.|.|||...|||.|||.....||||",
"|||.|||.|.|...||.|....||||.|.|||",
".||||||.|||||||...||..|||.||||.|",
"||||.|||||.|.||.||||..|.|||.||||",
"|.|.||||....|.||||||||.|||||.|.|"
};
this.ecoArray = new char[32][32];
int index = 0;
for (String s : stringArray) {
this.ecoArray[index] = s.toCharArray();
++index;
}
}
public void tryPlant(int X, int Y){
if (this.ecoArray[X][Y] == '~' || this.ecoArray[X][Y] == '|') {
return;
}
if (this.ecoArray[X][Y] == '.') {
this.ecoArray[X][Y] = '~';
if ((Y - 1) >= 0) {
tryPlant(X, Y - 1);
}
if((Y + 1) < 32){
tryPlant(X, Y + 1);
}
if((X - 1) >= 0 ) {
tryPlant(X - 1, Y);
}
if((X + 1) < 32){
tryPlant(X + 1, Y);
}
}
}
private void displayInConsole() {
for (char[] cl : this.ecoArray) {
System.out.println(cl);
}
}
public static void main(String[] args) {
for (int x = 0; x < 32; x++) {
for (int y = 0; y < 32; y++) {
Test t = new Test();
t.tryPlant(x, y);
System.out.println("After tryPlant('" + x + "','" + y + "'): ");
t.displayInConsole();
}
}
}
}
Is it doing what you need ? I don't really understand where you want to start and where you want to stop...
The result is too big sorry...

Map rotated 90 degrees?

I have a class Grid, which manages all map functions. The issue is, the pacman map is rotated by 90 degrees anticlockwise.
How it looks
How it should look
I got the 'fixed' version by swapping out grid[x][y] to be grid[y][x] inside isWall() (an untidy, incorrect method)
Here is the whole code for the Grid class;
package com.jackwilsdon.pacman.game;
import org.newdawn.slick.Graphics;
public class Grid {
public static final int BLOCK_SIZE = 20;
public int[][] grid = null;
public Grid()
{
grid = new int[][] { {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
{0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0},
{0,1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0},
{0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0},
{0,1,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,1,0},
{0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0},
{0,0,0,0,1,0,1,0,1,1,0,1,1,0,1,0,1,0,0,0,0},
{0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0},
{0,0,0,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,0,0,0},
{0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0},
{0,1,1,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,1,0},
{0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0},
{0,1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1,0},
{0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0},
{0,1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,0},
{0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0},
{0,1,0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0} };
}
public boolean isWall(int x, int y)
{
if (x >= 0 && x < grid.length && y >= 0 && y < grid[0].length)
{
return grid[y][x] == 1;
}
return true;
}
public void draw(Graphics g)
{
for (int cX = 0; cX < grid.length; cX++)
{
for (int cY = 0; cY < grid[cX].length; cY++)
{
if (this.isWall(cX, cY))
{
g.fillRect(cX*Grid.BLOCK_SIZE, cY*Grid.BLOCK_SIZE, Grid.BLOCK_SIZE, Grid.BLOCK_SIZE);
}
}
}
}
}
Have I made a silly mistake in my code?
I don't want to switch x and y, as that is no longer the proper format for the 2d array.
The problem I see with your code is that the bounds check is incorrect. In other words, this piece of code:
if (x >= 0 && x < grid.length && y >= 0 && y < grid[0].length)
{
return grid[y][x] == 1;
}
should actually be
if (x >= 0 && x < grid[0].length && y >= 0 && y < grid.length)
{
return grid[y][x] == 1;
}
Your current code works only because the dimensions are equal (the map is square).
You have the same error in draw function. In other words, it should be
for (int cY = 0; cY < grid.length; cY++)
{
for (int cX = 0; cX < grid[cY].length; cX++)
{
if (this.isWall(cX, cY))
{
g.fillRect(cX*Grid.BLOCK_SIZE, cY*Grid.BLOCK_SIZE, Grid.BLOCK_SIZE, Grid.BLOCK_SIZE);
}
}
}
In any case, grid[y][x] is correct and not grid[x][y] because grid[i] refers to the row at index i of the 2D array, not column.
This is just a symptom of the fact that grid[i][j] refers to the jth element in the ith sub-array, which is actually the position at the jth column and the ith row in your formatted grid.
Since you want x to represent the column and y to represent the row, grid[y][x] is the correct way to access a position in your array.

Categories