2
\$\begingroup\$

I've made quite a long text-based game which I'm quite proud of and would like to know ways in which to improve it! I plan to keep working on it and make it much longer and more complex!

Main:

import java.util.Scanner;
import Saves.GameSave;
import Saves.GenderSave;
public class MainGame {
 public static GameSave gameSave = new GameSave();
 static MaleDate male = new MaleDate();
 static GenderSave genderSave = new GenderSave();
 static FemaleDate female = new FemaleDate();
 public static void main(String[] args) {
 Scanner sc = new Scanner(System.in);
 // NEW GAME
 if (gameSave.loadGame().equals("0")) {
 System.out.println("Welcome to GAME_TEXT:FIRSTDATE.\nWho do you want to date, a boy or a girl? (B/G) ");
 while (true) {
 String gender = sc.nextLine();
 if (gender.equalsIgnoreCase("B")) {
 genderSave.saveGender(gender);
 gameSave.loadGame();
 male.go();
 } else if (gender.equalsIgnoreCase("G")) {
 genderSave.saveGender(gender);
 gameSave.loadGame();
 female.go();
 } else {
 System.out.println("Invalid input. Please type B or G.\n");
 }
 }
 }
 // LOAD SAVED GAME
 else {
 gameSave.loadGame();
 String g = genderSave.loadGender();
 if (g.equalsIgnoreCase("B")) {
 male.go();
 } else if (g.equalsIgnoreCase("G")) {
 female.go();
 }
 }
 }
}

MaleVersion (there's also a Female version, same code but changed name/pronouns):

import java.util.Random;
import java.util.Scanner;
import Saves.GameSave;
import Saves.NameSave;
import Saves.PointsSave;
public class MaleDate {
 public static String user = "";
 public static String name = "";
 public static Scanner scanner = new Scanner(System.in);
 public static String question;
 public static int points;
 public static GameSave gameSave = new GameSave();
 public static PointsSave pointsSave = new PointsSave();
 public static NameSave nameSave = new NameSave();
 public void go() {
 Random random = new Random();
 question = gameSave.loadGame();
 points = pointsSave.loadPoints();
 PointsCalculation pointsCalc = new PointsCalculation();
 name = nameSave.loadName();
 System.out.println("\n\t*** TEXT_GAME: FIRSTDATE ***\n");
 System.out.println("-You can exit the game at any time by typing 'exit'.-");
 System.out.println("-Press Enter to start and advance the game.-\n");
 // IF LOADED SAVED GAME, WELCOME [NAME]
 if (!name.isEmpty()) {
 System.out.println("\nWelcome Back " + name + "\n");
 }
 // RUN GAME
 while (true) {
 user = scanner.nextLine();
 switch (question) {
 case "0":
 System.out.println("You wake up with a hangover the following morning. "
 + "It's currently 11am and all you seem to remember is "
 + "a guy you met at a bar the night before. It's weird how "
 + "you remember this but not your own name.\n\nWhat's your name? ");
 question = "1";
 break;
 case "1":
 if (user.trim().equalsIgnoreCase("exit")) {
 System.exit(1);
 break;
 }
 switch (user) {
 case "":
 System.out.println("\nYou must type your name.");
 question = "1";
 break;
 default:
 System.out.println("\n\nYou are still a bit groggy from the drinks. "
 + "Are you sure this is your name?\n[1]Yes\n[2]No");
 nameSave.saveName(user);
 question = "1A";
 break;
 }
 break;
 case "1A":
 if (user.trim().equalsIgnoreCase("exit")) {
 System.exit(1);
 break;
 }
 switch (user) {
 case "1":
 System.out.println("\n\nAwesome! Let's continue.");
 question = "2";
 break;
 case "2":
 System.out.println("\nAlright! Let's rewind here a little bit!\n");
 nameSave.newName();
 question = "0";
 break;
 default:
 System.out.println("\nI do not understand your request.\n");
 question = "1A";
 break;
 }
 break;
 case "2":
 if (user.trim().equalsIgnoreCase("exit")) {
 System.exit(1);
 break;
 }
 System.out.println("The guy you met last night was nice. You want to "
 + "get back into contact with him. Why don't you check your phone for a number?");
 question = "2A";
 gameSave.saveGame("2A");
 break;
 case "2A":
 System.out.println("You find his phone number under the name 'Ian'. "
 + "You decide to call him but he doesn't pick up. What do you want to do? "
 + "\n[1]Call him again\n[2]Forget him");
 question = "3";
 break;
 case "3":
 if (user.trim().equalsIgnoreCase("exit")) {
 System.exit(1);
 break;
 }
 switch (user) {
 case "1":
 System.out.println("\n\nYou call him again and this time he picks it up! "
 + "You tell him that you had a great time last night and that "
 + "you'd like to take him for coffee. He gladly accepts.");
 points += 2;
 question = "3A";
 pointsSave.savePoints(points);
 gameSave.saveGame("3A");
 break;
 case "2":
 System.out.println("\n\nYou choose to forget about him for now and go " + "meet some friends. ");
 question = "3B";
 gameSave.saveGame("3B");
 break;
 default:
 System.out.println("\nI do not understand your request.\n");
 question = "3";
 break;
 }
 break;
 case "3A":
 System.out.println("It's 3pm. You meet up with Ian at a coffee shop and have "
 + "an awesome time together, but now you have a dilemma. Should you pay the bill, "
 + "should he, or should you split?\n[1]You\n[2]Him\n[3]Split");
 question = "4_Story1";
 break;
 case "3B":
 System.out.println("An hour later, Ian calls you back. He says he's sorry "
 + "for missing your call earlier and wants to make it up to you by "
 + "taking you to the movies. You:\n[1]Accept\n[2]Decline");
 question = "4_Story2";
 break;
 case "4_Story1":
 if (user.trim().equalsIgnoreCase("exit")) {
 System.exit(1);
 break;
 }
 switch (user) {
 case "1":
 System.out.println("\n\nIan is extremely grateful and wants to return the favor next time.");
 points += 2;
 pointsSave.savePoints(points);
 gameSave.saveGame("EndAB_1");
 question = "EndAB_1";
 break;
 case "2":
 System.out.println(
 "\n\nYou let Ian pay and he doesn't seem to mind, but you still feel like you screwed up.");
 pointsSave.savePoints(points);
 gameSave.saveGame("EndAB_1");
 question = "EndAB_1";
 break;
 case "3":
 System.out.println("\n\nYou both agree to split the bill.");
 points++;
 pointsSave.savePoints(points);
 gameSave.saveGame("EndAB_1");
 question = "EndAB_1";
 break;
 default:
 System.out.println("\nI do not understand your request.\n");
 question = "4_Story1";
 break;
 }
 break;
 case "4_Story2":
 if (user.trim().equalsIgnoreCase("exit")) {
 System.exit(1);
 break;
 }
 switch (user) {
 case "1":
 System.out.println("\n\nIan is overjoyed!");
 points++;
 pointsSave.savePoints(points);
 gameSave.saveGame("4B");
 question = "4B";
 break;
 case "2":
 System.out.println("\n\nYou decline and never see Ian again.\nScore: 0\nThanks for playing!");
 gameSave.newGame();
 pointsSave.newPoints();
 nameSave.newName();
 System.exit(1);
 break;
 default:
 System.out.println("\nI do not understand your request.\n");
 question = "4_Story2";
 break;
 }
 break;
 case "4B":
 System.out.println("It's 5pm. You meet up with Ian at the cinema, but you now have a "
 + "dilemma. You want to watch an action movie while he wants to watch a romance."
 + " What do you choose?\n[1]Action movie\n[2]Romance movie\n[3]Use rock, " + "paper, scissors");
 question = "5_Story2";
 break;
 case "5_Story2":
 if (user.trim().equalsIgnoreCase("exit")) {
 System.exit(1);
 break;
 }
 switch (user) {
 case "1":
 System.out.println("\n\nIan pretends not to be bothered but you can tell that he is. "
 + "Nevermind, you still get to enjoy the movie.");
 pointsSave.savePoints(points);
 gameSave.saveGame("EndAB_1");
 question = "EndAB_1";
 break;
 case "2":
 System.out.println(
 "\n\nIan thanks you for choosing his movie and you're just glad that " + "he's so happy.");
 points += 2;
 pointsSave.savePoints(points);
 gameSave.saveGame("EndAB_1");
 question = "EndAB_1";
 break;
 case "3":
 System.out.println("\n\nYou decide using rock, paper, scissors but you're out of luck."
 + " Ian wins and you end up watching the love story he wanted.");
 points++;
 pointsSave.savePoints(points);
 gameSave.saveGame("EndAB_1");
 question = "EndAB_1";
 break;
 default:
 System.out.println("\nI do not understand your request.\n");
 question = "5_Story2";
 break;
 }
 break;
 case "EndAB_1":
 System.out.println("It's late and you have to get home soon. How do you want to say goodbye to Ian?"
 + "\n[1]Handshake\n[2]Hug\n[3]Kiss");
 question = "EndAB_2";
 break;
 case "EndAB_2":
 if (user.trim().equalsIgnoreCase("exit")) {
 System.exit(1);
 break;
 }
 switch (user) {
 case "1":
 System.out.println("\n\nYou guys shake hands and agree to hang out again sometime.");
 points++;
 pointsSave.savePoints(points);
 pointsCalc.getResults(points);
 gameSave.newGame();
 pointsSave.newPoints();
 nameSave.newName();
 System.exit(1);
 break;
 case "2":
 System.out.println(
 "\n\nIan gladly hugs you back and says that he'd like to hang out with you again soon.");
 points += 2;
 pointsSave.savePoints(points);
 pointsCalc.getResults(points);
 gameSave.newGame();
 pointsSave.newPoints();
 nameSave.newName();
 System.exit(1);
 break;
 case "3":
 int number = random.nextInt(10);
 if (number > 4) {
 System.out.println("\n\nIan kisses you back and says that he really likes you.");
 points += 3;
 } else {
 System.out.println("\n\nIan stops you when you try to kiss him and says that he "
 + "had a nice time with you but prefers to take things slowly.");
 points--;
 }
 pointsSave.savePoints(points);
 pointsCalc.getResults(points);
 gameSave.newGame();
 pointsSave.newPoints();
 nameSave.newName();
 System.exit(1);
 break;
 default:
 System.out.println("\nI do not understand your request.");
 question = "EndAB_2";
 break;
 }
 break;
 default:
 break;
 }
 }
 }
}

PointsCalculation:

public class PointsCalculation {
 public void getResults(int points) {
 if (points < 4) {
 System.out.println(
 "\nScore: " + points + " out of 7." + "\nSorry, you didn't do so well! Thanks for playing.");
 } else if (points < 6) {
 System.out.println("\nScore: " + points + " out of 7." + "\nNice! You did quite well! Thanks for playing.");
 } else {
 System.out.println(
 "\nScore: " + points + " out of 7." + "\nCongrats! You were FANTASTIC! Thanks for playing.");
 }
 }
}

GameSave (there's also GenderSave, NameSave and PointsSave, all similar code).

package Saves;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class GameSave {
 public static Properties prop = new Properties();
 public void saveGame(String point) {
 try {
 prop.setProperty("Save_Point", point);
 prop.store(new FileOutputStream("config_Game.prop"), null);
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 public String loadGame() {
 String line = "";
 try {
 prop.load(new FileInputStream("config_Game.prop"));
 line = prop.getProperty("Save_Point");
 } catch (IOException e) {
 try {
 prop.setProperty("Save_Point", "0");
 prop.store(new FileOutputStream("config_Game.prop"), null);
 try {
 prop.load(new FileInputStream("config_Game.prop"));
 line = prop.getProperty("Save_Point");
 } catch (IOException exe) {
 exe.printStackTrace();
 }
 } catch (IOException ex) {
 ex.printStackTrace();
 }
 }
 return line;
 }
 public void newGame() {
 try {
 prop.setProperty("Save_Point", "0");
 prop.store(new FileOutputStream("config_Game.prop"), null);
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jan 11, 2017 at 12:48
\$\endgroup\$
3
  • 2
    \$\begingroup\$ One quick comment, in load_game, you assume that any io exception means the file doesn't exist, so you try and create a new save file. What if the io exception was out of space, or controller error? Exceptions are for exceptional circumstances, not expected ones like first save. Just check the save file is there, if not load some defaults. What if I'm playing the game on a r/o file system? Just trying to load the game will fail. \$\endgroup\$ Commented Jan 11, 2017 at 13:22
  • \$\begingroup\$ @Neil I'm not sure I follow. I know very little about exceptions, what should I change? Should I include other exceptions above try{ after first catch? And why would my program not run on linux? :/ \$\endgroup\$ Commented Jan 11, 2017 at 13:28
  • \$\begingroup\$ If you don't understand exceptions, then I suggest you remove them from your program until you do. Exception handling code should never be required (big statement I know, but for simple programs, it should be the case).. For example, you should not use exception handling to find out if a file doesn't exist, just check it exists before you use it. \$\endgroup\$ Commented Jan 11, 2017 at 14:13

1 Answer 1

1
\$\begingroup\$

This is quite well done as a first shot.

pros

  • naming conventions almost met
  • Separation of Concerns (created classes with specific scope)

cons

here is something to improve:

Naming of Packages

package name Saves should be all lowercase, especially the first letter -> saves.

BTW: the main class should also live in a package, e.g.: mygame.

Just for info: Usually package hierarchy start with the naming pattern [COUNTRY_CODE].[COMPANY_NAME].[PROJECT]

literal strings within code

You have lots of strings within your code. This makes your code somewhat hard to read and prevents to change the language of the game later.

You should use the same technique you used for saving the points and load the strings from a *.properties file.

The keys in this properties file could be the string you used in the case statements.

storing the strings to display in a file rather then among the code is called "externalization".

classes

MaleVersion (there's also a Female version, same code but changed name/pronouns).

You state that both MaleDate and FemaleDate have the same code but different properies (here they use different strings).

This is no reason for creating different classes.

You create classes when the behavior differs. This is not the case with your MaleDate and FemaleDate class.

If you store the display textx in tow different files, one female version and one male version, you would need only one class. You would create two instances of the same class and give it different files to load.

code duplication

Your game has lots of repeated code. This should really be reduced.

At some points it's rather simple as in the main method:

 while (true) {
 String gender = sc.nextLine();
 if (gender.equalsIgnoreCase("B")) {
 genderSave.saveGender(gender);
 gameSave.loadGame();
 male.go();
 } else if (gender.equalsIgnoreCase("G")) {
 genderSave.saveGender(gender);
 gameSave.loadGame();
 female.go();
 } else {
 System.out.println("Invalid input. Please type B or G.\n");
 }
 }

after applying the previous points you have your variables female and male being of same Type. Object of same type could be stored in a collection like a Map.

Then you could get the object out of the map and call the method go on it:

public class MainGame {
 public static GameSave gameSave = new GameSave();
 //static MaleDate male = new MaleDate();
 static GenderSave genderSave = new GenderSave();
 //static FemaleDate female = new FemaleDate();
 // pretent the unification of MaleDate and FemaleDate is UserDate...
 static Map<String,UserDate> userDates; = new HashMap<>();
 public static void main(String[] args) {
 userDates.put("M",new UserDate("male_texts.properties"));
 userDates.put("G",new UserDate("female_texts.properties"));
 // NEW GAME
 if (gameSave.loadGame().equals("0")) {
 System.out.println("Welcome to GAME_TEXT:FIRSTDATE.\nWho do you want to date, a boy or a girl? (B/G) ");
 while (true) {
 String gender = sc.nextLine().toUpperCase();
 if(userDates.cntainsKey(gender))
 UserDate userDate = userDates.get(gender);
 genderSave.saveGender(gender);
 gameSave.loadGame();
 userDate.go();
 } else {
 System.out.println("Invalid input. Please type B or G.\n");
 }
 // rest of the code

the duplication in MaleVersion could be reduces in a similar way.

answered Jan 11, 2017 at 18:48
\$\endgroup\$
2
  • \$\begingroup\$ Note: if your package reversed is a valid domain (ex. com.cad97.textgame -> http://textgame.cad97.com) you should only use it if you own the domain. Packages are done this way to minimize the chance of conflicts. (Though Java9's module system makes that a non-issue (or at least less of one).) docs.oracle.com/javase/tutorial/java/package/namingpkgs.html \$\endgroup\$ Commented Jan 11, 2017 at 20:16
  • \$\begingroup\$ @Timothy Truckle Thanks a lot man!! So good advice, will work on it all thank you! \$\endgroup\$ Commented Jan 11, 2017 at 22:59

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.