Currently, I am trying to create a program that draws a square anywhere in a 15x15 Quadrant I (Coordinate plane) grid. I am stuck on trying to get the axes displaying correctly.
This is the code I have thus far:
import java.util.Scanner;
public class Question2square {
public static void main(String[] args) {
// Axis variables
int yAxismin = 0;
int yAxismax = 15;
int xAxismin = 0;
int xAxismax = 15;
//Loop through all coordinates on plane using for loops
for(int y = yAxismin; y <= yAxismax; y++)
{
for(int x = xAxismin; x <= xAxismax; x++)
{
//Draw the axis
if (!Axis(x,y).equals("")) {
System.out.print(Axis (x,y));
}
}
System.out.println("");
}
}
// This method draws the 15x15 axis
public static String Axis(int x, int y)
{
// Each if and else if statement dictates what symbol needs to go where for the axes
// If there is nothing to be drawn, there will simply be a blank space
if (x == 15 && y== 0) return ">";
else if(x == 0 && y == 15) return "^";
else if (x == 0 && y == 0 )return ".";
else if(x == 0 && y >= 0) return "|";
else if(x >= 0 && y==0) return "-";
else return "";
}
/*
// Method to be used to draw actual square
public static ... drawSquare(...) {
}
*/
}
Unfortunately, instead of drawing the 'L' shaped axes I desire, it displays an 'r' shape instead. I'm trying to figure out how to display the axis properly.
I tried flipping the for loops but that didn't help. I don't see what else could be inhibiting this.
Try reversing the y loop:
for(int y = yAxismax; y >= yAxismin; y--) ...
As your loop prints lines to the console from "top to bottom" and then "left to right", you want your greatest value of y to come first and your least value of x to come first. Therefore you only need to reverse the y loop to go from yAxismax to yAxismin. The result (for limits of 3 and not 15 is then:
^
|
|
.-->
Related
I am writing a little program in Processing3 that enables me to change the background to a specific colour RGB code stored in arrays. Each vale for R, G and B is stored in a separate array.
Changing the mouse horizontal position changes the colour of the background.
However this solutions code is quite repetitive, and there is a lot of if/else statements. I want to use a for() loop to simplify the code and make it less repetitive. However, i am struggling to include the mouse position variable in the for() loop. Is there to simplify this code using a for() loop and somehow map the mouse position to access array items? This is the code I have right now:
int[] r = {255,249,240,233,227};
int[] g = {115,138,157,173,187};
int[] b = {0,18,63,94,120};
void setup() {
size(500, 500);
}
void draw() {
int x = mouseX;
if(x >= 0 && x <=100) {
background(r[0], g[0], b[0]);
}
else if (x >= 101 && x <= 200){
background(r[1], g[1], b[1]);
}
else if (x >= 201 && x <= 300){
background(r[2], g[2], b[2]);
}
else if (x >= 301 && x <= 400){
background(r[3], g[3], b[3]);
}
else {
background(r[4], g[4], b[4]);
}
}
I wish to simplify the code to something more like this:
int[] r = {255,249,240,233,227};
int[] g = {115,138,157,173,187};
int[] b = {0,18,63,94,120};
void setup() {
size(500, 500);
}
void draw() {
for(int i=0; i<r.length; i++) {
background(r[i],g[i],b[i]);
}
}
However, I don't know how to change this code in a way, that the background colour would change depending on mouse horizontal position, as it is shown in the first example.
Thank you for your reply and help!
If your steps between your different values are 100, then you can just divide the input X value by 100. Integer division will take care of the rest.
The if statement is just to make sure it stays within the bounds of your array.
int mouseX = ...;
int i = mouseX / 100;
if(i < r.length && i < g.length && i < b.length)
{
background(r[i], g[i], b[i]);
}
currently my program is only always giving me 4, how can I determine how many steps the ant took to cover the whole board? The ant can walk up down left right, but can't walk off the board, and then do this simulation 4 times.
public static void main(String args[]) {
int[][] grid = new int[8][8];
int count = 0;
int x = 0;
int y = 0; // arrays are 0 based
while(true)
{
int random = (int)Math.random()*4+1;
if (random == 1)
{
x--; // move left
}
else if (random == 2)
{
x++; // move right
}
else if (random == 3)
{
y--; // move down
}
else if (random == 4)
{
y++; // move up
}
if(x < 0 || y < 0 || x >= grid.length || y >= grid[x].length) break;
count++;
grid[x][y]++;
}
System.out.println("Number of Steps in this simulation: " + count); // number of moves before it fell
}
}
The problem is this expression:
int random = (int)Math.random()*4+1;
Through the explicit cast, only Math.random() ist casted to int. But since Math.random() returns a dobule < 1, it is casted to 0 and thus random is always 1 and the method always returns 0.
The problem can be fixed by casting Math.random() * 4:
int random = (int) (Math.random() * 4) + 1;
The parenthesis enforce that the value of Math.random() * 4 (which will be a value in the interval [0, 3)) will be casted to int.
Two remarks on your code:
I would recommend introducing an enum Direction with four values (one for each direction) and choose a random Direction by calling Direction.values()[(int) (Math.random() * 4)];
I would recommend to use a switch instead of the if-else-if cascade.
Ideone demo
The program will exit the while(true) loop once one of the 4 conditions is true. My suggestion is to move these conditions in your if(random == value) checks like this:
if( random == 1 )
{
x--;
if (x < 0 )
{
x++;
}
}
Now to exit your while(true) loop you need to have an extra condition. I would suggest to think about your board in terms of 0's and 1's. Everytime the ant cross a cell, you set the grid[x][y] = 1.
int stepsTaken = 0;
int cellsToCover = grid.length * grid[0].length ;
int coveredCells = 0;
while(true)
{
//your code here
if( random == 1 )
{
stepsTaken++;
x--;
if (x < 0 )
{
x++;
}
}
// the other if's with "stepsTaken" incremented too.
if ( grid[x][y] == 0 )
{
grid[x][y] = 1;
coveredCells++;
}
if (coveredCells == cellsToCover )
break;
}
But please notice the many ifs statements inside a while(true) loop. If you have to fill a board of 10 rows x 10 columns it would take too much until the board is filled. Instead I would suggest you to use some more efficient algorithms like backtracking, dynamic programming etc.
Edit : Added step counter.
I'm programming a little game and I'm having some problems with the intersections. I need an efficient algorithm to check if two objects (which have x and y coords. and also a width and an height) are intersecting.
I tried with the following, but it doesn't always work, sometimes it doesn't recnognize an intersection.
public boolean contains(int x, int y) {
if ((x < this.x + this.width) && (x >= this.x) && (y < this.y + this.height) && (y >= this.y))
return true;
else
return false;
}
I have an ArrayList containing the objects, and I do the following:
private boolean checkIntersection(String pDirection) {
for (int i = 0; i < walls.size(); i++) {
if (pDirection.equalsIgnoreCase("right") && car.contains(walls.get(i).getX() - 1, walls.get(i).getY()))
return true;
if (pDirection.equalsIgnoreCase("left") && car.contains(walls.get(i).getX() + 30, walls.get(i).getY()))
return true;
if (pDirection.equalsIgnoreCase("top") && car.contains(walls.get(i).getX(), walls.get(i).getY() + 30))
return true;
if (pDirection.equalsIgnoreCase("down") && car.contains(walls.get(i).getX(), walls.get(i).getY() - 1))
return true;
}
return false;
}
Note that "-1" and "+30" is to avoid the car enter the "walls", there the walls have a width of 30 and an height of 30. The car also has the same dimensions.
Also note that the x and y are the top-left cords of the rectangles. The car and the walls are rectangles.
I would be thankful for your help.
INFO: It doesn't recnognize an intersection at the beginn of a row of walls if I am above the wall and I change the direction to "down" or viceversa.
See picture
EDIT 1 (I tried inverting the objects, but it also doesn't always work):
private boolean checkIntersection(String pDirection) {
for (int i = 0; i < walls.size(); i++) {
if (pDirection.equals("right") && walls.get(i).contains(car.getX() + 30, car.getY()))
return false;
if (pDirection.equals("left") && walls.get(i).contains(car.getX() - 1, car.getY()))
return false;
if (pDirection.equals("top") && walls.get(i).contains(car.getX(), car.getY() - 1))
return false;
if (pDirection.equals("down") && walls.get(i).contains(car.getX(), car.getY() + 30))
return false;
}
return true;
}
The flaw in your algorithm is, you are always checking the left-top point of the wall whether it is in the car. However, this is not equivalent to having intersection.
Instead, you should check whether any one of the objects contains (at least) one corner (not necessarily the top left one) of the other object.
Note that you should perform this check for both sides, i.e. either the car contains any corner of the wall or the wall contains any corner of the car.
I solved modifying the contains method in the following way, and it now works perfectly:
public boolean contains(int x, int y) {
if ((x < this.x + this.width) && (x > this.x-this.width) && (y < this.y + this.height) && (y > this.y-this.height))
return true;
else
return false;
}
I think that I did it involuntarily (checking for non-intersection instead of intersection), but I can optimize it using the answer/suggestion of #samgak and #Gene. So thanks, problem solved.
I have a problem with array indexing. The code is supposed to move objects of type Ant around a 20x20 grid.
public class Test {
Organism[][] grid = new Organism[20][20];
public static void main(String[] args) {
for (int i = 0; i < 20; i++){
for (int j = 0; j < 20; j++){
if(grid[i][j] instanceof Ant){
int xpos = i;
int ypos = j;
grid[i][j].move(xpos, ypos);
grid[i][j].breed(xpos, ypos);
}
}
}
}
Class Ant extends Organism, class Organism extends Test.
public class Ant extends Organism{
public void move(int xpos, int ypos){
Random rand = new Random();
int direction = rand.nextInt(3);
if(direction == 0){
if(grid[xpos][ypos + 1] == null && xpos <20 && ypos <20)
{
grid[xpos][ypos] = grid[xpos][ypos];
grid[xpos][ypos] = null;
{
}
}
}
The method move is supposed to choose a random direction on the grid and move the Ant there if the adjoining space is empty. It also cannot go outside the 20x20 grid. (There are three more if loops for the other directions).
If I change the sixth line in the move method to:
if(grid[xpos][ypos] == null && xpos <20 && ypos <20)
Then no error is thrown.
I hesitate to post this because its probably a small error on my part but I have been staring at this for several hours.
Assistance is greatly appreciated.
The operands for an && are evaluated from left to right, and the evaluation stops if one of them evaluates to false. So if one or more of the operands are potentially dangerous (such as an array lookup that might go out of bounds), and some of the other operands are supposed to protect against this, the protection operands need to go first. Also, you need to check the indices you're actually using, namely xpos and ypos + 1, and you forgot to use ypos + 1 in the assignment that moves the ant:
if (xpos < 20 && ypos + 1 < 20 && grid[xpos][ypos + 1] == null) {
grid[xpos][ypos + 1] = grid[xpos][ypos];
grid[xpos][ypos] = null;
}
(And, assuming that xpos and ypos are valid indices, you don't need to check xpos.)
I've been researching "dead code" and "unreachable code" for awhile now and I still can't seem to figure out what's going on with this problem in my program. This is a snippet of what I have; the method "gameEnd()" which checks for winners in Tic Tac Toe:
private boolean gameEnd() {
// Setting local variables
int x = xMouseSquare;
int y = yMouseSquare;
int[][] g = gameBoard;
int c = CPU;
int h = HUMAN;
// Checking for a winner
/* Checking columns (xMouseSquare)
* Enter the y value, the vertical value, first; then x, the horizontal value, second
*/
// Set y equal to 0 and then add 1
for (y = 0; y < 3; y++) {
// Set CPU c equal to 0
c = 0;
// Set x equal to 0 and then add 1
for (x = 0; x < 3; x++) {
// Add CPU's value to the game board
c += g[x][y];
// If statement returning the absolute value of CPU
if (Math.abs(c) == 3) {
// If these values are correct, return true; the game ends with CPU win horizontally
return true;
}
}
}
// If not, return false; game continues until all marks are filled
return false;
// Set y equal to 0 and then add 1
for (y = 0; y < 3; y++) {
// This time, however, set HUMAN h equal to 0
h = 0;
// Set x equal to 0 and then add 1
for (x = 0; x < 3; x++) {
// Then add HUMAN's value to the game board
h += g[x][y];
// If statement returning the absolute value of HUMAN
if (Math.abs(h) == -3) {
// If these values are correct, return true; the game ends with HUMAN win horizontally
return true;
}
}
}
// If not, return false; game continues until all marks are filled
return false;
{
/* Checking rows (yMouseSquare)
* Enter the x value, the horizontal value, first; then y, the vertical value, second
*/
// Set x equal to 0 and then add 1
for (x = 0; x < 3; x++) {
// Set CPU equal to 0
c = 0;
// Set y equal to 0 and then add 1
for (y = 0; y < 3; y++) {
// Add CPU's value to the game board, but with y and then x
c += g[y][x];
// If statement returning the absolute value of CPU
if (Math.abs(c) == 3) {
// If these values are correct, return true; the game ends with CPU win vertically
return true;
}
}
}
// If not, return false; game continues until all marks are filled
return false;
{
// Set x equal to 0 and then add 1
for (x = 0; x < 3; x++) {
// This time, however, set HUMAN h equal to 0
h = 0;
// Set y equal to 0 and then add 1
for (y = 0; y < 3; y++) {
// Then add HUMAN's value to the game board
h += g[x][y];
// If statement returning the absolute value of HUMAN
if (Math.abs(h) == -3) {
// If these values are correct, return true; the game ends with CPU win vertically
return true;
}
}
}
// If not, return false; game continues until all marks are filled
return false;
}
}
}
} // error on this bracket; but when I remove it, some of the code above becomes unreachable. Can anyone point to what I'm doing wrong?
If it was indented properly, I think it would show that the first occurrence of 'return false' will always be executed if the first instance of 'return true' was not hit, hence all remaining code is never reached.
Here is your problem right here
// If not, return false; game continues until all marks are filled
return false; <-- code exits here, everything below will not run.
{
// Set x equal to 0 and then add 1
for (x = 0; x < 3; x++) {
...