I'm currently working on a java project to keep me busy for the summer. I've just finished my first year of University so I have a basic knowledge of Java and how it works. For my project I've decided to make a choose you own adventure game sort of thing. Where the user is given some dialogue then they are given two options of how to proceed. So far it's going well and I've came to a flaw that I can't get my head around solving. Below is my code for my primary class.
public DisplayPanel() {
core = new Core();
stat = new StatusPanel();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Quest!");
middle = new JPanel();
bottom = new JPanel();
left = new JButton("Explore");
right = new JButton("Think");
textArea = new JTextArea();
middle.setLayout(new GridLayout(1, 1));
middle.add(textArea);
bottom.add(stat);
left.addActionListener(this);
right.addActionListener(this);
setLayout(new BorderLayout());
add(left, BorderLayout.WEST);
add(right, BorderLayout.EAST);
add(middle, BorderLayout.CENTER);
add(bottom, BorderLayout.SOUTH);
changeText("You wake up in a strange woods and walk forwards into the mist\n " +
"You decide whether it's best to think how you got here " +
"\n or search the area for clues");
setSize(600, 700);
setResizable(false);
setVisible(true);
}
public static void changeText(String newText) {
textArea.setText(newText);
}
public static void appendText(String newText) {
textArea.append(newText);
}
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
Monsters m = new Monsters();
try {
core.load("goblinstier1.txt");
} catch (IOException e1) {
e1.printStackTrace();
}
/////////////////////////////////////////////////////////////////////////
/////////////////////////////LEFT/////OPTION1////////////////////////////
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//////////////////////////////ORIGINAL CHOICE////////////////////////////
/////////////////////////////////////////////////////////////////////////
if(e.getSource() == left) {
textArea.setText("You explore the area for clues and hear a rustling in a bush.\n " +
"It might be someone who can help? Or it could be a monster! \n" +
"You ready your knife in preperation!\n");
stat.incrementClickCount();
option2a = new JButton("Talk");
option2a.addActionListener(this);
option2a.setActionCommand("left2a");
add(option2a, BorderLayout.WEST);
option2b = new JButton("Leave");
option2b.addActionListener(this);
option2b.setActionCommand("right2b");
add(option2b, BorderLayout.EAST);
right.setVisible(false);
left.setVisible(false);
}
/////////////////////////////////////////////////////////////////////////
////////////////////////////LEFTA/////OPTION2////////////////////////////
/////////////////////////////////////////////////////////////////////////
Monsters temp = null;
temp = core.anyMonster();
if(cmd == "left2a") {
option2a.setText("Attack!");
option2b.setText("Flee!");
stat.incrementClickCount();
fightClick++;
if(fightClick >=2) {
appendText("You grip your shiv and cleave!");
temp.cleave();
if(temp.getHealth()<=0) {
appendText("You have " +stat.getHealth2()+ " health remaining ");
stat.gold();
stat.xp();
}else {
stat.hit();
}
}
}
My problem lies within LEFTA Option two I've tried to script a sort of fight system where the user has the chance to fight or flee. The way this works is by a method in my core class called anyMonster I will display it below.
public Monsters anyMonster() {
int index = randomGenerator.nextInt(monsters.size());
Monsters monsters1 = monsters.get(index);
DisplayPanel.changeText("A monster appears! It's a " + monsters1 + "!\n What shall you do?\n");
return monsters1;
}
The method loops through a pre set arrayList and picks a "Monster" at random. As you can see in the DisplayPanel I tried to call this in the actionPerformed class and then if the user presses a button it will attack the monster, code below.
public void cleave()
{
randomNum = 7 + (int)(Math.random() * ((10 - 7) + 1));
newHealth=health-randomNum;
health=newHealth;
DisplayPanel.appendText(" You attack for " +randomNum+ " Damage, it has " +health+ " health remaining!\n ");
if(health<=0){
DisplayPanel.appendText("The monster falls to the ground");
}
}
}
The way i made this work in DisplayPanel was assigning the method to a temp value and then calling the cleave() method from that which works. The problem is that every time i click the button it will select a new monster each time. I realise why this is happening, of course it's a button it will just do the same action each time. The problem is I'm completely out of ideas on how to solve this. Which is frustrating, I'd really like to continue with my project and any help you can give to a newbie would be highly appreciated. Thanks in advance, Rob.
Rather than create your minsters in actionPerformed, you should create this as a field, that way your monsters are only created once.
Related
When I try to run this, I keep getting an empty frame that cannot be closed, and I have to terminate the program from eclipse. I am fairly certain that the problem is a result of the while loop (about 2/3 of the way down the code block), but I haven't been able to figure out a way to fix this
public Draw()
{
super( "Uno");
JMenuBar bar = new JMenuBar(); // create menu bar
JMenu gameMenu = new JMenu( "Play Game" );
JMenu quitMenu = new JMenu( "Quit" ); //Quit Program
bar.add( gameMenu ); // add Add menu to menu bar
bar.add( quitMenu ); // add quit button to menu bar
setJMenuBar( bar ); // set menu bar for this application
window = new JDesktopPane();
add(window);
gameMenu.addMouseListener(
new MouseListener()
{
public void mouseClicked(MouseEvent e)
{
Dimension size = window.getSize();
double height = size.getHeight();
double width = size.getWidth();
JInternalFrame frame = new JInternalFrame("Uno", true, true, true, true );
JFrame input = new JFrame();
input.setTitle(" ");
input.setSize(350, 155);
input.setLayout(new FlowLayout());
input.setLocationRelativeTo(null);
input.setVisible(true);
JLabel label1 = new JLabel("How many total players? (2-10)");
final JTextField text1 = new JTextField(3);
JLabel label2 = new JLabel("How many computer players? *");
final JTextField text2 = new JTextField(3);
JLabel label3 = new JLabel("* Computer players must be <= total number of players");
JButton confirm = new JButton("OK");
label1.setVisible(true);
label2.setVisible(true);
label3.setVisible(true);
text1.setVisible(true);
text2.setVisible(true);
confirm.setVisible(true);
input.add(label1);
input.add(text1);
input.add(label2);
input.add(text2);
input.add(label3);
input.add(confirm);
while(valid == false)
{
confirm.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String players = text1.getText();
String computers = text2.getText();
int temp1 = Integer.parseInt(players);
System.out.println("Number of players = " + temp1);
int temp2 = Integer.parseInt(computers);
System.out.println("Number of computers = " + temp2);
if (temp1 >= 2 && temp1 <= 10)
if (temp2 <= temp1 && temp2 >= 0)
valid = true;
} //close actionPerformed
}); //close ActionListener
} //close while loop
} //close mouseClicked
} //close mouseListener
} //close Draw
Initially, I was having an issue where it kept infinitely drawing the frame on top of itself because the while loop kept returning false. That issue was solved by removing the components from the while loop, and placing them before it as they are above. Now when I run it, all I get is this: picture
The goal of this program is to make an Uno game, but the first step is to determine the number of players. This is the only way I know how to do this, and this is only the second program I have done with graphics, so I am by no means an expert at Java. I will appreciate any help I can get because I have been stuck for a few days now.
The problem is that you are not giving the event handlers any chance to do their job. Your while loop continually creates event handlers. However, the actionPeformed() method can never be called because the while loop has control of the CPU and the button will not respond to any clicks.
I suggest that you learn a bit more about event handling. You will need to redesign your code in order to get the behavior you wish. Most likely you need to remove the while loop entirely and just create an event handler which will execute code when the button is clicked.
For future reference:
In general, checking equality with a boolean value is unnecessary. The result of == is a bool, but the variable you are checking is already a bool. So use it directly: instead of while (valid == false), you can do while (!valid). If you read the ! as "not", this actually makes a lot of sense.
In this case, the point is moot, since you need to remove the while loop entirely. However, this might be useful information for you some time in the future.
Glad to be on this very helpful website. I have a problem with my Java program that will probably either be an easy fix, or impossible to fix.
You know how when you run a program that's open in NetBeans, it shows the output within the NetBeans application? I am trying to create a program that allows anybody who puts it on their computer to execute it, even if they have not installed an IDE like NetBeans or Eclipse. And when somebody executes my program, I want it to show the same thing as when I run it in NetBeans, with the same output and everything. The program doesn't use a GUI or anything like that. I managed to create an executable .jar file with the "Clean and build project" option, and I made a .bat file that successfully executes the program. This should achieve my goal of allowing anyone to run it. When I start up the .bat file, it works, and shows a white-text-black-background screen that runs the program exactly as it ran while in NetBeans.
The problem is that when I run the program (with the .bat file), the text is too small... I've tried looking everywhere for a solution to this, but I could only find discussion about how to make things work with GUIs, or other more complicated things than what my program needs. I am willing to work with GUI stuff if it is necessary, but I don't think it will help, due to what a GUI is. From my understanding, a GUI is not one big thing, but is a user interface composed of smaller parts (such as pop-up input prompts and scroll bars) that are each made by the programmer. I don't need any fancy scroll bars etc., I just need my program to execute like it does when ran in NetBeans (pretty sure this is called the console), and I need to change the text size of the program text when it executes.
I greatly appreciate any help, even if you aren't sure if it will work or not. If the answer requires a lengthy explanation and you don't feel like explaining, that's okay; just tell me what I'd have to learn to figure this out and I can research it if necessary.
I just created one. Try using this one and tell us if it helped or not.
EDIT Added a JTextField to read data. It is more advanced code than the previous one, since it uses concurrency. I tried to make it simple, these are the functions you can use:
MyConsole (): Constructor. Create and show the console
print (String s): Print the s String
println (String s) Print the s String and add a new line
read (): Makes you wait untill the user types and presses Enter
closeConsole (): Closes the console
Here is the code:
public class MyConsole implements ActionListener {
private JFrame frame;
private JTextArea myText;
private JTextField userText;
private String readText;
private Object sync;
/*
* Main and only constructor
*/
public MyConsole() {
// Synchronization object
sync = new Object();
// Create a window to display the console
frame = new JFrame("My Console");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 200);
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setContentPane(createUI());
frame.setVisible(true);
}
/*
* Creates user interface
*/
private Container createUI() {
// Create a Panel to add all objects
JPanel panel = new JPanel (new BorderLayout());
// Create and set the console
myText = new JTextArea();
myText.setEditable(false);
myText.setAutoscrolls(true);
myText.setBackground(Color.LIGHT_GRAY);
// This will auto scroll the right bar when text is added
DefaultCaret caret = (DefaultCaret) myText.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
// Create the input for the user
userText = new JTextField();
userText.addActionListener(this);
panel.add(new JScrollPane(myText), BorderLayout.CENTER);
panel.add(userText, BorderLayout.SOUTH);
return panel;
}
/*
* Waits until a value is typed in the console and returns it
*/
public String read(){
print("==>");
synchronized (sync) {
try {
sync.wait();
} catch (InterruptedException e) {
return readText = "";
}
}
return readText;
}
/*
* Prints s
*/
public synchronized void print(String s){
// Add the "s" string to the console and
myText.append(s);
}
/*
* Prints s and a new line
*/
public synchronized void println(String s){
this.print(s + "\r\n");
}
/*
* Close the console
*/
public void closeConsole(){
frame.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
// Check if the input is empty
if ( !userText.getText().equals("") ){
readText = userText.getText();
println(" " + readText);
userText.setText("");
synchronized (sync) {
sync.notify();
}
}
}
}
Here is how to use it (an example). It just asks your age and writes something depending on your input:
public static void main(String[] args) {
MyConsole console = new MyConsole();
console.println("Hello! (Type \"0\" to exit)");
int age = 1;
do{
console.println("How old are you ?");
String read = console.read();
try {
age = Integer.valueOf(read);
if ( age >= 18){
console.println("Wow! " + age + " ? You are an adult already!");
}else if ( age > 0 ){
console.println("Oh! " + age + " ? You are such a young boy!");
}else if (age == 0){
console.println("Bye bye!");
}else{
console.println("You can't be " + age + " years old!");
}
}catch (Exception e) {
console.println("Did you write any number there ?");
}
} while ( age != 0 );
console.closeConsole();
}
And here is a image:
Simplified: How to make String value to call specific existed JButton variable name in java?
I'm trying to make a non-ordinary Tic-Tac-Toe game...
Anyway, what I will post here is not really the whole concept of that. I just want to make it simple: I have 9 square jButtons named (3 by 3) (and maybe allow user to make 4x4, 5x5, 10x10 etc. via settings in future):
[markbox_00_00] / [markbox_00_01] / [markbox_00_02]
[markbox_01_00] / [markbox_01_01] / [markbox_01_02]
[markbox_02_00] / [markbox_02_01] / [markbox_02_02]
[btnSave] / [btnUndoActions]
where the first two digit represent the row and the next two is the column; and a save button (btnSave) and undo button(btnUndoActions).
Each markbox have default spring value of "0", when I click it turns "1"; and when I click "1" it turns "0". When you press undo button it will reset to last save.
Here is some of my simplified line of codes:
private byte markboxColLimit = 3, markboxRowLimit = 3, row, col;
private byte[][] saveNumber = new byte[markboxRowLimit][markboxColLimit];
private String buttonName;
public Astral_TicTacToe() {
initComponents();
/* I want something like this, but using a for loop based on markboxColLimit and
markboxRowLimit as limits */
markbox_00_00.setText("0");
markbox_00_01.setText("0");
markbox_00_02.setText("0");
markbox_01_00.setText("0");
markbox_01_01.setText("0");
markbox_01_02.setText("0");
markbox_02_00.setText("0");
markbox_02_01.setText("0");
markbox_02_02.setText("0");
/* I know the line below is wrong... what I'm trying is to avoid
* repetitiveness by looping and dynamically calling the variable
* name of JButtons, or in other ways...
*/
/* Attempting to make an alternative code from above (trying to make a loop instead) */
for(row = 0; row < markboxRowLimit; row++){
for(col = 0; col < markboxColLimit; col++){
buttonName = "markbox_0" + Byte.toString(row) + "_0" + Byte.toString(col);
buttonName.setText("0");
}
}
}
private void btnUndoActionsActionPerformed(java.awt.event.ActionEvent evt) {
markbox_00_00.setText(Byte.toString(saveNumber[0][0]));
markbox_00_01.setText(Byte.toString(saveNumber[0][1]));
markbox_00_02.setText(Byte.toString(saveNumber[0][2]));
markbox_01_00.setText(Byte.toString(saveNumber[1][0]));
markbox_01_01.setText(Byte.toString(saveNumber[1][1]));
markbox_01_02.setText(Byte.toString(saveNumber[1][2]));
markbox_02_00.setText(Byte.toString(saveNumber[2][0]));
markbox_02_01.setText(Byte.toString(saveNumber[2][1]));
markbox_02_02.setText(Byte.toString(saveNumber[2][2]));
}
private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) {
saveNumber[0][0] = Byte.parseByte(markbox_00_00.getText());
saveNumber[0][1] = Byte.parseByte(markbox_00_01.getText());
saveNumber[0][2] = Byte.parseByte(markbox_00_02.getText());
saveNumber[1][0] = Byte.parseByte(markbox_01_00.getText());
saveNumber[1][1] = Byte.parseByte(markbox_01_01.getText());
saveNumber[1][2] = Byte.parseByte(markbox_01_00.getText());
saveNumber[2][0] = Byte.parseByte(markbox_02_00.getText());
saveNumber[2][1] = Byte.parseByte(markbox_02_01.getText());
saveNumber[2][2] = Byte.parseByte(markbox_02_02.getText());
}
private void markbox_00_00ActionPerformed(java.awt.event.ActionEvent evt) {
if("0".equals(markbox_00_00.getText()))
markbox_00_00.setText("1");
else
markbox_00_00.setText("0");
}
private void markbox_00_01ActionPerformed(java.awt.event.ActionEvent evt) {
if("0".equals(markbox_00_01.getText()))
markbox_00_00.setText("1");
else
markbox_00_00.setText("0");
}
....
private void markbox_02_02ActionPerformed(java.awt.event.ActionEvent evt) {
if("0".equals(markbox_00_00.getText()))
markbox_02_02.setText("1");
else
markbox_02_02.setText("0");
}
In short: how can I make String a specific variable name of JButton for calling/accessing/editing for their properties?
Example:
buttonName = markbox_01_02;
buttonName.setText("2");
is equavalent to markbox_01_02.getText("2");
I really appreciate the help, thank you...
P.S. I use to make JFrame in NetBeans Design (just click and drag the objects in palette window like JPanel, JButton, etc., so I don't type the code manually except making my own logical Method).
You probably need to redo your program and rephrase your question because it's kind of unclear where you're stuck that's why I wrote this answer as a Community Wiki.
The following program creates a GridLayout for the board and add 2 JButtons below it which contain "Save" and "Undo" buttons.
Whenever you press a button it will change it's text to 0 or 1 depending on the previous state of the button, and "Undo" button will undo last clic the same way, if it was 0 it will become 1 and viceversa.
I guess you should read How to write an ActionListener before copy-pasting this example, understand what it says and try to understand how this program works.
The logic to "Save" button is up to you 'cause I'm not sure what you wanna do there and I'm not gonna write all the code for you. This is made only for you to get an idea on how to handle events.
Also, the logic to end the game is left to you for the same reasons as the "Save" button.
I wish I knew how to record my screen in Ubuntu and save as GIF but here's a screenshot on how this program looks like:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class TicTacToe implements ActionListener {
JFrame frame;
JButton buttons[];
JPanel pane, buttonPane;
boolean pressed[];
JButton save, undo;
int n = -1;
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < buttons.length; i++) {
if(e.getSource() == buttons[i]) {
pressed[i] = !pressed[i];
buttons[i].setText(pressed[i] ? "1" : "0");
n = i;
break;
}
}
}
public TicTacToe () {
frame = new JFrame("Tic Tac Toe Game");
buttons = new JButton[9];
pane = new JPanel(new GridLayout(3, 3));
pressed = new boolean[9];
buttonPane = new JPanel(new FlowLayout());
save = new JButton("Save");
undo = new JButton("Undo");
for (int i = 0; i < buttons.length; i++) {
buttons[i] = new JButton("0");
pressed[i] = false;
}
for (JButton b : buttons) {
b.addActionListener(this);
pane.add(b);
}
undo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (n == -1) {
return;
}
pressed[n] = !pressed[n];
buttons[n].setText(pressed[n] ? "1" : "0");
}
});
buttonPane.add(save);
buttonPane.add(undo);
frame.add(pane, BorderLayout.PAGE_START);
frame.add(buttonPane, BorderLayout.CENTER);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main (String args[]) {
new TicTacToe();
}
}
I am writing a Blackjack program using JFrame and trying to keep it as simple as possible. My JButton, jbHit works with a single click, however it overwrites the playersHand and playerSide slot with every click. I would like it to work with multiple clicks (3 clicks - since that is the max number of cards you can get after the first two are dealt) options It should count them so to speak so that the array index can record the card image. Here is my ActionListener code that I have so far. I am afraid I am stuck. Should I use some sort of for loop with an int i++?
//Hit Button ActionListener
jbHit.addActionListener( new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if ( playerValue < 21 ) {
//Draw a card
Card c = deck.drawCard();
playersHand.add(c);
playerSide[2].setIcon( new ImageIcon( c.getFilename() ) );
}
//If playerValue > 21, bust
else if ( playerValue > 21 ) {
//Toggle Buttons
jbDeal.setEnabled(true);
jbHit.setEnabled(false);
jbStand.setEnabled(false);
jbDoubleDown.setEnabled(false);
message = "You bust.";
}
}
});
You could create an array of "action commands" and every time you click the button, the action command changes to the next. If you reach the end, set the index back to zero. Perhaps something like this:
public static void main(String[] args)
{
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton button = new JButton("Action");
String[] commands = {"command1", "command2", "command3"};
button.setActionCommand(commands[0]);
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
JButton btn = (JButton)e.getSource();
String cmd = btn.getActionCommand();
System.out.println("Command: " + cmd);
if(cmd.equals("command1"))
{
btn.setActionCommand(commands[1]);
System.out.println("Command 1 was pressed");
}
else if(cmd.equals("command2"))
{
btn.setActionCommand(commands[2]);
System.out.println("Command 2 was pressed");
}
else if(cmd.equals("command3"))
{
btn.setActionCommand(commands[0]);
System.out.println("Command 3 was pressed");
}
else
System.out.println("Something went wrong!");
}
});
panel.add(button);
frame.add(panel);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
If you are using Java 7 or later, you can replace the if/else with a Switch statement.
I believe you're looking for a logical flag based on an integer, for example:
if(cardsDealt < 3) {
// DoThings();
} else {
return;
}
Which would require you to do
cardsDealt++;
at the bottom of your button click handle.
If this is not what you're asking, please re-explain the question.
It sounds like you might be a little confused about how jbHit will be called. Realize that it will be called one complete time every time the mouse is clicked. It's not like it inherently knows that it is on the second or third click. Add a class member like int clickCount; that you increment at the appropriate point inside of jbHit. Then you can alter your method's response depending on the value of clickCount.
I'm working on a textbased simple roleplaying game for my exame, but i have ran into some problems with my gui.
When the player registers, he can spend some attribute points in 3 categories. The gui is programmed to show the Raise Strength etc. button, if the player have any attribute points.
And that works cool, but then when the player clicks on a raise button, an attributepoint is taken for him, the problem is, that the gui doesn't seem to update.
if(Controller.player.getAttributePoints() > 0) {
JLabel attriL = new JLabel("You have " + Controller.player.getAttributePoints() + " unspent Attribute points.");
attriL.setBounds(110, 30, 250, 30);
hPanel.add(attriL);
JButton setStrB = new JButton("Raise Strength");
setStrB.setBounds(125, 60, 200, 30);
setStrB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// tabbedPane.removeAll();
Controller.player.setAttributePoints(Controller.player.getAttributePoints()-1);
Controller.player.setStrength(Controller.player.getStrength()+1);
gameCtn.validate();
gameCtn.repaint();
System.out.println(Controller.player.getStrength());
}
});
hPanel.add(setStrB);
}
As you can see i have tried using repaint and validate on my container but with no luck, also i have tried on the Frame, and the panel, nothing seems to work?
Am i doing something wrong?
Thx
not clear if Controller... didn't invoked long timed and hard taks, basically (if you remove and then add new JComponents) to the GUI then you have to call
revalidate();
repaint();// not required on all cases
simple demonstrations what's happens, what's possible or most completed here
Sorry about that.
You have no code that says to make the button invisible.
public void actionPerformed(ActionEvent evt) {
...
if (whateverIsLeft < 1) {
JButton src = (JButton)evt.getSource();
src.setVisible(false);
}
attriL.setText("You have " + whateverIsLeft + " attribute points left");
}