HashMap Workaround

Hello again! I’ve got another question for my Processing class. I found a great example in another forum on how to make a Choose Your Own Adventure game; I’m currently dissecting it and trying to make it my own, with the main issue right now being the HashMap. It’s not working correctly at all, and I’m not sure if it’s something I’m doing or if Processing just doesn’t support it (I checked the references and it seemed to behave with it fine), but I think it’s a little bit above my current knowledge at the moment anyhow. From my understanding, HashMap is essential to making this thing run, and that’s where I really need the help / a kick in the right direction.

My main questions are: do I absolutely need HashMap to make this functional? Is there something else I can use in place of HashMap, or a way to backtrack it to a more basic function? If both are a “no”, does anyone have any recommendations on what I can do instead?

Thank you so much for your time if you read this! Even just a “no, sorry” is a ton of help!

// BASE: By Chrisir https://forum.processing.org/two/discussion/9562/simple-choose-your-own-adventure.html

final int startScreen = 0; // final = int cannot be changed at any point
final int playGame = 1;

int state = startScreen;
String globalSelectionNumb;

Choice[] choices =
  {
  new Choice("1", "this the start of the game", "GO ON #2"),
  new Choice("2", "this is where the body goes", "do you GO ON #3", "or GO BACK #1"),
  new Choice("3", "congrats! you won", "START OVER #1"),
};

HashMap<String.Choice> allChoices = new HashMap<String.Choices>(); // for looking up options; all choices go to choices, go to number lookup(?)

  Choices currentChoice; // current choice that's displayed on screen

ArrayList<String> choiceUsed = new ArrayList<String>(); // choices that have been used so far

void setup()
{
  size(500, 500);

  for (Choice ch : choices)
  {
    allChoices.put (ch.numb, ch);
  }

  currentChoice = allChoices.get("1"); // choices start with number one
  globalSelectionNumb = "1";
  choiceUsed.add(currentChoice.body);

  state = startScreen;
}

void draw()
{
  background (255, 0, 0);

  switch(state) // allows for different game screens
  {
  case startScreen:
    showStartScreen();
    break;
  case playGame:
    play();
    break;
  default:
    println ("not sure what this is for yet");
    exit();
    break;
  }
}

void showStartScreen()
{
  fill(0, 255, 0);

  textSize(30);
  text("GAME TITLE", 250, 20);

  textSize(20);
  textLeading(15);
  text("information", 50, 50);
  text("more information /n"
    + "even more info", 50, 105); // /n = new line

  text("press any key.", 250, 250);
}

void play()
{
  fill(0);
  textSize(20);
  text(currentChoice.body, 10, 30);

  int y = 390;
  int toChoose = 1;
  for (String chs : currentChoice.options)
  {
    String [] myArray = split(chs, "#");
    text(toChoose++ + ":" + myArray[0], 20, y);
    y +=22;
  }

  // to test:
  text (globalSelectionNumb, width-30, height-30);
}

void keyPressed()
{
  switch(state)
  {
  case startScreen:
    state = playGame;
    break;
  case playGame:
    int optionNB = currentChoice.options.length;
    int cont = key - '1';
    if (cont <0 || cont >= optionNB)
      return;

    String contOn = currentChoice.options[cont];
    String [] myArray = split(contOn, "#");

    String contNumb = myArray[1];

    globalSelectionNumb = contNumb;
    choices chosen = choices.get(contNumb);

    if (chosen != null)
    {
      currentChoice = choices.get(contNumb);
      choiceUsed.add(currentChoice.body);
    }

    break;
  default:
    println("still don't know what this does");
    exit();
    break;
  }
}

class Choice
{
  String numb; // position in the array lineup, used to move to next option (i.e, move from line one to line fifty)
  String body; // body of text (i.e "you find yourself in a dark room")
  String[] options; // actual part that allows movement to next option (i.e, type 3 to move to line 3);

  //Choice (String n, String b, String o);
  Choice(String n, String b, String... o) // "..." allows for more than one option
  {
    numb = n;
    body = b;
    options = o;
  }

  String toString() // the string within a string
  {
    return numb + "-" + body + "(" + options.length +")";
  }
}

Hello @moffmix ,

Please scrutinize your code.

Your code:

See reference:

There should be commas in there.

Try renaming some of the similar names (Choice, choice, choices) to help debug this.

I did finally get something working… but then after a few choices an:
ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3

Update:

You are accessing elements of an array, ArrayList and HashMap.
Do a bit of research on how to access these.

Once I corrected the names and accessed these elements things seemed to work.

//choices chosen = choices.get(contNumb);   //Before :(
Choice chosen = choices[int(contNumb)-1];   // After :)

:)

2 Likes

I agree with @glv your choice of class and variable names is confusing.

If we think of an Adventure game we can consider it to be a collection of states where each state would represent a location or activity. For instance

  • You are in a dark cave …
  • You come face-to-face with Zoran an evil wizard …
  • You are hungry and need to find food …

So my choice would be call the main class State, where each state is given a unique String identifier.

If you do this a hash map would be an ideal choice because each state can be retrieved using the identifier in constant time (very fast).

There are always alternatives, you could use a sorted (by identifier) array of states sorted by their identifier, a binary search would be almost as fast as the HashMap but would involve a lot more coding on your part.

So in conclusion I think that a HashMap<String, State> is the best choice of data structure.

The large amount of data needed for an adventure game rules out hard-coding the state data. It would be better to store the game data in a text file e.g. JSON format which can be read in at runtime to create the State objects. Something else for you to look at. :smile:

3 Likes

there is a newer version of this here Switching between scenes with buttons as choices - #16 by Chrisir

Hi there! Thanks for pointing that out - I did have commas originally, but at some point I got frustrated and started guessing and checking all my punctuation ^^; besides that, thanks so much for your imput !

Hi there! I just wanted to thank you for your help! Unfortunately, I came to the conclusion this project is a little too advanced for me right this second, but if I ever decide to revisit it, future-me will be just as appreciative !

1 Like