Erick Ramirez Erick Ramirez - 2 months ago 8
Java Question

What is the best method to get the index of a String or Char Array?

I would like to know what is the best way to get the index of a specific letter in a word. The reason i am doing this, is because i am making and modifying a Hangman game. I am already done with the game and it works good, however i want to implement a score based system. I created a method called keepScore() that takes a boolean value to see if the answer is right or wrong. If it is right, i am going to add 10 points for each letter found. If its wrong, i will deduct 10 points. My method keepScore() is implemented incorrectly any help?

Hangman.java

import Game.Game;
import Prompter.Prompter;

/* This class is the main class that starts the game.
* It instantiates the Game and Prompter objects.
*/
public class Hangman {

public static void main(String[] args) {
//Check if an argument has been passed, we expect the answer to be passed
if(args.length == 0) {
System.out.println("Expected: Java Hangman <answer>");
System.err.println("Answer is required!");
System.exit(1);
}

System.out.println("Welcome to Hangman!");

//Create an instance of our game
Game game = new Game(args[0]);
//Create an instance of our prompter
Prompter prompter = new Prompter(game);

//Starts the game
while (game.getRemainingTries() > 0 && !game.isWon()) {
prompter.displayProgress();
prompter.promptForGuess();
}
//Displays the outcome of the game
prompter.displayOutcome();
}
}


Game.java

package Game;

/* This class is responsible for implementing the game
* logic.
*/
public class Game {
//Declare our member variables
public final static int TOTAL_TRIES = 3;
public final static int MAX_SCORE_POINTS = 10;
private String mAnswer;
private String lettersHit;
private String lettersMissed;
private int score;

//Default constructor
public Game(String answer) {
//Initialize our member variables
mAnswer = answer.toLowerCase();
lettersHit = "";
lettersMissed = "";
}

//This method checks to see if the letter was a hit or a miss
public boolean checkLetter(char letter){
letter = validateGuess(letter);
boolean isHit = mAnswer.indexOf(letter) != -1;
//If correct
if (isHit) {
//Add the letter to the lettersHit pool
lettersHit += letter;
keepScore(isHit);
System.out.println("Hit! Score: " + score);

}else {
//Add the letter to the lettersMissed pool
lettersMissed += letter;
keepScore(isHit);
System.out.println("Missed! Score: " + score);
}
return isHit;
}

private void keepScore(boolean isHit) {
if(isHit) {
for (int i = 0; i < lettersHit.length(); i++) {
score += MAX_SCORE_POINTS;
}
} else {
for (int i = 0; i < lettersMissed.length(); i++ ) {
score -= MAX_SCORE_POINTS;
}
}
}

/*
This method handles an empty string input. For example,
if the user were to press enter on input a 0 length String
will cause the program to crash.
*/
public boolean checkLetter(String letters) {
if (letters.length() == 0) {
throw new IllegalArgumentException("No letter entered");
}
return checkLetter(letters.charAt(0));
}

//This method validates the user guess
private char validateGuess(char letter) {
//If the character is not a letter
if (!Character.isLetter(letter)) {
//Ask user for a valid letter
throw new IllegalArgumentException("A letter is required!");
}
//If entry was valid, convert character to lowercase
letter = Character.toLowerCase(letter);

//Check if the letter has been guessed already
if (lettersHit.indexOf(letter) != -1 || lettersMissed.indexOf(letter) != -1) {
throw new IllegalArgumentException("The letter " + letter + " has already been guessed");
}
return letter;
}

//This method keeps track of the user's game progress
public String getCurrentProgress() {
String progress = "";
//For each character in the array of strings of mAnswer
for (char letter : mAnswer.toCharArray()) {
char display = '-';
if (lettersHit.indexOf(letter) != -1){
display = letter;
}
progress += display;
}
return progress;
}

//Get the current remaining tries
public int getRemainingTries() {
return TOTAL_TRIES - lettersMissed.length();
}

//Get the current answer
public String getAnswer() {
return mAnswer;
}

//This method checks if the game is won.
public boolean isWon() {
return getCurrentProgress().indexOf('-') == -1;
}


public int getScore(){
return score;
}
}


Prompter.java

package Prompter;
import Game.Game;
import java.util.Scanner;

/* This class is responsible for displaying instructions and information to the user
* regarding the game.
*/
public class Prompter {
//The game object
private Game mGame;
private boolean isHit;
private boolean acceptable;

//Default constructor
public Prompter(Game game) {
//Get the instance of our game
mGame = game;
isHit = false;
acceptable = false;
}

//This method prompts the user for a guess
public boolean promptForGuess() {
//Create an instance of scanner
Scanner scanner = new Scanner(System.in);

//Loop for input
do {
System.out.println("Please enter a letter: ");
String guess = scanner.nextLine();

try {
isHit = mGame.checkLetter(guess);
acceptable = true;
}catch (IllegalArgumentException iae) {
System.out.printf("%s. Please try again!%n", iae.getMessage());
}
} while (!acceptable);
return isHit;
}

//This method displays the progress
public void displayProgress() {
System.out.printf("You have %d tries to guess the answer" +
" before you are taken to the gallows. Try to solve: %s%n", mGame.getRemainingTries(),
mGame.getCurrentProgress());
}

//This method displays the outcome of the game
public void displayOutcome() {
if( mGame.isWon()) {
System.out.printf("Congratulations! you won with %d tries remaining.%n" +
"Your total score: %d%n", mGame.getRemainingTries(), mGame.getScore());
}else {
System.out.printf("Bummer! The answer was: %s", mGame.getAnswer());
}
}
}

Answer Source

Look at this method of yours:

private void keepScore(boolean isHit) {
    if(isHit) {
        for (int i = 0; i < lettersHit.length(); i++) {
            score += MAX_SCORE_POINTS;
        }
    } else {
        for (int i = 0; i < lettersMissed.length(); i++ ) {
            score -= MAX_SCORE_POINTS;
        }
    }
}

It doesn't add MAX_SCORE_POINTS times the number of good letters you just found, it does so with the number of good letters in lettersHit. Now, what is in lettersHit ? Well, there is all the letters you found since the start.

So you'll have :

word to guess: anaconda

letter: a
lettersHit = "a", score += (lettersHit.length * 10) = 10
letter: c
lettersHit = "ac", score += (lettersHit.length * 10) = 30

You could just use StringUtils.countMatches(mAnswer, letter); to get the number of occurence, hence the score.