Related
I'm using a piece of code taken from the website The Nature of Code - https://natureofcode.com/book/chapter-7-cellular-automata/ - the portion I used was from example 7.1. I'm trying to create a one-dimensional cellular automaton using the Processing IDE, but I keep getting an error saying that brackets are missing from particular locations.
Errors:
-Missing curlry bracket "}", line 32
-Syntax error on "}", delete this, line 40
I've gone over it multiple times, but I can't see how this is wrong. Though I did try changing them as it says, only to get more errors. I thought maybe they were just in the wrong place, but I also can't see how that's the case. They seem to be correct as far as I can tell, but maybe I'm missing something. This is my first time using Processing, and it's been a long time since I last used Java. So maybe I'm mistaken.
class CA {
int[] cells;
int[] ruleset;
int w = 10;
// The CA should keep track of how
// many generations.
int generation = 0;
CA() {
cells = new int[width/w];
ruleset = new int[]{0,1,0,1,1,0,1,0};
cells[cells.length/2] = 1;
}
// Function to compute the next generation
void generate() {
int[] nextgen = new int[cells.length];
for (int i = 1; i < cells.length-1; i++) {
int left = cells[i-1];
int me = cells[i];
int right = cells[i+1];
nextgen[i] = rules(left, me, right);
}
cells = nextgen;
// Increment the generation counter.
generation++;
}
int rules(int a, int b, int c) {
String s = "" + a + b + c;
int index = Integer.parseInt(s,2);
return ruleset[index];
}
for (int i = 0; i < cells.length; i++) {
if (cells[i] == 1) fill(0);
else fill(255);
// Set the y-location according to the generation.
rect(i*w, generation*w, w, w);
}
}
The program is supposed to print each generation of the one-dimensional CA on top of the next.
The for-loop in the end of the CA class is not supposed to be there. That is why you get the error: the parser expects either a method declaration or the end of the class, hence a curly bracket.
It looks like this loop is actually drawing the CA state, so you can try to wrap it in a void draw(){} method. Then it should be syntactically correct, not sure though whether it works as expected. Alternatively move the for-loop outside of the class and call fill based on the the cells state of an instance of the CA class.
In any case, will need some additional code that creates the CA instance and invokes the generate function.
I found recently the default renderable sort function in LibGDX wasn't quite up to my needs. (see; Draw order changes strangely as camera moves? )
Essentially a few objects rendered in front when they should render behind.
Fortunately, the renderables in question always have a guarantied relationship. The objects are attached to eachother so when one moves the other moves. One object can be seen as being literally "pinned" to the other, so always in front.
This gave me the idea that if I specified a "z-index" (int) and "groupname" (String) for each object, I could manually take over the draw order, and for things with the same groupname, ensure they are positioned next to eachother in the list, in the order specified by the z-index. (low to high)
//For example an array of renderables like
0."testgroup2",11
1."testgroup",20
2."testgroup2",10
3.(no zindex attribute)
4."testgroup",50
//Should sort to become
0."testgroup",20
1."testgroup",50
2.(no zindex attribute)
3."testgroup2",10
4."testgroup2",11
// assuming the object2 in testgroup2 are closer to the camera, the one without a index second closest, and the rest furthest<br>
//(It is assumed that things within the same group wont be drastically different distances)
I implemented a sort system in libgdx to do this as followed;
/**
* The goal of this sorter is to sort the renderables the same way LibGDX would do normally (in DefaultRenderableSorter)<br>
* except if they have a ZIndex Attribute.<br>
* A Zindex attribute provides a groupname string and a number.<br>
* Renderables with the attribute are placed next to others of the same group, with the order within the group determined by the number<br>
*
* For example an array of renderables like;<br><br>
* 0."testgroup",20<br>
* 1."testgroup2",10<br>
* 2.(no zindex attribute)<br>
* 3."testgroup",50<br>
* <br>Should become;<br><br>
* 0."testgroup",20<br>
* 1."testgroup",50<br>
* 2.(no zindex attribute)<br>
* 3."testgroup2",10<br>
* <br>
* assuming the object in testgroup2 is closer to the camera, the one without a index second closest, and the rest furthest<br>
* (It is assumed that things within the same group wont be drastically different distances)<br>
*
* #param camera - the camera in use to determine normal sort order when we cant place in a existing group
* #param resultList - an array of renderables to change the order of
*/
private void customSorter(Camera camera, Array<Renderable> resultList) {
//make a copy of the list to sort. (This is probably a bad start)
Array <Renderable> renderables = new Array <Renderable> (resultList);
//we work by clearing and rebuilding the Renderables array (probably not a good method)
resultList.clear();
//loop over the copy we made
for (Renderable o1 : renderables) {
//depending of if the Renderable as a ZIndexAttribute or not, we sort it differently
//if it has one we do the following....
if (o1.material.has(ZIndexAttribute.ID)){
//get the index and index group name of it.
int o1Index = ((ZIndexAttribute)o1.material.get(ZIndexAttribute.ID)).zIndex;
String o1GroupName = ((ZIndexAttribute)o1.material.get(ZIndexAttribute.ID)).group;
//setup some variables
boolean placementFound = false; //Determines if a placement was found for this renderable (this happens if it comes across another with the same groupname)
int defaultPosition = -1; //if it doesn't find another renderable with the same groupname, this will be its position in the list. Consider this the "natural" position based on distance from camera
//start looping over all objects so far in the results (urg, told you this was probably not a good method)
for (int i = 0; i < resultList.size; i++) {
//first get the renderable and its ZIndexAttribute (null if none found)
Renderable o2 = resultList.get(i);
ZIndexAttribute o2szindex = ((ZIndexAttribute)o2.material.get(ZIndexAttribute.ID));
if (o2szindex!=null){
//if the renderable we are comparing too has a zindex, then we get its information
int o2index = o2szindex.zIndex;
String o2groupname = o2szindex.group;
//if its in the same group as o1, then we start the processing of placing them nexto eachother
if (o2groupname.equals(o1GroupName)){
//we either place it in front or behind based on zindex
if (o1Index<o2index){
//if lower z-index then behind it
resultList.insert(i, o1);
placementFound = true;
break;
}
if (o1Index>o2index){
//if higher z-index then it should go in front UNLESS there is another of this group already there too
//in which case we just continue (which will cause this to fire again on the next renderable in the inner loop)
if (resultList.size>(i+1)){
Renderable o3 = resultList.get(i+1);
ZIndexAttribute o3szindex = ((ZIndexAttribute)o3.material.get(ZIndexAttribute.ID));
if (o3szindex!=null){
String o3groupname = o3szindex.group;
if (o3groupname!=null && o3groupname.equals(o1GroupName)){
//the next element is also a renderable with the same groupname, so we loop and test that one instead
continue;
}
}
}
// Gdx.app.log("zindex", "__..placeing at:"+(i+1));
//else we place after the current one
resultList.insert(i+1, o1);
placementFound = true;
break;
}
}
}
//if no matching groupname found we need to work out a default placement.
int placement = normalcompare(o1, o2); //normal compare is the compare function in DefaultRenderableSorter.
if (placement>0){
//after then we skip
//(we are waiting till we are either under something or at the end
} else {
//if placement is before, then we remember this position as the default (but keep looking as there still might be matching groupname, which should take priority)
defaultPosition = i;
//break; //break out the loop
}
}
//if we have checked all the renderables positioned in the results list, and none were found with matching groupname
//then we use the defaultposition to insert it
if (!placementFound){
//Gdx.app.log("zindex", "__no placement found using default which is:"+defaultPosition);
if (defaultPosition>-1){
resultList.insert(defaultPosition, o1);
} else {
resultList.add(o1);
}
}
continue;
}
//...(breath out)...
//ok NOW we do placement for things that have no got a ZIndexSpecified
boolean placementFound = false;
//again, loop over all the elements in results
for (int i = 0; i < resultList.size; i++) {
Renderable o2 = resultList.get(i);
//if not we compare by default to place before/after
int placement = normalcompare(o1, o2);
if (placement>0){
//after then we skip
//(we are waiting till we are either under something or at the end)
continue;
} else {
//before
resultList.insert(i, o1);
placementFound = true;
break; //break out the loop
}
}
//if no placement found we go at the end by default
if (!placementFound){
resultList.add(o1);
};
} //go back to check the next element in the incomeing list of renderables (that is, the copy we made at the start)
//done
}
//Copy of the default sorters compare function
//;
private Camera camera;
private final Vector3 tmpV1 = new Vector3();
private final Vector3 tmpV2 = new Vector3();
public int normalcompare (final Renderable o1, final Renderable o2) {
final boolean b1 = o1.material.has(BlendingAttribute.Type) && ((BlendingAttribute)o1.material.get(BlendingAttribute.Type)).blended;
final boolean b2 = o2.material.has(BlendingAttribute.Type) && ((BlendingAttribute)o2.material.get(BlendingAttribute.Type)).blended;
if (b1 != b2) return b1 ? 1 : -1;
// FIXME implement better sorting algorithm
// final boolean same = o1.shader == o2.shader && o1.mesh == o2.mesh && (o1.lights == null) == (o2.lights == null) &&
// o1.material.equals(o2.material);
o1.worldTransform.getTranslation(tmpV1);
o2.worldTransform.getTranslation(tmpV2);
final float dst = (int)(1000f * camera.position.dst2(tmpV1)) - (int)(1000f * camera.position.dst2(tmpV2));
final int result = dst < 0 ? -1 : (dst > 0 ? 1 : 0);
return b1 ? -result : result;
}
As far as I can tell my customSorter function produces the order I want - the renderables now look like they are drawn in the right order.
However, this also seems like a hackjob, and I am sure my sorting algorithm is horrendously inefficient.
I would like advice on how to either;
a) Improve my own algorithm, especially in regards to any quirks to bare in mind when doing cross-platform LibGDX development (ie, array types, memory management in regards to android/web etc)
b) Alternative more efficient solutions having a similar "z index override" of the normal draw-order sorting.
Notes;
. The grouping is necessary. This is because while things are firmly stuck relatively to eachother within a group, groups themselves can also move about in front/behind eachother. (but not between). This makes it tricky to do a "global" override of the draw order, rather then a local one per group.
. If it helps, I can add/change the zindexattribute object in any way.
. I am thinking somehow "pre-storeing" each group of objects in a array could help things, but not 100% sure how.
First of all do never copy a list if not needed. The list with renderables could be really huge since it also could contain resources. Copying will be very very slow. If you need something local and you need performance try to make it final since it can improve the performance.
So a simple approach would be the default sorting of Java. You need to implement a Comperator for your class for example the Class with z index could look like this:
public class MyRenderable {
private float z_index;
public MyRenderable(float i)
{
z_index = i;
}
public float getZ_index() {
return z_index;
}
public void setZ_index(float z_index) {
this.z_index = z_index;
}
}
If you want a faster sort since your list wont change that much on runtime you could implement a insertion sort since it does a faster job if the list is kind of presorted. If it is not pre sorted it does take longer but in general it should only be the first sort call where it is alot disordered in your case.
private void sortList(ArrayList<MyRenderable> array) {
// double starttime = System.nanoTime();
for (int i = 1; i < array.size(); i++) {
final MyRenderable temp = array.get(i);
int j = i - 1;
while (j >= 0 && array.get(j).getZ_index() < temp.getZ_index()) {
array.set(j + 1, array.get(j));
j--;
}
array.set(j + 1, temp);
}
// System.out.println("Time taken: " + (System.nanoTime() - starttime));
}
To use this method you simply call it with your Array
sortList(renderbales);
In your case you need to take care of the ones that do not have a Z index. Maybe you could give them a 0 since they'll get sorted at the right position(i guess). Else you can use the given methods in z case and the regular in no z case as you do already.
After the conversation in the comments. I dont think it is a good idea to push everything into one list. It's hard to sort and would be very slow. A better approach would be a list of groups. Since you want to have groups, programm a group. Do not use String names, use IDs or types (way more easy to sort and it doesn't really matter). So a simple group would be this:
public class Group{
//think about privates and getters or methods to add things which also checks some conditions and so on
public int groupType;
public ArrayList<MyRenderable> renderables;
}
And now all your groups into a list. (this contains all your renderbales then)
ArrayList<Group> allRenderables = new ArrayList<>();
Last but not least sort the groups and sort the renderables. Since i dont think that your group ids/names will change on runtime, sort them once or even use a SortedSet instead of a ArrayList. But basically the whole sorting looks like this:
for(Group g: allRenderables)
sortRenderables(g.renderables); //now every group is sorted
//now sort by group names
sortGroup(allRenderables);
With the following insertionsorts as shown above
public static void sortRenderables(ArrayList<MyRenderable> array) {
for (int i = 1; i < array.size(); i++) {
final MyRenderable temp = array.get(i);
int j = i - 1;
while (j >= 0 && array.get(j).getZ_index() < temp.getZ_index()) {
array.set(j + 1, array.get(j));
j--;
}
array.set(j + 1, temp);
}
}
public static void sortGroup(ArrayList<Group> array) {
for (int i = 1; i < array.size(); i++) {
final Group temp = array.get(i);
int j = i - 1;
while (j >= 0 && array.get(j).groupType < temp.groupType) {
array.set(j + 1, array.get(j));
j--;
}
array.set(j + 1, temp);
}
}
I have created a gameboard (5x5) and I now want to decide when a move is legal as fast as possible. For example a piece at (0,0) wants to go to (1,1), is that legal? First I tried to find this out with computations but that seemed bothersome. I would like to hard-code the possible moves based on a position on the board and then iterate through all the possible moves to see if they match the destinations of the piece. I have problems getting this on paper. This is what I would like:
//game piece is at 0,0 now, decide if 1,1 is legal
Point destination = new Point(1,1);
destination.findIn(legalMoves[0][0]);
The first problem I face is that I don't know how to put a list of possible moves in an array at for example index [0][0]. This must be fairly obvious but I am stuck at this for some time. I would like to create an array in which there is a list of Point objects. So in semi-code: legalMoves[0][0] = {Point(1,1),Point(0,1),Point(1,0)}
I am not sure if this is efficient but it makes logically move sense than maybe [[1,1],[0,1],[1,0]] but I am not sold on this.
The second problem I have is that instead of creating the object at every start of the game with an instance variable legalMoves, I would rather have it read from disk. I think that it should be quicker this way? Is the serializable class the way to go?
My 3rd small problem is that for the 25 positions the legal moves are unbalanced. Some have 8 possible legal moves, others have 3. Maybe this is not a problem at all.
You are looking for a structure that will give you the candidate for a given point, i.e. Point -> List<Point>.
Typically, I would go for a Map<Point, List<Point>>.
You can initialise this structure statically at program start or dynamically when needing. For instance, here I use 2 helpers arrays that contains the possible translations from a point, and these will yield the neighbours of the point.
// (-1 1) (0 1) (1 1)
// (-1 0) (----) (1 0)
// (-1 -1) (0 -1) (1 -1)
// from (1 0) anti-clockwise:
static int[] xOffset = {1,1,0,-1,-1,-1,0,1};
static int[] yOffset = {0,1,1,1,0,-1,-1,-1};
The following Map contains the actual neighbours for a Point with a function that compute, store and return these neighbours. You can choose to initialise all neighbours in one pass, but given the small numbers, I would not think this a problem performance wise.
static Map<Point, List<Point>> neighbours = new HashMap<>();
static List<Point> getNeighbours(Point a) {
List<Point> nb = neighbours.get(a);
if (nb == null) {
nb = new ArrayList<>(xOffset.length); // size the list
for (int i=0; i < xOffset.length; i++) {
int x = a.getX() + xOffset[i];
int y = a.getY() + yOffset[i];
if (x>=0 && y>=0 && x < 5 && y < 5) {
nb.add(new Point(x, y));
}
}
neighbours.put(a, nb);
}
return nb;
}
Now checking a legal move is a matter of finding the point in the neighbours:
static boolean isLegalMove(Point from, Point to) {
boolean legal = false;
for (Point p : getNeighbours(from)) {
if (p.equals(to)) {
legal = true;
break;
}
}
return legal;
}
Note: the class Point must define equals() and hashCode() for the map to behave as expected.
The first problem I face is that I don't know how to put a list of possible moves in an array at for example index [0][0]
Since the board is 2D, and the number of legal moves could generally be more than one, you would end up with a 3D data structure:
Point legalMoves[][][] = new legalMoves[5][5][];
legalMoves[0][0] = new Point[] {Point(1,1),Point(0,1),Point(1,0)};
instead of creating the object at every start of the game with an instance variable legalMoves, I would rather have it read from disk. I think that it should be quicker this way? Is the serializable class the way to go?
This cannot be answered without profiling. I cannot imagine that computing legal moves of any kind for a 5x5 board could be so intense computationally as to justify any kind of additional I/O operation.
for the 25 positions the legal moves are unbalanced. Some have 8 possible legal moves, others have 3. Maybe this is not a problem at all.
This can be handled nicely with a 3D "jagged array" described above, so it is not a problem at all.
I have been debugging my implementation of Game of Life, and my main problem looks like its coming from how I use arrays.
public boolean[][] oldState;
public boolean[][] newState;
private boolean gameState = true;
public LifeBoard(Seed seed) {
oldState = seed.getSeed();
newState = new boolean[oldState.length][oldState[0].length];
run();
}
public void run() {
//debug code to run for x generations
for (int i = 0; i < 5; i++) {
BoardPrinter.print(oldState);
evaluateCells();
oldState = newState;
}
BoardPrinter.print(oldState);
System.out.println("game over");
}
the boolean[][] from Seed is a 5x5 grid, all false (dead) except the 3 horizontal middle cells in the middle row
00000
00000
0+++0
00000
00000
evaluateCells() looks at each cell in the grid, looks at the 8 cells around it, counts them, and based on the number of neighbors it writes a new value to newState.
What should happen: use oldState to calculate newState, copy newState to oldState, then go back through newState, writing each cell again based on the new oldState.
What really happens: the first generation works correctly, but after that the results are increasingly weird, it evaluates cells to be false that I know to be true, etc. The problem seems to be in the way I am copying the arrays.
If I initialize a 3rd blank array blankState[][] = new boolean[5][5];
and during the loop in run say:
public void run() {
//debug code to run for x generations
for (int i = 0; i < 5; i++) {
BoardPrinter.print(oldState);
evaluateCells();
oldState = newState;
newState = blankState;
}
BoardPrinter.print(oldState);
System.out.println("game over");
}
...then the game works correctly for an additional 1 generation, then the weird garbage returns.
I have 2 questions: first, it looks like I have to use System.arraycopy(), but unless someone tells me about a version for multidimensional arrays, I will have to write a simple loop.
My real question: why do you have to use this special System method to copy an array? Why can't you use the = operator?
EDIT: the conceptual answer is accepted below. Here is the code that solved the implementation problem:
for (int n = 0; n < oldState.length; n++) {
System.arraycopy(newState[n], 0, oldState[n], 0, oldState.length);
}
for (int t = 0; t < newState.length; t++) {
System.arraycopy(blankState[t], 0, newState[t], 0, newState.length);
}
Also for the record, System.arraycopy(boolean[][], 0, boolean[][], 0, boolean.length); did not work correctly, you have to iterate through each line.
My real question: why do you have to use this special System method to copy an array? Why can't you use the = operator?
This is actually an important Java lesson, so pay attention. Are you paying attention? Good. This will be important in the future.
Now, this applies for all objects in Java, as arrays are objects. If you use = then you only set the reference, and encounter all kinds of fun as seen here. Namely, if I have a simple class with a getter and setter called TestClass with a public int test, then the following code will work:
TestClass t=new TestClass();
t.test=1;
TestClass t1=t;
t1.test=6;
System.out.println(t.test); //prints 6.
Now, why? Because the references t and t1 point to the same object on the heap. And this holds for arrays as well. To get copies, you need to perform tasks that are object-specific. Some let you call clone() directly(Cloneable interface), some let you pass another instance into the constructor to get a new instance(Like the ArrayList constructor), and some use utility methods, like arrays here.
evaluateCells() looks at each cell in the grid, looks at the 8 cells
around it, counts them, and based on the number of neighbors it writes
a new value to newState.
What should happen: use oldState to calculate newState, copy newState
to oldState, then go back through newState, writing each cell again
based on the new oldState.
What really happens: the first generation works correctly, but after
that the results are increasingly weird, it evaluates cells to be
false that I know to be true, etc. The problem seems to be in the way
I am copying the arrays.
Without seeing your bit shifting code, I'd bet this is caused by a higher level problem. Most likely your bit shifting algorithm has a bug somewhere.
Have you stepped through your code with Eclipse's debugger? If not, read this tutorial and try a few different seeds. This will tell you where, if anywhere, in your algorithm the bit shift error occurs.
http://www.vogella.com/articles/EclipseDebugging/article.html
Im writing a recursive function in Java (graph theory) to get all paths in a 4x4 table, beginning at a random starting point. Possible directions are horizontal, vertical & diagonal, but I have a requirement that the same location cannot be visited twice.
The script works fine so far, I get a lot of combinations. The problem is that in the for loop of the function, when there is more than one possible way, then I get wrong results in the second and following loops because the boolean[] tempvisited is not getting back to his old values.
I hope there is someone, that may understand my English and my problem too. Here is my code so far:
// here I define a constant input of values:
String letters = "1548987425461854"
// This matrix shows all possible directions from every startpoint in the matrix:
// from the second value, you may get to the following locations: 1,3,5,6 and 7
private int[][] matrix = {
{1,4,5},
{0,2,4,5,6},
{1,3,5,6,7},
{2,6,7},
{0,1,5,8,9},
{0,1,2,4,6,8,9,10},
{1,2,3,5,7,9,10,11},
{2,3,6,10,11},
{4,5,9,12,13},
{4,5,6,8,10,12,13,14},
{5,6,7,9,11,13,14,15},
{6,7,10,14,15},
{8,9,13},
{8,9,10,12,14},
{9,10,11,13,15},
{10,11,14}
};
// Here begins the recursive function
public List<Combination> depthFirst(int vertex, boolean[] visited, Combination zeichen, List<Combination> combis){
// A temporary list of booleans to mark every value position visited or not
boolean[] tempvisited = new boolean[16];
// combis is the whole list of ways, zeichen is just the actual combination
zeichen.name = zeichen.name + this.letters.charAt(vertex);
combis.add(zeichen.name);
//marks actual value as visited
visited[vertex] = true;
for(int i = 0; i < 16; i++){
tempvisited[i] = visited[i];
}//end for
// going to next possible locations
for (int i = 0; i < this.matrix[vertex].length; i++) {
if (!visited[this.matrix[vertex][i]]) {
combis = depthFirst(this.matrix[vertex][i], tempvisited, zeichen, combis);
}//end if
}//end for
return combis;
}
You have the right idea with tempvisited, making a copy. But you're doing so in the wrong place.
You're setting visited[vertex] = true, which means that the visited you passed in is changing. What you want is for visited to never change. Make a copy of it, and make your changes to that copy.
Also, I notice that you use the same zeichen every time. So if you have a path 3 steps long, your combis list with be 3 copies of the same zeichen. That seems incorrect.
You set visited[vertex] to true before the first for loop; you could reset it to false just before you return. If every call undoes the change it did (directly), then every call will return with visited back to its state when that call was made. No tempvisited needed.
Take a look to this other recursive solution (pseudocode) for the Depth First Search (DFS).
void search(Node root) {
if (root == null) return;
visit(root);
root.visited = true;
foreach (Node n in root.adjacent) {
if (n.visited == false)
search(n);
}
}
Actually you don't need a copy of the visited array. Mark the node as visited right before the reccurrent call of depthFirst and then "unmark" it right after the call. Something like:
for (int i = 0; i < this.matrix[vertex].length; i++) {
if (!visited[this.matrix[vertex][i]]) {
visited[this.matrix[vertex][i]] = true;
combis = depthFirst(this.matrix[vertex][i], tempvisited, zeichen, combis);
visited[this.matrix[vertex][i]] = false;
}//end if
}//end for