Variable string inputs.
Hello everyone, new programmer here.
I've been looking around recently for information that could help me with string comparisons. I haven't found anything so far and I am not sure the tutorial on the site was able to help me.
Right now I've been trying to make a short text-based game, and to perform actions in the game the player is to type such things as "pick up X" or "open Y" into the console. This is how I would like to it be ideally.
The obvious problem is that the user has to make an exact input (i.e. to "Read Book" the user has to type "Read Book" without error. I've tried playing around with the strcmp function but I can't seem to get it to work. I would like to not have to force this, but I don't want to default on a simple 1,2,3,etc. input system.
So I'm let with two options on making it accept multiple versions of the same input: make it so the comparison could be similar, or create a strcmp for each and every variable. The latter however seems horribly inefficient because it would mean making 2+ lines of code for every spelling. This leaves the former. And I've done stuff in the past where you could read "Examine Chest" as (examine|look.*at|see).+(chest|box), which would cover many variances in input. The problem is I have no idea if that is how it works when working with C, but it is my ideal solution.
Any help on this problem would be greatly appreciated!
If that is a regular expression, you could probably use it to accept alternative words and / or spelling. It will probably get a bit messy if you try to cover both though. I guess you could express your correct answers as a list of regex strings that you use to match.
btw, you can convert all inputs to lower case before you do any comparison to deal with sporadic upcase use in the input.
Just using strcmp to try and catch a couple of the variations is a possibility - and error msg if anything else typed - if you really want to get the input without using a number menu that is- but then how will the user know what the choices are without the menu at least saying 'pick up y' or pick up x - this then means you are expecting your user to read these choices - then type the choice back in them in themselves = tedious - in a non menu system it would be great to just type in an instruction and the game gets what you want to do every time - but just try and think that through...how much complexity trying to write something like that would introduce.
In any case, you might consider a regular expression library - if you fancy learning something like that right now just to acheive this 'get input' utlity.
If i were you, for now i would just use the simple 'input choice' from a numbered list and concentrate writing a good game rather than getting embroiled in a massive input validation exercise. - Besides it is much more fun that way for you if you are a new programmer.
You could crack on with the main game as is - and start a side project investigating an improved input method - this is like a unit test - where you can examine a desired feature independently.
Just thinking of this 'allow user to freetype commands without seeing any menus - without using a regex library also - could something like Levenshtein distance algorithm be useful. - As long as the user knows that the total game commands are say: pick up, walk, open, use : And the user is also aware of the names of the
items available in the current room - The available actions in each room would have to be internalised - then when user types "pick up lantern" - This would then have to be matched against the current rooms available actions and if the distance algorithm returns a close enough match (by a pre set threshold) then play is actioned. If not error 'you cant do that here' or whatever.
I mean it would be a good catch all for the odd typo also. Dunno just prepostulating
Normally I would have to resign to defaulting to a numerical input system, but sadly it would defeat the real purpose to the game. When I said the game was short, I really did mean it was short. It literally only has one room, and that's the extent of it. I wanted to use making the game as a platform to learn C with, since if you do something you remember it better. So yes, I am admittedly more interested in "getting embroiled in a massive input validation exercise", since that's what it truly is, an exercise. If it were a longer game then I'd definitely put much more thought into playability and enjoyability, but for now I want to focus on more of the "could" than the "should."
I suppose it does answer my question in that sadly there is no method in C that can truly do it. But the library idea is something I will definitely explore, and this distance algorithm sounds similar to what I had in mind. In fact I had seen a couple of things about this algorithm floating around during my search, but wasn't entirely sure if it was what I needed. So it's good to know it might be viable.
I will be a bit honest in that while I'm not neccessarily new to programming as a whole (as I've worked with visual programming in LabView for robotics, and I might have done a few hundred lines in PERL), C is definitely a new language for me and I'd imagine it takes a while to get used to it when you're used to functionalists with other languages. Ey yey yeh.
As long as the expressions are "verb the foobar" type phrases, the advice in post two is everything you need IMO.
Using a Levenshtein distance algorithm sounds interesting. It could probably be interesting to use a combination of all methods in series. That is, first apply a "preprocessing function" that removes punctuation (.,!?) and flattens the any upcase characters. Then apply a Levenshtein distance algorithm to allow a generous match and spell correction then use regular expressions to allow synonyms and omission of parts of the sentence.
Originally Posted by rogster001
It depends, if you are on a POSIX box you probably have regex.h, otherwise get pcre. A regular expression is imo probably best suitable to allow variations in the input and synonyms. For example a regex string like this:
Originally Posted by .RK
Would allow for some variation in the input, including the lazy single "woods" "forrest" answer. If you also pre-process the string to flatten the case and get rid of punctuation and multiple whitespace, even more so.
const char *woods = "^((go|travel) to (the |teh )?)?(forrest|woods)$";
I beleive C++ 11 has built in regex library - so you may consider learning c++ also