Use variable instead of keycode unity - c#

Okay so I'm trying to make a system that picks a random word then it turns that word into a char array. Then it will track if you type the characters. But the method that I'm trying to do hasn't been working. mainly because it won't let me use a variable name as a keycode. Is this a worthwhile problem, or should I abort mission and try something else.
string currentWord = wordArray[Random.Range(0, typingWords.Length)];
char[] wordAsArray = currentWord.ToCharArray();
Keycode currentLetter = wordAsArray[0];
if (Input.GetKey(currentLetter))
{
Debug.Log("Test");
}
most of this works fine but what doesn't work the problem is the if (Input.GetKey(currentLetter))
is there something that can turn the word into a KeycodeArray or something like that or turn the specific character into keycode.
Does anybody know if this problem is solvable or will I have to use another method.

is there something that can turn the word into a KeycodeArray or something like that or turn the specific character into keycode.
There is not a built-in function for that. You can create a keycode array with each keycodes in it and use that to determine current letter. Like:
KeyCode[] letterCodes = new KeyCode[] {
KeyCode.A, KeyCode.B, KeyCode.C, ... KeyCode.Z
};
KeyCode currentLetterCode = letterCodes[wordAsArray[0] - 'A'];
'A' is subtracted from it to get the index of the letter in the letterCodes array. This assumes that the word only contains uppercase letters.
Instead of that method i would use a different approach. I will write down a complete example of how i would do it with comments.
public class TypingGame : MonoBehaviour
{
public Text wordText;
private string currentWord;
private int currentIndex;
private void Start()
{
// Pick a random word to type
currentWord = GetRandomWord();
// Display the word on screen
wordText.text = currentWord;
}
private void Update()
{
// Check if the current letter has been typed
if (Input.anyKeyDown)
{
KeyCode keyPressed = GetKeyPressed();
if (keyPressed != KeyCode.None && keyPressed == GetNextKeyCode())
{
currentIndex++;
if (currentIndex >= currentWord.Length)
{
// The word has been completely typed
currentWord = GetRandomWord();
wordText.text = currentWord;
currentIndex = 0;
}
else
{
// Update the display to show the next letter
wordText.text = currentWord.Substring(currentIndex);
}
}
}
}
private string GetRandomWord()
{
// Replace this with your own word selection logic
string[] words = { "cat", "dog", "bird", "fish" };
return words[Random.Range(0, words.Length)];
}
private KeyCode GetNextKeyCode()
{
char nextChar = currentWord[currentIndex];
KeyCode keyCode = (KeyCode)System.Enum.Parse(typeof(KeyCode), nextChar.ToString().ToUpper());
return keyCode;
}
private KeyCode GetKeyPressed()
{
foreach (KeyCode keyCode in System.Enum.GetValues(typeof(KeyCode)))
{
if (Input.GetKeyDown(keyCode))
{
return keyCode;
}
}
return KeyCode.None;
}
}
GetNextKeyCode method converts the next letter in the word to a KeyCode value by converting the letter to uppercase and using System.Enum.Parse to look up the corresponding KeyCode value.
GetKeyPressed method checks which key was pressed and returns the corresponding KeyCode value by looping over all possible KeyCode values and checking which one has been pressed using Input.GetKeyDown.

Related

Compare the text array and the input array

I have an array of text and an array of fields, I need to implement so that when a user enters a value in a field, the value is compared with the text for this field. I.e., for example, the number "12" is written in one text field, and the user entered "13" and "Not correct" was output to the log, and there are 6 such fields and text. (this is the solution of the number 6+6=12) Please tell me how to do it better, I started doing this:
public InputField[] Inputfield1;
public Text[] text1;
public void CurBtn()
{
foreach (InputField inputField in Inputfield1)
{
for (int i = 0; i < text1.Length; i++)
{
for (int j = 0; j < Input_Numer_1.Length; j++)
{
if (text1[i].ToString() == Inputfield1[j].text)
{
Debug.LogFormat($"OK");
}
else{
Debug.LogFormat($"Not correct");
}
}
}
}
Text is a UnityEngine.Object and Object.ToString basically returns the GameObjects name like Text.name.
You rather would want it's UI.Text.text
if(text1[i].text == Inputfield1[j].text)
However, why not rather actually store int values and use int.TryParse to convert your user input to a numeric values and rather compare int based which is way more efficient.
You also have one loop to much there .. currently you iterate the inputs twice.
To me it sounds like you don't even want to compare each input to each text but rather have certain pairs of both you want to compare like
[Serializable]
public class CheckPair
{
public InputField Input;
public Text Text;
public bool Compare()
{
var correct = Text.text == Input.text;
Debug.Log($"{correct ? "" : "NOT "} correct", Input);
return correct;
}
}
And in the Inspector rather assign these in a single
public CheckPair pairs;
and then
public void CurBtn()
{
foreach (var pair in pairs)
{
pair.Compare();
}
}
or if you e.g. want to know if all are correct
public void CurBtn()
{
foreach (var pair in pairs)
{
if(!pair.Compare())
{
Debug.Log($"{pair.Input} is not correct!");
return;
}
}
Debug.Log("All are correct!");
}

How can I set a char variable to the KeyCode of Input.GetKey?

I'm trying to make a cheat code system. I had an array of chars. I want to assign whatever input the player puts in to that char, and then ill change the index to the next char and repeat with that. At the end I want to combine all the chars together to a string and see if that's a cheat code. If it is then the player will get a powerup or whatever.
I basically want the char to be whatever button I press. Is there any better way to do it that's not like this:
if (Input.GetKeyDown(KeyCode.A))
{
CodeAttempt[index] = 'a'
index++;
}
if (Input.GetKeyDown(KeyCode.C))
{
CodeAttempt[index] = 'b'
index++;
}
if (Input.GetKeyDown(KeyCode.C))
{
CodeAttempt[index] = 'c'
index++;
}
And so on?
You can use Input.anyKeyDown and Input.inputString (case-sensitive):
private void Update()
{
if( Input.anyKeyDown )
{
foreach( char c in Input.inputString )
CodeAttempt[index++] = char.ToLowerInvariant( c );
}
}
As far as I know, Unity doesn't have built-in KeyCode to char mappings.
I found a Gist that has a char to KeyCode dictionary. Simply swap the keys and values and you should be good to go: https://gist.github.com/b-cancel/c516990b8b304d47188a7fa8be9a1ad9
I don't want to put the code here in the answer since it is too long, but I made a fork in case the original Gist goes down: https://gist.github.com/starikcetin/62506e691ecd465159a235fb7acb44f0
Edit: Why don't you keep your cheat code in the form of a KeyCode array? Then you don't have to deal with chars.

TopCoder Alogirithm System Test Failure

I am doing a problem from Top-Coder.The problem statement is-
One day, Jamie noticed that many English words only use the letters A
and B. Examples of such words include "AB" (short for abdominal),
"BAA" (the noise a sheep makes), "AA" (a type of lava), and "ABBA" (a
Swedish pop sensation).
Inspired by this observation, Jamie created a simple game. You are
given two Strings: initial and target. The goal of the game is to find
a sequence of valid moves that will change initial into target. There
are two types of valid moves:
Add the letter A to the end of the string. Reverse the string and then
add the letter B to the end of the string. Return "Possible" (quotes
for clarity) if there is a sequence of valid moves that will change
initial into target. Otherwise, return "Impossible".
Below is my solution of the problem which passed all the tests in the Panel but failed in system test.But,I did not get any specific information about which test case failed.Please check if my code will not work in some scenario.
class ABBA
{
public string canObtain(string initial,string target)
{
string s = "Impossible";
if (initial.Length > target.Length)
return "Impossible";
if (initial.Equals(target))
return "Possible";
if (CheckFirstWay(target,initial))
{
s=canObtain(initial+"A",target);
}
if (s.Equals("Impossible") && CheckSecondWay(target,initial))
{
s=canObtain(ReverseStringDirect(initial) + "B",target);
}
return s;
}
public static string ReverseStringDirect(string s)
{
char[] array = new char[s.Length];
int forward = 0;
for (int i = s.Length - 1; i >= 0; i--)
{
array[forward++] = s[i];
}
return new string(array);
}
private static bool CheckSecondWay(string final, string initial)
{
if (final.Contains(ReverseStringDirect(initial) + "B") || final.Contains("B"+initial))
{
return true;
}
else
{
return false;
}
}
private static bool CheckFirstWay(string final1, string initial)
{
if (final1.Contains(initial + "A") || final1.Contains(ReverseStringDirect(initial+"A")))
{
return true;
}
else
{
return false;
}
}
}
You can check on which test failed by following procedure,
Go to the specified room.
Open the problem.
Compile.
Submit it.
Then go to run system test.
you will see the error test there.
OR
Select the match from here.
Then in the page as shown you will see set of blue coders and red coders who topped the match.
Select any one player as per your division. [.] --> this logo beside name.
Then check their solution you will see those tests.
Here are the test cases..check it out.
You have to type system tests here. You can check the image below. Image credit : Google

Key Listner in a console application using multithreading

I have to create this console based application and I have this problem:
I have created something like a KeyListener using multithreading (can't do simple loop, because there is a second thread running simultaneously).
And the loop in a thread needs to check if pressed key is an integer.
What is that I don't understand?
The way I get this: there is an infinite loop within the thread that tries to capture the input and if the input == 1 it writes text in the console.
What am I missing?
static void KeyRead()
{
do
{
int i = (int) Console.ReadKey().KeyChar;
if (i == 1) {
Console.Out.Write("Key 1 pressed");
}
} while (true);
}
static void Main(string[] args)
{
Thread keyListner = new Thread(new ThreadStart(KeyRead));
keyListner.Start();
}
KeyChar returns value of type char and casting char to int returns unicode value representing that character. But character '1' have unicode value 49, not 1. So you have to modify condition to compare i to be eqaual to 49 instead of 1.
static void KeyRead()
{
do
{
int i = (int)Console.ReadKey().KeyChar;
if (i == 49)
{
Console.Out.Write("Key 1 pressed");
}
} while (true);
}
But it is even beter to avoid this integer conversion altogether and compare character directly:
static void KeyRead()
{
do
{
char c = Console.ReadKey().KeyChar;
if (c == '1')
{
Console.Out.Write("Key 1 pressed");
}
} while (true);
}

TPIN number validation in java, c++ or c#

I have small requirement for TPIN validation in my college project, The requirement is, we should not allow the user to set his TPIN in the below scenarios .
TPIN should not be in sequence. (either ascending or descending ex: 123456, 456789, 987654 or 654321)
TPIN should not start from Zero (ex: 0127865, 098764)
TPIN should not be repetitive digit (ex: 888888,222222 etc.)
For the third one my idea is to divide the number by 11 and check for the reminder..
Any ideas plz..
public class Validate
{
public static void main(String[] args)
{
int iTpin = Integer.parseInt(args[0]); // Converted string to int
System.out.println("The entered TPIN is:"+iTpin);
boolean flag = validate(iTpin);
if (flag== true)
System.out.println("The entered TPIN is valid");
else
System.out.println("The entered TPIN is Invalid");
}
public static boolean validate(int passedTpin)
{
if (passedTpin == 0)
return false;
else if ( passedTpin%11 == 0)
return false;
else
return true;
}
}
Finally created code for the sequence of digits. It might be useful for others
private static boolean containsRepetitiveDigits(String tpin) {
char firstChar = tpin.charAt(0);
for (int i = 1; i < tpin.length(); i++) {
char nextChar = tpin.charAt(i);
if ((Character.valueOf(nextChar)).compareTo(Character
.valueOf(firstChar)) != 0) {
return false;
}
}
System.out.println("Error:TPIN contains repetitive digits");
return true;
}
For start, using Int32 to store a number means it shouldn't exceed 2,147,483,647. And apart from this, you won't be able to check for the leading zero once you have converted to a number, since leading zeros obviously disappear once you get a number.
This means you should keep the input as a string during validation. This actually makes your job easier, since you can index individual characters, without the need to use arithmetic operations.
Since you are working with strings, you should also check if the input string contains invalid (non-digit) characters before anything else:
bool ContainsInvalidCharacters(string input)
{
// check if there is a non-digit character
foreach (char c in input)
if (!char.IsDigit(c))
return true;
return false;
}
Then you can continue adding individual rules. For example, to check if characters are repeating, you will do something like:
bool ContainsRepetitiveDigits(string input)
{
if (input.Length == 0)
return false;
// get the first character
char firstChar = input[0];
// check if there is a different character
foreach (char c in input)
if (c != firstChar)
return false;
// if not, it means it's repetitive
return true;
}
bool StartsWithZero(string input)
{
if (input.Length == 0)
return false;
return (input[0] == '0');
}
To detect sequences, the most straightforward way is to get the difference of first two characters, and then check if it changes through the entire string:
bool IsSequence(string input)
{
// we need at least two characters
// for a sequence
if (input.Length < 2)
return false;
// get the "delta" between first two
// characters
int difference = input[1] - input[0];
// allowed differences are:
// -1: descending sequence
// 0: repetitive digits
// 1: ascending sequence
if (difference < -1 || difference > 1)
return false;
// check if all characters are equally
// distributed
for (int i = 2; i < input.Length; i++)
if (input[i] - input[i - 1] != difference)
return false;
// this is a sequence
return true;
}
Once you've defined all of your rules, you can create a single method which will test them one by one:
bool Validate(string input)
{
// list of all predicates to check
IEnumerable<Predicate<string>> rules = new Predicate<string>[]
{
ContainsInvalidCharacters,
ContainsRepetitiveDigits,
StartsWithZero,
IsSequence
};
// check if any rule matches
foreach (Predicate<string> check in rules)
if (check(input))
return false;
// if no match, it means input is valid
return true;
}
Note that IsSequence detects repetitive digit patterns also (when character difference is zero). If you want to explicitly prevent this, alter the condition where allowed differences are checked. Alternatively, you can remove the ContainsRepetitiveDigits rule altogether.
[Edit]
Since I see you are using Java instead of C#, I will try to provide a better example.
Disclaimer: I don't usually program in Java, but from what I know, Java doesn't support delegates the way C# does. So I will try to provide a Java example (hope it will work), which expresses my "composite validation" intent better.
(Suspicious Java code follows)
First, define an interface which all validation rules will implement:
// (java code)
/**
* Defines a validation rule.
*/
public interface IValidationRule
{
/**
* Returns a description of this
* validation rule.
*/
String getDescription();
/**
* Returns true if this rule
* is matched.
*/
boolean matches(String tpin);
}
Next, define each rule in a separate class, implementing both getDescription and matches methods:
// (java code)
public class RepetitiveDigitsRule implements IValidationRule
{
public String getDescription()
{
return "TPIN contains repetitive digits";
}
public boolean matches(String tpin)
{
char firstChar = tpin.charAt(0);
for (int i = 1; i < tpin.length(); i++)
if (tpin.charAt(i) != firstChar)
return false;
return true;
}
}
public class StartsWithZeroRule implements IValidationRule
{
public String getDescription()
{
return "TPIN starts with zero";
}
public boolean matches(String tpin)
{
if (tpin.length() < 1)
return false;
return tpin.charAt(0) == '0';
}
}
You can see that matches method does not print anything to console. It simply returns true if rule is matched, and leaves to its caller to decide whether to print its description (to console, a message box, web page, whatever).
Finally, you can instantiate all known rules (implementations of IValidationRule) and check them one by one:
// (java code)
public class Validator
{
// instantiate all known rules
IValidationRule[] rules = new IValidationRule[] {
new RepetitiveDigitsRule(),
new StartsWithZeroRule()
};
// validate tpin using all known rules
public boolean validate(String tpin)
{
System.out.print("Validating TPIN " + tpin + "... ");
// for all known rules
for (int i = 0; i < rules.length; i++)
{
IValidationRule rule = rules[i];
// if rule is matched?
if (rule.matches(tpin))
{
// print rule description
System.out.println("Error: " + rule.getDescription());
return false;
}
}
System.out.println("Success.");
return true;
}
}
I recommend trying to follow this pattern. You will end up with code much easier to reuse and maintain.
You can generate sequetial tpin (ascending & decending) based on the first digit then compare it to the inputted tpin. If it matches then it is invalid.
public static bool IsSequential(string pin, bool descending)
{
int p = Convert.ToInt32(pin.Substring(0,1));
string tpin = string.Empty;
for (int i = 0; i < 6; i++)
{
tpin += descending ? (p--).ToString() : (p++).ToString();
}
return pin.Equals(tpin);
}
For item 3, you cannot just divide by 11 because some pin will have remainder 0. (i.e. 221199 is a valid one but the remainder is 0). You can get the first digit and use a loop to compare to the remaining digits.

Categories