Java: How to check if a generated level is possible? - java

I've created a text based game which automatically generates a map with 10x10 rooms, a few of the rooms are blocked by various debris and I couldn't work out the most efficient way to check if a player can still reach a key and get to the exit without them being cut off from the map.
Currently there's a low chance needed rooms are cut off from the rest of the map, making the level impossible, I thought about checking each adjacent square to the start position, and then repeat and repeat until all of the squares that are accessible are set to 'accessible' in a variable and then if the three objects aren't reachable just regen'ing the map again until they are.
This may be slow if it regens a few times though.
Does anyone have any thoughts on the repetitive part to keep it fast, or a better way of achieving this?
Here's an image of a generated map: #'s are blocked rooms.
http://postimg.org/image/8oo88jxgb/

You can use the Dijkstra's algorithm, or some other pathfinding algorithm, to check if there is a way from the room entrance to each object and then discard the invalid rooms. This would probably be a bit slow though, specially if the rooms get bigger or you add more objects.
A better option would be to guarantee by construction that each part of the room can be reached. This can be achieved using Binary Space Partioning (BSP). It can be used to create random dungeons while assuring that all the rooms are connected. You can find more information in this tutorial.
There is a lot of material about procedurally generated dungeons around. You can check another interesting tutorial here.

The real problem is that programmers have spent far too much time
worrying about efficiency in the wrong places and at the wrong times;
premature optimization is the root of all evil (or at least most of
it) in programming.
Donald Knuth (1974 Turing Award Lecture, Communications of the ACM 17 (12), (December 1974), pp. 667–673)
Taking Knuth's advice, I recommend implementing the simplest solution that comes to mind (as outlined in the question, for example) and only looking for a more efficient algorithm if that approach turns out to be a bottleneck in the program. If he was right for computers with the performance they had in 1974, he's much more right now ...

You could represent your board as a graph holding a coordinate value as the key and a set of coordinates as the values representing each coordinates neighbors..example Map<Coordinate, HashSet<Coordinate> = new Hashmap<Coordinate, HashSet<Coordinate>();.
Then populate the graph with each coordinate value as a key with their respective neighbors as their values.
Whenever a blocked off room appears, simply remove that coordinate from each of the coordinates neighbors that surround it.
So if you have coordinate (5,5) as a blocked room, you would removed (5,5) from (4,5)s neighbor set, (5,4)s neighbor set, (6,5)s neighbor set, and (5,6)s neighbor set. This would basically not allow you to move through this path any more.
To populate the graph you could use two loops:
for(int r = 0; r <= 10; r++){
for(int c = 0; c <= 10; c++){
HashSet<Coordinate> neighbors = new HashSet<Coordinate>();
if(r > 0){
neighbors.add(new Coordinate(r - 1, c));
}
if(r < 8){
neighbors.add(new Coordinate(r + 1, c));
}
if(c > 0){
neighbors.add(new Coordinate(r, c - 1));
}
if(c < 8){
neighbors.add(new Coordinate(r, c + 1));
}
graph.put((new Coordinate(r,c)), neighbors);
}
}
I hope this is what you were asking for.

Make an array A with a row for each room and a column for each room.
Put a 1 in each i, j (row,column) position if the two rooms are connected.
This matrix( A ) is the numeric representation of the graph that is your game, the nodes of the graph are rooms and the edges are doors.
Now take a vector with a length corresponding to the number of rooms you have and fill it with zeros except for a one in the position corresponding to the room you start in. This vector( P ) is the number of ways you can get to a given room after 0 transitions. To check if it is possible to get to a given room in ( n )transitions simply multiply P A^n and look for a non zero value in the position in the vector that represents the given room.
this is a generalization of maths described well here https://en.wikipedia.org/wiki/Markov_chain

Related

Displaying Numbers in Certain Shapes

I just thought of this problem 15 minutes ago and even though it appears insanely easy I'm having a serious problem coming up with an answer.
Basically what I would like to do is based on a number (n) given by the user, I would like to draw a square shape.
Example: let's say the user gives the number 2, the result should be:
12
43
Now, suppose the user gives the number 3, the result should be:
123
894
765
etc..
Please don't give me the solution to this problem, I just want a clue or two to get me going.
I thought about doing it with a simple java class but I'm still struggling to get past the first condition:
public class DrawSquareWithNumbers {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter your number: ");
int number = scanner.nextInt();
for (int i = 0; i <= number; i++) {
if (i<number)
System.out.print(i);
if (i>=number) {
System.out.println("\n"+i);
}
}
}
}
Any tip? Thanks in advance.
So I think I just put way too much time in this but it's a fun challenge so I thought let's give it a go.
I implented a code version for this solution and it works quite well although it's probably not the cleanest as I approached the whole problem backwards.
Here is my solution to try out online (note it's severely unoptimized and by no ways good Java code. It's a quick and dirty implementation to be honest):
https://ideone.com/97JB7Y
So the idea is quite simple: We first calculate the correct value for each position in a matrix and then we print that matrix out.
Let's go over it in a bit more detail:
We start of by creating the Matrix for our values to print:
With a given size n this is
int[][] values = new int[n][n];
Now we want to calculate the correct value at each point. I chose to tackle it the "wrong way" around by not starting at the first point but at the center of the spiral.
Basically imagine this matrix with n = 3:
[1][2][3]
[8][9][4]
[7][6][5]
Instead of at 1 I just start at 9. Reasoning for this is that it's actually easier to calculate the position spiraling out from a point over spiraling in to a point.
So starting at this center point we spiral out from there in a circular fashion. For the matrix
[1][2]
[4][3]
this means we visit 4 -> 3 -> 2 -> 1. And then just save the correct value in the matrix.
Only problem with my approach is that for a matrix with uneven size (3, 5, 7, etc.) I still visit the points in spiraling order, for 3x3 the order of visiting is e.g. 9 -> 4 -> 3 -> 2 -> 1 -> 8 -> 7 -> 6 -> 5, as visualized in this perfect picture I totally drew in Paint:
This leads to the result matrix being inversed as such:
[5][6][7]
[4][9][8]
[3][2][1]
This small problem is easily fixed though by simply printing the matrix out inversed once more should n%2 != 0.
Hope I could help with maybe a different approach to the problem.
I think you want to make nxn matrix with user entered number. So you can check the input and then you can use loop as for(i=1; i<=n; i++) for rows and similarly for column(for j=0;j<=n;j++) and then you can print your desired shape. Since you have asked to give you idea only so I am not posting any code here. If in case you get stuck somewhere you can refer : https://www.google.com/amp/s/www.geeksforgeeks.org/print-a-given-matrix-in-spiral-form/amp/
Ok, let's give this a try. First let's assume you'll have to store the matrix before printing it and that there's no magic formula that allows you to print what you need in a single iteration.
Now, you've the NxN matrix, for example for 3 it'd be 3x3, 9 positions. Instead of solving it with a series of ifs in an ugly way, you could use direction vectors for a cleaner solution. Also assume for now that you've another NxN matrix filled with booleans, all set to false, that will represent the already printed positions in the NxN matrix that you will print in the end. When you write a number in the final NxN matrix, you put the same position's boolean to true in the boolean matrix.
So for example, you want to print the positions of the first row, 1 2 3. You are displacing to the right to print. This'd be the direction (1,0), aka the starting direction vector. You advance through the NxN matrix using this coordinates. When you go outside the matrix (in the example, your x position is 3) you decrease your x position by one and you "spin" your direction vector (this should be done in a separate function). (1,0) would spin to (0,-1). You keep using this vector to iterate your matrix, spinning as necesary. After the first whole circle, you will get to an already printed position before going outside the matrix. So after every print you've to check not only if you go outside the matrix, but also if that position has already a number on it. For this, you use the boolean matrix.
This is how I'd solve it, there are probably many other ways (and better ones). For starters you could use null, or a mark, in the final matrix and save yourself the booleans one.
Create the result matrix beforehand, and declare a variable for the current number, starting value = 1, the current co-ordinates, starting with (0,0), the stepping direction starting with "to the right"
Start loop
Calculate the co-ordinates of next step, and check it
If it is off the matrix, then change direction, and re calculate, re-check
If free, then put the number in the matrix, increment it, and loop
If it is not free, then end loop, print out result matrix

How to efficiently select neighbour in 1-dimensional and n-dimensional space for Simulated Annealing

I would like to use Simulated Annealing to find local minimum of single variable Polynomial function, within some predefined interval. I would also like to try and find Global minimum of Quadratic function.
Derivative-free algorithm such as this is not the best way to tackle the problem, so this is only for study purposes.
While the algorithm itself is pretty straight-forward, i am not sure how to efficiently select neighbor in single or n-dimensional space.
Lets say that i am looking for local minimum of function: 2*​x^​3+​x+​1 over interval [-0.5, 30], and assume that interval is reduced to tenths of each number, e.g {1.1, 1.2 ,1.3 , ..., 29.9, 30}.
What i would like to achieve is balance between random walk and speed of convergence from starting point to points with lower energy.
If i simply select random number form the given interval every time, then there is no random walk and the algorithm might circle around. If, on the contrary, next point is selected by simply adding or subtracting 0.1 with the equal probability, then the algorithm might turn into exhaustive search - based on the starting point.
How should i efficiently balance Simulated Annealing neighbor search in single dimensional and n-dimensional space ?
So you are trying to find an n-dimensional point P' that is "randomly" near another n-dimensional point P; for example, at distance T. (Since this is simulated annealing, I assume that you will be decrementing T once in a while).
This could work:
double[] displacement(double t, int dimension, Random r) {
double[] d = new double[dimension];
for (int i=0; i<dimension; i++) d[i] = r.nextGaussian()*t;
return d;
}
The output is randomly distributed in all directions and centred on the origin (notice that r.nextDouble() would favour 45º angles and be centred at 0.5). You can vary the displacement by increasing t as needed; 95% of results will be within 2*t of the origin.
EDIT:
To generate a displaced point near a given one, you could modify it as
double[] displaced(double t, double[] p, Random r) {
double[] d = new double[p.length];
for (int i=0; i<p.length; i++) d[i] = p[i] + r.nextGaussian()*t;
return d;
}
You should use the same r for all calls (because if you create a new Random() for each you will keep getting the same displacements over and over).
In "Numerical Recepies in C++" there is a chapter titled "Continuous Minimization by Simulated Annealing". In it we have
A generator of random changes is inefficient if, when local downhill moves exist, it nevertheless almost always proposes an uphill move. A good generator, we think, should not become inefficient in narrow valleys; nor should it become more and more inefficient as convergence to a minimum is approached.
They then proceed to discuss a "downhill simplex method".

Optimize algorithm to find intersection points in 2d roads (lines)

I have a list of Lines which represent Roads such that each road has a "StartingPoint" and an "EndingPoint". My goal is to find "Next" road of each road. A road is Next of another road if its starting point OR ending point falls on top of the starting point or ending point of another road. For example :
Road A : starting point of : (0,0) and ending point of (2,0)
Road B : starting point of : (2,0) and ending point of (5,0)
Road C: starting point of : (2,0) and ending point of (4,2)
So Roads Next is will be :
A NEXT { B , C}
B NEXT { A }
C NEXT { A }
My current algorthim is doing it in O(n^2) by comparing every starting point of a road to starting and ending of another road. How can make this faster. I think sorting the roads might work but I'm not sure. Please tell me what you think!
Note: Those who are saying use Hashmap<Start/EndPoint,Road> your solution is still O(N^2).
It depends what you want to do with the result. The result of your calculation is of size O(#roads^2). This means that if you want to iterate over it then you will need O(#roads^2) at best. This being said if you just want to be able to answer questions like "return all adjacencies of a given road" then you can do that in O(#roads) with the algorithm you implemented.
In Java, a HashMap<XYPoint, HashSet<Road>> endPoints, and another HashMap<Road, HashSet<Road> next should suffice; assuming your Road objects have a ending and starting XYPoint s. The logic would go as follows:
for each road R,
add it, using its starting point, to the endPoints map; and
for each road X with a co-incident endpoint,
next.put(R, X); next.put(X, R);
add it, using its ending point, to the map endPoints map; and
for each road X with a co-incident endpoint,
next.put(R, X); next.put(X, R);
At the end of this procedure, your next map would contain the next roads for each road. You would just have to iterate this map to generate the desired output.
If there are no next roads, the algorithm is O(n). In the worst case (all roads have the same starting and ending points), it is O(n^2); you can eliminate this by using suitable equals/hashcode for your Roads, at the cost of some extra complexity (you would need to count repetitions).
In my opinion, the easiest way to do this is to create a class Cell that would represent a certain point like (x;y). Override equals and hashCode of Cell and then simply store your Cell objects in a HashMap that guaranties a high speed of retrieving its elements.
There's an O(n log n) algorithm, I'm not sure if there are any that are superior.
You can:
1) Create a Point class that consists of a 2D point, and a pointer to the road that it has an endpoint (starting point or ending point) of.
2) Create an Array twice as big as your collection of roads
3) Loop through all roads, and add a Point representing both the starting point or the ending point to an Array - have said Point point back to the road that created it.
4) Order the array using the sort of your choice. You can use a lot of sorting functions, but since you're writing code I would say you use one that first sorts by y, then uses x to tiebreak on equal y's. So:
if ( a.y < b.y ) return -1;
if ( a.y > b.y ) return 1;
if ( a.x < b.x ) return -1;
if ( a.x > b.x ) return 1;
return 0;
Only for points you should probably rewrite it as non-branching if you care about speed.
5) Adjacent points may be the same. Non-adjacent points are certainly not. Run through the ordered array in O(n) time. Points refer back to their roads. Combine as you see fit.
The storage of your final result doesn't have to be of size O(roads^2) if you allow 3 things:
Store separate sub-lists for roads that overlap a road's start point and its end point. You can just concatenate the two lists together to get a road's complete next list when looking it up, or iterate through one and then the other.
Share lists between roads. The start point list of one road might be another road's start or end point list. In other words, for each point there is a single list of all roads that either start or end there.
Allow a road to be a member of its own lists (and just ignore it when retrieving the list).
The hash map you need is HashMap<XYPoint, List<Road>>
For each road, store List<Road> startList and endList
The algorithm is (pseudo-code):
For each road in list
For point in [start, end]
Look up List<Road> roadlist from hash map based on point X,Y
If null then
roadlist = new List<Road>
add road to roadlist
add roadlist to hash map
else
add road to roadList
set roadList as either road.startList or road.endList
You only add each road to a List twice. Assuming hash lookups and adds are O(1) then this should be O(n).

Fix collision detection penetration

I am implementing collision detection in my game, and am having a bit of trouble understanding how to calculate the vector to fix my shape overlap upon collision.
Say for example, I have two squares. squareA and squareB. For both of them, I know their xCo, yCo, width and height. squareA is moving however, so he has a velocity magnitude, and a velocity angle. Let's pretend I update the game once a second. I have illustrated the situation below.
Now, I need a formula to get the vector to fix the overlap. If I apply this vector onto the red square (squareA), they should not be overlapping anymore. This is what I am looking to achieve.
Can anyone help me figure out the formula to calculate the vector?
Bonus points if constructed in Java.
Bonus bonus points if you type out the answer instead of linking to a collision detection tutorial.
Thanks guys!
Also, how do I calculate the new velocity magnitude and angle? I would like sqaureA to continue moving along the x axis (sliding along the top of the blue square)
I had an function that looked something like this:
Position calculateValidPosition(Position start, Position end)
Position middlePoint = (start + end) /2
if (middlePoint == start || middlePoint == end)
return start
if( isColliding(middlePont) )
return calculateValidPosition(start, middlePoint)
else
return calculate(middlePoint, end)
I just made this code on the fly, so there would be a lot of room for improvements... starting by not making it recursive.
This function would be called when a collision is detected, passing as a parameter the last valid position of the object, and the current invalid position.
On each iteration, the first parameter is always valid (no collition), and the second one is invalid (there is collition).
But I think this can give you an idea of a possible solution, so you can adapt it to your needs.
Your question as stated requires an answer that is your entire application. But a simple answer is easy enough to provide.
You need to partition your space with quad-trees
You seem to indicate that only one object will be displaced when a collision is detected. (For the case of multiple interpenetrating objects, simply correct each pair of objects in the set until none are overlapping.)
Neither an elastic nor an inelastic collision is the desired behavior. You want a simple projection of the horizontal velocity (of square A), so Vx(t-1) = Vx(t+1), Vy(t-1) is irrelevant and Vy(t+1)=0. Here t is the time of collision.
The repositioning of Square A is simple.
Define Cn as the vector from the centroid of A to the vertex n (where the labeling of the vertices is arbitrary).
Define A(t-1) as the former direction of A.
Define Dn as the dot product of A(t-1) and the vector Cn
Define Rn as the width of A measured along Cn (and extending past the centroid in the opposite direction).
Define Sn as the dilation of B by a radius of Rn.
Let j be the vertex of B with highest y-value.
Let k be the vertex that is most nearly the front corner of A [in the intuitive sense, where the value of Dn indicates that Ck is most nearly parallel to A(t-1)].
Let K be the antipodal edge or vertex of A, relative to k.
Finally, translate A so that k and j are coincident and K is coincident with Sk.

magnetism simulation

Say I have p nodes on a n by m pixel 2D surface, I want the nodes to be attracted to each other such that the further they are apart the strong the attraction. But if the distance between two nodes, say d(A,B) is less than some threshold say k then they start to repel. Could anyone get me started on some code on how to update the co-ordinates of the nodes over time.
I have something a little like the code below which is start to do the attraction, but looking for some advice. (P.S. I can not use an existing library to do this).
public class node{
float posX;
float posY;
}
public class mySimulator{
ArrayList<node> myNodes = new ArrayList<node>();
// Imagine I add a load of nodes to myNodes
myNodes.add(.....
// Now image this is the updating routine that is called at every fixed time increment
public void updateLocations(){
for(int i =0; i <= myNodes.size(); i++){
for(int i =0; i <= myNodes.size(); i++){
myNodes.get(i).posX = myNodes.get(i).posX + "some constant"*(myNodes.get(j).posX -myNodes.get(i).posX);
myNodes.get(i).posY = myNodes.get(i).posY + "some constant"*(myNodes.get(j).posY -myNodes.get(i).posY);
}
}
}
}
}
This kinetic model of elastic collisions is completely unrelated to magnetism, but the design might give you some ideas on modeling an ensemble of interacting particles.
Say I have p nodes on a n by m pixel 2D surface, I want the nodes to be attracted to each other such that the further they are apart the strong the attraction. But if the distance between two nodes, say d(A,B) is less than some threshold say k then they start to repel.
You realize, of course, that this is not how the physics of magnetism work?
Could anyone get me started on some code on how to update the co-ordinates of the nodes over time.
Nobody will be able to give you code to do this easily, because it's actually a difficult problem.
You can numerically integrate the ordinary differential equations for each particle over time. Given initial conditions for position, velocity, and acceleration vectors in 2D, you'll take a time step, integrate the equations to get the values at the end of the time step, update the values by adding the increment, and then doing it again.
It requires some knowledge of 2D vectors, numerical integration, ordinary differential equations, linear algebra, and physics. Do you know anything about those?
Even if you "make up" your own physical laws governing the interactions between your particles, you'll still have to integrate that set of equations.
I'd recommend looking at Runge-Kutta for systems of ODEs. "Numerical Recipes" has a nice chapter on it, even if you go elsewhere for the implementation.
"NR" is now in its third edition. It's a bit controversial, but the prose is very good.

Categories