8
\$\begingroup\$

I'm making a text based java game to help me learn java. I would like to know if I am doing things ok and if there is a better way to do the things I'm doing thanks. I have two separate files.

adventure.java

package sam;

import java.util.Scanner;

public class Adventure extends TheGame{

public static void main(String[] args) {

    @SuppressWarnings("resource")
    Scanner input = new Scanner(System.in);


    System.out.println("Welcome to my adventure game, in this game you have certain quests and you can pick options each time. There is shops where you can buy wepons and where you can upgrade damage."
            + "In the shops it will ask you to pick numbers that go with each wepon and the wepons cost money. If you press a number that isnt on the shop then you will skip that part with no wepon or "
            + "upgrades so you will probably lose. ");
    System.out.println("--------------------------------");

    System.out.println("What is your name: ");
    String name = input.next();
    System.out.println("--------------------------------");

    System.out.println("Hello " + name + " Would you like to start type 1 if you would");
    int Wantstostart = input.nextInt();
    if(Wantstostart==1){
        System.out.println("Ok lets start then");
        System.out.println("--------------------------------");
        System.out.println("--------------------------------");
        Start(null);
    }




}

}

the second is TheGame.java

package sam;

import java.util.Scanner;

import org.omg.Messaging.SyncScopeHelper;


public class TheGame {

public static void Start(String args[]){

    //Scanner
    @SuppressWarnings("resource")
    Scanner input = new Scanner(System.in);

    //Money and things
    int money = 20;
    @SuppressWarnings("unused")
    boolean Sword = false;
    @SuppressWarnings("unused")
    boolean Axe = false;
    int damage = 0;
    double health = 1;



    //first question

    System.out.println("Hello what would you like to buy");
    System.out.println("--------------------------------");
    System.out.println("we sell a sword and an axe");
    System.out.println("if you would like to buy axe press 1 and it will cost 10(+2 damge) and if you want to buy a sword(+3 damage) press 2 and it will cost 12");
    System.out.println("--------------------------------");
    System.out.println("--------------------------------");
    int ATB1 = input.nextInt();
    if(ATB1==1){
        money = money - 10;
        System.out.println("You have " + money + " pound left");
        Axe = true;
        damage = damage + 2;
        System.out.println("You have an axe now");
        System.out.println("--------------------------------");
        System.out.println("--------------------------------");
    }




    if(ATB1==2){
        money = money - 12;
        System.out.println("You have " + money + " pound left");
        Sword = true;
        damage = damage + 3;
        System.out.println("You have a sword now");
        System.out.println("--------------------------------");
        System.out.println("--------------------------------");

        }
    //first boss
    System.out.println("You came agasint the first boss if you have more then 1 damage you will surely win!!!!!");
    System.out.println("Hope you got that wepon");
    System.out.println("--------------------------------");
    System.out.println("--------------------------------");
    if(damage>1){
        System.out.println("Well done you beat the first boss!!");
        System.out.println("--------------------------------");
        System.out.println("--------------------------------");
    }
    else if(damage<=0){
        System.out.println("Unlucky you lost");
        System.out.println("--------------------------------");
        System.out.println("--------------------------------");
        System.exit(0);


    }

    //first random event
    System.out.println("You see a homeless man on the streets will you spare 5 pound press 1 for yes or 2 for no: ");
    System.out.println("--------------------------------");
    System.out.println("--------------------------------");
    int FRE1= input.nextInt();

    if(FRE1==1){
        System.out.println("He thanks you and gives you a new sword upgrade (+1 damge) but you have 5 less pound");
        money = money -5;
        damage = damage + 1;
        System.out.println("You now have " + money + " pound left");
        System.out.println("You now have " + damage + " damage");

    }
    if(FRE1==2){
        System.out.println("You walk by him without paying him he tells you you will regreat it later");
        System.out.println("You now have " + money + " pound left");
        System.out.println("You now have " + damage + " damage");

    }
    //first job

    System.out.println("--------------------------------");
    System.out.println("--------------------------------");
    System.out.println("You are worried you are running low on money, you get offered a job,(+ 5 money) but itwill lower you health by half as you will be tired");
    System.out.println("Health is very important as when you come to fight bosses health is a mutilpler to add to damge if you have half health you will do half damage.");
    System.out.println("Would you like to take the job (+5 money -half health) press 1 if yes 2 if no: ");
    int Job1 = input.nextInt();

    if(Job1==1){
        System.out.println("You took the job so you have +5 money but half health");
        money = money + 5;
        health = health - 0.5;
        System.out.println("You now have " + money + " pound left");
        System.out.println("You now have " + damage + " damage");
        System.out.println("You now have " + health + " health");


    }


    if(Job1==2){
        System.out.println("You didnt take the job so you gained or loss nothing.");
        System.out.println("You now have " + money + " pound left");
        System.out.println("You now have " + damage + " damage");
        System.out.println("You now have " + health + " health");


    }
    //second boss
    System.out.println("--------------------------------");
    System.out.println("--------------------------------");
    System.out.println("Second boss if you have 2 damage or more you will win. unless your health is too low.");
    if(damage*health>=2){
        System.out.println("You cleared the second boss");
        System.out.println("--------------------------------");
        System.out.println("--------------------------------");

    }

    if(damage*health<2){
        System.out.println("you loss due to not enough damage or your health was too low.");
        System.out.println("--------------------------------");
        System.out.println("--------------------------------");
        System.exit(0);
    }

    }














}   
\$\endgroup\$
  • 1
    \$\begingroup\$ What is org.omg.Messaging.SyncScopeHelper, and why are you importing it? \$\endgroup\$ – 200_success Nov 21 '16 at 17:58
  • \$\begingroup\$ umm I'm not sure why I imported it I will get rid off it. Thanks for noticing it. \$\endgroup\$ – Sam Head Nov 21 '16 at 18:01
  • 3
    \$\begingroup\$ Aw, shucks. I was hoping that this was the beginning of some CORBA-based enterprise-class adventure game. \$\endgroup\$ – 200_success Nov 21 '16 at 18:02
  • \$\begingroup\$ no lol I must have imported it by accident. I'm new to java and I don't even know what it does. \$\endgroup\$ – Sam Head Nov 21 '16 at 18:05
4
\$\begingroup\$

Usually I start with pros, but I didn't find any. Sorry...

cons

General coding

You have only static methods. Java is an object oriented programming language, so get used to use objects. You may later find the benefits of it when it comes to polymorphism.

Naming

You don't use Java Naming conventions which is in general:

  • Identifiers use CamelCaseNaming except constants which are all UPPER_CASE.
  • Class names begin with capital letter.
  • Methods and variables begin with a lower case letter.
  • Methods begin with a "do" word (a verb).
  • Variables are "thing" words (nouns).

Inheritance

Your class Adventure extends your TheGame class. This looks OK at first glance since you schould use inheritance when you have an "is a" relationship which is obviously true for Adventure and TheGame by means of the words.

But if we look closer to what the classes really do then it is false: Adventure is only launching TheGame so its name is misleading and the inheritance is not justified.

Code duplication

This code has lots of duplicated code.

This should be extracted to parameterized methods.

\$\endgroup\$
  • \$\begingroup\$ thanks for the advice and yeh I know the code is awful but I only started java like a week ago and I am trying to teach my self. \$\endgroup\$ – Sam Head Nov 21 '16 at 17:24
  • \$\begingroup\$ @SamHead you should try the Java tutorials: docs.oracle.com/javase/tutorial \$\endgroup\$ – Timothy Truckle Nov 21 '16 at 17:26
  • \$\begingroup\$ Why "Methods begin with a "do" word"? Methods do represent an action being performed on an object but I've never seen that their name should start with "do". In fact, if they do, I'd find that a bit weird; methods called doStuff() are not very descriptive. \$\endgroup\$ – Tunaki Nov 21 '16 at 17:40
  • \$\begingroup\$ @Tunaki given the context of the variables are things, I think he is referring to doing/action/verb words, rather than the actual word do. \$\endgroup\$ – forsvarir Nov 21 '16 at 17:56
  • \$\begingroup\$ @forsvarir Ah yes, I didn't read it that way, thanks, this makes sense. \$\endgroup\$ – Tunaki Nov 21 '16 at 17:57
3
\$\begingroup\$

SuppressWarnings

Compiler warnings are there for a reason, it's quite rare that you will encounter a good reason for suppressing them. Where possible, you should try to do what the warning is asking you to do (such as cleaning up after the Scanner).

Player

It feels a lot like your code is missing the concept of a Player/Adventurer. This could include properties such as:

  • Name
  • Money
  • CurrentHealth
  • MaximumHealth
  • Weapon

Not only will this collect related data in one spot, it will make it easier to keep track of that information across method/class boundaries. At the moment, you get the players name in your main, say hi and then forget about it. Creating a Player and passing it to your TheGame method would allow the name to be used in future interactions.

Unused Arguments

Your Start method takes an args parameter, which you're not currently using. In fact you're passing null as the parameter when calling it from main. When you're writing fresh code, it's tempting to introduce concepts because you might need them in the future. Usually it's a bad idea. It is more productive to try to only introduce code as and when required. If you stop using code / parameters remove it straight away. This helps to minimise the complexity of your application. If you're worried about losing work / getting yourself into a state that you can't undo then consider using a source control system. Something like git allows you to commit regularly and rollback to previous versions if required.

Variable Naming

As you get more code, naming becomes increasingly important. If methods, classes and variables are well named they help the code to tell a story that describes what it's doing. This reduces the need for comments and makes your code much more approachable. Consider this line:

if(ATB1==1)

What does it mean? Is the meaning of ATB1 obvious? Something like itemToBuy might be a bit more descriptive.

What do I start with?

Consider telling the player what their starting point is. At the moment, the first time they found out how much money they have is after they have decided to buy an Axe or a Sword.

Typo's and telling a story

You have some grammar/spelling errors in your text. For example ('wepon' and 'isnt') in the following:

"In the shops it will ask you to pick numbers that go with each wepon and the wepons cost money. If you press a number that isnt on the shop then you will skip that part with no wepon or "

It may be that you're doing it as part of setting the environment, or it may that you've simply made typos (I automatically type 'byte' whenever I try to type 'bye' then have to correct it). Either way, the more text you embed in your program, the more likely it is that you're going to encounter errors. If you push a lot of the text out of the application into a text file, it can be easier to validate the text using something like a word processor. The process of moving the descriptive text to an external resource can also help to identify what is common and what is different between your different interactions. This can help to direct your file format & your code structure.

So, for example you might have a file structure something like:

<Interactions>
    <Interaction Id="1">
        <Text>Hello what would you like to buy
              we sell a sword and an axe
              if you would like to buy axe press 1 and it will cost 10(+2 damge) and if you want to buy a sword(+3 damage) press 2 and it will cost 12
        </Text>
        <Choices>
            <Choice input="1">2</Choice>
            <Choice input="2">3</Choice>
            <DefaultChoice>4</DefaultChoice>
        <Choices>
    </Interaction>
    <Interaction Id="2">
        <Text>You have an axe!</Text>
        <Choices>
            <DefaultChoice>4</DefaultChoice>
        <Choices>
    </Interaction>
    <Interaction Id="3">
        <Text>You have a sword!</Text>
        <Choices>
            <DefaultChoice>4</DefaultChoice>
        <Choices>
    </Interaction>
    <Interaction Id="4">
        <Text>The End!</Text>
    </Interaction>
<Interactions>

This defines interactions and choices which lead to the next interaction. You can then add extra information like Mobs/Bosses, effects on stats etc etc and fairly easily rearrange your adventure. You can introduce well known tokens into your text which are expanded by the code (such as Player.Name, Player.Weapon etc). Your code then becomes more focused on representing the structure and walking through it.

Taking this sort of approach makes it possible to move towards a database back-end for representing the scenarios (if you want to learn about accessing databases from Java). IT also makes it possible for you to use the same game engine to tell different adventures by simply using a different text file.

\$\endgroup\$
  • \$\begingroup\$ thanks for the advice i have improved it since with some new methods because before i had duplicate code. l will improve it again and start using choices and interactions i will re post when i have done it thanks. @forsvarir \$\endgroup\$ – Sam Head Nov 23 '16 at 10:33
3
\$\begingroup\$

The only thing I can think of is rather minor, but it might help a little bit: consider making a short method that calls System.out.println():

void print(String string) { System.out.println(string); }

Also helpful, you can use "\n" for a new line. Thus:

    print("You didn't take the job so you gained or lost nothing."
        + "\nYou now have " + money + " pound left"
        + "\nYou now have " + damage + " damage"
        + "\nYou now have " + health + " health");

I'm wondering if you can come up with a basic way to make the story segments into a class structure.

As long as the story is short, it doesn't matter a whole lot. I'm not into making objects just for the sake of making objects because the language is OO. There should be some clear purpose being served for going to the trouble.

I haven't programmed a word-adventure game before, so I don't know the common structures used. But as you go on, if you find yourself repeating anything, there is most likely a way to code it so that you can avoid the repetition.

For example, maybe set up a method or class that prints the status information.

printPlayerStatus()
{
     print( "You now have " + money + " pound left"
        + "\nYou now have " + damage + " damage"
        + "\nYou now have " + health + " health");
}

Then you can call this periodically instead of writing all three lines repeatedly. That sort of thing.

The folks at Java-gaming.org may have some advice on how to structure a text-adventure game. There is a lot of game-making expertise there.

\$\endgroup\$
1
\$\begingroup\$

It would be better practice to separate your I/O from your game logic. Your Adventure Class should not create its own Scanners and manually call System.out.println.

The game class should take an input stream of sorts and an output stream of sorts. Then, the class's methods would pull input from the input stream and then give output to the output stream. This allows for purely game logic to be in your game adventure class.

The main method could pass in a Scanner and System.out to the game class upon instantiation. Then, you could create unit testing classes and manually create and fill input streams so that you can control the behavior of the class automatically.

\$\endgroup\$
1
\$\begingroup\$

I would suggest creating a method for text so you don't have System.out.println every time, but instead have something like text("Text here..."); or something similar. This is done with the following:

public static void text(String text) {
    System.out.println(text);
}

And to call the method, you type text("Text here");, like mentioned above. This may make the file size a little smaller and make it much faster to type a text output.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.