I am fairly new to programming and have decided to take on a project where I create a game in the console. The user has the options to move up, down, left, or right from the center of an area that is a 3x3 grid. One of the x,y locations is marked a 'bad' square and the game ends when the user's x and y are equal to that of the bad square's. The bad squares location is x = 1 and y = 3.
The problem I have is that when the user enters Up or Left (hence the users y becomes 3 or the users x becomes 1) and the game ends even though one of the other axis values does not match the bad squares.
Here is my code:
public static void main (String[]args){
//scanner
Scanner userIn = new Scanner(System.in);
//string that will get users value
String movement;
//strings that are compared to users to determine direction
String up = "Up";
String down = "Down";
String left = "Left";
String right = "Right";
//starting coordinates of user
int x = 2;
int y = 2;
//coordinates of bad square
int badx = 1;
int bady = 3;
//message telling user options to move (not very specific yet)
System.out.println("Up, Down, Left, Right");
//do while loop that continues until
do {
movement = userIn.nextLine();
//checking user input and moving them accordingly
if (movement.equals(up)) {
y++;
} else if (movement.equals(down)) {
y--;
} else if (movement.equals(left)) {
x--;
} else if (movement.equals(right)) {
x++;
} else {
System.out.println("Unacceptable value");
}
//checking if user is out of bounds, if user tries to leave area, x or y is increased or decreased accordingly
if (x < 0 || y < 0 || x > 3 || y > 3) {
System.out.println("Out of bounds");
if (x < 0) {
x++;
} else if (y < 0) {
y++;
} else if (x > 3) {
x--;
} else if (y > 3) {
y--;
}
}
//message showing user x and y coordinates
System.out.println("x =" + x + " y =" + y);
} while (y != bady && x != badx); //what checks to see if user has come across the bad square
//ending message (game ends)
System.out.println("Bad Square. Game over.");
}
Your while(y != bady && x != badx) test tests y isn't bad AND x isn't bad therefore it only takes one of these to be false for your loop to cease.
An easy fix might be to swap your logic around a little.
while(!(y == bady && x == badx))
If you think about how your conditional statement is phrased while(y != bady && x != badx) you will see that when either x = 1 or y = 3, one of the sides in the AND statement evaluates to false and causes the whole condition to be false. You could handle it by instead writing:
while(y != bady || x != badx)
Just set logic OR in condition
while(y != bady || x != badx);
&& matters that both conditions should be true
Related
I am making a pacman arcade game on Java but my collisions have problems.
If you see my image
here my pacman sprite stands still (no x or y movement) when visiting a corner or when trying to turn back the direction it came (ie goes left but does not go right again). I understand this is because I set my xMovement to 0 and yMovement to 0 if a collision is detected (see second code block under collide()).
How would I allow the pacman sprite to move the other way (ie it comes from the left and I want it to go right) or traverse a corner if my collision() does not allow this?
Below is my draw method in the App.java class which draws the player based on the user's input. The keys wasd correspond with up, left, down, right respectively. this.direction is only used so the player does not waste a move nor go through a wall when a collision happens. *Note, I put (this.player.x_ord + 2) % 16 == 0 because my pacman image is not a 16x16 image unlike my walls which are.
public void draw() { // This is an infinite loop
mapDraw(); // this draws my map constantly so I do not have multiple pacman sprites drawn
this.player.tick(); // see second code below for details
if (keyPressed){ // Used wasd rather than arrow keys
if (key == 's' && this.direction != 's' && (this.player.x_ord + 2) % 16 == 0 &&
(this.player.y_ord + 4) % 16 == 0){ // We dont want Player to turn ever on a non 16 divisible area
this.player.p = this.loadImage("src/main/resources/playerDown.png");
this.player.yMovement = this.player.speed;
this.player.xMovement = 0;
this.direction = 's';
}
else if (key == 'w' && this.direction != 'w' && (this.player.x_ord + 2) % 16 == 0 &&
(this.player.y_ord + 4) % 16 == 0){
this.player.p = this.loadImage("src/main/resources/playerUp.png");
this.player.yMovement = -this.player.speed;
this.player.xMovement = 0; // I do not want my pacman to move diagonally so thats why
this.direction = 'w';
}
else if (key == 'd' && this.direction != 'd' && (this.player.x_ord + 2) % 16 == 0 &&
(this.player.y_ord + 4) % 16 == 0){
this.player.p = this.loadImage("src/main/resources/playerRight.png");
this.player.xMovement = this.player.speed;
this.player.yMovement = 0;
this.direction = 'd';
}
else if (key == 'a' && this.direction != 'a' && (this.player.x_ord + 2) % 16 == 0 &&
(this.player.y_ord + 4) % 16 == 0){
this.player.p = this.loadImage("src/main/resources/playerLeft.png");
this.player.xMovement = -this.player.speed;
this.player.yMovement = 0;
this.direction = 'a';
}
}
this.player.draw(this); //see second code below for details
}
Below is my player.java class
*Note again that this.x_ord + 2 == w.x_pos + 16 && this.y_ord + 4 == w.y_pos is offset because of my pacman sprite is larger than my 16x16 walls.
public void tick(){
// //logic
this.detectCollision();
if (this.isLiving){
this.y_ord += this.yMovement;
this.x_ord += this.xMovement;
}
}
public void draw(PApplet a){ //just draw the sprite
if (this.isLiving){
a.image(this.p, this.x_ord, this.y_ord);
}
}
public void collide(boolean isX){ // Is it an x or y collision
if (isX == true){ // If it moves left or right into a wall
this.xMovement = 0;
}
else if (isX == false){ // If it moves up or down into a wall
this.xMovement = 0;
}
}
public void detectCollision(){
for (Walls w: this.wallLocations){ // A list of wall locations from a .txt file
if (this.x_ord + 2 == w.x_pos + 16 && this.y_ord + 4 == w.y_pos){ // Detect left movement into right wall piece
collide(true);
}
if (this.x_ord + 2 + 16 == w.x_pos && this.y_ord + 4 == w.y_pos){ // Detect right movement into left wall piece
collide(true);
}
if (this.y_ord + 4 == w.y_pos + 16 && this.x_ord + 2 == w.x_pos){ // Detect up movement into bottom wall piece
collide(false);
}
if (this.y_ord + 4 + 16 == w.y_pos && this.x_ord + 2 == w.x_pos){ // Detect down movement into top wall piece
collide(false);
}
}
Any help to my problem is much appreciated.
I didn't analyze your code deeply but it seems to me that your main problem is that collide method considers only 2 cases, vertical movement or horizontal movement. If you want to have movement in 4 different directions that method need to have 4 different states.
To achieve that you could create an enum representing direction. Then in detectCollision pass appropriate Direction into collide. Finally, in the collide consider 4 different directions. For example, if there is barrier on the right, xMovement need to be non-positive. The collide method could look like so:
public void collide(Direction direction){
if (direction == Direction.RIGHT){
this.xMovement = Math.min(0, this.xMovement);
}
if (direction == Direction.LEFT){
this.xMovement = Math.max(0, this.xMovement);
}
if (direction == Direction.UP){
this.yMovement = Math.min(0, this.yMovement);
}
if (direction == Direction.DOWN){
this.yMovement = Math.max(0, this.yMovement);
}
}
Hey guys I started programming a year ago and recently discovered streams. So I decided to complete my old tasks using streams whenever I could just to get used to them. I know it might not be smart to force using them but it's just practice.
One of my old tasks was to program Minesweeper and right now I try to find a better solution for counting adjacent mines whenever I click a field.
Some details:
I saved a bunch of mines in a Mine[] (arsenal.getArsenal()) and each of the mines has an x and y value. Whenever I click on a field I need to count all mines around the clicked field (from x-1,y-1 till x+1,y+1).
My current solutions are:
private int calculateNearby(int x, int y) {
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine -> mine.getX() == x + 1 && mine.getY() == y
|| mine.getX() == x && mine.getY() == y + 1
|| mine.getX() == x - 1 && mine.getY() == y
|| mine.getX() == x && mine.getY() == y - 1
|| mine.getX() == x - 1 && mine.getY() == y - 1
|| mine.getX() == x - 1 && mine.getY() == y + 1
|| mine.getX() == x + 1 && mine.getY() == y - 1
|| mine.getX() == x + 1 && mine.getY() == y + 1)
.count();
}
private int calculateNearby(int x, int y) {
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine ->
{
boolean b = false;
for (int i = -1; i < 2; ++i) {
for (int j = -1; j < 2; ++j) {
if ((x != 0 || y != 0) && mine.getX() == x + i && mine.getY() == y + j) {
b = true;
}
}
}
return b;
})
.count();
}
Both solutions work fine but the first looks "wrong" because of all the cases and the seconds uses for-loops which I basically tried to avoid using.
It would be nice if you could show me a better (ideally shorter) solution using streams. :D
I'm sorry if there's already a thread about this. I really tried to find anything related but there either isn't anything or I searched for the wrong keywords.
You can simplify your stream condition. Instead of checking each case if getX() equals x, x-1 or x+1 you can just check if getX() is greater or equals than x-1 and smaller or equals x+1. The same for getY().
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine -> mine.getX() >= x - 1 && mine.getX() <= x + 1
&& mine.getY() >= y - 1 && mine.getY() <= y + 1)
.count();
You could also create a method for the check to make the code more readable.
private int calculateNearby(int x, int y) {
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine -> inRange(mine.getX(), x)
&& inRange(mine.getY(), y))
.count();
}
private boolean inRange(int actual, int target) {
return actual >= target - 1 && actual <= target + 1;
}
Another way is to check if the absolute distance in each direction is less than or equal to 1:
private int calculateNearby(int x, int y) {
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine -> Math.abs(mine.getX() - x) <= 1 && Math.abs(mine.getY() - y) <= 1)
.count();
}
Note that this also counts a mine which is at the point (x, y) which is not the case with the code in the question.
When is a mine adjacent? When its only one field horizontally or vertically away.
Horizontal distance is Math.abs(mine.getX() - x), vertical distance is Math.abs(mine.getY() - y). It doesn't matter if its -1 or 1, just that it is one field away.
But it shouldn't be more than one field, either vertical or horizontal be away, so max(dx, dy) == 1.
Predicate<Mine> isAdjacent = mine ->
Math.max(
Math.abs(mine.getX() - x)
Math.abs(mine.getY() - y)
) == 1;
return (int) Arrays.stream(arsenal.getArsenal())
.filter(isAdjacent)
.count();
I am working on below task:
Given a sequence of moves for a robot, check if the sequence is circular or not. A sequence of moves is circular if first and last positions of robot are same.
A move can be on of the following.
G - Go one unit
L - Turn left
R - Turn right
Examples:
Input: path[] = "GLGLGLG"
Output: Given sequence of moves is circular
Input: path[] = "GLLG"
Output: Given sequence of moves is circular
The movements described in the input string are repeated for an infinite time. Your task is to find if there exists a circle, whose radius is some positive real number R,
such that the robot never leaves it. If such a circle exists return "YES" otherwise "NO"
I found a solution for this task :
public class Circle {
String check(String commands) {
int initialX = 0;
int initialY = 0;
int x = 0;
int y = 0;
String direction = "north";
for (int i = 0; i < commands.length(); i++) {
if (direction.equals("north")) {
if (commands.charAt(i) == 'G') {
y++;
} else if (commands.charAt(i) == 'L') {
direction = "west";
} else if (commands.charAt(i) == 'R') {
direction = "east";
} else {
System.out.println("Wrong command");
}
} else if (direction.equals("east")) {
if (commands.charAt(i) == 'G') {
x++;
} else if (commands.charAt(i) == 'L') {
direction = "north";
} else if (commands.charAt(i) == 'R') {
direction = "south";
} else {
System.out.println("Wrong command");
}
} else if (direction.equals("south")) {
if (commands.charAt(i) == 'G') {
y--;
} else if (commands.charAt(i) == 'L') {
direction = "east";
} else if (commands.charAt(i) == 'R') {
direction = "west";
} else {
System.out.println("Wrong command");
}
} else if (direction.equals("west")) {
if (commands.charAt(i) == 'G') {
x--;
} else if (commands.charAt(i) == 'L') {
direction = "south";
} else if (commands.charAt(i) == 'R') {
direction = "north";
} else {
System.out.println("Wrong command");
}
}
}
if (direction.equals("north") && (((x-initialX)*(x-initialX) + (y-initialY)*(y-initialY)) > 0)) {
return "NO";
} else {
return "YES";
}
}
}
Everything seems perfect, but I am not able to understand the condition:
if (direction.equals("north") && (((x-initialX)*(x-initialX) + (y-initialY)*(y-initialY)) > 0))
Can you please help me in understanding why we need to return NO for this case, what the formula && (((x-initialX)*(x-initialX) + (y-initialY)*(y-initialY)) > 0 indicates? and why the condition is checking only for direction "north" and not for other directions.
The last condition could be shortened to:
if (direction.equals("north") && (x != 0 || y != 0))
This condition means that after given sequence of steps robot has initial direction but not the initial position. In this case, this sequence shifts the position of the robot by (x, y). That means that after n repetitions of this sequence robot will have position (n*x, n*y). That is not bound by any radius when x != 0 || y != 0.
When both x and y are equal to zero, the robot has the initial direction and initial position after the given sequence of steps. That is a cycle and the answer is "Yes".
Otherwise, the direction of the robot has changed after the sequence of steps. There are two possibilities:
The direction has changed to the opposite (south). Let's assume that after the sequence of steps robot shifted to coordinates (x, y). But when we repeat this sequence in opposite direction coordinates will be changed by (-x, -y) and we will return to the (0, 0) coordinates with the initial direction.
The direction has changed to west or east. In this case, we will return to the initial position with the initial direction after four sequences of steps. For example, let's assume that direction was changed to east and position is (x, y) after the first sequence then:
Direction | Coordinates
-----------+--------------
north | (0, 0)
east | (x, y)
south | (x+y, y-x)
west | (y, -x)
north | (0, 0)
I am trying to write a program that asks the user to enter two points. Each point is entered one at a time. Then I need the x coordinate to me less than or equal to 5 and greater than or equal to -5.
I need to follow the same logic but with 2.5 and -2.5. For some reason it's not returning the string statement after the check. I don't have any syntax errors, so I am not sure what the issue is.
import java.util.Scanner;
public class coordinates {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//prompt user to enter coordinates
System.out.println("Enter a X coordinate: ");
double x = input.nextDouble();
System.out.println("Enter a Y coordinate: ");
double y = input.nextDouble();
//check x coordinate to see if it is less or equal to 5 and greater than or equal to -5
if (x <= 5 && x >= -5){
if (y <= 2.5 && y >= -2.5)
System.out.println("Yes");
}else
System.out.println("no");
}
}
If your x value is in range but your y value is not in range, then nothing will be printed, because the first if was followed but the second if was not followed. Change your if condition to one bigger condition, so that if either condition fails, then the else will be followed.
if ((x <= 5 && x >= -5) && (y <= 2.5 && y >= -2.5)) {
System.out.println("Yes");
}else {
System.out.println("no");
}
Working on a java project and having difficulty, the second else if statement brings up multiple errors claiming that } is not the proper start of a method and that the else has no if statement. Been stuck on this for hours. :-/
import java.util.Scanner;
public class Practice_4_4
{
public static void main(String[]args)
{
Scanner scan = new Scanner(System.in);
int x;
int y;
int coordinate;
System.out.print("Enter the X coordinate: ");
x = scan.nextInt();
System.out.print("Enter the Y coordinate: ");
y = scan.nextInt();
if (x == 0 && y == 0)
System.out.print("(0,0) is the origin");
else if (x > 0 || x < 0 && y == 0)
System.out.print("(" + x + ",0) is on the X axis");
else if (y > 0 || y < 0 && x == 0)
}
}
Note that an if condition must be followed by a code statement or block, and this statement or block will only be called if the if condition is true. Your last else if... has no statement or code block after it.
So this statement: else if (y>0 || y<0 && x==0) should be followed by some code block that is called if the statement is true. For example:
else if (y>0 || y<0 && x==0) {
// this block is called if the condition is true.
}
As an aside, please also note that good code formatting helps you with your debugging and sloppy formatting, especially sloppy indentation, does just the opposite. A little effort towards clean and regular indentation will go a long way towards helping you to debug your code better.
So improved formatting would look something like...
import java.util.Scanner;
public class Practice_4_4 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int x;
int y;
int coordinate; // what are you going to do with this variable?
System.out.print("Enter the X coordinate: ");
x = scan.nextInt();
System.out.print("Enter the Y coordinate: ");
y = scan.nextInt();
if (x == 0 && y == 0) {
System.out.print("(0,0) is the origin");
} else if (x > 0 || x < 0 && y == 0) {
System.out.print("(" + x + ",0) is on the X axis");
} else if (y > 0 || y < 0 && x == 0) {
// you need this block here
}
}
}
As another aside, at this stage of your programming education, you should strongly consider enclosing all if statements, else statements, for loops, while loops, any kind of loops, all with curly braces so that they're enclosed within a code block. Doing this will prevent future errors, where you add a line of code thinking that it is controlled by an if boolean condition when in fact it is not.
class IfElse {
public static void main(String[] args) {
int x1=0, y1=0, x2=1, y2=1, x3=1, y3=0, x4=0, y4=1;
// 0, 0 is origin
// 1, 1 is quadrant
// 1, 0 is X axis
// 0, 1 is Y axis
ifElse(x1, y1);
ifElse(x2, y2);
ifElse(x3, y3);
ifElse(x4, y4);
}
public static void ifElse(int x, int y) {
if(x == 0 && y == 0)
System.out.println("point is on origin...");
else {
if(x == 0)
System.out.println("point is on Y axis...");
else if(y == 0)
System.out.println("point is on X axis...");
else
System.out.println("point is in a quadrant...");
}
}
}
There is no problem, because you are newbie in Java programming language. Buddy, just listen me up, in the last else if block you haven’t anything and last else if block is useless. You can fix it like:
else if (y > 0 || y < 0 && x == 0){
System.out.println(“Something!”);
}
I hope, it was useful for you! Good luck, my java friend ; - )