Initializing 2d java array - java

I am working on an extremely basic game. However when I try to create the array i am running into errors. The error is index out of bounds. However I thought I fixed it by adding the -1 to make sure I don't go out of bounds. can someone tell me, or give me a clue as to what I did wrong?
package gameProject;
public class world {
int numEnemies, numBosses;
int [][] world = new int[10][10];
public world(){
int[][] world = createArray(10,10);
populateWorld(world);
}
private int[][] createArray(int inX, int inY){
//create the array that holds world values
int[][] world = new int[inX][inY];
//initialize the world array
for(int i = 0; i < world.length - 1; i ++){
for(int j = 0; j < world[0].length - 1; j++){
world[i][j] = 0;
}
}
return world;
}
private void populateWorld(int[][] world){
for(int i = 0; i < world.length - 1; i++){
for(int j = 0; j < world[0].length - 1; i++){
world[i][j] = 0;
}
}
}
}

In your populateWorld method, change
for(int j = 0; j < world[0].length - 1; i++)
to
for(int j = 0; j < world[0].length - 1; j++)
You keep incrementing the wrong counter, going eventually out of its bounds. (10)
(PS: you don't need the length - 1 in your loops' condition, just length would do)

The error is in
for (int j = 0; j < world[0].length - 1; i++)
you should write
for (int j = 0; j < world[0].length - 1; j++)
instead.
Note that you can reduce your code a little bit:
You create the array for member World.world twice. Also the elements of an int array are already initialized to 0 so you don't need to do this explicitly.

You should just do
private int[][] createArray(int inX, int inY) {
int[][] world = new int[inX][inY];
for (int i = 0; i < inX; i++)
for (int j = 0; j < inY; j++)
world[i][j] = 0;
return world;
}
You never actually need to check the length of the world array, because the length was already passed in as a parameter value.
And then also
private void populateWorld(int[][] world) {
for (int i = 0; i < world.length; i++)// v error 'i' should be 'j'
for (int j = 0; j < world[i].length; j++) // <- error on this line
world[i][j] = 0;
}

Your basic problem is that you're incrementing the wrong loop variable.
Why? Because you're far off from any clean code.
Lemme show you how clean coding is done:
class names start with a capital letter, method and variable name with lower case letters
you might prefix your variables with their scope ('m' for member, 'p' for parameter, nothing for local variables). Saves you the all-time-reference to 'this'. Strongly depends on your code style. I highly suggest doing it, keeps your code clean and really easy to debug.
use the final and private keywords where possible
use descriptive variable names. Here especially x and y for loop variables, as you're abstracting a 2d-plane
Some more considerations:
usually games grow more complex. Usually simple primitives (like your int-array) will not suffice for long to store all relevant information. Use classes like Cell
use enums so you can lose magic numbers => coding, reading and debugging made a lot easier
So - after a lot of talk - here's the final code:
package gameproject;
/**
* Use comments like this to describe what the classes purpose is.
* Class comment is the most important one. If you can't tell what a method/variable is doing by its name, you should also comment methods and/or variables!
* #author JayC667
*/
public class World {
/*
* STATIC part of the class - keep separated from object code
*/
// you could/should also put these static classes to their separate files and make em non-static
/**
* Denotes, what a {#linkplain Cell} is occupied with
*/
static public enum CellType {
EMPTY, //
BOSS, //
ENEMY
}
/**
* Represents a single cell within the world. Stores information about its coodrinates (redundant) and its occupator (see {#linkplain CellType})
* #author JayC667
*/
static private class Cell { // use cell to store data for you
public final int mX; // x and y are actually not useful at the moment, you could also remove them
public final int mY;
private CellType mCellType = CellType.EMPTY;
public Cell(final int pX, final int pY) {
mX = pX;
mY = pY;
}
public CellType getCellType() {
return mCellType;
}
public void setCellType(final CellType pCellType) {
mCellType = pCellType;
}
}
// when possible, make methods static, unless you unnecessarily blow up the parameter list
// this is a typical demo for a factory method
static private Cell[][] createWorld(final int pWidth, final int pHeight) {
final Cell[][] newWorld = new Cell[pWidth][pHeight];
for (int y = 0; y < pHeight - 1; y++) {
for (int x = 0; x < pWidth - 1; x++) {
newWorld[y][x] = new Cell(x, y);
}
}
return newWorld;
}
/*
* OBJECT part of the class - keep separated from static code
*/
private final Cell[][] mWorld;
private final int mWorldWidth;
private final int mWorldHeight;
private final int mNumberOfEnemies;
private final int mNumberOfBosses;
public World(final int pWidth, final int pHeight, final int pNumberOfEnemies, final int pNumberOfBosses) {
if (pWidth < 1 || pHeight < 1) throw new IllegalArgumentException("World width and height must be greater than 0!");
if (pNumberOfEnemies < 0 || pNumberOfBosses < 0) throw new IllegalArgumentException("Enemy and boss counts must not be negative!");
if (pWidth * pHeight < pNumberOfEnemies + pNumberOfBosses) throw new IllegalArgumentException("World is too small for all the bad guys!");
mWorldWidth = pWidth;
mWorldHeight = pHeight;
mNumberOfEnemies = pNumberOfEnemies;
mNumberOfBosses = pNumberOfBosses;
mWorld = createWorld(pWidth, pHeight);
populateWorld();
}
// refers to many member variables, so not static (would only blow up parameter list)
private void populateWorld() {
for (int i = 0; i < mNumberOfBosses; i++) {
final Cell c = getRandomCell(CellType.EMPTY);
mWorld[c.mY][c.mX].setCellType(CellType.BOSS);
}
for (int i = 0; i < mNumberOfEnemies; i++) {
final Cell c = getRandomCell(CellType.EMPTY);
mWorld[c.mY][c.mX].setCellType(CellType.ENEMY);
}
}
private Cell getRandomCell(final CellType pCellType) {
while (true) { // TODO not a good, but simple solution; might run infinite loops
final int randomX = (int) (mWorldWidth * Math.random());
final int randomY = (int) (mWorldHeight * Math.random());
if (mWorld[randomY][randomX].getCellType() == pCellType) return new Cell(randomX, randomY);
}
}
}

Related

"Encoding" algorithm giving different result in separate method

So i set out to make a little "encoding" program that uses a simple algorithm and so far it all works. i came up with the algorithm, and then found the inverse of it to "decode" the given String.
How it works is that in command line you do "java Diver lock message password". It then takes the ascii values and runs it through the algorithm Z_n = (X_n + Y_n) / 2, giving you an "encoded" string that can then be used in the program arguments on start as "java Driver unlock code password". It takes these values and runs them through X_n = 2Z_n - y_n.
These algorithms work when simply using the lock portion, and i've put the same process at the end of lock that happens in the unlocking process, yet when trying only the locking process, the output is incorrect.
Here's a little snippet as to how i believe it is working
lock Oliver Chipper
unlock ĤƨƤnjƪƮä Chipper
x = message, y = password, z = code
x & y = z
z & y = x
I have a feeling that it has to do with the command line not taking in the symbols that are used as output, but a thorough explanation of what i've done would be great... Thank you!
public class Driver {
private static int[] x; //Message or code
private static int[] y; //Password
public static void main(String[] args) {
int SIZE = args[1].length() + args[2].length();
if (args[0].equals("lock")) {
lock(args, SIZE);
} else if (args[0].equals("unlock")) {
unlock(args, SIZE);
}
}
private static void lock(String[] args, int size) {
x = new int[size];
for (int i = 0; i < args[1].length(); i++) {
x[i] = args[1].charAt(i); //Message to ints
}
y = new int[size];
for (int i = 0; i < args[2].length(); i++) {
y[i] = args[2].charAt(i); //Password to ints
}
//code
int[] z = new int[size];
for (int i = 0; i < size; i++) {
z[i] = ((x[i] + y[i]) * 2); //Locking algorithm
System.out.print((char)z[i]);
}
System.out.println("\n");
for (int i = 0; i < size; i++) {
System.out.print((char)((z[i] / 2) - y[i])); //Unlocking algorithm
}
}
private static void unlock(String[] args, int size) {
x = new int[size];
for (int i = 0; i < args[1].length(); i++) {
x[i] = args[1].charAt(i); //Code to ints
}
y = new int[size];
for (int i = 0; i < args[2].length(); i++) {
y[i] = args[2].charAt(i); //Password to ints
}
for (int i = 0; i < size; i++) {
System.out.print((char)((x[i] / 2) - y[i])); //Unlocking algorithm
}
}}

MineSweeper game array

I have the same problem as some guy who asked this.
I want to code some basic stuff for a little minesweeper game.
Now I have the problem that my code
public class Minesweeper1 {
public static int[][] makeRandomBoard(int s, int z, int n){
int feld[][] = new int [s][z];
for(int i = 0; i < s; i++){
for(int j = 0; j < z; j++){
feld[i][j] = 0;
}
}
for(int i = 0; i < n; i++){
selectRandomPosition(s, z);
feld[randomHeight][randomWidth] = 1;
}
}
so it starts the selectRandomPosition code:
public static int[] selectRandomPosition(int maxWidth, int maxHeight) {
int randomHeight = StdRandom.uniform(0, maxHeight);
int randomWidth = StdRandom.uniform(0, maxWidth);
return new int[]{randomHeight, randomWidth};
}
Here I am not allowed to change anything, but it returns a new array. Now my question is how can I use the new array in makeRandomBoard?, since I do not know any name of the array. When I use feld[randomHeight][randomWidth] = 1; it says that it does not know these variables.
And he did get the answer:
Call the method, and assign its return value to a variable. Now you have a name for the array:
// Make a call
int[] randomArray = selectRandomPosition(maxW, maxH);
// Access the width
int randomW = randomArray[0];
// Access the height
int randomH = randomArray[1];
but what do I have to write now?
I tried it with:
feld[randomW][randomH] = 1;
but it seems like it doesn't work. I also need a return statement.
Can anyone help me?
I believe this is the solution you are looking for:
Solution
public class Minesweeper1 {
// Note:
// s == Height
// z == Width
public static int[][] makeRandomBoard(int s, int z, int n) {
// Note: Misspelling of "field"?
int feld[][] = new int [s][z];
// Initialize the game board with no mines (value of 0)
for(int i = 0; i < s; i++) {
for(int j = 0; j < z; j++) {
feld[i][j] = 0;
}
}
// Iterate through n times to place "mines" (value of 1)
for(int i = 0; i < n; i++){
// selectRandomPosition returns an array of length 2
// the first index (0) = randomHeight
// the second index (1) = randomWidth
// Notice that z and s is flipped
// because the first parameter is for width, which is z
// and the second parameter is for height, which is s
int[] position = selectRandomPosition(z, s);
int positionX = position[1];
int positionY = position[0];
// The order of positionY/positionX is key!
// If it's in the wrong order you will get an
// IndexOutOfBoundsException!
feld[positionY][positionX] = 1;
}
// Return the newly created array
return feld;
}
public static int[] selectRandomPosition(int maxWidth, int maxHeight) {
int randomHeight = StdRandom.uniform(0, maxHeight);
int randomWidth = StdRandom.uniform(0, maxWidth);
// Notice that this is returning a fixed array of two elements
// the first being the Y component, and the second being the X
// component.
return new int[]{randomHeight, randomWidth};
}
}
Problems
Passing the wrong values
You were calling selectRandomPosition wrong. Remember that s is the Height, and z is the Width. So you were passing into selectRandomPosition the Height for the first parameter, and the Width for the second parameter. Look at the method declaration:
public static int[] selectRandomPosition(int maxWidth, int maxHeight)
That meant you passed the Height into the maxWidth, and the Width into the maxHeight. My solution flips it for you. This can be confusing because s and z don't really give you hints to what they are (Height and Width) - consider renaming these variables to help you.
Accessing in the wrong order
You have in your question:
feld[randomW][randomH] = 1;
This is wrong, it should be:
feld[randomH][randomW] = 1;
This image shows a visual representaion of what a two dimensional array looks like:
So the access would be:
feld[0][0] == 1
feld[0][1] == 1
feld[0][2] == 1
feld[1][0] == 1
feld[1][1] == 2
feld[1][2] == 4
feld[2][0] == 1
feld[2][1] == 3
feld[2][2] == 9
Nit-Pick: Misspellings
Other than having weird variable names like s and z that do not help you at all in remembering what means what, your main variable that you will eventually return is misspelled. Did you mean "field"?
Variable naming is important and can help you, and other readers, to easily understand your code. Also, comments in places where you think you need them also help!

Java multi-thread matrix multiplication

Trying to get a multi-threaded matrix multiplication to work in Java. It is given a (m x n) matrix, a (n x k) matrix and 't' threads to perform the operation on.
My program works when the matrices are square and t == n. When running with t < n, the other threads do not pick up the additional operations, and it returns a partially completed matrix. When the matrices are not square, the additional threads return array out of bounds errors and do not run. I would really appreciate any advice. Here are the relevant code snippets
Beginning threads. multipliers is an array of MatrixMultiplier, a class defined later.
Multiply multiply = new Multiply(cols_mat, rows_mat2);
for (int i = 0; i < threads; i++) {
multipliers[i] = new MatrixMultiplier(multiply);
}
for (int i = 0; i < threads; i++) {
my_threads[i] = new Thread(multipliers[i]);
}
for (int i = 0; i < threads; i++) {
my_threads[i].start();
}
for (int i = 0; i < threads; i++) {
my_threads[i].join();
}
Multiply class which defines the matrix multiplication
class Multiply extends MatrixMultiplication {
private int i;
private int j;
private int chance;
public Multiply(int i, int j) {
this.i = i;
this.j = j;
chance = 0;
}
public synchronized void multiplyMatrix() {
int sum = 0;
int a = 0;
for (a = 0; a < i; a++) {
sum = 0;
for (int b = 0; b < j; b++) {
sum = sum + mat[chance][b] * mat2[b][a];
}
result[chance][a] = sum;
}
if (chance >= i)
return;
chance++;
}
}
And the matrix multiplier
class MatrixMultiplier implements Runnable {
private final Multiply mul;
public MatrixMultiplier(Multiply mul) {
this.mul = mul;
}
#Override
public void run() {
mul.multiplyMatrix();
}
}
Where I personally think the issue lies is with if (chance >= i) return; but I have not found a way to incorporate a thread's column responsibilities with the program still working. Again, any advice pointing me in the right direction would be greatly appreciated.
There are several issues with your code.
The t threads assume that only t multiplications are required to produce your result matrix. This is not to be the case when m != k or t != m or t != k. The threads are worker threads that will only process your requests. I would consider making each MatrixMultiplier have access to the mxn, nxk, mxk matrices and a rolcolumn entries container.
class MatricMultiplier {
private double a[][], b[][], results[][];
private Queue<..> entries;
....
}
The run method will then use the entries container to calculate the sum for a given <row,column> entry of the resulting mxk matrix. The run method could become:
run() {
for (Entry entry = entries.poll(); entry != null; entry = entries.poll()) {
int row = entry.row;
int col = entry.col;
double sum = 0.0;
for (int i = 0; i < a[row].length; i++) {
sum += a[row][i] * b[i][col];
}
results[row][col] = sum;
}
}
There are three things to note here that is different than what you have.
you are not using a synchronization block
each entry is calculating the answer for a unique row/column of the result matrix
the Multiple class is not required any longer
You can then create t threads that process each entry in the entries container and will exit when the entries container is empty.
Note that the entries container should be one of the concurrent Queue containers available in the java.util.concurrent package.
The remaining task is how to create the rowcolumn entries container. Here is some code that you could use:
Queue<..> entries = new Concurrent...<..>();
int rowSize = a.length;
int colSize = b[0].length;
for (int row = 0; row < rowSize; row++) {
for (int col = 0; col < colSize; col++) {
entries.add(new RowColumnEntry(row, col));
}
}
Noting that the a and b are the m×n and n×k matrices.
Hope this helps.

Strange unreachable yet compilable Code

Well I made this method Resize with in my Class Object2D, which is supposed to resize the two-dimensional Color-Array PointInformation of the Object2D, that it is called onto, by a certain Percentage. (I found that easier to do when convertig the 2D-Array into an 1D Array)
public class Object2D
{
int width;
int height;
int ResizePercentage = 100;
Color PointInformation[][];
public void Resize(int Percentage)
{
Color[]temp = Standart_Methods.Reduce2DArray(this.PointInformation);
int temp_width = this.width;
int temp_height = this.height;
double Faktor = (Percentage+100)/100;
this.width = (int) (this.width*Faktor);
this.height = (int) (this.height*Faktor);
this.ResetPointInformation();
Color[]temp2 = Standart_Methods.Reduce2DArray(this.PointInformation);
int SamePixelCount = 0;
Color LastColor = temp[0];
for (int i = 0; i < temp.length; i++)
{
if (temp[i] == LastColor )
{
SamePixelCount += 1;
}
else
{
for (int i2 = (int) (i*Faktor); i == 1; i-- )
//Method Resize will only be called when i*Faktor is going to be 100% = X.0 (An Integer)
{
temp2[i*2-i] = LastColor;
}
SamePixelCount = 0;
}
}
Standart_Methods.PrintArray(temp2);
int a = 10;
int b = 0;
System.out.print(a/b); //No Exeption, Code unreachable!?
}
}
It basically starts at temp[0] and adds 1 to the int SamePixelCount as long as it finds the same Color.
When a different Color is found, the method writes the Color of the former Pixels into the right Places in the temp2 Array.
for (int i = 0; i < temp.length; i++)
{
if (temp[i] == LastColor )
{
SamePixelCount += 1;
}
else
{
for (int i2 = (int) (i*Faktor); i == 1; i-- )
//Method Resize will only be called when i*Faktor is going to be 100% = X.0 (An Integer)
{
temp2[i*2-i] = LastColor;
}
SamePixelCount = 0;
}
}
The correct translation of the manipulated Array temp2 into the Object's PointInformation is still missing, because I wanted to test, if temp2 was correctly resized out of temp, so I did
Standart_Methods.PrintArray(temp2); //the Method works btw
but it just did nothing! And even bader! Everything I put at the place of that command, also didn't!
int a = 10;
int b = 0;
System.out.print(a/b); //No Exeption!
And what is even stranger is, that as soon as I call the Method Resize, somewhere, everything after the Call turns into the same strange unreachable Code!?
I am seriously totally clueless about what could have caused this problem.
Any help would be nice!
dividing by zero certainly will give you ArithmeticException:
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 0;
System.out.println(a/b);
}
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Test.main(Test.java:14)
I suggest use eclipse and trace your code using the debugger. Inspect your variables per code line and I'm sure you can figure our what's wrong

Hidden Markov Model, Clarification on a Previous Implementation

I'm experimenting with hidden markov models. I really have no prior experience working with them so I decided to check out a few examples of implementations.
Looking at the below implementation, I was a bit confused about the purpose of the Baum-Welch algorithm (found under the train method) taking a variable steps. I understand providing a training set, but not providing steps. Does anyone have an explanation for this, since I don't understand it from the documentation.
Here's a link to the original code http://cs.nyu.edu/courses/spring04/G22.2591-001/BW%20demo/HMM.java since the code isn't being presented very nicely in my post.
import java.text.*;
/** This class implements a Hidden Markov Model, as well as
the Baum-Welch Algorithm for training HMMs.
#author Holger Wunsch (wunsch#sfs.nphil.uni-tuebingen.de)
*/
public class HMM {
/** number of states */
public int numStates;
/** size of output vocabulary */
public int sigmaSize;
/** initial state probabilities */
public double pi[];
/** transition probabilities */
public double a[][];
/** emission probabilities */
public double b[][];
/** initializes an HMM.
#param numStates number of states
#param sigmaSize size of output vocabulary
*/
public HMM(int numStates, int sigmaSize) {
this.numStates = numStates;
this.sigmaSize = sigmaSize;
pi = new double[numStates];
a = new double[numStates][numStates];
b = new double[numStates][sigmaSize];
}
/** implementation of the Baum-Welch Algorithm for HMMs.
#param o the training set
#param steps the number of steps
*/
public void train(int[] o, int steps) {
int T = o.length;
double[][] fwd;
double[][] bwd;
double pi1[] = new double[numStates];
double a1[][] = new double[numStates][numStates];
double b1[][] = new double[numStates][sigmaSize];
for (int s = 0; s < steps; s++) {
/* calculation of Forward- und Backward Variables from the
current model */
fwd = forwardProc(o);
bwd = backwardProc(o);
/* re-estimation of initial state probabilities */
for (int i = 0; i < numStates; i++)
pi1[i] = gamma(i, 0, o, fwd, bwd);
/* re-estimation of transition probabilities */
for (int i = 0; i < numStates; i++) {
for (int j = 0; j < numStates; j++) {
double num = 0;
double denom = 0;
for (int t = 0; t <= T - 1; t++) {
num += p(t, i, j, o, fwd, bwd);
denom += gamma(i, t, o, fwd, bwd);
}
a1[i][j] = divide(num, denom);
}
}
/* re-estimation of emission probabilities */
for (int i = 0; i < numStates; i++) {
for (int k = 0; k < sigmaSize; k++) {
double num = 0;
double denom = 0;
for (int t = 0; t <= T - 1; t++) {
double g = gamma(i, t, o, fwd, bwd);
num += g * (k == o[t] ? 1 : 0);
denom += g;
}
b1[i][k] = divide(num, denom);
}
}
pi = pi1;
a = a1;
b = b1;
}
}
/** calculation of Forward-Variables f(i,t) for state i at time
t for output sequence O with the current HMM parameters
#param o the output sequence O
#return an array f(i,t) over states and times, containing
the Forward-variables.
*/
public double[][] forwardProc(int[] o) {
int T = o.length;
double[][] fwd = new double[numStates][T];
/* initialization (time 0) */
for (int i = 0; i < numStates; i++)
fwd[i][0] = pi[i] * b[i][o[0]];
/* induction */
for (int t = 0; t <= T-2; t++) {
for (int j = 0; j < numStates; j++) {
fwd[j][t+1] = 0;
for (int i = 0; i < numStates; i++)
fwd[j][t+1] += (fwd[i][t] * a[i][j]);
fwd[j][t+1] *= b[j][o[t+1]];
}
}
return fwd;
}
The other two questions I have are in regards to the Forward method, which implements the Forward part of the Forward-Backward algorithm. From reading up on HMMs, I gather that, after training my model, I should use something like this method to predict future observations. So is the param O (representing output sequences) just the sequence of observations up until this point?
With some experimentation with this method, I'm returned what the documentation says are Forward-Variables, which just look like a bunch of probabilities. How are these translated into future observations?
I'm delving into regions of programming that are quite difficult for me, so I really appreciate your help in helping me understand this stuff!

Categories

Resources