Java 2d Array Logic Error - java

UPDATE AT BOTTOM:
I am creating a program with a 2d array. The array has 26 rows, and 26 columns. I am searching, one line at a time, for case-insensitive two-letter pairs, such as: "AA","AB","AC","AD", etc. If I find a letter pair, I add one to it's corresponding index in the array. The first letter determines the row, and second letter determines the column. For example this is how it is supposed to run:
aa
ab
ac
ad
ba
bb
bc
za
zb
zc
1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
My program is able to do above, however when I input:
AABBAACCAA
AA
4 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
I want the upper-left most number that currently says 4, to say 2. In other words, I want any particular letter pair to be only counted once per line. So If I input AAAAAAAAAAA, I want to only add one to alphabet[0][0]
Here is my code:
import java.util.Scanner;
public class Freq{
private static final int ROWS = 26;
private static final int COLS = 26;
private static int[] [] alphabet = new int[ROWS][COLS];
public static void main(String[] args) {
String line;
Scanner userInput = new Scanner(System.in);
while(userInput.hasNextLine()) {
line = userInput.nextLine();
processLine(line);
}
printArray();
}
public static void processLine(String line) {
line = line.toUpperCase();
for(int a = 0; a < line.length() - 1; a++) {
char firstLetter = line.charAt(a);
char secondLetter = line.charAt(a + 1);
alphabet[firstLetter - 65][secondLetter - 65] += 1;
}
}
public static void printArray() {
for (int b = 0; b < alphabet.length; b++) {
for (int c = 0; c < alphabet[b].length; c++){
System.out.print(alphabet[b][c] + " ");
}
System.out.println();
}
}
}
Any help is appreciated.
UPDATE: The top row of my array represents these two-letter pairs:
AA AB AC AD AE AF AG AH AI AJ AK AL AM AN AO AP AQ AR AS AT AU AV AW AX AY AZ
The second row represents these two-letter pairs:
BA BB BC BD BE BF BG BH BI BJ BK BL BM BN BO BP BQ BR BS BT BU BV BW BX BY BZ
etc.
The string: "This is a test" has these letter pairs: TH, HI, IS, IS, TE, ES, ST. These are all the letter pair occurrences in that string. However, I want to count each letter pair only once, so for my purposes, I want to record that string as having these letter pairs: TH, HI, IS, TE, ES, ST. Note the IS is not listed twice as I am only looking for one occurrence per line of input
This means if I enter on one line:
AAAAAAAAAAAA
I only want to add 1 to the first element in my array. So I would want the top row of my array to look like this:
1 0 0 0 0 0 0...
However, if I input the string "AAAAAAAAAAAA" on multiple lines like this:
AA
AA
AA
AA
AA
AA
AA
Then I want to add 6 to the first element of my array. Because AA occurred 6 different times on 6 different lines So I would want the top row of my array to look like this:
6 0 0 0 0 0 0...

Just put a condition in here:
for (int a=0; a < line.length() - 1; a++) {
char firstLetter = line.charAt(a);
char secondLetter = line.charAt(a + 1);
if (alphabet[firstLetter - 65][secondLetter - 65] == 0) { // Put it here
alphabet[firstLetter - 65][secondLetter - 65] = 1;
}
}

The following implementation adds a two dimensional boolean array called visited which keeps track of whether a given pair of letters has been seen for the current line. If we come across a pair of letters, for a given line, which we have not seen before, then we add one to the total for that cell. But seeing the same pair again in the current line will be ignored and the total won't move up. After consuming each line, we reset the visited array to false for every pair so that it can be reused with the proceeding line.
public class Freq {
private static final int ROWS = 26;
private static final int COLS = 26;
private static int[][] alphabet = new int[ROWS][COLS];
private static boolean[][] visited = new boolean[ROWS][COLS];
public static void main(String[] args) {
String line;
Scanner userInput = new Scanner(System.in);
while (userInput.hasNextLine()) {
clearVisited();
line = userInput.nextLine();
processLine(line);
}
printArray();
}
public static void clearVisited() {
for (int r=0; r < visited.length; r++) {
for (int c=0; c < visited[r].length; c++){
visited[r][c] = false;
}
}
}
public static void processLine(String line) {
line = line.toUpperCase();
for (int i=0; i < line.length()-1; i++) {
char firstLetter = line.charAt(i);
char secondLetter = line.charAt(i + 1);
if (!visited[firstLetter-65][secondLetter-65]) {
alphabet[firstLetter - 65][secondLetter - 65] += 1;
visited[firstLetter-65][secondLetter-65] = true;
}
}
}
}

Related

How to swap rows and columns in a very large file using java

In Python, we can use iterator(generator function) on the file and finally use zip() which maps similarly indexed columns and write those columns as rows in a new file. Here is an example:
f=open('inp.tsv')
lines = (line.strip().split('\t') for line in list(f))
with open('out.tsv', 'a') as fo:
for line in zip(*lines):
print(*line, sep = '\t', file = fo)
f.close()
say the file has the following content:
Xkr4 0 0 0 0
Gm1992 0 0 0 0
Gm37381 0 0 0 0
Rp1 0 0 0 0
Rp1.1 0 0 0 0
Sox17 0 0 0 0
Result:
Xkr4 Gm1992 Gm37381 Rp1 Rp1.1 Sox17
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
How can we perform a similar task in java?

Iterative Deepening using recursion bug

This is iterative deepening search and I want to keep track of the nodes generated before the goal state. I am using RUNNING_TIME as a counter and then assign it to each node in the tree. The thing is, because o recursion RUNNING_TIME is incremented more than once and the value is not valid anymore. Hence, I get a RUNNING_TIME for BFS which is better than this one which theoretically doesn't make sense (only worst case scenario). Do you have any idea how I should increment this value in my methods? I sincerely have no idea, thanks.
public void IDS() {
Grid startNode = new Grid(initState, A, B, C, agent);
for(int depth = 0; depth < Integer.MAX_VALUE; depth ++) {
Grid found = DLS(startNode, depth);
if(found != null) {
retracePath(found);
return;
}
}
}
public Grid DLS(Grid current, int depth) {
RUNNING_TIME ++;
current.nodesGeneratedBefore = RUNNING_TIME;
if(depth == 0 && current.checkGoalState()) {
return current;
}
if(depth > 0) {
for(Grid neighbor : current.getNeighbors(current)) {
Grid found = DLS(neighbor, depth - 1);
if(found != null) {
return found;
}
}
}
return null;
}
EDIT: Also I forgot to mention that I get the correct path to the destination, but only the "RUNNING_TIME" variable is wrongly incremented.
0 0 0 0
0 0 0 0
0 0 0 -1
1 2 3 0
Number of nodes generated by now 4680622
0 0 0 0
0 0 0 0
0 0 -1 0
1 2 3 0
Number of nodes generated by now 6297726
0 0 0 0
0 0 0 0
0 -1 0 0
1 2 3 0
Number of nodes generated by now 7106272
0 0 0 0
0 0 0 0
0 2 0 0
1 -1 3 0
Number of nodes generated by now 7760396
0 0 0 0
0 0 0 0
0 2 0 0
-1 1 3 0
Number of nodes generated by now 7837602
0 0 0 0
0 0 0 0
-1 2 0 0
0 1 3 0
Number of nodes generated by now 7837603
0 0 0 0
0 0 0 0
2 -1 0 0
0 1 3 0
Number of nodes generated by now 7842162
0 0 0 0
0 0 0 0
2 1 0 0
0 -1 3 0
Number of nodes generated by now 7848122
0 0 0 0
0 0 0 0
2 1 0 0
0 3 -1 0
Number of nodes generated by now 7849095
0 0 0 0
0 0 0 0
2 1 -1 0
0 3 0 0
Number of nodes generated by now 7849096
0 0 0 0
0 0 -1 0
2 1 0 0
0 3 0 0
Number of nodes generated by now 7849097
0 0 0 0
0 -1 0 0
2 1 0 0
0 3 0 0
Number of nodes generated by now 7849111
0 0 0 0
0 1 0 0
2 -1 0 0
0 3 0 0
Number of nodes generated by now 7849125
0 0 0 0
0 1 0 0
-1 2 0 0
0 3 0 0
Number of nodes generated by now 7849127

Java 2d array adding one to element error

On the program I am working on I have to find a letter pair contained in an unspecified amount of input. If two consecutive English letters that are the same, case-insensitive, are found, then I add one to an element within my 2d array that is 26 rows by 26 columns. Here is my code:
import java.util.Scanner;
public class Freq{
private static final int ROWS = 26;
private static final int COLS = 26;
private static int[] [] alphabet = new int[ROWS][COLS];
public static void main(String[] args) {
String line;
Scanner userInput = new Scanner(System.in);
while(userInput.hasNextLine()) {
line = userInput.nextLine();
processLine(line);
}
printArray();
}
public static void processLine(String line) {
line = line.toUpperCase();
for(int i = 0; i < alphabet.length; i++) {
for(int j = 0; j < alphabet[i].length; j++) {
for (int a = 0; a < line.length() - 1; a++) {
char firstLetter = line.charAt(a);
char secondLetter = line.charAt(a + 1);
if (firstLetter == secondLetter) {
alphabet[firstLetter - 65][secondLetter - 65] += 1;
}
}
}
}
}
public static void printArray() {
for (int b = 0; b < alphabet.length; b++) {
for (int c = 0; c < alphabet[b].length; c++){
System.out.print(alphabet[b][c] + " ");
}
System.out.println();
}
}
}
However when I run my program and input "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz"
this is what happens:
aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz
676 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 676 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 676 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 676 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 676 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 676 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 676 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 676 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 676 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 676 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 676 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 676 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 676 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 676 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 676 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 676 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 676 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 676 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 676 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 676 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 676 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 676 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 676 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 676 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 676 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 676
I believe they are being added in the correct location, but why is my program adding 676 to the index and not just adding 1? Any help is greatly appreciated. Thank you!
Your processLine() method does not make much sense. First, you should only be iterating over the input string, and not the entire 2D array, i.e.:
public static void processLine(String line) {
line = line.toUpperCase();
for (int a=0; a < line.length() - 1; a++) {
char firstLetter = line.charAt(a);
char secondLetter = line.charAt(a + 1);
if (firstLetter == secondLetter) {
alphabet[firstLetter - 65][secondLetter - 65] += 1;
}
}
}
Second, your 2D array will only ever have entries on the diagonal, because you only ever make assignments where the two characters are the same for both dimensions. So you could just use a 1D array:
private static int[] alphabet = new int[ROWS];
public static void processLine(String line) {
line = line.toUpperCase();
for (int a=0; a < line.length() - 1; a++) {
char firstLetter = line.charAt(a);
char secondLetter = line.charAt(a + 1);
if (firstLetter == secondLetter) {
alphabet[firstLetter - 65] += 1;
}
}
}
What your are doing is that you are adding value from that position on matrix with 1 instead if you want 1 at that place just assign it
Replace this line
alphabet[firstLetter - 65][secondLetter - 65] += 1;
with this
alphabet[firstLetter - 65][secondLetter - 65] = 1;
or change your processLine method to this
public static void processLine(String line) {
line = line.toUpperCase();
for (int a = 0; a < line.length() - 1; a++) {
char firstLetter = line.charAt(a);
char secondLetter = line.charAt(a + 1);
if (firstLetter == secondLetter) {
alphabet[firstLetter - 65][secondLetter - 65] += 1;
}
}
}
hope this answer your question

constructor exceeding the 65535 bytes limit

I have a class where I store the terrain of the world of my game. The gameworld consists of cubes and every cube has a terrain. The information is stored as a pretty big 3D-Array of integers.
The problem that I now encounter is that my 'map' is too big to store in a class (or enum). Since I don't really know anything outside of classes and enums, I don't know what to do with this.
Should i make a tekst file out of it and read that out? If so, how do I do that?
A different solution would be to split the map over several classes or enums and then merge them again at runtime, but I don't know how to do that either and it seems like a pretty bad solution.
EDIT: This is part of the worldmap:
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 2 2 0 0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 2 2 0 0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1
0 0 0 0 1 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 1 1 1 0 0
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0
0 0 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 1 1 1 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
There are 40 of of these blocks (so 38 more) and each one represents the world at a certain z-coordinate. I also have this in arrayformat.
It would be great if you could provide some (sample) code on how to read this from a file.
It's much better to put it into resource. Just create a text file next to your class (e.g. named map.txt), put there your world map in the same format you've used in the question, then load it using the code like this:
public int[][][] loadMap() {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(getClass()
.getResourceAsStream("map.txt"), StandardCharsets.ISO_8859_1))) {
List<int[][]> result = new ArrayList<>();
List<int[]> cur = new ArrayList<>();
String line;
while((line = reader.readLine()) != null) {
line = line.trim();
if(line.isEmpty() && !cur.isEmpty()) {
result.add(cur.toArray(new int[0][]));
cur.clear();
} else {
String[] cells = line.split("\\s+");
int[] row = new int[cells.length];
for(int i=0; i<cells.length; i++) row[i] = Integer.parseInt(cells[i]);
cur.add(row);
}
}
if(!cur.isEmpty())
result.add(cur.toArray(new int[0][]));
return result.toArray(new int[0][][]);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
If it is possible in your use case you could use blocks of byte[] instead, or even short[]. Then you should be well within the 65535 byte limit.
size för byte[] : 20 x 20 x 40 x 1 = 16000 bytes
size för short[]: 20 x 20 x 40 x 2 = 32000 bytes
Can you show your error?
If you don´t need all your map be loaded you can divide your map by chunks, and save all your map in a Xml for example, like this:
<map>
<chunk x=0 y=0>
<!--chunk informations>
</chunk>
<chunk x=0 y=1>
<!--chunk informations>
</chunk>
<!--other chunks>
</map>

Java 2d game tiled map clipping?

Well I've created a simple tile map loading, from .txt file & then drawing.
25
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
So if the current tile is 1, it will be a green block.
Now the game window looks like this (ignore yellow dots at top):
(source: gyazo.com)
Okay everything is fine and great, but now can you see the red box? that's the character, and when it walks, I don't want it to go over the gates (any green block).
How can I do that?
My attempt:
private void makeClips() {
int[][] tiledMap = this.map.getMap();
for (int i = 0; i < this.map.getHeight(); i++) {
for (int j = 0; j < this.map.getWidth(); j++) {
if (tiledMap[i][j] == 1) {
clips.add(new Clip(j * 30, i * 30, 0, 0));
System.out.println("Added clip: " + j + " " + i + " " + (j + 30) + " " + (i + 30));
}
}
}
}
That should create an array of clips, so we can check if player's next walk equals to the clips coordinates, but I've had problems with setting the clip x, y like what will it's position be.
The 30 is the tile size, so each block will be 30 width 30 height sized.
And then in the walking method i've done this:
for (Clip clip : clips) {
if (myPlayer.getX() + x >= clip.getFirstX() && myPlayer.getX() + x <= clip.getSecX()
&& myPlayer.getY() + y >= clip.getFirstY() && myPlayer.getY() + y <= clip.getSecY()) {
System.out.println("Bad");
return;
}
}
But I don't know, this is 100% incorrect, mostly the coordinate calculating part.
What would you do in this case?
This is the drawing part for map:
private void renderMap(Graphics2D g) {
int[][] tiledMap = this.map.getMap();
for (int i = 0; i < this.map.getHeight(); i++) {
for (int j = 0; j < this.map.getWidth(); j++) {
int currentRow = tiledMap[i][j];
if (currentRow == 1) {
g.setColor(Color.green);
}
if (currentRow == 0) {
g.setColor(Color.black);
}
g.fillRect(0 + j * map.getTileSize(), 0 + i * map.getTileSize(),
map.getTileSize(), map.getTileSize());
g.setColor(Color.yellow);
for (Clip clip : clips) {
g.fillRect(clip.getFirstX(), clip.getFirstY(), 2, 2);
}
}
}
}
What can I do?
Why not do a check every time you move your player on the tile you want to move him onto.
Lets assume the player is at (0,0) on this small map.
0 0 1
0 0 0
0 0 0
We will try and move him to the right twice. The first time will work as at the position (1,0) the tile is equal to 0. The second time we try this the tile at (2,0) will return 1 and the player won't move.
if (tiledMap[player.getX() + 1)[player.getY()] == 1) {
//do nothing
} else {
//move player
}

Categories