4

I'm working on a random name generator to be used in a game I'm developing, the problem is there are different species with different naming styles, and I would like a single name generator to work with all of them. I have part one of this problem sorted - the name generator uses a series of templates, one set for each species of player/NPC.

The main problem I have is some vowels need to have a randomly selected accent mark. I have searched and searched, but I cannot find a way to randomly select a character and then apply an accent mark to it. So, what are the ways one can compose an accented letter by selecting the letter and then applying an accent mark to it?

  • If you know what vowels you should mark with an accent, make a method to check the accent of that vowel. For example, if you have an `a` char which you want to apply accent, change it using a `vowelsWithAccent.getAccent(`a`)` method that will change it into `á`. The method can use a `Map` to give you the vowel with accent. – Luiggi Mendoza Jun 15 '12 at 21:58
  • See also http://stackoverflow.com/a/29111105/32453 – rogerdpack Mar 18 '15 at 21:42

3 Answers3

4

Unicode has 'combining' characters representing most types of accents. It would be pretty easy to randomly select a combining character from an array of combining characters you create. Then you could just put whatever accents you have on any characters you like.

http://en.wikipedia.org/wiki/Combining_character

Since these are represented by codepoints you can treat them as a character on their own:

String s = "a" + "\u0300"; // latin lowercase letter a + combining grave accent
char combining_grave_accent = '\u0300';
bames53
  • 86,085
  • 15
  • 179
  • 244
  • Unfortunately it seems Java does not have an API that would allow one to have `String s = LATIN_LETTER_A | ACCENT_GRAVE` or something to that effect. – Lady Serena Kitty Jun 16 '12 at 02:56
  • So it can be done in Java, one just has to know the character codes for the combining characters. This is great, because I can add the accent marks then normalize the string in the final step of name generation. – Lady Serena Kitty Jun 16 '12 at 14:20
1

Hmm perhaps use a 2d array and create a conversion table which will have 2 columns and how many ever rows(how many ever accented chars there are), now in the 1st column store the every accented value and in the second store the value un-accented i.e a,e,i,o,u and when you generate a vowel for the name you can randomly choose whether to accent it or not, and if you choose to accent it you will iterate through the 2d array get all accented values that use 'a' or whatever and by getting and checking values in the 2nd column (so that all accented a's are picked) of the array then randomly pick one to use...

Thats the long way around, i know of no shortcut in java for this.

EDIT: here is some code to match what i suggested:

import java.util.ArrayList;

/**
 *
 * @author David
 */
public class JavaApplication145 {

    static char[][] chars = new char[6][6];

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        createConversionTable();

        char c = 'u';

        ArrayList<String> charsList = getAccentedChar(c);

        for (int i = 0; i < charsList.size(); i++) {
            System.out.println(charsList.get(i));
        }

    }

    private static void createConversionTable() {
        chars[0] = new char[]{'ù', 'ü', 'é', 'ê', 'ä', 'à'};
        chars[1] = new char[]{'u', 'u', 'e', 'e', 'a', 'a'};
    }

    private static ArrayList getAccentedChar(char c) {

        ArrayList<String> charsList = new ArrayList<>();

        for (int i = 0; i < chars[0].length; i++) {

            for (int x = 0; x < chars[1].length; x++) {

                if (chars[i][x] == c) {
                    charsList.add(chars[i - 1][x] + "");
                }

            }
        }
        return charsList;
    }
}
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
  • 1
    Intead of using 2 arrays, it will be better to use a Map (easy to maintain, faster access). Still, your point of view is good one. – Luiggi Mendoza Jun 15 '12 at 22:05
  • Yes that would be even more efficient hey?! +1... well hopefully the OP got the idea and will do that – David Kroukamp Jun 15 '12 at 22:10
  • Maybe, maybe don't, we don't know for sure. Still, you should give a look into [Java Collections](http://docs.oracle.com/javase/tutorial/collections/index.html) and practice a bit with real code to learn another ways to implement more maintainable and better performance code. As I've said to you, its good to at least have the idea, but in the real world you will need more than ideas to survive :). – Luiggi Mendoza Jun 15 '12 at 22:13
  • Java Collections contains some awesome and FAST utilities. – Lady Serena Kitty Jun 15 '12 at 22:22
-1

Needed the same thing, so I ended up making this:

        /**
 * Given a letter and an accent, return the char with the accent included.
 * 
 * @param accentCode: The accent char; i.e '~', '´';
 * @param letter: Letter to put accent in it.
 * @return: Char with {@code letter} with accent if it was a valid letter.
 */
public static int getAccent(char accentChar, int letter) {
    int index = 0;
    boolean upperCase = false;
    for (char vogal : vogalList) {
        if (letter == vogal) {
            if (index >= 5) {
                index -= 5;
                upperCase = true;
            }
            for (int accentType = 0; accentType < convertTable.length; accentType++) {
                if (convertTable[accentType][0] == accentChar) {
                    char converted = convertTable[accentType][index + 1];
                    if (converted != '-') {
                        if (upperCase)
                            converted = Character.toUpperCase(converted);

                        return converted;
                    }
                }
            }
        }
        index++;
    }
    return letter;
}

/**
 * Verify if {@code charID} is an accent character;
 * 
 * @param charID: Character code id to be verified.
 * @return: true in case {@code charID} is an accent character id.
 */
public static boolean isAccent(int charID) {
    for (int i = 0; i < convertTable.length; i++) {
        if (convertTable[i][0] == charID)
            return true;
    }
    return false;
}

private static final char[] vogalList = { 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' };
private static final char[][] convertTable = { { '´', 'á', 'é', 'í', 'ó', 'ú' }, { '`', 'à', 'è', 'ì', 'ò', 'ù' }, { '^', 'â', 'ê', 'î', 'ô', 'û' }, { '~', 'ã', '-', '-', 'õ', '-' }, { '¨', 'ä', 'ë', 'ï', 'ö', 'ü' } };
Pb600
  • 130
  • 1
  • 5