For anyone interested, this is a scenario on codingame.com for an optimisation puzzle called code vs zombies.
I was working on a code challenge which focusses on a player having to move towards a destination. If the co-ordinates for the destination are close, the player will move more slowly towards the position, as the speed is dictated by the position difference from the player to the destination. To solve this issue and make the player always move as fast as possible (the speed logic is outside of my control in this situation) I created a function.
let p = parseInt
let speedup = (destination,playerPosition) =>{
let [destX,destY] = destination.split(" ");
let [playerX,playerY] = playerPosition.split(" ");
destX = p(destX);destY=p(destY);playerX=p(playerX);playerY=p(playerY)
let [xDist,yDist] = [destX-playerX,destY-playerY]
let i=1
do {
if ((xDist*i) playerX<0 || (yDist*i) playerY<0 || xDist> 20000 || yDist > 20000){
xDist = (xDist*(i-1)) playerX;
yDist = (yDist*(i-1)) playerY;
return xDist " " yDist;
}
else if(i==19){
xDist = (xDist*i) playerX;
yDist = (yDist*i) playerY;
return xDist " " yDist;
}
i
} while (i<20);
}
The function takes in two parameters. Both parameters have an X and a Y position inside a string, like so:
destination = "3000 5800"
playerPosition = "6000 7800"
The X Y map goes does not have any negatives in it, so it moves from top left 0,0.
If I pass a negative value back into the movement, for example "-2000 3000" the program will crash (again, this bit is outside of my control in this scenario).
So to break this down, I've split the array into the individual variables, written a loop to multiply the velocity and then added the player position to it. each time I check if X or Y are less than 0 and if they are, I use the previous result.
The code seems to work, but it's pretty clunky I think, and I'm sure there are better ways to do it.
Edit - for clarity on what is being returned.
the return is a string which has an X and a Y co-ordinate with a space for example:
return "20 300"
this is telling the player to go to the X co-ordinate 20, and the Y co-ordinate 300
in terms of the speed, the input of this return is at a set rate, so say it's once per second. So if I tell my player at 100,100 to move to 99,99 the player will do it very slowly. It will take the entire second to move a distance of 1,1, that said if I tell the player to move to 1,1, he will move in the same direction, but much faster.
the variable I am passing in is an intersection between two points, I want the player to travel to that destination fast (and even move past it) regardless of how close it is.
CodePudding user response:
I still feel like we are missing some information because it is a pretty weird problem, but here is a solution (completely untested).
From what I understand, we want a point with integer coordinates on the line from playerPosition
to destination
. The point should have non-negative coordinates and (if possible) at least at a distance of 2000 from playerPosition
.
const minDistance = 2000;
const parse = (str) => str.split(" ").map(s => parseInt(s));
const speedup = (destination, playerPosition) => {
const [playerX, playerY] = parse(playerPosition);
const [destX, destY] = parse(destination);
const [dx, dy] = [destX - playerX, destY - playerY];
// Now we want to return the player position a certain number of times [dx, dy]
// First we compute the amount of times we need to multiply it
const dist = Math.sqrt(dx * dx dy * dy);
if (dist == 0) {
return `${playerX} ${playerY}`; // We are already arrived
}
let steps = Math.ceil(minDistance / dist);
// Then we deal with the non-negative stuff by limiting the amount of steps if it would result in a negative position
if (dx < 0) {
steps = Math.min(steps, Math.floor(-playerX / dx));
}
if (dy < 0) {
steps = Math.min(steps, Math.floor(-playerY / dy));
}
// We are done
return `${playerX steps * dx} ${playerY steps * dy}`;
}