I am trying to get a function where, when you press enter, you start the game, but it isn't working. There is no error.
I have followed a tutorial.
here is my code:
import greenfoot.*;
/**
* Write a description of class Menu here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class Menu extends World
{
/**
* Constructor for objects of class Menu.
*
*/
public Menu()
{
// Create a new world with 600x400 cells with a cell size of 1x1 pixels.
super(800, 500, 1);
prepare();
}
public void start()
{
{
if(Greenfoot.isKeyDown("ENTER"))
{
MinionWorld MinionWorld= new MinionWorld();
Greenfoot.setWorld(MinionWorld);
}
}
}
/**
* Prepare the world for the start of the program. That is: create the initial
* objects and add them to the world.
*/
private void prepare()
{
Controls controls = new Controls();
addObject(controls, 300, 100);
controls.setLocation(175, 50);
}
}
if(Greenfoot.isKeyDown("ENTER"))
Change this line to
if(Greenfoot.isKeyDown("enter"))
Key name for Enter is "enter" all small-caps.
Your code check if the Enter button is pressed at the moment it is run. You should use a KeyListener to catch the 'Enter' pressed event. If you are not using a GUI you can just use a Scanner and wait for the user to press Enter:
Scanner scanner = new Scanner(System.in);
scanner.nextLine();
This will wait until the user press Enter.
With your actual code now, what's happening is that when you call start(), it's checking ONCE, at the time you called start() if the user pressed enter.
One thing you can do is to put the code of your start method in a while loop, which will make it checking if the user pressed enter all the time, and when the condition is met, you can break the while loop to end the start method.
Here is an example of code:
public void start()
{
while(true){
if(Greenfoot.isKeyDown("ENTER"))
{
MinionWorld MinionWorld= new MinionWorld();
Greenfoot.setWorld(MinionWorld);
break; // Ends the loop
}
}
}
Related
I'm working on a personal project where I'm trying to create Simon game in Java. It is essentially a memory game where the user has to repeat the sequence the computer generates. So, I created a basic CLI version of the game and now I'm looking to give it a GUI. I haven't worked with Java Swing before so I'm having some trouble replicating the same behavior in GUI form.
The structure of the CLI version looked something like this:
public static void main(String[] args) {
GameContext simon = new GameContext();
simon.start();
while (!simon.getRoundEndState()) {
simon.playSequence();
simon.pickColour();
}
}
Here's what the playSequence() method looks like. It essentially generates a number between 0 and 3 and keeps adding one number to the array each round if the player gets the previous one right.
public void playSequence() {
int rand = getRandomNumber(4);
computerSequence.add(rand);
for(int i:computerSequence) {
System.out.println(i);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
gameContext.setState(gameContext.getHumanPlayingState());
}
pickColour() method that asks the user for the pattern and checks if the pattern matches the one generated by the computer.
public void pickColour() {
boolean roundWon = true;
for(int i=0; i<gameContext.getSequence().size();i++){
Scanner input = new Scanner(System.in);
Integer userInput = input.nextInt();
if(userInput == gameContext.getSequence().get(i)) {
continue;
}
else {
System.out.println("Input mismatched the sequence");
roundWon = false;
break;
}
}
if (roundWon == true) {
score++;
gameContext.setState(gameContext.getComputerPlayingState());
} else {
gameContext.setRoundEndState(true);
System.out.println("Your score is: " + score);
gameContext.setState(gameContext.getInLobbyState());
}
}
Please note that I'm using the state pattern here and hence the change in states. I got the first part working where I need to light up the colors after the computer generates the the sequence. So now, playSequence() looks something like this:
public void playSequence() {
int rand = getRandomNumber(4);
computerSequence.add(rand);
gameContext.setState(gameContext.getHumanPlayingState());
}
And I added a mouse listener to the start button which looks something like this:
btnStart.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me) {
simon = new GameContext();
simon.start();
while (!simon.getRoundEndState()) {
simon.playSequence();
for(int i : simon.getSequence()) {
lightPanels(i);
Timer timer = new Timer(1000, e -> {
darkenPanels(i);
});
timer.setRepeats(false);
timer.start();
}
simon.pickColour();
}
}
});
I have 4 JPanels that now act as the input buttons. How do I change simon.pickColour() so that instead the asking the user for the correct sequence like it did in the CLI version, it would register the clicks made in the JPanels as the input.
It essentially generates a number between 0 and 3 and keeps adding one number to the array each round if the player gets the previous one right.
and
I have 4 JPanels that now act as the input buttons.
Why have 4 panels. Just have one panel that contains 4 buttons. You would then add an ActionListener to the button (not a MouseListner) to handle the clicking of the button.
The buttons would be created with code like:
for (int i = 1; i <= 4; i++)
{
JButton button = new JButton("" + i);
button.addActionListener(...);
panel.add( button );
}
The ActionListener code would then get the text of the button and add the text to an ArrayList to track the order the the buttons that have been clicked.
A working example of this approach of sharing an ActionListener for all the buttons can be found here: https://stackoverflow.com/a/33739732/131872. Note the "action command" will default from the text that is set on the button.
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:
I'm a beginner in Java and I am making a basic game for practice. I'm almost done, but I have one further obstacle to overcome.
I would like to know how to make the game loop on the game() method after pressing no as a choice when asked whether to end the game.
Here is my code:
private static void game() //game method
{
//...
int play = JOptionPane.showOptionDialog(null
,"End"
, "Do you want to play again?"
, JOptionPane.PLAIN_MESSAGE
,JOptionPane.DEFAULT_OPTION
, null
, again
, again[1]);
//end of game
if (play == 0)
System.exit(0);//exit
else
/* what do I put here to restart the program in the same method(game())
after pressing the No button on the JOptionPane??? */
System.out.println("Service not available");
To anybody who can help, I thank you very much!
Given the current state of your program, the easiest simplest most straightforward readable method is recursion. Just call your game method again. Note that there's probably a recursion limit, so the loop is the recommended method, even if it does involve restructuring your code a bit.
else{
game();
}
Loop method: declare play at the beginning and use a loop:
private static void game(){
boolean play = true;
while (play){
//...
//find out if user wants to play again
//set play to false if player doesn't want to play anymore
}
}
Extract the JOptionPane part from your game() function code
int play=0;
do{
game();
play = JOptionPane.showOptionDialog(null
,"End"
, "Do you want to play again?"
, JOptionPane.PLAIN_MESSAGE
,JOptionPane.DEFAULT_OPTION
, null
, again
, again[1]);
}while(play);
If you just want to make it work you can do something like this :
private static void game()//game method
{
boolean exit = false;
while(!exit){
//...int play = JOptionPane.showOptionDialog(null,"Play Again?", "Do you want to play again?", JOptionPane.PLAIN_MESSAGE,JOptionPane.DEFAULT_OPTION, null, again, again[1]);
//end of game
if (play == 0) {
exit = true;
}
}
System.exit(0);//exit
But a better more professionnal approach would be to refactor your code, so you extract game logic and separate it from User dialog interaction.
You can use this method which i am very sure will work in your program since it is something that i have done before. You'll use Desktop class of the system that will initiate the opening of the program. The program will look like this
public static void restart()
{
Desktop desktop = Desktop.getDesktop();
try {
desktop.open(new File("name_of_your_jarfile.jar").getCanonicalFile());
// desktop.open(new File("name_of_your_exe.exe").getCanonicalFile());//for exe
} catch (IOException e) {
//if this happen try looking whether the name of your jar file is correct
e.printStackTrace();
}
}
private static void game() //game method
{
//...
int play = JOptionPane.showOptionDialog(null
,"End"
, "Do you want to play again?"
, JOptionPane.PLAIN_MESSAGE
,JOptionPane.DEFAULT_OPTION
, null
, again
, again[1]);
//end of game
if (play == 0)
System.exit(0);//exit
else
/* what do I put here to restart the program in the same
after pressing the No button on the JOptionPane??? */
System.out.println("Service not available");
restart();//this will reopen your jar/exe file
System.exit(0);
}
I have looked over this code and i don't know what is wrong. I keep getting incorrect outputs when i enter a command (any input). Please look at the bottom part of my code.
public class gui {
private final static javax.swing.JFrame frame = new javax.swing.JFrame();
private final static javax.swing.JPanel panel = new javax.swing.JPanel();
public final static javax.swing.JTextArea outtextArea = new javax.swing.JTextArea("");
public final static javax.swing.JTextField intextArea = new javax.swing.JTextField();
public static void main(String[] args) {
java.awt.Font font = new java.awt.Font(java.awt.Font.SANS_SERIF, java.awt.Font.PLAIN, 15);
String command;
/* Optional */
frame.setTitle("Console");
frame.setUndecorated(true);
frame.getRootPane().setWindowDecorationStyle(javax.swing.JRootPane.FRAME); // COMMENT THIS OUT WHEN COMPLETE
frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); //if exit command, dispose() first
frame.setBackground(java.awt.Color.BLACK);
/* size */
frame.setMinimumSize(new java.awt.Dimension(0b001011010100,0b000110000100));
frame.setLocation(0,0);
frame.setExtendedState(javax.swing.JFrame.MAXIMIZED_BOTH);
/* Sets panel */
panel.setBackground(java.awt.Color.PINK); // if sees pink, has error
panel.setLayout(new java.awt.BorderLayout());
panel.setSize(frame.getWidth(),frame.getHeight());
/* Sets text area */
//javax.swing.JScrollPane inscrollPane = new javax.swing.JScrollPane(intextArea);
intextArea.setHorizontalAlignment(javax.swing.JTextField.LEFT);
intextArea.setFont(font);
intextArea.setBackground(java.awt.Color.BLACK);
intextArea.setForeground(java.awt.Color.GREEN);
intextArea.setFocusable(true);
javax.swing.JScrollPane outscrollPane = new javax.swing.JScrollPane(outtextArea);
outtextArea.setRows(10);
outtextArea.setLineWrap(true);
outtextArea.setFont(font);
outtextArea.setBackground(java.awt.Color.BLUE);
outtextArea.setForeground(java.awt.Color.GREEN);
outtextArea.setEditable(false);
/* Sets all necessary components */
frame.add(panel);
panel.add(outscrollPane,java.awt.BorderLayout.CENTER);
// panel.add(inscrollPane,java.awt.BorderLayout.SOUTH);
panel.add(intextArea,java.awt.BorderLayout.SOUTH);
/* Adjusts components */
frame.pack();
frame.setVisible(true);
//every time a command is entered, it is sent to handler and
//textbox should be cleared
// THIS BELOW IS WHERE THE PROBLEM LIES/////////////////////////////
boolean keepGoing=true;
while(keepGoing){
command = intextArea.getText();
String refactored;
if(entering_a_command(command) && !command.equals("exit")){
refactored=command.substring(0,command.length()-1);
outtextArea.append(refactored+"\n");
intextArea.setText("");
}
else if(!command.equals("exit")){//no need to read before submission
outtextArea.append("");
command=intextArea.getText();
}
else{
outtextArea.append("EXITING\n");
keepGoing=false;
}
}
}
/*
Method is strictly for entering user input at appropriate time
*/
private static boolean entering_a_command(String temp){
//handler.print(temp);
return temp.contains("="); //key to submit user input
}
}
My input:
12345=
123456=
This is hell=
This is hello=
My EXPECTED output:
12345
123456
This is hell
This is hello
My ACTUAL output:
12345
12345
This is hell
This is hell
My problem:
When i enter an input the first time, it all checks out. When i enter an input the second time, an input that has greater length than the first, it is automatically submitted just as if i had pressed the trigger key (=).
The input box is the black box in the bottom. To submit an input, press '='
The problem is that you're abusing the threading model. You shouldn't be accessing UI components in a thread other than the UI thread - and having a tight loop like this is pretty much always a bad idea. You should read about the Swing threading model. From that tutorial:
Swing event handling code runs on a special thread known as the event dispatch thread. Most code that invokes Swing methods also runs on this thread. This is necessary because most Swing object methods are not "thread safe": invoking them from multiple threads risks thread interference or memory consistency errors.
Instead, you should add an event listener to your text area. There are loads of options here, none of which is obviously ideal, unfortunately. Adding a key listener and handling keyTyped sounds good - but you get the event before the key ends up in the text area, which isn't ideal. Adding a document listener is a nice abstraction in that then it doesn't matter how the text is changed (e.g. programmatically) - but you can't mutate the document within a listener, so you can't clear it.
As a starting point, adding a key listener and handling keyReleased works well at least for the simple case. Get rid of your current loop (and the unconventionally named entering_a_command method) and replace them with:
intextArea.addKeyListener(new java.awt.event.KeyAdapter() {
#Override public void keyReleased(java.awt.event.KeyEvent e) {
String command = intextArea.getText();
if (!command.contains("=")) {
return;
}
command = command.substring(0, command.length() - 1);
if (command.equals("exit")) {
frame.setVisible(false);
frame.dispose();
return;
}
outtextArea.append(command + "\n");
intextArea.setText("");
}
});
I have a type game in which you have to type the words that appear as fast as possible before the time limit runs out, but every time you type a word, you must move the mouse and click enter and click back into the user input to type the next word. I was just hoping if there was way to use "keyCode.VK_Enter" to issue an Action Command called by the JButton.
Some snippets of my code:
The Enter button and user input and output:
enter = new JButton("Enter");
enter.setFont(serif); //serif is specified earlier
enter.setActionCommand("Enter");
enter.addActionListener(this);
container.add(enter);
userOutput = new JTextField(50);
userOutput.setFont(serif);
container.add(userOutput);
userOutput.setEditable(false);
userInput = new JTextField(43);
userInput.setFont(serif);
container.add(userInput);
userInput.setEditable(false);
The actionPerformed method getting the enter button's action command:
if(userInput.getText().equals(userOutput.getText())){
userInput.setText("");
score += 100;
Why don't you just add an actionlistener to the JTextField (which would be triggered when the user hits enter).
userInput.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Do something
}
});