I am nowhere near complete with this code it is just a template and I have not finished formatting my code. I am having trouble calling the message part of the array in my other class. I basically have an if/else statement saying when roomId = some#, it will outprint the message the correlates to the # from the array. I am just having trouble understanding how to call the array. Eclipse is throwing me an error in the if/else statement under "grid" saying grid cannot be resolved to a variable. I also tried calling the array method inside the method that the statements are in.Thanks for the help guys.
public class location{
public int roomId;
public String name, message;
public location() {
roomId = 0;
}
public location(String name, int roomId, String message){
this.name = name;
this.roomId = roomId;
this.message = message;
}
public void LocArray() {
location[][] grid = new location[4][4];
grid [1][0] = new location("LABORATORY", 0, "You're in the lab.");
grid [2][0] = new location("DUNGEON", 1, "You entered the dungeon.");
grid [3][0] = new location("COURTYARD ENTRANCE",2,"You have left the dungeon out the backdoor. Either head east and search the courtyard maze, or travel north back to the dungeon");
grid [3][1] = new location("FIRST PATH", 3,"You have now entered the courtyard, either continue east or move north.");
grid [3][2] = new location("DEADEND", 4,"You have reached a deadend that has a Magic Shop. Go inside and explore it.");
grid [3][3] = new location ("MAGIC SHOP", 5, "Search around the Magic Shop and see what there is. When you're done searching continue through the maze.");
grid [2][1] = new location("SECOND PATH",6,"Search the surroundings for items that will help you get into the locked room, then keep moving.");
grid [2][2] = new location("END MAZE", 7, "You've made it to the end of the courtyard. There seems to be a cave in the distance; go check it out.");
grid [1][2] = new location("CAVE",8,"Explore the cave to find the remaining items that will lead to your freedom.");
grid [0][0] = new location("EXIT",9,"This room will lead to your freedom, but you need the three essential items that will open this door.");
}
}
//This is a different class called projectTwo.
while (stillPlaying) {
Scanner scan = new Scanner(System.in);
userInput = scan.nextLine();
if (roomId == 0){
if (userInput.equals("n")) {
System.out.println(grid[2][0].message);
roomId = 1; // Moves user from location 0 to 1
}
grid variable is declared inside the locArray method.
You can't call it in another method or in an another method inside another class.
Related
I have an array of JButtons which are displayed on a window when it is loaded up.
For some reason, when the window loads, the first button seems to be already selected and so puts my programme into an infinite loop.
I know that to stop this infinite loop I should change the condition in my while(true) loop, but am unsure what conditions to put in.
So I thought another way round would be to figure out why one of the buttons is already selected.
actionPerformed method - this gets the name of the button selected which I made to be a string to represent co-ordinates. It then turns the co-ordinates into integers which can be obtained by the HumanPlayer class with the getXInt and getYInt methods. The board and pieces are already set up in other classes, I know it all works because i've already created a text version, this is now the GUI version I am working on.
It's just a case of enabling the user to select a button without the while(true) loop getting stuck.
The Screen class:
public void actionPerformed(ActionEvent e) {
JButton piece = (JButton) e.getSource();
String xy = piece.getName();
String x = xy.substring(0,1);
String y = xy.substring(2,3);
xInt = Integer.parseInt(x);
yInt = Integer.parseInt(y);
}
public int getXInt() {
return xInt;
}
public int getYInt() {
return yInt;
}
HumanPlayer class which gets the information of the piece selected and checks whether it can be moved.
//Sets up new instance of Screen class which is where the window displaying the buttons is set up (this contains the getXInt and getYInt methods are- so the HumanPlayer class can retrieve the piece which has been selected.
Screen s = new Screen(board);
public boolean makeMove() {
int fromXCo , fromYCo, toXCo, toYCo;
Piece p;
ArrayList<Move> moves = null;
while (true){
//reads x and y co-ordinate
System.out.println("Click on a piece to move");
//takes information from which button is clicked from other class
fromXCo = s.getXInt();
fromYCo = s.getYInt();
p = board.getPiece(fromXCo, fromYCo);
System.out.println("Your selected piece is " + p.getChar());
//looks through available moves for piece
moves = p.availableMoves();
//if no moves available, asks for new co-ordinates.
if (moves == null)
{
System.out.println("No moves available for this piece \n");
continue;
}
break;
}
So the output is a continuous:
Click on a piece to move
Your selected piece is r
There are no available moves for this piece...
I am having a problem with my text array, the text keeps switching constantly. This is the code that I have so far for it:
private void drawSplash(Graphics2D g) {
if (displayed == false) {
Random r = new Random();
String list;
String items[] = { "Buggy!", "New Game!", "Roll up, roll up!",
"Made from Scratch" };
int amount;
amount = (int) (Math.random() * 25 + 1);
list = items[r.nextInt(3 + 1)];
System.out.println(list);
g.setFont(font2);
g.setColor(Color.BLACK);
g.drawString(list, 320, 240);
displayed = true;
}
}
I want to make it so that whenever the program is restarted, the string change.
Can anyone help me with this please? It's really bugging me.
Problem is that you want to keep state between program startups, otherwise you will get repeats. So what you want to do is:
During startup: if no property file with a shuffled list exists, create a shuffled list, set index to 1
Then:
during startup: retrieve shuffled list and index from property file
put the item with the given index in a static field
increase the index and store the property file again
display the item during paint
I'll leave it up to you what you do when you run out of items.
For a quick fix that simply displays a random item each time the class is used:
private static String ITEMS[] = { "Buggy!", "New Game!",
"Roll up, roll up!", "Made from Scratch" };
private String itemDisplayed = chooseItem();
private String chooseItem() {
Random r = new SecureRandom();
int i = r.nextInt(ITEMS.length);
return ITEMS[i];
}
private void drawSplash(Graphics2D g) {
g.setColor(Color.BLACK);
g.setFont(font2);
g.drawString(itemDisplayed, 320, 240);
displayed = true;
}
I guess drawSplash is called each time the text changes. If you only want to draw a random String on e.g. initialize make a own function for
list = items[r.nextInt(3+1)];
which gets only called once
The problem is not drawSplash(), but a) how often it gets called, and b) even if it gets called frequently, then somebody must change the value of displayed to false outside of the method.
Just some minor comments:
if (!displayed) is the usual style
amount is never used
Random r is not really needed
Here is what is wrong:
list = items[r.nextInt(3+1)]
Each time drawSplash() method is executed, list has a new random value.
You should init it only once:
String list;
Random r = new Random();
public void initListIndex(){
String items[] = { "Buggy!", "New Game!", "Roll up, roll up!",
"Made from Scratch" };
int listIndex = r.nextInt(3 + 1);
list= items[listIndex];
}
private void drawSplash(Graphics2D g) {
if (displayed == false) {
System.out.println(list);
g.setFont(font2);
g.setColor(Color.BLACK);
g.drawString(list, 320, 240);
displayed = true;
}
}
I am a little new to swing. In order to learn to use the API correctly, I am designing the following project:
The project is a solving block puzzle solver sliding block puzzle similar to the rush-hour puzzles common in toy stores - https://en.wikipedia.org/wiki/Rush_Hour_(board_game) except there is no escape for a special car.
By dragging the blocks from an off board area to the board, the user specifies the starting configuration of the puzzle. The user, in the same way, specifies an ending goal configuration which dictates where some (or all) of the blocks the user specified initially must be at the end of the puzzle - the ending configuration can be specified using only SOME of the blocks, making multiple legal ending configurations.
The algorithm for solving the puzzle is already complete - I just need to design the interface and I am getting stuck. For designing the tray, I used a grid layout. Since blocks need to be entered at certain positions, I need to be able to place blocks in specific cells in the grid and move them around.
A 'block' object has four attributes - its height, width, its top row, and its left most column (ie - each block is addressed by its top left corner).
I used the suggestion here ( https://stackoverflow.com/questions/2510159/can-i-add-a-component-to-a-specific-grid-cell-when-a-gridlayout-is-used ) for the grid layout.
Right now I have only programmed to the point where java reads the puzzle from a .txt file and is supposed to display it on the screen ( I have not designed any user interactablity yet ).
First, here is the code I have written so far.
public class SolverPuzzleGUI extends JFrame {
//Specs from the puzzle.
Board initBoard;
ArrayList<Block> goalBlocks;
LinkedList<Move> moveList;
JLayeredPane layeredpane;
JPanel Board;
Dimension boardsize = new Dimension(400, 500);
JPanel[][] panelHolder = new JPanel[5][4];
public SolverPuzzleGUI(Board startBoard, ArrayList<Block> startGoalBlocks,
LinkedList<Move> startMoveList) {
this.initBoard = startBoard;
this.goalBlocks = startGoalBlocks;
this.moveList = startMoveList;
} // end constructor.
//gives the actual simulation
public void runSimulation() {
// Initalizing the main window.
setSize(500, 600);
setName("Solution");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setMinimumSize(getMinimumSize());
//Using layered pane
layeredpane = new JLayeredPane();
add(layeredpane);
layeredpane.setPreferredSize(boardsize);
layeredpane.setBackground(Color.YELLOW);
layeredpane.setVisible(true);
// adding the game tray
Board = new JPanel();
layeredpane.add(Board, JLayeredPane.DEFAULT_LAYER);
Board.setLayout(new GridLayout(5, 4));
// centering the game tray.
Board.setPreferredSize(boardsize);
Board.setMinimumSize(boardsize);
Board.setMaximumSize(boardsize);
Box box = new Box(BoxLayout.Y_AXIS);
box.add(Box.createVerticalGlue());
box.add(Board);
box.add(Box.createVerticalGlue());
add(box);
//Adding placeholders to the board for creating blocks
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 4; j++) {
panelHolder[i][j] = new JPanel();
panelHolder[i][j].setBackground(Color.DARK_GRAY);
Board.add(panelHolder[i][j]);
layeredpane.setLayer(panelHolder[i][j], JLayeredPane.DEFAULT_LAYER);
panelHolder[i][j].setVisible(false);
} // end 'j' for
} // end 'i' for
ArrayList<Block> initBlocks = initBoard.getBlocks();
//int count = 0; //DEBUG
for (Block block : initBlocks) {
this.drawBlock(block);
//count++;
//if(count > 4) { break; }
} // end 'for'
Board.setBackground(Color.DARK_GRAY);
Board.setVisible(true);
setVisible(true);
} // end 'run'
private void drawBlock(Block block) {
Dimension blockSize = new Dimension(block.getWidth()*100, block.getHeight()*100);
System.out.println(blockSize.width);
System.out.println(blockSize.height);
JPanel screenBlock = new JPanel();
screenBlock.setPreferredSize(blockSize);
screenBlock.setMinimumSize(blockSize);
screenBlock.setMaximumSize(blockSize);
screenBlock.setSize(blockSize);
screenBlock.setBackground(Color.BLUE);
screenBlock.setBorder(BorderFactory.createLineBorder(Color.BLACK));
layeredpane.setLayer(screenBlock, JLayeredPane.MODAL_LAYER);
int leftRow = block.getRow();
int leftCol = block.getColumn();
panelHolder[leftRow][leftCol].setSize(blockSize);
panelHolder[leftRow][leftCol].setVisible(true);
panelHolder[leftRow][leftCol].add(screenBlock);
layeredpane.setLayer(panelHolder[leftRow][leftCol], JLayeredPane.MODAL_LAYER);
screenBlock.setVisible(true);
}// end 'drawBlock'
public static void main(String[] args) {
String file = "C:\\Users\\Tim\\Desktop\\init.from.handout.txt";
String goal = "C:\\Users\\Tim\\Desktop\\goal.2.from.handout.txt";
/*
A SolverPuzzle object is the object which actually solves the algorithm -
when the class is constructed, it takes the file path of the inital
configuration as an input, as well as the file path of the goal
configuration. It has the following fields:
A 'board' object which specifies the inital configuration of the board.
It contains an ArrayList of Block objects(Remember block objects store
the height and width of the block, as well as the address of the
top left corner of block) which specify the starting
blocks, an ArrayList of EmptySpace objects which specify the empty
spaces on the board, an ArrayList of Move objects, which contain
the legal moves of the configuration, and the height and width of
the tray (in this application, the tray will always be 5 x 4).
An ArrayList of Block objects which specify the ending configuration.
A LinkedList of Move objects which specify the shortest possible
list of Moves which brings the configuration to a position which
satisfies the goal position. A Move object has three fields -
The block object being moved, and the row and column of the
top left corner of the block in the new position.
*/
SolverPuzzle test;
try { test = new SolverPuzzle(file, goal); }
catch (IOException ex) {
System.out.println("IOException");
return;
}
Board testBoard = test.getStartBoard();
ArrayList<Block> testGoalBlocks = test.getGoalBlocks();
LinkedList<Move> testMoveSolution = test.getMoveList();
// testing the gui
SolverPuzzleGUI testGUI = new SolverPuzzleGUI(testBoard, testGoalBlocks,
testMoveSolution);
testGUI.runSimulation();
}
} // end class 'SolverPuzzleGUI'
Here's the current output vs desired output.
http://imgur.com/a/ykXXP
So specifically, I have two questions:
1 - Why is the image only showing the top left corners of the blocks instead of the whole block?
2 - Is it better to continue using the GridLayout or switch to GridBagLayout?
Thanks
GridBagLayout would definitely be suitable for want you want to do. For example, you can expand components to envelop more than one column or row - just like what you want to do. Check out the java tutorials for how to use them.
A key point to remember when using GridBagLayoutis that you need to reset the Constraints after each component, assuming that they're unique to that particular component.
Also - I can't discern what you mean by only showing the top-left - it looks likes its showing the whole thing to me...
The thing is that i'm helping a friend with a java project for the universty, and we have to create a remake of MSX's Knightmare. The game is pretty developed already but we don't know how to create the collision with the scenary's stuff, like the columns and the bridge over the river. In order to do this i thought that we could just create a logical "grid-mapping" over the png (the whole level is this image, invoked on the game like a plain image) and do the logic on it, just a boolean logic.
So the basic way, that i suggest to do, is a 2D array with this grid calculated on our minds. Is there some tool that we could use in order to do this easier or automated somehow?
Knightmare original version video
And this is the image that we are using on the game
I am going to try answering the title question, which seemed like the important one.
I wrote a little platform game in Java some time ago, and there I wrote a method called comprobarColisiones() (check collisions) which I call everytime
// Check collisions
comprobarColisiones();
h.mover(pasadas); //Move hero
// Moving enemies
if (h.x > en.getX()){
en.mover(h.getdx(), h.getIzq(),pasadas);
}
if (h.x> en2.getX()){
en2.mover(h.getdx(), h.getIzq(),pasadas);
}
// Moving static objects (rocks)
roca1.mover(h.getdx(),h.getIzq());
roca2.mover(h.getdx(),h.getIzq());
roca3.mover(h.getdx(),h.getIzq());
// REPAINTING
repaint();
// A time calculation that I use to control the game speed somewhere
tiempoAnteriorTipito = System.currentTimeMillis();
When I mean "static objects" it's just to differentiate objects with self-movement with those that just scroll as long as the hero moves, in your game (as in mine's) there probably will not be any static object (well, probably the scores and stuff), even rocks will scroll.
public void comprobarColisiones(){
// Getting bounds
Rectangle r1 = en.getBounds();
Rectangle r2 = en2.getBounds();
Rectangle rec_roca1 = roca1.getBounds();
Rectangle rec_roca2 = roca2.getBounds();
Rectangle rec_roca3 = roca3.getBounds();
// Getting bounds and resolving collisions with shooting objects
ArrayList martillos = Heroe.getMartillos();
for (int i = 0; i < martillos.size(); i++) {
Martillo m = (Martillo) martillos.get(i);
Rectangle m1 = m.getBounds();
if (r1.intersects(m1) && en.vive())
{
en.setVive(false);
m.visible = false;
}
else if (r2.intersects(m1)&& en2.vive())
{
en2.setVive(false);
m.visible = false;
}
}
// Checking if hero touches enemies
Rectangle heroecuad = h.getBounds();
if (heroecuad.intersects(r1)&&en.vive()){
perdio = true;
System.out.println("PERDIO CON EL ENEMIGO 1");
}
if (heroecuad.intersects(r2)&&en2.vive()){
perdio = true;
System.out.println("PERDIO CON EL ENEMIGO 2");
}
// Checking if hero touches static objects
if(heroecuad.intersects(rec_roca1)){
System.out.println("CHOCO ROCA 1");
}
if(heroecuad.intersects(rec_roca2)){
System.out.println("CHOCO ROCA 2");
}
if(heroecuad.intersects(rec_roca3)){
System.out.println("CHOCO ROCA 3");
}
}
I created enemies and static stuff and placed them when I load the escenario, just like this:
en = new Enemigo(800, ALTURA_PISO+8);
en2 = new Enemigo(900, ALTURA_PISO+8);
roca1 = new Roca(1650, ALTURA_PISO+17);
roca2 = new Roca(2200, ALTURA_PISO+17);
roca3 = new Roca(3400, ALTURA_PISO+17);
// Being the first number the initial X-Pos and the second the initial Y-Pos, this will change everytime the hero moves, of course
Probably in your game, you'll define any area of the map as explorable, and add some ghost objects to check intersection with the hero and stop his movement. For what I could see, water and columns should NOT be explorable by your hero.
Hope this would give you some ideas.
I've run into a little problem.
In my GUI, I have a text area in the center (BorderLayout). Then I have a JList on the West.
When I click on a member of the song titles I have in my list, the text area should display the title, artist, and price of the song.
I have everything working, but the problem is that when I click on a member, the title,artist, and the price is displayed TWICE.
Here is the code for "valueChanged()" and parts of codes relevant.
public void valueChanged(ListSelectionEvent e)
{
Object source = e.getSource();
int index = songList.getSelectedIndex();
Song selection = songCollection[index];
if(source == songList)
{
textArea.append(selection.getTitle() + " " + selection.getArtist() + " " + selection.getPrice() + "\n" );
}
}
private Song songCollection[] = new Song[5];
private String songTitle[] = new String[5];
//Fill song array
songCollection = getSongs();
songTitle = getSongTitle();
//Methods:
public Song[] getSongs()
{
Song[] array = new Song[5];
array[0] = new Song("Summer", "Mozart", 1.50);
array[1] = new Song("Winter", "Mozart", 1.25);
array[2] = new Song("Spring", "Mozart", 2.00);
array[3] = new Song("Baby", "Justin Bieber", 0.50);
array[4] = new Song("Firework", "Katy Perry", 1.00);
return array;
}
public String[] getSongTitle()
{
String[] names = new String[5];
for(int i = 0; i < 5; i++)
names[i] = songCollection[i].getTitle();
return names;
}
I noticed something just now when I was fiddling around with my program again. When I press a member in the list, it is still printed TWICE like before. However, I noticed that it prints once when I press and hold down my mouse, and it prints AGAIN when I let go of it. So if I press my mouse on 1 member, and drag the cursor up/down to other members, they print once, but when I let go of the mouse, it prints the one I ended in one more time.
JTextArea.append() is being called twice from your ListSelectionListener.
The reason can be found in How to Use Lists:
Many list selection events can be generated from a single user action such as a mouse click. The getValueIsAdjusting method returns true if the user is still manipulating the selection. This particular program is interested only in the final result of the user's action, so the valueChanged method does something only if getValueIsAdjusting returns false.
You need to check that the selection in the JList is no longer being manipulated. You can surround the append method with the check:
if (!e.getValueIsAdjusting()) {
textArea.append(...);
}