Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
My question is:
Is this code correct and is it properly assigned to the Wheel speeds and duration
What do I need to do in order to add the main method to run the code
use a for loop to iterate through each row, instructing the Finch robot to move according to the numbers in each row. Pause after each movement using the code JOptionPane.showMessageDialog(null,"Click OK to continue...");
public class FinchArray {
public static final int LEFT_WHEEL = 0;
public static final int RIGHT_WHEEL = 1;
public static final int DURATION = 2;{
int[][] x = new int[10][3]; // 2D array filled with zeros
int time = 25;
for (int[] row : x) {
row[2] = time;
time += 25;
}
for (int[] row : x) {
row[DURATION] = time;
time += 25;
}
for (int[] row : x){
row[LEFT_WHEEL] = time;
time += 25;
}
for (int[] row : x){
row[RIGHT_WHEEL] = time;
time += 25;
}
Finch fRobot = new Finch();
fRobot.setWheelVelocities(LEFT_WHEEL,RIGHT_WHEEL,DURATION);
long before = System.currentTimeMillis();
while (System.currentTimeMillis() - before < 5000){
if(fRobot.isObstacle())break; {
}
fRobot.stopWheels();
fRobot.quit();
}
}
You can initialize your 2D array (which, in Java, is really just an array of 1D arrays) like this:
int[][] x = new int[10][3]; // 2D array filled with zeros
int time = 25;
for (int[] row : x) {
row[2] = time;
time += 25;
}
This uses an enhanced for loop and is equivalent to this:
int[][] x = new int[10][3]; // array filled with zeros
int time = 25;
for (int i = 0; i < x.length; ++i) {
int[] row = x[i];
row[2] = time;
time += 25;
}
Note that this leaves the left and right wheel speeds at their default values of zero.
Your current code is first creating a 10x3 2D array, but then your loop is reassigning each row to be a new 10-element array, so you end up with a 10x10 array (which is not what you want).
P.S. Using a 3-element array to represent three distinct pieces of data is not a good programming style (although it will work just fine). A slight improvement can be obtained by using symbolic constants for the subscripts. Declare at the top of your class:
public static final int LEFT_WHEEL = 0;
public static final int RIGHT_WHEEL = 1;
public static final int DURATION = 2;
Then use these to index into each row:
for (int[] row : x) {
row[DURATION] = time;
time += 25;
}
Since each row represents three different attributes, a better approach would be to define a separate class to contains the data:
public class Step {
public int leftWheelSpeed;
public int rightWheelSpeed;
public int duration;
}
Then instead of a 2D array of int values, you can declare a 1D array of Step objects:
Step[] x = new Step[10];
int time = 25;
for (Step step : x) {
step.duration = time;
time += 25;
}
I'm not sure, but is this maybe what you are looking for?
import java.util.Arrays;
public class FinchArray {
public static void main(final String[] args) {
int[][] array = new int[3][10]; // initializing the array
for(int i = 0; i < array.length; i++) { // outer for loop loops over first dimension
int n = 25; // initializing the counter from 25 to 250
for(int j = 0; j < array[i].length; j++) { // inner for loop loops over second dimension
array[i][j] = n; // access the slots with the two indices i and j and give them the value of n
n += 25;
}
n = 25; // reset n to 25 after finishing the inner for loop
}
System.out.println(Arrays.deepToString(array));
}
}
Output: [[25, 50, 75, 100, 125, 150, 175, 200, 225, 250], [25, 50, 75, 100, 125, 150, 175, 200, 225, 250], [25, 50, 75, 100, 125, 150, 175, 200, 225, 250]]
Related
I am trying to avoid duplicates in my lottery rows , ie if number 35 is in the first lottery row then it must not be in the second row
I am confused about why I keep on getting duplicates I have added a image that explains my problem better?
What is the best way to go about this probelem?
I have tried to change nt lottoTal = rand.nextInt(35) + 1 to nt lottoTal = rand.nextInt(34) + 1
public class LottoCanvas extends BorderPane{
private Canvas canvas;
private GraphicsContext gc;
private Text text;
private Text textExtra; ///
private Set<Number> lottorad;
private Set<Number> lottoradExtra;//
Random rand;
public LottoCanvas() { //constructor
lottorad = new HashSet();
lottoradExtra = new HashSet();
rand = new Random();
canvas = new Canvas(250, 250);
gc = canvas.getGraphicsContext2D();
Button button = new Button("Rita om");
button.setOnAction(new EventHandler() {
#Override
public void handle(Event event) {
drawLotto(gc);
}
});//end EventHandler
VBox vbox = new VBox();
vbox.setPadding(new Insets(5,5,5,5));
vbox.setAlignment(Pos.CENTER);
text = new Text();
textExtra = new Text(); //
vbox.getChildren().addAll(text,textExtra,button);
drawLotto(gc);
setCenter(canvas);
setBottom(vbox);
}//end constructor
private void createLottoRad(){
lottorad.clear();
lottoradExtra.clear();
while (lottorad.size()<7) {
int lottoTal = rand.nextInt(35) + 1;
lottorad.add(lottoTal);
}
while (lottoradExtra.size()<4) {
int lottoTal = rand.nextInt(35) + 1;
lottoradExtra.add(lottoTal);
}
}//end metoden createLottoRad
private void drawLotto(GraphicsContext gc) {
createLottoRad();
int x = 0;
int y = 0;
int bredd=30;
int hojd=30;
for (int i = 0; i < 35; i++) {
x += 35;
if (i % 7 == 0){
y += 35;
x = 0;
}
if (lottorad.contains(i+1)){
gc.setFill(Color.RED);
}
if (lottoradExtra.contains(i+1)){
gc.setFill(Color.GREEN);
}
gc.fillRoundRect(x, y, bredd, hojd , 10, 10);
gc.setFill(Color.WHITE);
gc.fillText("" + (i + 1), x + 10, y + 20);
gc.setFill(Color.BLACK);
}
List myList = new ArrayList(lottorad);
Collections.sort(myList);
text.setText(myList.toString());
List myListExtra = new ArrayList(lottoradExtra);
Collections.sort(myListExtra);
textExtra.setText(myListExtra.toString());
}//end metoden drawLotto
}//enter piture of what i am trying to avoid
I am trying to avoid duplicates in my lottery rows , ie if number 35 is in the first lottery row then it must not be in the second row I am confused about why I keep on getting duplicates I have added a image that explains my problem better? What is the best way to go about this probelem?
Your current approach is something like this:
Add random numbers into lottorad until there are 7 unique values in it.
Add random numbers into lottoradExtra until there are 4 unique values in it.
The two sets are independent, so there is nothing to prevent from having the same numbers in both. You could add an explicit condition when populating lottoradExtra to skip over the number if it's already in lottorad, for example:
while (lottoradExtra.size() < 4) {
int lottoTal = rand.nextInt(35) + 1;
if (lottorad.contains(lottoTal)) {
continue;
}
lottoradExtra.add(lottoTal);
}
However, the current approach is flawed, since it's a bit of a waste to do extra loops when the same number keeps coming up repeatedly. In theory, your program might not terminate.
An alternative approach is the build a list of numbers, shuffle it, and just take the first 7 values, and then the first 4 values. That way it's guaranteed there will be no duplicates. For example:
List<Integer> numbers = IntStream.rangeClosed(1, 35).boxed().collect(Collectors.toList());
Collections.shuffle(numbers);
lottorad.clear();
lottorad.addAll(numbers.subList(0, 7));
lottoradExtra.clear();
lottoradExtra.addAll(numbers.subList(7, 11));
JButton[][] buttons = new JButton[20][20];
public void mines(){
ArrayList<Integer> x = new ArrayList<>();
ArrayList<Integer> y = new ArrayList<>();
for(int a=0;a<20;a++){
x.add(a);
y.add(a);
}
for(int i=0;i<30;i++){
int random_x = x.get(new Random().nextInt(x.size()));
int random_y = y.get(new Random().nextInt(y.size()));
x.remove(random_x);
y.remove(random_y);
buttons[random_x][random_y].setText("X");
}
}
I Want to create random mines for a minesweeper game..can anyone tell what I am doing wrong ?If i run the program it won't show me 30 random mines
You have chosen an unusual model for holding information on where mines are located. While you will likely resolve the immediate problem through some judicious debugging I expect it will cause you further problems down the track.
I would suggest changing your model to be something more direct such as:
class Cell {
private final JButton button = new JButton();
private boolean mine = false;
private boolean hidden = true;
public Cell() {
button.setText(" ");
}
public void setMine() {
assert hidden;
mine = true;
}
public boolean hasMine() {
return mine;
}
public void reveal() {
hidden = false;
button.setText(mine ? "X" : "-");
}
public boolean isHidden() {
return hidden;
}
}
class Field {
public static final int SIZE = 20;
private final Cell[][] cells = new Cell[SIZE][SIZE];
public Field(int minesToAdd) {
for (int x = 0; x < SIZE; ++) {
for (int y = 0; y < SIZE; y++) {
cells[x][y] = new Cell();
}
}
Random random = new Random();
while (minesToAdd > 0) {
Cell cell = cells[random.nextInt(SIZE)][random.nextInt(SIZE)];
if (!cell.hasMine()) {
cell.setMine();
minesToAdd--;
}
}
}
public JPanel getButtonPanel() {
....
}
}
I believe that would make your intention clearer. There are a few issues with this such as the tight link between the model and presentation (JButton) but that's entirely fixable with various design patterns.
Try this method:
public static void mines(JButton[][] buttons)
{
Random rand = new Random();
int mineCount = 0;
while (mineCount < 30)
{
int randomInteger = (int) (rand.nextDouble() * buttons.length);
int randomInteger2 = (int) (rand.nextDouble() * buttons[0].length);
if (buttons[randomInteger][randomInteger2].getText().equals("X"))
continue;
else
{
buttons[randomInteger][randomInteger2].setText("X");
mineCount++;
}
}
}
.nextDouble() method returns a Double value less than 1.0. But we need a random integer between 0 and 19(which is buttons.length-1).
So we multiply this random double value with the size of the button list, which is 20, and we cast it to int. So we can get values between 0 and 19.
Difference between buttons.length and buttons[0].length is, with the first one you get the length of first dimension(it's a two dimension array, as you know) and the second one gives the length of the second dimension. So you get the number dynamically and multiply with the random number, to avoid ArrayIndexOutOfBounds exception.
You can use this method with any size of two dimensional buttons array, it will work. But warning, if you use an array which has less than 30 buttons, while loop will continue forever, as you can't get 30 mines :)
One way to improve this method would be parameterizing mineCount, so you can change the method like public static void mines(JButton[][] buttons, int mineCount) so you can set mine count on method call.
This here:
for (int i = 0; i < 30; i++) {
int random_x = x.get(new Random().nextInt(x.size()));
int random_y = y.get(new Random().nextInt(y.size()));
x.remove(random_x);
y.remove(random_y);
....
is going to generate a IndexOutOfBoundsException some when....
Your List have 20 elements and you are removing 30 times element from it...
Your random coordinates may be larger than your grid size. If the size of x is 20, and your random_x is also 20, you will have an IndexOutOfBoundsException.
Change it to:
int random_x = x.get(new Random().nextInt(x.size() - 1));
int random_y = y.get(new Random().nextInt(y.size() - 1));
Which will give you a random number between 0 and 19, if the size is 20.
Additionally, because your List is of type Integer, the x.remove(random_x) call is interpreting it as the index in the list, not the object itself.
To fix this, use an Integer, not an int when calling remove(). Such as:
x.remove(Integer.valueOf(random_x));
Edit:
To further improve/fix the random generator, change it to:
int random_x = x.get(new Random().nextInt(x.size() == 1 ? 1 : x.size() - 1));
When tested with the following snippet:
Test t = new Test();
t.mines();
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
if ("X".equals(t.buttons[i][j].getText())) {
System.out.println("x:" + i + ", y:" + j);
}
}
}
Gives the output:
x:0, y:18
x:1, y:5
x:2, y:1
x:3, y:3
x:4, y:9
x:5, y:15
x:6, y:14
x:7, y:10
x:8, y:8
x:9, y:11
x:10, y:16
x:11, y:17
x:12, y:0
x:13, y:7
x:14, y:4
x:15, y:12
x:16, y:2
x:17, y:6
x:18, y:13
x:19, y:19
You can try with this:
int x = 20;
int y = 20;
JButton[][] buttons = new JButton[x][y];
public void mines(){
int mines = 30;
Random rand = new Random()
while(mines>0){
int random_x = rand.nextInt(x);
int random_y = rand.nextInt(y);
if(buttons[random_x][random_y]!=null){
buttons[random_x][random_y] = new Button();
buttons[random_x][random_y].setText("X")
mines--;
}
}
}
I'm writing a deck with 52 cards. Everything is perfect but I can't figure out how to shuffle it without using any library from java and using the sort method built into java. Here is my code. I been trying to figure something out for a while and so far I'm unable to.
String [] deck2=new String [52];
String[] deck=new String [52];
String suits[]={"Spades","Hearts","Diamonds","Clubs"};
String rank[]={"2","3","4","5","6","7","8","9","10","Jack","King","Queen","Ace"};
for(int i=0;i<deck.length;i++){
deck[i]=rank[i%13]+" "+"of "+suits[i/13];
deck2[i]=deck[i];
System.out.println(deck[i]);
}}}
Of course it's possible. After all, a library is nothing more than some code you could as well write yourself. You'll have to write your own random number generator. This is one simple example:
private static long x = System.currentTimeMillis();
public static long rndNumber() {
x ^= (x << 21);
x ^= (x >>> 35);
x ^= (x << 4);
return x < 0 ? -x : x;
}
public static void shuffle(int a[]) {
for (int i = a.length - 1; i > 0; i--) {
int pos = (int) (rndNumber() % a.length);
int temp = a[i];
a[i] = a[pos];
a[pos] = temp;
}
}
public static void main(String[] args) {
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
System.out.println(Arrays.toString(a));
shuffle(a);
System.out.println(Arrays.toString(a));
}
for (int i = 0; i < 500; i++) {
int from = (int) (Math.random() * array.length); //The place to get the first from
int to = (int) (Math.random() * array.length); // The place to get the second from
String perm = array[from]; // Store the "from" value
array[from] = array[to]; // Set the first value to the second
array[to] = perm; // Set the second value to the first
}
I don't know, why you don't want to use a java built-in library, they are there for a reason.
To create a random number without any built in methods is hard. I found a way long time ago, using float, and making it overflow
float random = 1 << 32 + 1256224; //Have a random number here, it doesn't matter
I didn't tested it, this may not work.
float random = 1 << 32 + 1256224;
String [] deck2=new String [52];
String[] deck=new String [52];
String suits[]={"Spades","Hearts","Diamonds","Clubs"};
String rank[]={"2","3","4","5","6","7","8","9","10","Jack","King","Queen","Ace"};
for(int i=0;i<deck.length;i++){
deck[i]=rank[i%13]+" "+"of "+suits[i/13];
deck2[i]=deck[i];
System.out.println(deck[i]);
}
for (int i = 0; i < 500; i++) {
int from = (int) (Math.random() * array.length); //The place to get the first from
int to = (int) (Math.random() * array.length); // The place to get the second from
String perm = array[from]; // Store the "from" value
array[from] = array[to]; // Set the first value to the second
array[to] = perm; // Set the second value to the first
}
}}
This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 7 years ago.
So, I've been doing this java class for several months now, and I've been assigned a project before the end of the year. I'm trying to rewrite some old code to use vectors and arrays, but... I get the topic title error. Here is the relevant code:
public static double VectorX(int len, double angle) {
return Math.cos(angle)*len;
}
public static double VectorY(int len, double angle) {
return Math.sin(angle)*len;
}
public static class Projectile {
public int x;
public int y;
public double angle;
public int speed;
public boolean Player;
}
...
public static Projectile[] Shoot = new Projectile[0];
public static double RadianAngle(int x1, int y1, int x2, int y2) {
return Math.atan2(x2-x1, y2-y1);
}
...
for (int i = 1; i <= Shoot.length; i++)
{
Shoot[i].x += VectorX(Shoot[i].speed, Shoot[i].angle);
Shoot[i].y += VectorY(Shoot[i].speed, Shoot[i].angle);
}
...
if (Cooldown == 75 || Cooldown == 25)
{
Projectile Hey = new Projectile();
Hey.x = EX;
Hey.y = EY;
Hey.Player = false;
Hey.speed = 2;
Hey.angle = RadianAngle(Hey.x, Hey.y, X, Y);
Projectile[] Shoot2 = new Projectile[Shoot.length + 1];
for (int l = 0; l <= Shoot.length - 1; l++)
{
Shoot2[l] = Shoot[l];
}
Shoot2[Shoot2.length - 1] = Hey;
Shoot = Shoot2;
}
I've no idea what is going on. I imported these Vector functions from a C#-based language that I am well versed in, but translated them to java. I am getting the error at
Shoot[i].x += VectorX(Shoot[i].speed, Shoot[i].angle);
Shoot[i].y += VectorY(Shoot[i].speed, Shoot[i].angle);
Could you guys give me a hand?
You're getting an ArrayIndexOutOfBoundsException because you are initializing the Shoot array with a size of 0 :
public static Projectile[] Shoot = new Projectile[0];
so the call to
Shoot[0].x += VectorX(Shoot[0].speed, Shoot[0].angle);
in your loop is invalid.
for (int i = 1; i <= Shoot.length; i++)
should be
for (int i = 0; i < Shoot.length; i++)
the reason why
int[] arr = new int[]{ 0, 1, 2 };
arr.length will now equal 3, my array does not have an index at 3, instead, it has indexes at 0, 1, and 2.
Your definition for the shoot array creates an array of length 0: Shoot = new Projectile[0];
Yet when you iterate over the array, you are setting the bounds of your loop variable incorrectly:
for (int i = 1; i <= Shoot.length; i++)
Arrays are zero-indexed (meaning an array of length 1 will have index [0] and no more). So starting your loop index at 1 (int i = 1) is bad to begin with.
Then you are looping too far. Say you have 3 elements in your array, the indexes will be 0, 1 & 2. And your array.length will be 3, but you never want to index 3. So your loop condition needs to be < array.length, not <= array.length.
Hi I am having some problems with using random numbers inside of loops.
private void SetMines()
{
Random randRowGen = new Random();
Random randColGen = new Random();
int mineCount = 0;
int numMines = (ROWS * COLUMNS)* (int)0.156;
while(mineCount <= numMines)
{
int randRow = randRowGen.nextInt(ROWS)+1;
int randCol = randColGen.nextInt(COLUMNS)+1;
grid[randRow][randCol] = new Character('*');
mineCount++;
}
}
Here is my method it is going through an array size 25 * 25 and picking random spots and putting "mines" there. The only problem is it only selects one location to put a "mine" in and it needs to put 97 mines in random spots.
Any help will be appreciated thanks!!
Your numMines calculation will always return 0, because when you cast a double that is less than 1 to an int, it will be set to 0, which means that the statement in your while loop will only be run a single time, hence only a single mine being placed.
The problem isn't Random, it's int numMines = (ROWS * COLUMNS)* (int)0.156;. Have you checked what that value is? It's 0, because (int) 0.156 equals 0.
Perhaps you want int numMines = (int) ((double) 0.156 * ROWS * COLUMNS);. The problem with integer maths is that you can lose a LOT of precision.
Make your computer suffer and make it drop all those mines.
Remember. The definition of "computation" is "to force a machine do a boring job that nobody else would like to do" :-)
public static void main(String[] args) {
int rows = 25;
int cols = 25;
boolean[][] mines = new boolean[rows][cols];
while(mineCount(mines) < 97){
dropMine(mines);
}
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
System.out.print("[");
if (mines[i][j]){
System.out.print("*");
}else{
System.out.print(" ");
}
System.out.print("] ");
}
System.out.println();
}
}
private static void dropMine(boolean[][] mines) {
int x = (int)(Math.random()*25);
int y = (int)(Math.random()*25);
mines[x][y] = true;
}
private static int mineCount(boolean[][] mines) {
int count = 0;
for(int i=0;i<25;i++){
for(int j=0;j<25;j++){
if (mines[i][j]){
count++;
}
}
}
return count;
}