I have an assignment where I am to create a chutes and ladder game using JavaFX.
What I am currently stuck on is once the user selects how many players they want, the method I run pushes an error.
I have run it through the debugger and I know what line is the problem, but I have no idea where to go from here.
The exception is:
Exception in thread "JavaFX Application Thread"
java.lang.ArrayIndexOutOfBoundsException: 0
I found that if I change the zero in private Players [] players = new Players[0]; to a 4, it works. However, I get another error if I try to change the 0 in private Circle [] c = new Circle[0];
public class Main extends Application {
private final int BOARD_DIM = 10;
private Players [] players = new Players[0];
private Circle [] c = new Circle[0];
public static void main(String[]args){
launch();
}
public void start(Stage pStage) throws Exception{
//ROOT PANE
BorderPane root = new BorderPane();
//MENUBAR
//BOARD CREATION
//PLAYER SELECTION/RESUME PREVIOUS GAME
//Drop down menu
HBox players = new HBox();
Label intro = new Label("Select # of players");
ChoiceBox<String> p = new ChoiceBox<>();
p.getItems().addAll("2","3","4");
p.setPadding(new Insets(6));
//Button to start new game
Button startGame = new Button("Start Game");
startGame.setOnAction(e -> getChoice(p));
startGame.setPadding(new Insets(10));
players.getChildren().addAll(intro,p,startGame);
root.setRight(players);
Scene scene = new Scene(root, 900, 650);
pStage.setTitle("Chutes and Ladders");
pStage.setScene(scene);
pStage.show();
}
private void getChoice(ChoiceBox<String> p) {
int numOfPlayers = Integer.parseInt(p.getValue());
for(int i = 0; i < numOfPlayers; i++){
players[i] = new Players("p"+(i+1),9,0, false);
c[i] = new Circle(25);
}
c[0].setFill(Color.GREEN);
c[1].setFill(Color.YELLOW);
if(numOfPlayers >= 3){
c[2].setFill(Color.RED);
}
if(numOfPlayers == 4){
c[3].setFill(Color.BLACK);
}
}
You are initalizing players and c as arrays with length 0. And in the loop you are iterating over the elements from 0 to numOfPlayers. That's what is causing the exception.
First just declare your arrays:
private Players [] players;
private Circle [] c;
Then in the your method, initalize the arrays with the length you need (If you need to alter the length later I would suggest to switch to ArrayLists).
private void getChoice(ChoiceBox<String> p) {
int numOfPlayers = Integer.parseInt(p.getValue());
c = new Circle[numOfPlayers]; //add these lines
players = new Players[numOfPlayers]; //add these lines
for(int i = 0; i < numOfPlayers; i++){
players[i] = new Players("p"+(i+1),9,0, false);
c[i] = new Circle(25);
}
...
}
Related
Hey I'm currently creating a bracket program however I have hit a snag. In this first class I get the names of each person in the bracket and then in the second class I would like to have access to a separate variable/label for each person. Problem is that I used a for loop and I believe that the only variable being inserted is person. Sorry if this explanation was not great as my coding language knowledge is still beginner.
public class EnterNames extends BorderPane {
public EnterNames(int amount, boolean seedRandom){
TextField person = new TextField();
for (int j = 0; j < amount; j++) {
int teamNum = j + 1;
if(seedRandom){
person.setPromptText("Enter Seed #" + teamNum);
} else {
person.setPromptText("Enter A Random Team");
}
box.getChildren().add(person);
person.setMaxWidth(500);
}
Button submit = new Button("Submit Teams");
submit.setOnAction(e ->{
MainScene.mainStage.setScene(new BracketScene(amount, person));
});
}
}
This is where BracketsScene is declared
public class BracketScene extends Scene {
public BracketScene(int amount, TextField test){
super(new Bracket(amount, test), 1600, 900);
}
}
Here is the code for the class that I would like to access seperate variables like person1 & person2 ect.
public class Bracket extends StackPane {
public Bracket(int amount, TextField person){
javafx.scene.image.Image winner8 = new javafx.scene.image.Image("file:src/Images/Winner8.jpg");
javafx.scene.image.Image winner16 = new javafx.scene.image.Image("file:src/Images/Winner16.jpg");
javafx.scene.image.Image winner32 = new javafx.scene.image.Image("file:src/Images/Winner32.jpg");
BackgroundSize bSize = new BackgroundSize(BackgroundSize.AUTO, BackgroundSize.AUTO, false, false, true, false);
if(amount > 16){
this.setBackground(new Background(new BackgroundImage(winner32, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER, bSize)));
} else if(amount > 8 && amount < 32){
this.setBackground(new Background(new BackgroundImage(winner16, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER, bSize)));
} else {
this.setBackground(new Background(new BackgroundImage(winner8, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER, bSize)));
Label person1 = new Label();
Label person2 = new Label();
person1.setText(person.getText());
person2.setText(person.getText());
this.getChildren().addAll(person1,person2);
}
}
}
#FXML AnchorPane gamePane;
public void gameStart() {
if(!Started) {
board = new Board();
stones = new Circle[8][8];
newTurn();
applyBoard();
Started = true;
}
else {
DestroyBoard(); // <--- Erase all the stones
board = new Board();
stones = new Circle[8][8];
newTurn();
applyBoard();
}
}
public void applyBoard() {
for(int i = 0; i < board.boardsize; i++) {
for(int j = 0; j < board.boardsize; j++) {
if(board.board[i][j] != board.EMPTY) {
if(board.board[i][j] == board.BLACK) {
stones[i][j] = new Circle(155 + 90 * j, 85 + 90 * i, 40);
stones[i][j].setFill(Color.BLACK);
gamePane.getChildren().add(stones[i][j]);
}
else if(board.board[i][j] == board.WHITE) {
stones[i][j] = new Circle(155 + 90 * j, 85 + 90 * i, 40);
stones[i][j].setFill(Color.WHITE);
gamePane.getChildren().add(stones[i][j]);
}
}
}
}
}
public void DestroyBoard() { // <---Test Function and not worked!!
gamePane.getChildren().remove(stones[3][3]);
}
I Tried to make if press start button again then all stones on board erased and start a new game. As a first step I tried to erase one basic stone, but I can't delete any of stone on the board. What should I do to solve that?
The stones are stored in an ObservableList within the gamePane container, which you access with the getChildren() method. The list has a very helpful clear() method that removes all items in the list.
So if you are just looking to remove all the stones from gamePane, just call this method:
gamePane.getChildren().clear();
I am trying to develop a program to generate 10 prime numbers each time a button is pressed but I am struggling. The code to identify the primes is correct but I get the error NullPointerException probably because I am handling the Label Array badly. I'll paste the code below, thanks for any tip on what's going wrong.
public class PrimeGenerator extends Application {
Button generate;
Label listNumbers;
int i;
int multiple = 2;
int number = 2;
int z = 1;
int t = 0;
Label[] primeList;
#Override
public void start(Stage primaryStage) throws Exception {
VBox root = new VBox();
generate = new Button("Generate 10 more primes!");
generate.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
primeList = new Label[10];
while (i < primeList.length) {
multiple = 2;
while (multiple < number) {
t = number % multiple;
if ((t == 0)) {
z = 0;
}
multiple++;
}
// Here I'd like to add the prime number to the array while also adding the Label to the Vbox
if ((z == 1)) {
primeList[i].setText(Integer.toString(number));
root.getChildren().add(primeList[i]);
i++;
}
z = 1;
number++;
}
}
});
root.getChildren().add(generate);
Scene scene = new Scene(root);
primaryStage.setTitle("Prime Numbers Generator");
primaryStage.setScene(scene);
primaryStage.show();
}
}
I think you forgot to initialize the array element
....
primeList[i] = new Label();
primeList[i].setText(Integer.toString(number));
....
You can also in one line
primeList[i] = new Label(Integer.toString(number));
For example
if ((z == 1)) {
primeList[i] = new Label();
primeList[i].setText(Integer.toString(number));
root.getChildren().add(primeList[i]);
i++;
}
Alternatively, you can pre-create elements in advance:
...
#Override
public void handle(ActionEvent e) {
primeList = new Label[10];
for(int labelIdx=0; labelIdx<primeList.length; labelIdx++)
primeList[labelIdx] = new Label();
while (i < primeList.length) {
...
Beginner Java programmer here. I'm trying to create a card game to learn more about Java. I have an array of names I pulled out a database. For each String in the array I want to create a JPanel and inside JLabels where I will set the name, power, health, etc.
The problem is when I create these in a loop they all have the same name and overwrite each other. Since I read Java doesn't have dynamic Variable names, how do I solve this?
public void loadDatabaseCardElements(ArrayList cards) {
ArrayList<String> buildCards = cards;
int i;
for(i = 0; i != buildCards.size();) {
String var = buildCards.get(0);
//create the Panel etc
JPanel mainHolder = new JPanel();
mainHolder.setLayout(new BoxLayout(mainHolder, BoxLayout.PAGE_AXIS));
JLabel name = new JLabel("Name: " + var);
JLabel powerLabel = new JLabel("Power: ");
JLabel healthLabel = new JLabel("Health: ");
JLabel armorLabel = new JLabel("Armor: ");
JLabel type1Label = new JLabel("Type1");
JLabel type2Label = new JLabel("Type2: ");
JLabel ability1Label = new JLabel("Ability1: ");
JLabel ability2Label = new JLabel("Ability2: ");
JLabel ability3Label = new JLabel("Ability3: ");
JButton card1 = new JButton("Add to deck");
mainHolder.add(name);
mainHolder.add(powerLabel);
mainHolder.add(healthLabel);
mainHolder.add(armorLabel);
mainHolder.add(type1Label);
mainHolder.add(type2Label);
mainHolder.add(ability1Label);
mainHolder.add(ability2Label);
mainHolder.add(ability3Label);
mainHolder.add(card1);
mainHolder.setBorder(BorderFactory.createLineBorder(Color.black));
mainHolder.setPreferredSize( new Dimension( 130, 200 ) );
frame1.add(mainHolder, BorderLayout.WEST);
SwingUtilities.updateComponentTreeUI(frame1);
card1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
preDeck.add(var); //add to another array when clicked
}
});
if (buildCards.size() != 0) {
buildCards.remove(0);
} else {
}
}
}
The reason for overwriting all the panels with same name is due to this part of your code:
int i;
for(i = 0; i != buildCards.size();) {
String var = buildCards.get(0);
You are assigning the first element of your list to each JLabel. This could help you achieve what you need:
for(int i = 0; i < buildCards.size(); i++){
String var = buildCards.get(i);
// Followed by your code
}
set a growable layout for a standard jpanel in the frame and then add a new jpanel to the standard jpanel every time. this should solve the naming problem. if u need access to each panel, you can store them in an array
The code below is supposed to create and object instance for a specific type (say color) JButton I want to represent in a grid. When I iterate through the for-loop to add the buttons to the jframe it adds nothing. But if I add a single instance variable it will add that. Anybody have an idea?
public class Grid {
protected JButton [][] board;
private JButton player;
private JButton openCell;
private JButton wall;
private JButton closedCell;
public Grid(String [] args) { // args unused
// Instantiation
board = new JButton [6][6];
layout = new String [6][6];
blueCell = new JButton("BLUE CELL");
redCell = new JButton("RED CELL");
greenCell = new JButton("GREEN CELL");
whiteCell = new JButton("WHITE CELL");
// Configuration (add actions later)
// Decoration
blueCell.setBackground(Color.blue);
redCell.setBackground(Color.red);
greenCell.setBackground(Color.green);
whiteCell.setBackground(Color.white);
for (int rows = 0; rows < 6; rows++) {
for (int cols = 0; cols < 6; cols++) {
if ((layout[rows][cols]).equals('*')) {
board[rows][cols] = blueCell;
}
else if ((layout[rows][cols]).equals('.')) {
board[rows][cols] = redCell;
}
else if ((layout[rows][cols]).equals('x')) {
board[rows][cols] = greenCell;
}
else {
board[rows][cols] = whiteCell;
}
}
}
JFrame game = new JFrame();
game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.setLayout(new GridLayout (6, 6));
game.setSize(500, 500);
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
if ((board[i][j]).equals(blueCell)) {
grid.add(blueCell);
}
else if ((board[i][j]).equals(redCell)) {
grid.add(redCell);
}
else if ((board[i][j]).equals(greenCell)) {
grid.add(greenCell);
}
else {
grid.add(whiteCell);
}
}
}
grid.setVisible(true);
} // end of constructor
} // end of Grid class
You can add a component to your GUI only once. If you add it to another component, it will be removed from the previous component. You're trying to add the same JButtons several times, and that won't work. Instead you're going to have to create more JButtons. Consider having your buttons share Actions which is allowed.
If you need more help, consider posting compilable code (your current code is not), a small runnable, compilable program that demonstrates your problem, in other words, an sscce.
Edit
You comment:
But don't these count as instances of a JButton not the same JButton? (I don't understand what your answer meant...)
Think of it mathematically... how many JButtons do you create in your code above? Well, this is easy to figure, exactly 4:
blueCell = new JButton("BLUE CELL");
redCell = new JButton("RED CELL");
greenCell = new JButton("GREEN CELL");
whiteCell = new JButton("WHITE CELL");
So, now ask yourself, how many JButtons are you trying to display in your GUI with these four JButtons? If it's four, then you're possibly OK (as long as you use each button), but if it's more, then you're in trouble. From your 6x6 grid, board = new JButton [6][6];, it looks like you're trying to display 36 JButtons, and if this is true, you've got problems.
But again, if still stuck, please consider creating and posting an sscce.