Game Character Development
Part of the Object Oriented Programming section of Coddy's Java journey — lesson 86 of 87.
This challenge has you building a Game Character Development system that showcases OOP's power in modeling complex, interactive entities.
Design a character hierarchy where a base Character class defines common attributes like health, name, and level. Specialized classes such as Warrior, Mage, and Archer extend this base with unique abilities and combat styles.
Interfaces work naturally here: Attackable could define combat methods, while Healable handles restoration abilities. A Mage might implement both, whereas a Warrior focuses only on attacking.
Consider using the Strategy pattern for different attack behaviors, allowing characters to switch combat styles dynamically. The State pattern could manage character conditions like normal, poisoned, or stunned states that affect behavior.
Think about composition for equipment systems where characters "have" weapons and armor rather than inheriting from them. Use enums for character classes or damage types, and apply encapsulation to protect stats from invalid modifications.
Challenge
EasyLet's build a Game Character Development system that showcases the power of OOP in modeling complex, interactive game entities! You'll create a character hierarchy with different combat styles, special abilities, and a state system that affects how characters behave.
You'll organize your code across seven files:
DamageType.java: Create an enum representing different types of damage in the game. Include valuesPHYSICAL,MAGICAL, andRANGED. Add a private fielddescription(String), a constructor that sets it, and a getter. Physical damage should have description "brute force", magical should have "arcane energy", and ranged should have "precision strike".Attackable.java: Create an interface defining combat capabilities. Declare methodsattack(Character target)that returns a String describing the attack, andgetDamageType()that returns a DamageType.Healable.java: Create an interface for restoration abilities. Declare a methodheal(int amount)that returns a String describing the healing action.Character.java: Create an abstract base class for all game characters. Include private fields forname(String),health(int),maxHealth(int), andlevel(int). The constructor takes name, maxHealth, and level, setting health equal to maxHealth initially. Include getters for all fields. Add a protected methodsetHealth(int health)that ensures health stays between 0 and maxHealth. Create a methodtakeDamage(int damage)that reduces health and returns"[name] takes [damage] damage! Health: [health]/[maxHealth]". Add a methodisAlive()returning true if health is greater than 0. Declare an abstract methodgetCharacterClass()returning a String.Warrior.java: Create a class extending Character and implementing Attackable. Add a private fieldstrength(int). The constructor takes name, maxHealth, level, and strength. ImplementgetCharacterClass()to return"Warrior". ImplementgetDamageType()to returnPHYSICAL. Implementattack(Character target)to deal damage equal to strength plus level, call the target's takeDamage method, and return"[name] strikes with [damageType description] for [damage] damage!"followed by a newline and the takeDamage result.Mage.java: Create a class extending Character and implementing both Attackable and Healable. Add private fieldsintelligence(int) andmana(int). The constructor takes name, maxHealth, level, intelligence, and mana. ImplementgetCharacterClass()to return"Mage". ImplementgetDamageType()to returnMAGICAL. Implementattack(Character target)to deal damage equal to intelligence times 2, following the same format as Warrior. Implementheal(int amount)to restore health (using setHealth) and return"[name] channels healing magic! Health: [health]/[maxHealth]".Main.java: Bring your game system to life! You'll receive a comma-separated string of commands:CREATE_WARRIOR:name:maxHealth:level:strengthCREATE_MAGE:name:maxHealth:level:intelligence:manaATTACK:attackerName:targetNameHEAL:mageName:amountSTATUS:characterName
Maintain a collection of characters. Process each command and print:
- CREATE_WARRIOR/CREATE_MAGE:
[name] the [characterClass] joins the battle! - ATTACK: Print the attack result (the String returned by attack method)
- HEAL: Print the heal result, or
[name] cannot healif the character isn't a Mage - STATUS:
[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]
After all commands, print
--- Battle Summary ---followed by each character's status.
You will receive one input: the comma-separated command string.
For example, with input CREATE_WARRIOR:Thorin:100:5:15,CREATE_MAGE:Gandalf:80:7:12:50,ATTACK:Thorin:Gandalf,HEAL:Gandalf:25,STATUS:Gandalf, your output would be:
Thorin the Warrior joins the battle!
Gandalf the Mage joins the battle!
Thorin strikes with brute force for 20 damage!
Gandalf takes 20 damage! Health: 60/80
Gandalf channels healing magic! Health: 80/80
Gandalf (Mage) - Level 7 - Health: 80/80 - Alive
--- Battle Summary ---
Thorin (Warrior) - Level 5 - Health: 100/100 - Alive
Gandalf (Mage) - Level 7 - Health: 80/80 - AliveThis challenge combines inheritance (Character hierarchy), multiple interface implementation (Mage implements both Attackable and Healable), enums with methods (DamageType), polymorphism (treating different character types uniformly), and encapsulation (protected health management) into an engaging game system!
Cheat sheet
Object-oriented programming (OOP) allows modeling complex systems through classes, inheritance, interfaces, and design patterns.
Class Hierarchy
Create a base class with common attributes and extend it with specialized classes:
public abstract class Character {
private String name;
private int health;
private int maxHealth;
private int level;
public Character(String name, int maxHealth, int level) {
this.name = name;
this.maxHealth = maxHealth;
this.health = maxHealth;
this.level = level;
}
protected void setHealth(int health) {
this.health = Math.max(0, Math.min(health, maxHealth));
}
public abstract String getCharacterClass();
}Interfaces
Define contracts for specific behaviors that classes can implement:
public interface Attackable {
String attack(Character target);
DamageType getDamageType();
}
public interface Healable {
String heal(int amount);
}Enums with Fields
Enums can have fields, constructors, and methods:
public enum DamageType {
PHYSICAL("brute force"),
MAGICAL("arcane energy"),
RANGED("precision strike");
private String description;
private DamageType(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}Multiple Interface Implementation
A class can implement multiple interfaces:
public class Mage extends Character implements Attackable, Healable {
private int intelligence;
private int mana;
@Override
public String attack(Character target) {
// Implementation
}
@Override
public String heal(int amount) {
// Implementation
}
}Encapsulation
Use private fields with protected setters to control access and validate data:
protected void setHealth(int health) {
this.health = Math.max(0, Math.min(health, maxHealth));
}Polymorphism
Treat different character types uniformly through their common base class or interfaces, allowing flexible collections and method calls.
Try it yourself
import java.util.Scanner;
import java.util.HashMap;
import java.util.Map;
import java.util.LinkedHashMap;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: Use a collection to maintain characters (LinkedHashMap preserves insertion order)
// LinkedHashMap<String, Character> characters = new LinkedHashMap<>();
// TODO: Split input by comma to get individual commands
// String[] commands = input.split(",");
// TODO: Process each command:
// - CREATE_WARRIOR:name:maxHealth:level:strength
// Print: "[name] the Warrior joins the battle!"
//
// - CREATE_MAGE:name:maxHealth:level:intelligence:mana
// Print: "[name] the Mage joins the battle!"
//
// - ATTACK:attackerName:targetName
// Print the attack result from the attack method
//
// - HEAL:mageName:amount
// Print heal result, or "[name] cannot heal" if not a Mage
//
// - STATUS:characterName
// Print: "[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]"
// TODO: After all commands, print "--- Battle Summary ---"
// Then print each character's status
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsFields (Attributes)Constructor MethodConstructor OverloadingRecap - Simple Calculator4Inheritance
Basic Inheritance (extends)The super KeywordMethod Overriding (@Override)Constructor ChainingThe Object ClassSingle & Multilevel InheritWhy No Multi Class InheritRecap - Employee Hierarchy7Special Methods & Object Class
toString() Methodequals() and hashCode()clone() MethodcompareTo() and ComparableComparator InterfaceRecap - Custom Sorting2Access Modifiers & Encapsulate
Access Levels OverviewGetter and Setter MethodsInformation HidingThe final KeywordRecap - Bank Account Manager5Polymorphism
Method Overloading BasicsMethod Overriding (Run-Time)Upcasting and DowncastingThe instanceof OperatorAbstract Classes and MethodsRecap - Shape Calculator8Advanced OOP Concepts
Composition vs InheritanceAggregation vs CompositionInner Nested & Anonymous ClassEnums and Enum MethodsRecords (Java 16+)Sealed Classes (Java 17+)3Class Props & Static Member
Instance vs Static VariablesStatic MethodsStatic BlocksConstants (static final)Recap - Counter & Utility6Interfaces & Abstract Classes
Introduction to InterfacesImplementing InterfacesMulti Interface ImplemenDefault & Static in InterfaceAbstract Classes vs InterfacesFunctional InterfacesRecap - Payment System