How can I use while loops in a text based game Java? - java

So first off is just some text showing my thought process on the way the code should work. I am super new to programming in general and just started learning java only a few days ago. I think I have a basic understanding of how oop works but I can't implement it well into my code. The use of while loops makes a bit of sense to me though so I'm just starting out with those ;D
Things I want:
a main menu with 3 options
Menu (camp)
Quest (activates the quest loop)
Go to Town (activates the town loop)
quit game (exits the program)
Quest
Gameplay loop of fighting random monsters and gaining gold/score
"monster appears"
fight monster
does damage to monster
monster does damage back
back to main loop
use item
choose item
use item
item effects applied
back to main loop
run
return back to main menu (activates main menu)
Town
allows you to spend gold on "gear" to increase health and damage values
"I am the blacksmith blah blah blah"
Upgrade Weapon (increases damage)
Upgrade Armor (increases health)
Leave Town (returns player back to main menu)
Game Ends when player dies or chooses quit game
Display a Score and thank player for playing game
Below is just a prototype of the logic
I feel like this should work but every time I run it,
it doesn't work right and just ends up doing an
infinite loop. I'm hoping one of you guys will be able
to see why it doesn't work and kinda steer me in the right
direction. Anything would be greatly appreciated!
Also any comments on those booleans for camp, dungeon, town?
I don't know if I really needed those and its probably just
an extra bit of useless code but I'm really not sure.
import java.util.Scanner;
public class logic
{
public static void main(String[] args)
{
boolean running = true;
Scanner in = new Scanner(System.in);
System.out.println("This is a test");
while(running)
{
boolean camp = true;
boolean dungeon = false;
boolean town = false;
String input = in.nextLine();
while(camp)
{
System.out.println("what u do?");
System.out.println("1. go dungeon");
System.out.println("2. go town");
System.out.println("3. quit");
if (input.equals("1"))
{
dungeon = true;
while(dungeon)
{
System.out.println("you are in the dungeon");
dungeon = false;
break;
}
}
else if (input.equals("2"))
{
dungeon = false;
town = true;
while(town)
{
System.out.println("you are in the town");
town = false;
break;
}
}
else if (input.equals("3"))
{
break;
}
else
{
System.out.println("invalid command!");
}
}
}
}
}

Personally, I wouldn't use so much while loops and instead put each section's logic into its own function then use an if-else-if / switch statement to decide which function should be called and do this in a while loop, sadly I can't test this because I haven;t got a Java environment and its been a while since I used Java.

This is the new code I came up with. I was able to figure out how to break all the different areas up into their own methods. This should make building the game world much easier :D
import java.util.Scanner;
public class LogicTest
{
Scanner in = new Scanner(System.in);
public static void main(String[] args)
{
LogicTest game;
game = new LogicTest(); // a new instance of the public class folder has to be created in order to use all the other methods
game.run();
}
public void run() // this method is used to run the game from the main method
{
camp();
}
public void quest()
{
System.out.println("you go on quest");
camp();
}
public void town()
{
System.out.println("you go to town");
camp();
}
public void camp() // this method acts as the game hub where the player can choose what they want to do next
{
System.out.println("you are in your camp");
System.out.println("----------------------");
System.out.println("what do you want to do?");
System.out.println("1. go quest");
System.out.println("2. go town");
System.out.println("3. quit");
String input = in.nextLine();
// each one of these options just calls its respective method
// the methods are what have the menus and everything for each location
if (input.equals("1"))
{
quest();
}
else if (input.equals("2"))
{
town();
}
else if(input.equals("3")) // by leaving this empty the program has nothing else to read with this option and so it closes
{
}
else
{
camp();
}
}
}

Related

How to track mouse clicks as input in Java swing

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.

How to restart a program from a method

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);
}

How do I add a keypress action in my program?

I am making a very basic Java based RPG game with many of options as you go along and I want to make it so when you get the ability to type, if you press "x" it will automatically quit the game. I don't want to continuously add the "if-then" statement every time the user progresses.
What I don't want to do: (I would have to do this over 50 times for: inventory, quit game, character information and more)
switch (choice1)
{
case "x":
System.out.println("\nYou quit the game!");
System.exit(0);
break;
}
What I have: (Doesn't work)
import java.util.Scanner;
import java.awt.*;
import java.awt.event.*;
public class TheDungeon extends KeyAdapter
{
public void keyPressed(KeyEvent e) {
char ch = e.getKeyChar();
if (ch == 'a')
{
System.out.println("You pressed A");
}
}
public static void main(String[] args)
{
/* My variables...
*/
System.out.println("e: Check experience and level");
System.out.println("c: Character Information");
System.out.println("i: Inventory");
System.out.println("x: Quit Game");
choice1 = keyboard.nextLine();
switch (choice1)
{
case "x": //This section
System.out.println("\nYou quit the game!"); //here works
System.exit(0); //but I don't
break; //want to add this section
} //every time the user
//progresses.
To use KeyAdapters and/or KeyListeners you will need to construct a Gui in which to add these Adapters/Listners too.
The way you are currently reading in the users action is a valid way to do it for a console app.
Edit Extending on BlakeP's Answer if you have your determineAction method you could have a Map of the text your print out like so then you only need to add the special actions for the keys.
Map<Character, String> actionText = new HashMap<Character, String>();
actionText.put('x', "\nYou quit the game!");
actionText.put('i', "\nInventory Items:\n Things are here");
private void determineAction(char choice) {
System.out.println(actionText.get(choice));
switch (choice1)
{
case "x":
System.exit(0);
break;
}
}
Or you should have another method to do each special action, this will keep your switch shorter and easier to read. Like so
private void determineAction(char choice) {
System.out.println(actionText.get(choice));
switch (choice1)
{
case "x":
doExit();
break;
case "i":
printInventory();
break;
}
}
private void doExit()
{
System.out.println("\nYou quit the game!");
System.exit(0);
}
private void printInventory()
{
System.out.println("\nInventory Items:");
System.out.println("\n Things are here");
}
The KeyAdapter class is meant for GUI apps (notice the AWT package that it is in), and it sounds like you are doing just a console app. As far as I know, there is no "keypress" listener for console apps.
I would suggest putting the switch statement in a method such as "determineAction" and then return what you need (if anything).
Example method:
private void determineAction(char choice) {
switch (choice1)
{
case "x":
System.out.println("\nYou quit the game!");
System.exit(0);
break;
case "i":
System.out.println("\nInventory Items:");
System.out.println("\n Things are here");
break;
}
}
So after every time you ask for the choice, put this line --
determineAction(choice);
And it will run the switch statement without you having to copy it each time.

Relaunch a java console application code

I'm searching on the internet for hours and i cannot find the right answer that works for me.
So.. I made a game called 'seabattle'
After playing that game the console comes with the question to play again.
System.out.println("Well done! " + whosturn.getName() + ". A ship down!" );
System.out.println("Hurraaaaaayyyyy, All boats down!!");
System.out.println("Do you want to play this game again? (y/n) ");
input = scanner.next().toLowerCase();
if(input == "y"){
System.out.println("The game should start again now..");
System.out.println("Butttttttt, I don't know how to...");
}
else{
System.out.println("Thank you for player Battleships!");
System.out.println("See you next time ;)");
}
}
else{
FiredPosition.setDisplayValue('*');
System.out.println("Good job, you hit a ship!");
switchTurn();
}
If the user types y in console. The game should start again.
I read something about Main(args) or something like that.. That didn't work for me because this is another class.
I hope you guys can help me?
Ciaoo
If your main class SeaBattle is currently as this:
public class SeaBattle {
public static void main(String[] args) {
...
}
}
you could change it the following way:
public class SeaBattle {
private static String[] args;
public static void run() {
//do the same than main() previously
}
public static void main(String[] args) {
SeaBattle.args = args;
run();
}
}
Then to relaunch the game,
SeaBattle.run();
A simple answer is: Whatever you do to start the game in the first place, do it again when you detect the 'y'.
However, a more in depth answer involves the use of an object to store and update the game state, it is not fully clear from your description whether you are currently doing this. So if it is a battleships type game the object may contain a 2d array for the game area, and perhaps a variable to store whose turn it is. This object would have an 'initialise' method where you randomly select where the ships are in the game area, set the value for whose turn it is, etc.
Your main method would interact with this object, so it would call the game object's initialise method, and after each turn it would call another method (e.g. 'isGameFinished') to check whether the game is over. The isGameFinished method would check if all of the ships have been destroyed and return true if so. If it returns true, then the user would be prompted for a new game. If they enter 'y', then you can either create a completely new object of the game state or just call the game state's initialise method again. You will then have a new game state to begin a new game with.

extensive symbol/method/variable confusion

I am working on a project that creates a simple text-based adventure game. It's a little complicated, but basically there are about eight rooms in the game, each with a certain item. You can only move in certain directions depending on the room, and the goal is to get to the last room. I have a class called Item, a class called Room, and then the main Game class.
Anyway, I'm having some trouble with my checkForItem and drop methods at this point. I have to check my itemsHeld ArrayList for a certain item, but whenever I type in "item" it says it can't find the symbol item. Similar issues arise with my drop method. Any suggestions? Here is the (very lengthy) code.
import java.util.ArrayList;
public class Game
{
private ArrayList<Item> itemsHeld = new ArrayList<Item>();
private Room planetHarvest;
private Room planetReach;
private Room alphaHalo;
private Room newMombasa;
private Room deltaHalo;
private Room voi;
private Room theArk;
private Room forerunnerShieldWorld;
private Item DMR;
private Item Launcher;
private Item Shotgun;
private Item Health;
private Item Key;
private Room currentLocation;
private String msg;
public Game(){
createRooms();
ArrayList<Item> itemsHeld = new ArrayList<Item>(0);
currentLocation = planetHarvest;
}
private void createRooms(){
DMR = new Item("DMR", "The Designated Marksman Rifle fires a medium-range shot that defeats one enemy at a time.",
10, false);
Launcher = new Item("Launcher", "The rocket launcher fires a long-range rocket that defeats two enemies at a time.",
30, false);
Shotgun = new Item("Shotgun", "The shotgun fires a short-range buckshot blast that defeats one enemy at a time.",
10, false);
Health = new Item("Health", "The health pack heals you if you've been attacked.", 10, true);
Key = new Item("Key", "The Key is the secret to saving the galaxy.", 10000, false);
planetHarvest = new Room("a farming colony at the edge of human-controlled space. Though usually quiet, it has now been disturbed by an invasion from extraterrestrials who call themselves the Covenant. The Covenant will not let you escape without a fight.", DMR);
planetReach = new Room("twenty-seven years in the future. The Covenant has invaded every human colony world and bombarded each one with plasma, reducing the surface to molten glass. Planet Reach is the only human colony that remains. The aliens know their campaign to exterminate humanity is almost over and they show it in their ferocity on the battlefield.", Launcher);
alphaHalo = new Room("a strange, alien, planet-sized ring following your escape from the doomed planet Reach. The inside of the mysterious non-Covenant hoop structure has continents, oceans, ecosystems, breathable atmosphere – and two relentless foes. The Covenant has arrived; so has the Flood, a terrifying alien parasite that will eat both you and the Covenant. On top of that, you learn that this Halo is not just a habitat but also a weapon that will destroy all life in the galaxy if you don’t stop it.", Key);
newMombasa = new Room("an African city on Earth, humanity's last safe haven in the universe. A Covenant invasion force has landed. You’ll need to fend them off and follow them to wherever they’re headed next.", Health);
deltaHalo = new Room("where the Covenant and the Flood are already waiting. The same rules from Alpha Halo apply here, but now you learn that there are a total of eleven Halos and that the only way to stop them all is to shut them down from a structure outside the galaxy called the Ark. Meanwhile, the Covenant is still attacking Earth.", Key);
voi = new Room("The Flood has arrived and is infecting humans and aliens; meanwhile, the Covenant is in civil war and some of the aliens are helping you. Following your escape from Delta Halo, all of the Halos in the galaxy have been put on standby, so if you don’t find the Ark soon then it’s the end of life as we know it.", Shotgun);
theArk = new Room("a massive installation many times bigger than even a Halo. Shutting down the Ark will mean saving the galaxy. However, most of the Covenant and the Flood are still after you. Finish the fight.", Key);
forerunnerShieldWorld = new Room("an artificial planet made by a super-advanced alien civilization that disappeared 100,000 years ago – the makers of the Halos and the Ark. The war against the Covenant is finally over, the Flood has been defeated, and the galaxy is safe. The mysteries of the Forerunners, however, are just beginning to be unraveled.");
planetHarvest.addNeighbor("Slipspace Forward", planetReach);
planetReach.addNeighbor("Slipspace Out", alphaHalo);
alphaHalo.addNeighbor("Slipspace Back", planetReach);
alphaHalo.addNeighbor("Slipspace Forward", newMombasa);
newMombasa.addNeighbor("Slipspace Out", deltaHalo);
newMombasa.addNeighbor("Forward", voi);
deltaHalo.addNeighbor("Slipspace Back", newMombasa);
voi.addNeighbor("Slipspace Out", theArk);
voi.addNeighbor("Back", newMombasa);
theArk.addNeighbor("Slipspace Unknown", forerunnerShieldWorld);
}
private void setWelcomeMessage(){
msg = "You are John-117, an augmented soldier fighting for Earth and its colonies in the year 2552. You battle the Covenant, an alien religious alliance, and the Flood, an alien parasite that infects both humans and Covenant and turns them into zombies. Your battles take you to planetary colonies like Harvest and Reach, ancient alien ring-worlds called Halos, futuristic cities in Africa, and the Halos’ control station called the Ark, located outside the galaxy. The goal of the game is to defeat all enemies and make it to the safety of the Forerunner Shield World.";
}
public String getMessage(){
return msg;
}
public void help(){
msg = "Every place you enter is crawling with Covenent and/or Flood. You'll have to neutralize them before they neutralize you. As a Reclaimer, you're the only one who can use Keys on a Halo or Ark. Some places involve more than one mission.";
}
public void look(){
msg = currentLocation.getLongDescription();
}
public void move (String direction){
Room nextRoom = currentLocation.getNeighbor(direction);
if (nextRoom == null){
msg = "You can't go there.";
}else{
currentLocation = nextRoom;
msg = currentLocation.getLongDescription();
}
}
public void list(){
if(itemsHeld != null){
msg += itemsHeld;
}else{
msg = "You are not holding anything.";
}
}
public boolean gameOver(){
if(currentLocation == forerunnerShieldWorld){
msg = "You defeated the Covenant and survived the war. You won!";
}
return false;
}
public void pickup(){
if(currentLocation.hasItem()){
if(currentLocation.getItem().getWeight() < 50){
msg = "You are now holding the" + currentLocation.getItem().getName();
itemsHeld.add(currentLocation.getItem());
currentLocation.removeItem();
}else{
msg = "This item is too heavy to pick up.";
}
}else{
msg = "There is no item to pick up.";
}
}
private Item checkForItem (String name){
if(itemsHeld.contains(name)){
return ();
}else{
return null;
}
}
public void drop (String item){
if(itemsHeld.contains(item)){
itemsHeld.remove(item);
currentLocation.addItem;
}
}
}
Item is the type in this case. Not the variable name, which is what you want. You have several variables of type Item, but no variables named item.
Also, you have no field named itemsHeld. In your constructor you create a local variable with that name, but a variable by that name on the class is not defined.
Add
private ArrayList<Item> itemsHeld
to your field declarations, and in the constructor do
itemsHeld = new ArrayList<Item>(0);
to initialize it.
Or just do
private List<Item> itemsHeld = new ArrayList<Item>(0);
in your field declarations...
if(!PlayerLocation.hasItem()){
msg = "The player does not have that Item";
}
if(PlayerLocation.hasItem()){
for(Item lookfor: ItemsHeld){
String result = lookfor.getName();
if(result.contains(PlayerLocation.getItem().getName())){
msg = "The room already has an item " +
PlayerLocation.getItem().getName() +
".";
}
}
}
else {
for(Item lookfor: ItemsHeld){
String result = lookfor.getName();
if(result.contains(name)){
dropped = lookfor;
ItemsHeld.remove(lookfor);
PlayerLocation.addItem(dropped);
msg = "the player has successfully" +
"dropped the item in the room";
}
}
}
Idk if we have the same java teacher, but I was googling around
and browsing the interwebs for some answers and came accross your question.
Mine method works for droping the item; however, I'm degubbing my code for if the array list is empty, and has no items for it.

Categories

Resources