Skip to content

Commit

Permalink
Reformat concept exercise Wizards and Warriors (exercism#2729)
Browse files Browse the repository at this point in the history
* Reformat concept exercise Wizards and Warriors
Adding two new tasks so the user has to implement the classes and inheritance concept instead of being given
Updating hints, instructions and introduction acordingly to the updated
Adding new tests for the new tasks, and update the code given to the student

* Update exercises/concept/wizards-and-warriors/.docs/hints.md

Co-authored-by: Sander Ploegsma <[email protected]>

* Applying suggestions

* Modifying the order of the tasks
Updating Fighter class to not be abstract
Updating instructions and hints
Updating tests accordingly

* Implementing Reflection proxy for wizard and warriors exercise

* Finish tests using reflection proxy

* Merging preparespell and isvulnerable tasks for wizard into one task

* Update test method names and descriptions

* Update the exercise instructions to be less verbose

* Clean up reference solution

* Add if-else-statements as prerequisite, clean up design.md

* Add test to check that prepareSpell is not added to base class

* Add TODOs to stub

---------

Co-authored-by: Sander Ploegsma <[email protected]>
  • Loading branch information
manumafe98 and sanderploegsma authored Feb 16, 2024
1 parent b6f79bc commit 3c73508
Show file tree
Hide file tree
Showing 13 changed files with 833 additions and 159 deletions.
6 changes: 6 additions & 0 deletions concepts/inheritance/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,19 @@ Consider an animal named `Lion`, having a class like,
//Lion class is a child class of Animal.
public class Lion extends Animal {

@Override
public void bark() {
System.out.println("Lion here!!");
}

}
```

~~~~exercism/note
The `Override` annotation is used to indicate that a method in a subclass is overriding a method of its superclass.
It's not strictly necessary but it's a best practice to use it.
~~~~

Now whenever we do,

```java
Expand Down
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@
"prerequisites": [
"classes",
"strings",
"booleans"
"if-else-statements"
],
"status": "active"
},
Expand Down
51 changes: 33 additions & 18 deletions exercises/concept/wizards-and-warriors/.docs/hints.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,56 @@

## General

Detailed explanation of inheritance can be found at [Inheritance][inheritance-main].
Detailed explanation of inheritance can be found at [Inheritance][inheritance-concept].
The whole inheritance concept has a lot to do with the concepts around [overriding][java-overriding].

## 1. Describe a Fighter
## 1. Create the Warrior class

- Review the [concept:java/classes](https://github.com/exercism/java/tree/main/concepts/classes) concept.
- Review the [inheritance][inheritance-concept] concept.

## 2. Describe a Warrior

- In Java, the `toString()` method is actually present inside the `Object` class (which is a superclass to all the classes in Java).
You can read more about it [here][object-class-java].
- To override this method inside your implementation class, you should have a method with same name i.e. `toString()` and same return type i.e. `String`.
- The `toString()` method must be `public`.

## 2. Making Fighters not vulnerable by default
## 3. Make Warriors invulnerable

- Consider having a method `isVulnerable()` inside the `Fighter` class which states vulnerability of the fighter, return `false` to make it non-vulnerable by default.
- This can than be overridden by any child class(the class extending `Fighter`), according to its requirements.
- Again the [overriding][java-overriding] concept will come handy.
- Override the `isVulnerable()` method in the `Warrior` class to make Warriors always invulnerable.

## 3. Allowing wizards to prepare a spell
## 4. Calculate the damage points for a Warrior

- Preparing a spell can only be done by a wizard.
So, it makes sense to have this property defined inside the `Wizard` class.
- Create `prepareSpell()` method inside `Wizard` class.
- Remember: Parent class (here `Fighter`) has no access to the properties of the child class (for example, `Wizard`)
- Override the `getDamagePoints(Fighter)` method in the `Warrior` class.
- Use a [conditional statement][if-else] to return the damage points, taking into account the vulnerability of the target.

## 4. Make Wizards vulnerable when not having prepared a spell
## 5. Create the Wizard class

- Override the `isVulnerable()` method in the `Wizard` class to make Wizards vulnerable if they haven't prepared a spell.
- Review the [concept:java/classes](https://github.com/exercism/java/tree/main/concepts/classes) concept.
- Review the [inheritance][inheritance-concept] concept.

## 5. Calculate the damage points for a Wizard
## 6. Describe a Wizard

- Use a [conditional statement][if-else] to return the damage points, taking into account the value of the prepare spell field.
- In Java, the `toString()` method is actually present inside the `Object` class (which is a superclass to all the classes in Java).
You can read more about it [here][object-class-java].
- To override this method inside your implementation class, you should have a method with same name i.e. `toString()` and same return type i.e. `String`.
- The `toString()` method must be `public`.

## 6. Calculate the damage points for a Warrior
## 7. Allow Wizards to prepare a spell and make them vulnerable when not having prepared a spell

- Use a [conditional statement][if-else] to return the damage points, taking into account the vulnerability of the target.
- Preparing a spell can only be done by a wizard. So, it makes sense to have this property defined inside the `Wizard` class.
- Create `prepareSpell()` method inside `Wizard` class.
- Remember: Parent class (here `Fighter`) has no access to the properties of the child class (for example, `Wizard`)
- Remember: As the method does not have a return type you should use `void` instead.
- Override the `isVulnerable()` method in the `Wizard` class to make Wizards vulnerable if they haven't prepared a spell.

## 8. Calculate the damage points for a Wizard

- Override the `getDamagePoints(Fighter)` method in the `Wizard` class.
- Use a [conditional statement][if-else] to return the damage points, taking into account the value of the prepare spell field.

[inheritance-main]: https://www.geeksforgeeks.org/inheritance-in-java/
[inheritance-concept]: https://www.geeksforgeeks.org/inheritance-in-java/
[object-class-java]: https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
[java-overriding]: https://docs.oracle.com/javase/tutorial/java/IandI/override.html
[if-else]: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/if.html
82 changes: 48 additions & 34 deletions exercises/concept/wizards-and-warriors/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -1,83 +1,97 @@
# Instructions

In this exercise you're playing a role-playing game named "Wizards and Warriors," which allows you to play as either a Wizard or a Warrior.

There are different rules for Warriors and Wizards to determine how much damage points they deal.
In this exercise you're playing a role-playing game where different types of fighters can combat each other.
The game has different rules for each type of fighter.
We are going to focus on two specific types: Wizards and Warriors.

For a Warrior, these are the rules:

- Deal 6 points of damage if the fighter they are attacking is not vulnerable
- Deal 10 points of damage if the fighter they are attacking is vulnerable
- A Warrior is never vulnerable.
- A Warrior deals `6` points of damage if the fighter they are attacking is not vulnerable.
- A Warrior deals `10` points of damage if the fighter they are attacking is vulnerable.

For a Wizard, these are the rules:

- Deal 12 points of damage if the Wizard prepared a spell in advance
- Deal 3 points of damage if the Wizard did not prepare a spell in advance
- A Wizard can prepare a spell in advance.
- A Wizard is vulnerable unless they have prepared a spell in advance.
- A Wizard deals `12` points of damage if they prepared a spell in advance.
- A Wizard deals `3` points of damage if they did not prepare a spell in advance.

In general, fighters are never vulnerable. However, Wizards _are_ vulnerable if they haven't prepared a spell.
## 1. Create the Warrior class

You have six tasks that work with Warriors and Wizard fighters.
Create a new class called `Warrior`.
This class should inherit from the existing `Fighter` class.

## 1. Describe a fighter
## 2. Describe a Warrior

Override the `toString()` method on the `Fighter` class to return a description of the fighter, formatted as `"Fighter is a <FIGHTER_TYPE>"`.
Update the `Warrior` class so that its `toString()` method describes what kind of fighter they are.
The method should return the string `"Fighter is a Warrior"`.

```java
Fighter warrior = new Warrior();
Warrior warrior = new Warrior();
warrior.toString();
// => "Fighter is a Warrior"
```

## 2. Make fighters not vulnerable by default
## 3. Make Warriors invulnerable

Ensure that the `Fighter.isVulnerable()` method always returns `false`.
Update the `Warrior` class so that its `isVulnerable()` method always returns `false`.

```java
Fighter warrior = new Warrior();
Warrior warrior = new Warrior();
warrior.isVulnerable();
// => false
```

## 3. Allow Wizards to prepare a spell
## 4. Calculate the damage points for a Warrior

Implement the `Wizard.prepareSpell()` method to allow a Wizard to prepare a spell in advance.
Update the `Warrior` class so that its `getDamagePoints(Fighter)` method calculates the damage dealt by a Warrior according to the rules above.

```java
Warrior warrior = new Warrior();
Wizard wizard = new Wizard();
wizard.prepareSpell();

warrior.getDamagePoints(wizard);
// => 10
```

## 4. Make Wizards vulnerable when not having prepared a spell
## 5. Create the Wizard class

Create another new class called `Wizard`.
This class should also inherit from the existing `Fighter` class.

## 6. Describe a Wizard

Ensure that the `isVulnerable()` method returns `true` if the wizard did not prepare a spell; otherwise, return `false`.
Update the `Wizard` class so that its `toString()` method describes what kind of fighter they are.
The method should return the string `"Fighter is a Wizard"`.

```java
Fighter wizard = new Wizard();
wizard.isVulnerable();
// => true
Wizard wizard = new Wizard();
wizard.toString();
// => "Fighter is a Wizard"
```

## 5. Calculate the damage points for a Wizard
## 7. Allow Wizards to prepare a spell and make them vulnerable when not having prepared a spell

Implement the `Wizard.damagePoints()` method to return the damage points dealt: 12 damage points when a spell has been prepared, 3 damage points when not.
Update the `Wizard` class to add a method called `prepareSpell()`.
The class should remember when this method is called, and make sure that its `isVulnerable()` method returns `false` only when a spell is prepared.

```java
Wizard wizard = new Wizard();
Warrior warrior = new Warrior();

wizard.prepareSpell();
wizard.damagePoints(warrior);
// => 12
wizard.isVulnerable();
// => false
```

## 6. Calculate the damage points for a Warrior
## 8. Calculate the damage points for a Wizard

Implement the `Warrior.damagePoints()` method to return the damage points dealt: 10 damage points when the target is vulnerable, 6 damage points when not.
Update the `Wizard` class so that its `getDamagePoints(Fighter)` method calculates the damage dealt by a Wizard according to the rules above.

```java
Warrior warrior = new Warrior();
Wizard wizard = new Wizard();
Warrior warrior = new Warrior();

warrior.damagePoints(wizard);
// => 10
wizard.prepareSpell();
wizard.getDamagePoints(warrior);
// => 12
```
6 changes: 6 additions & 0 deletions exercises/concept/wizards-and-warriors/.docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,19 @@ Consider an animal named `Lion`, having a class like,
//Lion class is a child class of Animal.
public class Lion extends Animal {

@Override
public void bark() {
System.out.println("Lion here!!");
}

}
```

~~~~exercism/note
The `Override` annotation is used to indicate that a method in a subclass is overriding a method of its superclass.
It's not strictly necessary but it's a best practice to use it.
~~~~

Now whenever we do,

```java
Expand Down
4 changes: 4 additions & 0 deletions exercises/concept/wizards-and-warriors/.meta/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
"authors": [
"himanshugoyal1065"
],
"contributors": [
"manumafe98",
"sanderploegsma"
],
"files": {
"solution": [
"src/main/java/Fighter.java"
Expand Down
9 changes: 4 additions & 5 deletions exercises/concept/wizards-and-warriors/.meta/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,24 @@ The goal of this exercise is to teach the student the basics of the Concept of `
- Know what inheritance is.
- Know how to inherit from a class.
- Know that all types inherit from object.
- Know what the override annotation means.

## Out of scope

- Inheritance from interfaces
- Abstract classes

## Concepts

- `inheritence`
- `objects`
- `inheritance`

## Prerequisites

This exercise's prerequisites Concepts are:

- `classes`
- `abstract`
- `functions`
- `strings`
- `boolean`
- `if-else-statements`

## Representer

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
abstract class Fighter {
class Fighter {

/**
* this method sets the default vulnerability to false for all the child classes.
*
* @return the vulnerability i.e. false.
*/
boolean isVulnerable() {
return false;
return true;
}

abstract int damagePoints(Fighter fighter);

int getDamagePoints(Fighter fighter) {
return 1;
}
}

class Warrior extends Fighter {
Expand All @@ -21,12 +17,13 @@ public String toString() {
}

@Override
int damagePoints(Fighter wizard) {
if (wizard.isVulnerable()) {
return 10;
} else {
return 6;
}
public boolean isVulnerable() {
return false;
}

@Override
int getDamagePoints(Fighter target) {
return target.isVulnerable() ? 10 : 6;
}
}

Expand All @@ -41,23 +38,15 @@ public String toString() {

@Override
boolean isVulnerable() {
if (isSpellPrepared == false) {
return true;
}
return false;
return !isSpellPrepared;
}

@Override
int damagePoints(Fighter warrior) {
if (isSpellPrepared) {
return 12;
} else {
return 3;
}
int getDamagePoints(Fighter target) {
return isSpellPrepared ? 12 : 3;
}

void prepareSpell() {
isSpellPrepared = true;
}

}
Loading

0 comments on commit 3c73508

Please sign in to comment.