Jumble Word Game in Java

In Jumble word game, the computer program randomly picks up a secret word from a database of words and then shuffles it. The shuffled word is presented to the user and he is asked to guess the original word. The program ends when the user correctly guesses the word. The program also prints the number guesses made by the user for finding the correct answer.

The following Java program implements the Jumble word game. This program demonstrates a number of important language features such as getting user input, conditional checks, loops and string operations. It also demonstrates how a random word is picked up using the ThreadLocalRandom class, how a word is shuffled using array operations and how Scanner class can be used for user input.

import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;

// How to create a Jumble word game in Java

public class JumbleGame {

    private static final String[] WORDS_DATABASE = new String[] {
        "superman","jungle","programmer","letter","house","helium"
    };
    
    public static void main(String[] args) {
        JumbleGame jg = new JumbleGame();
        jg.startGame();
    }

    /**
     * Run a game of Jumble in Java. The steps in the game are,
     * 1. Get a random word from the words database
     * 2. Shuffle/jumble the word by randomly shuffling characters
     * 3. Present the jumbled word to the user and ask him to guess the word.
     * 4. Repeat the guess till answer is found or user decides to quit.
     */
    private void startGame() {
        int numberOfGuesses = 0;
        String original = selectRandomWord();
        String shuffled = getShuffledWord(original);
        boolean gameOn = true;
        while(gameOn) {
            System.out.println("Shuffled word is: "+shuffled);
            numberOfGuesses++;
            String userGuess = getUserGuess();
            if(original.equalsIgnoreCase(userGuess)) {
                System.out.println("Congratulations! You found the word in "+numberOfGuesses+" guesses");
                gameOn = false;
            }else {
                System.out.println("Sorry, Wrong answer");
            }
        }        
    }
    
    /**
     * Get the user's word guess from command line
     * @return 
     */
    public String getUserGuess() {
        Scanner sn = new Scanner(System.in);
        System.out.println("Please type in the original word: ");
        return sn.nextLine();
    }
    
    /**
     * Select a random word from the WORDS_DATABASE array.
     * @return 
     */
    public String selectRandomWord() {
        int rPos = ThreadLocalRandom.current().nextInt(0, WORDS_DATABASE.length);
        return WORDS_DATABASE[rPos];
    }
    
    /**
     * Shuffle the original word by randomly swapping characters 10 times
     * @param original
     * @return 
     */
    public String getShuffledWord(String original) {
        String shuffledWord = original; // start with original
        int wordSize = original.length();
        int shuffleCount = 10; // let us randomly shuffle letters 10 times
        for(int i=0;i<shuffleCount;i++) {
            //swap letters in two indexes
            int position1 = ThreadLocalRandom.current().nextInt(0, wordSize);
            int position2 = ThreadLocalRandom.current().nextInt(0, wordSize);
            shuffledWord = swapCharacters(shuffledWord,position1,position2);
        }
        return shuffledWord;
    }

    /**
     * Swaps characters in a string using the given character positions
     * @param shuffledWord
     * @param position1
     * @param position2
     * @return 
     */
    private String swapCharacters(String shuffledWord, int position1, int position2) {
        char[] charArray = shuffledWord.toCharArray();
        // Replace with a "swap" function, if desired:
        char temp = charArray[position1];
        charArray[position1] = charArray[position2];
        charArray[position2] = temp;
        return new String(charArray);
    }
}

Here are a number of ideas to improve the above program,

  • Modify the program so that the user can resign so that the computer will print the correct answer.
  • Modify the program so that you can play the game for multiple words at a time.

Guess the Number Game in Java

In guess the number game, the computer program will come up with a random number within a range (for example, 1 to 1000). The player (user) is asked to guess this number. If the guessed number is bigger than the actual number, the computer will respond with the message "too high". If the guessed number is smaller than the actual number, computer will respond with the message "too low". This process repeats until the number is found. The aim of the game is to find the secret number in minimum number of guesses. At the end of the game the number and the number of guesses are revealed.

Guess the number game is used to illustrate basic principles of programming. It demonstrates use of user input, conditional checking and loop constructs. It also demonstrates use of random number generation.

The following example program shows how guess the number game can be written in Java. It also demonstrates proper use of Java functions where each function is responsible for a specific feature of the program. This refactoring of the program into multiple functions is the key to highly maintainable and readable programs.

import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;


public class GuessNumberGame {
    // Guess limits
    private static final int MIN_NUMBER = 1;
    private static final int MAX_NUMBER = 1000;
    
    public static void main(String[] args) {
        GuessNumberGame game = new GuessNumberGame();
        game.startGame();
    }
    
    /**
     * Play the guess number game.
     */
    public void startGame() {
        boolean isUserGuessCorrect = false;
        int numberOfGuesses = 0;
        // computer thinks a number
        int computerNumber = getNumberByComputer();
        
        // Program continues till user guesses the number correctly
        while(!isUserGuessCorrect) {
            int userNumber = getUserGuessedNumber();
            if(userNumber > computerNumber) {
                System.out.println("Sorry, the number you guessed is too high");
            }else if(userNumber < computerNumber) {
                System.out.println("Sorry, the number you guessed is too low");
            }else if(userNumber == computerNumber) {
                System.out.println("Congratulations! Your guess is correct!");
                isUserGuessCorrect = true;
            }
            numberOfGuesses++;
        }
        System.out.println("You found the number in "+numberOfGuesses+" guesses");
    }
    
    /**
     * Returns a random number between 1 and 1000 inclusive.
     * @return 
     */
    public int getNumberByComputer() {
        return ThreadLocalRandom.current().nextInt(MIN_NUMBER, MAX_NUMBER+1);
    }
    
    /**
     * Returns the number guessed by user
     * @return 
     */
    public int getUserGuessedNumber() {
        Scanner sn = new Scanner(System.in);
        System.out.println("Please guess the number: ");
        return sn.nextInt();
    }
}

How to Encrypt and Decrypt Data In Java Using AES Algorithm

AES (Advanced Encryption Standard) is a strong symmetric encryption algorithm. A secret key is used for the both encryption and decryption of data. Only someone who has access to the same secret key can decrypt data. AES encryption provides strong protection to your data.

The following sample Java program shows how to encrypt data using AES encryption algorithm. Java provides a number of helper classes for AES encryption such as Cipher (for encryption/decryption), SecretKey (represents the shared secret key) and KeyGenerator (generates the shared secret key). Also note that both secret key and encrypted data is binary data and hence cannot be printed directly. The following program prints them in hexadecimal form.

In the following program, the KeyGenerator is initialized with a 128 bit secret key. If you want stronger keys such as 256 bit key, you need to Java cryptography extension (JCE) unlimited strength jurisdiction policy files.

These zip files contain a number of jars and you need to copy them to {java.home}/jre/lib/security  directory of your JRE installation. Now you can pass 256 as secret key bit size to KeyGenerator.

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.xml.bind.DatatypeConverter;

/**
 * This example program shows how AES encryption and decryption can be done in Java.
 * Please note that secret key and encrypted text is unreadable binary and hence 
 * in the following program we display it in hexadecimal format of the underlying bytes.
 * @author Jayson
 */
public class AESEncryption {
 
    /**
     * 1. Generate a plain text for encryption
     * 2. Get a secret key (printed in hexadecimal form). In actual use this must 
     * by encrypted and kept safe. The same key is required for decryption.
     * 3. 
     */
    public static void main(String[] args) throws Exception {
        String plainText = "Hello World";
        SecretKey secKey = getSecretEncryptionKey();
        byte[] cipherText = encryptText(plainText, secKey);
        String decryptedText = decryptText(cipherText, secKey);
        
        System.out.println("Original Text:" + plainText);
        System.out.println("AES Key (Hex Form):"+bytesToHex(secKey.getEncoded()));
        System.out.println("Encrypted Text (Hex Form):"+bytesToHex(cipherText));
        System.out.println("Descrypted Text:"+decryptedText);
        
    }
    
    /**
     * gets the AES encryption key. In your actual programs, this should be safely
     * stored.
     * @return
     * @throws Exception 
     */
    public static SecretKey getSecretEncryptionKey() throws Exception{
        KeyGenerator generator = KeyGenerator.getInstance("AES");
        generator.init(128); // The AES key size in number of bits
        SecretKey secKey = generator.generateKey();
        return secKey;
    }
    
    /**
     * Encrypts plainText in AES using the secret key
     * @param plainText
     * @param secKey
     * @return
     * @throws Exception 
     */
    public static byte[] encryptText(String plainText,SecretKey secKey) throws Exception{
		// AES defaults to AES/ECB/PKCS5Padding in Java 7
        Cipher aesCipher = Cipher.getInstance("AES");
        aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
        byte[] byteCipherText = aesCipher.doFinal(plainText.getBytes());
        return byteCipherText;
    }
    
    /**
     * Decrypts encrypted byte array using the key used for encryption.
     * @param byteCipherText
     * @param secKey
     * @return
     * @throws Exception 
     */
    public static String decryptText(byte[] byteCipherText, SecretKey secKey) throws Exception {
		// AES defaults to AES/ECB/PKCS5Padding in Java 7
        Cipher aesCipher = Cipher.getInstance("AES");
        aesCipher.init(Cipher.DECRYPT_MODE, secKey);
        byte[] bytePlainText = aesCipher.doFinal(byteCipherText);
        return new String(bytePlainText);
    }
    
    /**
     * Convert a binary byte array into readable hex form
     * @param hash
     * @return 
     */
    private static String  bytesToHex(byte[] hash) {
        return DatatypeConverter.printHexBinary(hash);
    }
}

In highly secure systems, the secret key is usually stored in a separate hardware known HSMs(Hardware Security Modules). HSMs are expensive devices and hence a more cost effective way is to store the secret key in a separate secure partition or schema.

How to Generate Random Numbers in a Range in Java

Random numbers are used in a number of programming applications such as games, computer simulation, cryptography etc. It is also used to generate test data. Usually you want to generate random numbers in a specific range of values. The following example program in Java generates 5 random numbers between 10 and 20 (both inclusive).

import java.util.concurrent.ThreadLocalRandom;

/**
 * Prints random numbers within a range of values inclusive of boundary values.
 * For example, if the range is 10 to 20, this program will print random numbers
 * which will be between 10 and 20 including 10 and 20.
 */
public class RandomInRange {
    
    public static void main(String[] args) {
        // We want numbers to vary from 10 to 20 including 10 and 20.
        int minValueForRange = 10;
        int maxValueForRange = 20;
        
        // create 5 random numbers and then print them
        for(int i=0;i<5;i++) {
            int randomNumber = ThreadLocalRandom.current().nextInt(minValueForRange, maxValueForRange + 1);
            System.out.println(randomNumber);
        }
    }
}

If  you want random floating point values or long values you can use nextDouble() or nextLong() methods of ThreadLocalRandom.

How to Print Arrays in Java

When working with arrays in Java, it is useful to print the array contents on the console or on the log file. This is useful for debugging the application. It is possible to print one dimensional or multi-dimensional arrays using for loops. However a much easier solution is to use the deepToString() static method of Arrays class. The following sample program in Java shows how any type of arrays can be printed using the Arrays class of util package.

import java.util.Arrays;

/**
 * How to print arrays in Java. This works with multi-dimensional arrays as well. 
 */
public class PrintArray {
    public static String[] LANGUAGES = new String[] {
                    "English","Spanish","German"
                    };
    
    public static String[][] COUNTRIES = new String[][] {
                     {"India","New Delhi"},
                     {"United States","Washington"},
                     {"Germany","Berlin"},
                    };
    
    public static void main(String[] args) {
        System.out.println(Arrays.deepToString(LANGUAGES));
        System.out.println(Arrays.deepToString(COUNTRIES));
    }
}