I'm trying to follow as many OO concepts as possible. This project is for my github, as a means to enhance my portfolio for possible internships in the future.
Question 1: Is there anything that's declared static that shouldn't be?
Question 2: Should I have created a constructor for the Dungeon class, that way each dungeon is its own instance instead of have a factory make it every time?
Some notes about the program:
I generate a 30x30 array of Room objects, which also randomly generate a random monster in each room. As of now, the player can select new game, and pick a character. From there, they spawn in the middle room [14][14] where they fight each monster and can move room to room.
Any general tips or advice about the code of the program would be greatly appreciated!
ProjectMoria class:
package projectmoria;
import java.util.Random;
import java.util.Scanner; //needed for user_input
public class ProjectMoria {
public static final Scanner USERINPUT = new Scanner(System.in);
public static final Random RAND = new Random();
public static Room[][] currDungeon;
public static Player currPlayer;
public static void main(String[] args) {
mainMenu();
}
public static void mainMenu() {
boolean status = false;
do {
IO.Welcome();
String selection = USERINPUT.nextLine();
switch (selection) {
case "1":
newGame();
status = true;
break;
case "2":
loadGame();
status = true;
break;
case "3":
settings();
status = true;
break;
case "4":
IO.credits();
status = true;
break;
case "5":
System.exit(0);
}
} while (status == false);
}
public static void newGame() {
Dungeon dungeon = new Dungeon();
boolean status = false;
do {
IO.newGameIntroduction();
String selection = USERINPUT.nextLine();
switch (selection) {
case "1":
status = IO.displayPlayerStats("Warrior", "A tough, "
+ "well-rounded fighter with a balanced skillset.",
100, 20, 30, 3, 0.10);
currPlayer = Player.newWarrior();
break;
case "2":
status = IO.displayPlayerStats("Dueler", "A quick, nimble "
+ "duelist with an aptitude for landing critical "
+ "attacks.", 80, 10, 50, 2, 0.18);
currPlayer = Player.newDuelist();
break;
}
} while (status == false);
currDungeon = Dungeon.newRandomDungeon(currPlayer);
dungeon.dungeonLogic(currPlayer, currDungeon);
}
public static void loadGame() {
}
public static void settings() {
}
}
Dungeon class:
package projectmoria;
public final class Dungeon {
private static boolean northDirection = false;
private static boolean southDirection = false;
private static boolean westDirection = false;
private static boolean eastDirection = false;
public static Room[][] newRandomDungeon(Player player) {
Room[][] dungeon = new Room[30][30];
for (int i = 0; i < dungeon.length; i++) {
for (int j = 0; j < dungeon.length; j++) {
dungeon[i][j] = Room.newRoomInstance();
}
}
player.setCurrRoom(dungeon[14][14]);
return dungeon;
}
public boolean roomExists(int x, int y) {
return (rowExists(x)) && (colExists(y));
}
public boolean rowExists(int x){
return (x >= 0) && (x <= 29);
}
public boolean colExists(int y){
return (y >= 0) && (y <= 29);
}
public void playerMovement(Player player) {
northDirection = roomExists(player.getCurrX(), player.getCurrY()
+ 1);
southDirection = roomExists(player.getCurrX(), player.getCurrY()
- 1);
eastDirection = roomExists(player.getCurrX() + 1,
player.getCurrY());
westDirection = roomExists(player.getCurrX() - 1,
player.getCurrY());
IO.movePlayer(player);
}
public void battle(Player player, Monster monster, Room[][] dungeon) {
IO.battleIntro(player, dungeon[player.getCurrX()][player.getCurrY()]);
IO.battle(player, monster);
}
public void dungeonLogic(Player player, Room[][] dungeon) {
while (player.isAlive()) {
if (player.isAlive() && dungeon[player.getCurrX()][player.getCurrY()]
.getMonster().isAlive()) {
battle(player, dungeon[player.getCurrX()][player.getCurrY()]
.getMonster(), ProjectMoria.currDungeon);
} else if (player.isAlive()) {
playerMovement(player);
}
}
}
public static boolean isNorthDirection() {
return northDirection;
}
public static boolean isSouthDirection() {
return southDirection;
}
public static boolean isWestDirection() {
return westDirection;
}
public static boolean isEastDirection() {
return eastDirection;
}
}
IO class:
package projectmoria;
import java.io.*;
public final class IO {
public static void playerCrit() {
System.out.println("Nice! You landed a critical hit! (x2 Damage)");
}
public static void monsterCrit() {
System.out.println("Ouch! The monster landed a critical hit! "
+ "(x2 Damage)");
}
public static void Welcome() {
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
System.out.println("Welcome traveler.......");
System.out.println("To the mines of Moria! ");
System.out.println("-----------------------");
System.out.println(" MAIN MENU ");
System.out.println("_______________________");
System.out.println();
System.out.println(" 1. New Game ");
System.out.println();
System.out.println(" 2. Load Game ");
System.out.println();
System.out.println(" 3. Settings ");
System.out.println();
System.out.println(" 4. Credits ");
System.out.println();
System.out.println(" 5. Exit Game ");
System.out.println();
System.out.print(" Make a Selection: ");
System.out.println();
System.out.println();
System.out.println();
}
public static void newGameIntroduction() {
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
System.out.println("------------------");
System.out.println("CHOOSE A CHARACTER");
System.out.println("------------------");
System.out.println();
System.out.println("1. WARRI0R");
System.out.println("----------");
System.out.println("A tough, well-rounded fighter with"
+ " a balanced skillset.");
System.out.println();
System.out.println("2. DUELIST");
System.out.println("----------");
System.out.println("A quick, nimble duelist with an"
+ "aptitude for landing critical attacks.");
System.out.println();
System.out.println("________________________");
System.out.print("Choose Either Character: ");
System.out.println();
System.out.println();
System.out.println();
}
public static boolean displayPlayerStats(String name, String description,
int maxHitPoints, int minDamage, int maxDamage, int defense,
double critChance) {
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
System.out.println(name);
System.out.println("-------");
System.out.println(description);
System.out.println();
System.out.println("MAX HP: " + maxHitPoints);
System.out.println();
System.out.println(
"ATTACK: " + minDamage + "-" + maxDamage);
System.out.println();
System.out.println("DEFENSE(Scale:1-5): " + defense);
System.out.println();
System.out.println("CRIT CHANCE: " + critChance + "%");
System.out.println();
System.out.println("ARE YOU SURE YOU WANT TO PLAY AS A "
+ name.toUpperCase() + "? "
+ "(y/n)");
System.out.println();
System.out.println();
System.out.println();
if (ProjectMoria.USERINPUT.nextLine().equals("y")) {
return true;
} else {
return false;
}
}
public static void credits() {
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
System.out.println("This game was created by Jackson Kolb.");
System.out.println("Would you like to return to the main menu? (y/n)");
if (ProjectMoria.USERINPUT.nextLine().equals("y")) {
ProjectMoria.mainMenu();
}
}
public static void movePlayer(Player player) {
if (Dungeon.isNorthDirection() == true) {
System.out.println("North (n)\n");
}
if (Dungeon.isSouthDirection() == true) {
System.out.println("South (s)\n");
}
if (Dungeon.isEastDirection() == true) {
System.out.println("East (e)\n");
}
if (Dungeon.isWestDirection() == true) {
System.out.println("West (w)\n");
}
System.out.print("Where would you like to travel?: ");
String selection = ProjectMoria.USERINPUT.nextLine();
if (selection.equals("n") && Dungeon.isNorthDirection()) {
player.setCurrY(player.getCurrY() + 1);
} else if (selection.equals("s") && Dungeon.isSouthDirection()) {
player.setCurrY(player.getCurrY() - 1);
} else if (selection.equals("e") && Dungeon.isEastDirection()) {
player.setCurrX(player.getCurrX() + 1);
} else if (selection.equals("w") && Dungeon.isWestDirection()) {
player.setCurrX(player.getCurrX() - 1);
}
}
public static void battleIntro(Player player, Room room) {
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
System.out.println("You arrive at Room [" + player.getCurrX() + "]["
+ player.getCurrY() + "]");
System.out.println("You enter the room and look around and see...");
System.out.println(room.getDescription() + "\n\n");
System.out.println("Number of monsters: " + room.getNumOfMonsters());
System.out.println("Your fight with " + room.getMonster().getName()
+ " begins.\n");
}
public static void battle(Player player, Monster monster) {
while (player.isAlive() && monster.isAlive()) {
System.out.println("\nMonster HP: " + monster.getHitPoints()
+ " " + "Player HP: " + player.getHitPoints());
System.out.println("----------------------------------");
System.out.print("\nAttack (a) Heal (h)");
String action = ProjectMoria.USERINPUT.nextLine();
if (action.equals("a")) {
monster.defend(player);
if (monster.isAlive()) {
player.defend(monster);
}
}
}
if (!player.isAlive()) {
System.out.println("Your lifeless body hits the floor. GAME OVER");
} else if (!monster.isAlive()) {
System.out.println("The monster has been defeated!");
System.out.println("--------------------------------\n");
}
}
public static void playerHitPointsMessage(int damage, Monster monster) {
System.out.println("The " + monster.getName() + " hit you for "
+ damage + " damage.");
}
public static void monsterHitPointsMessage(int damage, Monster monster) {
System.out.println("You hit the " + monster.getName()
+ " for " + damage + " damage.");
}
}
Player class:
package projectmoria;
import java.util.ArrayList;
import java.util.List;
public class Player {
private final String name;
private final String description;
private final int maxHitPoints;
private int hitPoints;
private final int minDamage;
private final int maxDamage;
private final int defense;
private double critChance;
private int currX;
private int currY;
private Room currRoom;
private List<Item> inventory;
public Player(String name, String description, int maxHitPoints,
int minDamage, int maxDamage, int defense, double critChance) {
this.name = name;
this.description = description;
this.maxHitPoints = maxHitPoints;
this.hitPoints = maxHitPoints;
this.minDamage = minDamage;
this.maxDamage = maxDamage;
this.defense = defense;
this.critChance = critChance;
this.currX = 14;
this.currY = 14;
inventory = new ArrayList<>();
}
public int attack() {
return ProjectMoria.RAND.nextInt(maxDamage - minDamage + 1);
}
public int defend(Monster monster) {
int incomingAttack = monster.attack();
int random = ProjectMoria.RAND.nextInt(99) + 1;
if (random <= monster.getCritChance()) {
incomingAttack = incomingAttack * 2;
IO.monsterCrit(); //TODO - move to different spot
}
IO.playerHitPointsMessage(incomingAttack, monster);
hitPoints = (hitPoints * defense > incomingAttack)
? hitPoints - incomingAttack : 0;
return hitPoints;
}
public void heal(Item potion){
this.hitPoints =+ 20;
inventory.remove(potion);
IO.heal(this.hitPoints);
}
public static Player newWarrior() {
return new Player("Warrior", "A tough, well-rounded fighter with"
+ " a balanced skillset.", 100, 20, 30, 3, 10);
}
public static Player newDuelist() {
return new Player("Duelist", "A quick, nimble duelist with an"
+ " aptitude for landing critical attacks.", 8000, 10, 50, 2,
18);
}
public String getDescription() {
return description;
}
public int getHitPoints() {
return hitPoints;
}
public boolean isAlive() {
return hitPoints > 0;
}
public String getName() {
return name;
}
public int getMaxHitPoints() {
return maxHitPoints;
}
public int getMinDamage() {
return minDamage;
}
public int getMaxDamage() {
return maxDamage;
}
public int getDefense() {
return defense;
}
public double getCritChance() {
return critChance;
}
public int getCurrX() {
return currX;
}
public int getCurrY() {
return currY;
}
public List<Item> getInventory() {
return inventory;
}
public Room getCurrRoom() {
return currRoom;
}
public void setCurrRoom(Room room) {
currRoom = room;
}
public void setCurrX(int currX) {
this.currX = currX;
}
public void setCurrY(int currY) {
this.currY = currY;
}
}
Monster class:
package projectmoria;
import java.util.Random;
public class Monster {
private final String name;
private final String description;
private final int maxHitPoints;
private int hitPoints;
private final int minDamage;
private final int maxDamage;
private final int defense;
private final double critChance;
private boolean aggression;
private static final Random rand = new Random();
public Monster(String name, String description, int maxHitPoints,
int minDamage, int maxDamage, int defense, double critChance,
boolean aggression) {
this.name = name;
this.description = description;
this.maxHitPoints = maxHitPoints;
this.hitPoints = maxHitPoints;
this.minDamage = minDamage;
this.maxDamage = maxDamage;
this.defense = defense;
this.critChance = critChance;
this.aggression = aggression;
}
public int attack() {
return rand.nextInt(maxDamage - minDamage - 1);
}
public int defend(Player player) {
int incomingAttack = player.attack();
int random = rand.nextInt(99) + 1;
if (random <= player.getCritChance()) {
incomingAttack = incomingAttack * 2;
IO.playerCrit();
}
IO.monsterHitPointsMessage(incomingAttack, this);
hitPoints = (hitPoints * defense > incomingAttack)
? hitPoints - incomingAttack : 0;
return hitPoints;
}
public static Monster newRandomMonster() {
int random = rand.nextInt(4) + 1;
Monster monster = null;
switch (random) {
case 1:
monster = newGoblin();
break;
case 2:
monster = newOrc();
break;
case 3:
monster = newShadowAssassin();
break;
case 4:
monster = newFeralGhoul();
break;
}
return monster;
}
public static Monster newGoblin() {
return new Monster("Goblin", "A grotesque, small enemy with a sub-par "
+ "skill-set. ", 30, 10, 15, 2, 10, true);
}
public static Monster newOrc() {
return new Monster("Orc", "A brutish, green mass of destruction. High "
+ "Attack and Defense.", 50, 15, 20, 3, 10, true);
}
public static Monster newDragon() {
return new Monster("Dragon", "A massive scaled wivern. I hope you "
+ "brought some potions..", 100, 20, 30, 4, 11, true);
}
public static Monster newShadowAssassin() {
return new Monster("Shadow Assassin", "A dark, elusive assassin trained"
+ " to land critical hits. Low HP, with high attack.", 20, 15,
35, 2, 20, true);
}
public static Monster newGhoul() {
return new Monster("Ghoul", "A humaniod exposed to radiation, but still"
+ " maintains a consciousness. Can be aggressive in certain "
+ "situations.", 40, 10, 25, 2, 8, false);
}
public static Monster newFeralGhoul() {
return new Monster("Feral Ghoul", "A humaniod exposed to radiation, so "
+ "much that it can't distinguish friend from foe.",
40, 10, 25, 2, 8, true);
}
public String getDescription() {
return description;
}
public int getHitPoints() {
return hitPoints;
}
public boolean isAlive() {
return hitPoints > 0;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name + " " + description;
}
public double getCritChance() {
return critChance;
}
}
Room class:
package projectmoria;
public final class Room {
private final String description;
private final Monster monster;
private final int numOfMonsters;
private final boolean isBossRoom;
//private final boolean lighting;
private Room(String description, Monster monster, boolean isBossRoom,
int numOfMonsters) {
this.description = description;
this.monster = monster;
//this.lighting = lighting;
this.isBossRoom = isBossRoom;
this.numOfMonsters = numOfMonsters;
}
public static Room newRoomInstance() {
String description = null;
int numOfMonsters = 0;
//boolean lighting = true;
boolean isBossRoom = false;
int random = ProjectMoria.RAND.nextInt(3) + 1; //Change random value parameter to add more room types
switch (random) {
case 1:
description = "A dark corridor with creeping, animated vines.";
numOfMonsters = 1;
//lighting = false;
break;
case 2:
description = "A single lantern lays on the floor, illuminating"
+ " a skeleton of a past explorer. Two pairs of eyes "
+ "can be seen.";
numOfMonsters = 1;
//lighting = true;
break;
case 3:
description = "A green, floral room full of massive plants.";
numOfMonsters = 1;
//lighting = true;
break;
/*case 4:
description = "a giant dragon";
numOfMonsters = 1;
isBossRoom = true;
break;
case 5:
description = "";
numOfMonsters = 1;
break;
case 6:
description = "";
numOfMonsters = 1;
break;
case 7:
description = "";
numOfMonsters = 1;
break;
case 8:
description = "";
numOfMonsters = 1;
break;
case 9:
description = "";
numOfMonsters = 1;
break;
case 10:
description = "";
numOfMonsters = 1;
break;*/
}
return new Room(description, Monster.newRandomMonster(), false,
numOfMonsters);
}
@Override
public String toString() {
return description;
}
public boolean isBossRoom() {
return isBossRoom;
}
public String getDescription() {
return description;
}
public Monster getMonster() {
return monster;
}
public int getNumOfMonsters() {
return numOfMonsters;
}
public boolean isIsBossRoom() {
return isBossRoom;
}
}
Item class:
package projectmoria;
public class Item {
private final String name;
private final String type;
private final String description;
public Item(String name, String type, String description) {
this.name = name;
this.type = type;
this.description = description;
}
public void use(Player player, Item item) {
if (item.type.equals("Potion")) {
player.heal(item);
}
}
public static void addPotion(int numOfPotions, Player player) {
for (int i = 0; i < numOfPotions; i++) {
player.getInventory().add(potion());
}
}
private static Item potion() {
return new Item("Potion", "Potion", " a small vial filled with a " + "translucent red liquid");
}
}