I've been stuck on this for a while now and i cant seem to get it to work. I want my program to be able to select a random word from the "Words" array (array contents previously added by the user) and allow the user to then enter another word and see if it matches the randomly selected word selected by the program from the array. If the words match a message will be out put but if not a message will also be output but the system should indicate to the user if any letters that they had entered were in the random String. I know this is quite a bit but I've been stuck for ages haha, thanks!
Here is part of the code i have been using, a bit simplified.
private void btnGuess_Click(object sender, EventArgs e)
{
string guess = txtGuess.Text;
string[] words = new string[6];
lstWords.Items.Add(txtEnterWord.Text);
Random rand = new Random();
for (int i = 0; i < words.Length; i++)
{
words[i] = rand.ToString();
}
if (String.Equals(guess, rand))
{
MessageBox.Show("Congratulations you have won! Your words are a match");
}
else
{
MessageBox.Show("Sorry but your words are not a match, try again");
}
}
you have to
initialize your words array with actual words
have a method that picks up a random word from words array
like follows:
private void btnGuess_Click(object sender, EventArgs e)
{
string guess = txtGuess.Text;
string[] words = new string[6] { "word1", "word2", "word3", "word4", "word5", "word6" }; //<--| initialize words array
lstWords.Items.Add(txtEnterWord.Text); //<--| what is that for?
string randWord = GetRandomWord(words); //<--| get rabdom word from words array
if (String.Equals(guess, randWord))
{
MessageBox.Show("Congratulations you have won! Your words are a match");
}
else
{
MessageBox.Show("Sorry but your words are not a match, try again");
}
}
static private string GetRandomWord(string[] words)
{
Random rnd = new Random();
return words[rnd.Next(0, words.Length)].ToString();
}
Random rand = new Random()
for (int i = 0; i < words.Length; i++)
{
words[i] = rand.ToString();
}
In this loop you're assigning the output of rand.ToString() to every element in your array. If you looked at the array after the loop every element would then be "System.Random" because calling the ToString method on an object of type Random returns the type of the object, as a string.
When you create a new Random object you're creating an object. An object that can return you random numbers. You're NOT creating a random number.
You're wanting to pick one of the strings out of the array, this is how you can get it out.
string thirdWordFromMyArrayOfWords = words[3];
To get a random number using Random that will be within the range of your words element:
int randomNumberWithinTheRangeOfMyArray = rand.Next(0,words.Length-1)
You need to subtract one because the array has 6 elements (words.Length = 6) but it starts counting at zero 0,1,2,3,4,5 so if you tried to reference words[6] you'll throw an exception.
int randomNumberWithinTheRangeOfMyArray = rand.Next(0,words.Length-1);
string randomWordFromArray = words[randomNumberWithinTheRangeOfMyArray];
if (String.Equals(guess, randomWordFromArray))
and it can be further condensed
if (String.Equals(guess, words[rand.Next(0,words.Length-1)]))
Something else to consider is that since your calling for a new random number every time the button is clicked you'll get a new random number and therefore a new random word out of the array.
using System;
using System.Collections.Generic;
using System.Linq;
namespace RandomWords
{
class Program
{
static void Main(string[] args)
{
string[] words = new[] { "csharp", "Stack", "overflow", "microsoft", "word5", "Coding"};
Random rnum = new Random();
string input = null;
while ( input != "end") {
int intnum = rnum.Next(0, words.Length);
Console.WriteLine("Guess a word or enter end to exit");
input = Console.ReadLine();
List<string> l = words.Where(x => x == input).ToList<string>();
if (l.Count != 0) { Console.WriteLine("Congratulations you have won! Your words are a match"); } else { Console.WriteLine("Sorry but your words are not a match, try again"); }
}
}
}
}
Related
This is the exercise that I have to deal with:
You are given a word and a list of words. Your task is to check
whether all the words from the list are anagrams of the word. Input
Read from the standard input
On the first line, find W - the word to check against; On the second
line, find N - the number of words in the list of words WORDS; On the
next N lines, the words from WORDS; Output Print to the standard
output
For each word from WORDS print either: "Yes", if the word is an
anagram of W; "No", if the word is NOT an anagram of W;
And this is my code:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
string word1 = Console.ReadLine();
char[] mainWord = word1.ToLower().ToCharArray();
Array.Sort(mainWord);
int numberOfWords = int.Parse(Console.ReadLine());
List<Array> anagramWords = new List<Array>();
for (int i = 0; i < numberOfWords; i++)
{
string wordForList = Console.ReadLine();
char[] wordCharacters = wordForList.ToLower().ToCharArray();
Array.Sort(wordCharacters);
anagramWords.Add(wordCharacters);
}
foreach(object word in anagramWords)
{
if (word == mainWord)
{
Console.WriteLine("Yes");
}
else
{
Console.WriteLine("No");
}
}
}
}
For some reason, the answer that I get is always No.
if (word == mainWord)
doesn't compare the content of the word array with the content of the mainWord array.
Array variables are references types, or, in other words, they just contain the reference to the memory area where the elements of the array are really stored.
So if you compare the two arrays in that way you are comparing
two values (two references) that point to the memory area where the respective elements are stored. Of course these values are different because, even if the arrays contain the same characters, the elements are stored in different memory areas.
To solve your problem a different approach is needed.
Something like this should work
static void Main()
{
string word1 = Console.ReadLine();
IEnumerable<char>mainWord = word1.ToLower().OrderBy(w => w);
int numberOfWords = int.Parse(Console.ReadLine());
List<IEnumerable<char>> anagramWords = new List<IEnumerable<char>>();
for (int i = 0; i < numberOfWords; i++)
{
string wordForList = Console.ReadLine();
IEnumerable<char> wordCharacters = wordForList.ToLower().OrderBy(fl => fl);
anagramWords.Add(wordCharacters);
}
foreach (var word in anagramWords)
{
// Here we are asking to compare the full set of elements
// with each other and we find if they contain the same data.
if (word.SequenceEqual(mainWord))
{
Console.WriteLine("Yes");
}
else
{
Console.WriteLine("No");
}
}
}
This question already has answers here:
Check if a value is in an array (C#)
(10 answers)
Closed 4 years ago.
I'm working on a problem and i've tried it every way I can think of with a for loop but i can't figure out how to make it work as I only started on c# and programming as a whole a few weeks ago.
Write an app that inputs five numbers. As each number is read search the array if the number doesn’t exist in the array output the word “new” and insert the number into the array. If the number does exist in the array output “exists”. Once all five numbers have been entered output the content of the array.
This is what I have so far. Thanks for any help
using System;
public class Program
{
// Main method begins execution of C# application
public static void Main(string[] args)
{
int[] array = new int[5];
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine("Enter a number:");
array[i] = Convert.ToInt32(Console.ReadLine());
for (int a = 0; a < 5; a++)
{
if (array[i] != array[a])
{
array[i] = int.Parse(Console.ReadLine());
Console.WriteLine("new\n");
}
}
array[i] = int.Parse(Console.ReadLine());
Console.WriteLine("exists\n");
}
Console.WriteLine(array);
Console.ReadKey();
}
} // end class
First of all try thinking about a solution before you actually start writing some code, couple of hints
You expect some user input, we will use a variable to save the user input
You need to validate that the values does not exist in you array or structure, this can be done using the Contains method.
If it exists we continue to the next user input and print the required message.
If the value does not exists we add the value and print the new message
We will do this until the Count of the structure is equal to 5.
for reference use this While loop, Hashset.Contains and Hashset
try this:
var numbers = new HashSet<int>();
while(numbers.Count < 5)
{
Console.WriteLine("Enter a number:"); //1.
var number = Convert.ToInt32(Console.ReadLine());
if (numbers.Contains(number)) // 2.
{
Console.WriteLine("exists\n"); //3.
continue;
}
Console.WriteLine("new\n"); //4.
numbers.Add(number);
}
foreach (var n in numbers)
{
Console.WriteLine(n);
}
Use .Any() in System.Linq. Also, you don't need to continuously grab user input in your loop:
using System;
using System.Linq;
public class Program
{
// Main method begins execution of C# application
public static void Main(string[] args)
{
int[] array = new int[5];
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine("Enter a number:");
// Get user input and convert to integer:
int input = Convert.ToInt32(Console.ReadLine());
// Check if given input is already in the array:
if (! array.Any(number => number == input))
{
array[i] = input;
Console.WriteLine("new\n");
}
else
{
Console.WriteLine("exists\n");
}
}
// Print the contents of array separated by ','
Console.WriteLine(string.Join(", ", array));
Console.ReadKey();
}
}
Edit: Another variant if you want the user to fill the array completely:
using System;
using System.Linq;
public class Program
{
public static void Main(string[] args)
{
// Btw, if this is not an array of nullables,
// we will not be able to insert a zero later, as
// we will treat them as duplicates.
int?[] array = new int?[5];
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine("Enter a number:");
int input = 0;
bool duplicateAttempt = false;
do {
// Get and convert the input.
input = Convert.ToInt32(Console.ReadLine());
// See if this number is already in.
duplicateAttempt = array.Contains(input);
// Report if we attempt to insert a duplicate.
if (duplicateAttempt) Console.WriteLine("exists");
}
while (duplicateAttempt); // Keep asking while we don't get a unique number.
array[i] = input; // Store the number
Console.WriteLine("new");
}
// Print the contents of array separated by ','
Console.WriteLine(string.Join(", ", array));
Console.ReadKey();
}
}
A couple of issues with your code. You should only increment the array index if successful - otherwise the missing values will be zero. It's also a good idea to validate the input in case the user entered an invalid value. You can use linq to check if the value already exists in the array:
Here's an example:
static void Main(string[] args)
{
int[] array = new int[5];
var index = 0;
while (index < array.Length)
{
Console.WriteLine("Enter a number:");
var input = Console.ReadLine();
var value = 0;
if (!int.TryParse(input, out value))
{
Console.WriteLine("Error - value entered was not a number");
}
else
{
var match = array.Where(a => a == value);
if (match.Any())
{
Console.WriteLine("exists\n");
}
else
{
array[index] = value;
Console.WriteLine("new\n");
index++;
}
}
}
foreach (var item in array)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
This appears to be a homework question, so I think it's more helpful to explain what you've done wrong and tell you what you should do...
It won't help you learn to copy and paste other people's answers.
using System;
public class Program
{
// Main method begins execution of C# application
public static void Main(string[] args)
{
int[] array = new int[5];
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine("Enter a number:");
// you are putting the value into your array here. so it will always 'exist' below
array[i] = Convert.ToInt32(Console.ReadLine());
// you need to do this check before you insert the number into the array
// put the ReadLine into a variable, not directly into the array.
// then check if it's in the array already
for (int a = 0; a < 5; a++)
{
if (array[i] != array[a])
{
// here you are trying to read another value from the user.
// Console.ReadLine() will always wait for user input
// use the variable from above. but only after you have looped through all the items.
// and verified that it is not present
array[i] = int.Parse(Console.ReadLine());
Console.WriteLine("new\n");
}
}
// this is the third time you have assigned the number to the array
// and the third time you've asked for user input per loop
array[i] = int.Parse(Console.ReadLine());
Console.WriteLine("exists\n");
}
Console.WriteLine(array);
Console.ReadKey();
}
} // end class
To summarize:
you need a for loop that runs 5 times.
The for loop will do the following:
assign the user input to a variable
loop through your array (second loop) and see if it contains this variable
if the number is found, set a boolean to true. (found)
if after the loop is over, found = false, then print false
also add the number to the array (at the index of the outer loop is fine)
I'm trying to create something that will be like a basic random password generator including uppercase, lowercase and digits - but for some reason this
static void Main(string[] args)
{
bool validLength = false;
int userDefinedLength = 0;
Console.WriteLine("How many characters would you like your password to be?");
do
{
try
{
userDefinedLength = int.Parse(Console.ReadLine());
validLength = true;
if (userDefinedLength < 3)
{
Console.WriteLine("Please enter something larger than 3.");
validLength = false;
}
}
catch (Exception)
{
Console.WriteLine("Please input a valid integer length.");
}
} while (validLength == false);
char[] passwordArray = new char[userDefinedLength];
int asciiValue = 0;
char asciiChar = ' ';
bool validPassword = false;
Random ranAsciiGroup = new Random();
Random ascValue = new Random();
do
{
for (int i = 0; i < passwordArray.Length; i++)
{
int randomAsc = 0;
randomAsc = ranAsciiGroup.Next(1, 4);
//Console.WriteLine(randomAsc);
if (randomAsc == 1)
{
asciiValue = ascValue.Next(65, 91);
//Console.WriteLine(asciiValue);
}
else if (randomAsc == 2)
{
asciiValue = ascValue.Next(97, 123);
//Console.WriteLine(asciiValue);
}
else if (randomAsc == 3)
{
asciiValue = ascValue.Next(48, 58);
//Console.WriteLine(asciiValue);
}
asciiChar = (char)asciiValue;
passwordArray[i] = asciiChar;
//validPassword = true;
}
bool isDigit = false;
bool isUpper = false;
bool isLower = false;
for (int i = 0; i < passwordArray.Length; i++)
{
if (char.IsDigit(passwordArray[i]))
{
isDigit = true;
}
if (char.IsUpper(passwordArray[i]))
{
isUpper = true;
}
if (char.IsLower(passwordArray[i]))
{
isLower = true;
}
}
if (isDigit == true && isUpper == true && isLower == true)
{
validPassword = true;
}
} while (validPassword == false);
Console.WriteLine("Your password is...");
Console.ForegroundColor = ConsoleColor.DarkGreen;
foreach (char c in passwordArray)
{
Console.Write(c);
}
Console.ReadLine();
}
The password that it produces seems to not be using any numbers that are less than 6. And some of the characters that it produces are quite repeated - e.g. the lower case tend to have characters that appear much more than some others - or some that don't appear at all. I'll leave a 100 character example here.
m9nj88m8GBpF7Hk87E8p9CAE987pEj7pm7j89iHplo7DIpB87B9irlAk9Ik9C8q8i97B9o8l8GDjj88j898Dmk9A69969Ino988I
Seed your RNG
Don't forget to seed your instance of random, e.g.
var random = new System.Random(Environment.TickCount);
Also, one instance should be enough.
Eliminating repetition
If you wish to ensure that all characters are represented, you can use a different random selection technique. For example, you could generate a very very long string that contains all the characters you want, sort it randomly, then take the first n characters. This approach would completely eliminate repeated characters and guarantee that every character gets used eventually. For example:
using System;
using System.Linq;
public class Program
{
static readonly Random _random = new System.Random(Environment.TickCount);
const string dictionary = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklpmnopqrstuvwxyz0123456789!##$%^&*()_+-=";
static string GetPassword(int length)
{
return new String
(
dictionary
.OrderBy( a => _random.NextDouble() )
.Take(length)
.ToArray()
);
}
public static void Main()
{
var s = GetPassword(30);
Console.WriteLine(s);
}
}
In this example we treat the string as an Enumerable<char> (yes, this is allowed) and use LINQ methods to sort it randomly and take the first n characters. We then pass the results to the constructor for a new System.String containing the answer.
Sample output:
Run #1:
!#t(hfTz0rB5cvKy1d$oeVI2mnsCba
Run #2:
y7Y(MB1pWH$wO5XPD0b+%Rkn9a4F!_
Run #3:
tH92lnh*sL+WOaTYR160&xiZpC5#G3
Looks pretty random to me.
Controlled repetition
The above solution of course only allows at most one instance of each character in the dictionary. But maybe you want them to be able to appear more than once, but not too much. If you'd like a controlled, limited number of possible repeats, you can make a small change:
static string GetPassword(int length, int maxRepeats)
{
return new String
(
Enumerable.Range(0, maxRepeats)
.SelectMany( i => dictionary )
.OrderBy( a => _random.NextDouble() )
.Take(length)
.ToArray()
);
}
In this example we clone the dictionary maxRepeats times and concatenate them using SelectMany. Then we sort that gigantic string randomly and take the first n characters for the password.
Working code on .NET Fiddle
The System.Random class is not designed to be a strong RNG, it is designed to be a fast RNG. If you want a quality random number generator you need to use one based on the System.Security.Cryptography.RandomNumberGenerator class.
Here is a gist I found that uses a crypto random generator as the internals of the existing random class.
Running it with the new generator gives me
mm77D5EDjO0OhOOe8kppiY0toc0HWQjpo37b4LFj56LvcQvA4jE83J8BS8xeX6zcEr2Od8A70v2xFKiY0ROY3gN105rZt6PE8F2i
which you can see appears to not have the biases you found.
I am trying to learn C# and I am making a password generator. I have set an array with the letters and number I want the program to use.
String alphabet[] = {"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
I am trying to write a piece of code in a for loop that will pick random letters or numbers any amount of length that the user inputs.
Example for
(y in alphabet (PwLength));
I just can't figure out how to get it to cycle through the loop choosing random letters.
You can use infinite random chars generator:
IEnumerable<char> GetRandomChars()
{
string alphabet =
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Random random = new Random();
while (true)
yield return alphabet[random.Next(alphabet.Length)];
}
Take first N random characters and create string:
var result = new String(GetRandomChars().Take(length).ToArray());
You should use Random here. The idea is to get the password length from user and set the allowed characters and then use Random to generate the password.
public static string CreatePassword(int passwordLength)
{
const string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789!#$?_-";
char[] chars = new char[passwordLength];
Random rd = new Random();
for (int i = 0; i < passwordLength; i++)
chars[i] = allowedChars[rd.Next(0, allowedChars.Length)];
return new string(chars);
}
String password = "";
for(int i = 0; i < USERINPUTLENGTH; i++)
{
//Get Random Char
String randomChar = alphabet[Random.next(alphabet.length)];
password += randomChar;
}
You don't need to loop over the alphabet, but loop once for each character you want in the generated password.
string GeneratePassword(int pwLength)
{
string alphabet = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var builder = new StringBuilder();
var random = new Random();
for(var i = 0; i < pwLength; i += 1) {
builder.Append(alphabet[random.Next(alphabet.Length)]);
}
return builder.ToString();
}
I have an input as
2:{{2,10},{6,4}}
I am reading this as
string input = Console.ReadLine();
Next this input has to be passed to a function
GetCount(int count, int[,] arr)
{
}
How can I do so using C#?
Thanks
You could use RegularExpressions for extracting in an easy way each token of your input string. In the following example, support for extra spaces is included also (the \s* in the regular expressions).
Remember that always is a great idea to give a class the responsibility of parsing (in this example) rather than taking an procedural approach.
All the relevant lines are commented for better understanding.
Finally, i tested this and worked with the provided sample input strings.
using System;
using System.Text.RegularExpressions;
namespace IntPairArrayParserDemo
{
class Program
{
static void Main(string[] args)
{
var input = "2:{{2,10},{6,4}}";
ParseAndPrintArray(input);
var anotherInput = "2 : { { 2 , 10 } , { 6 , 4 } }";
ParseAndPrintArray(anotherInput);
}
private static void ParseAndPrintArray(string input)
{
Console.WriteLine("Parsing array {0}...", input);
var array = IntPairArrayParser.Parse(input);
var pairCount = array.GetLength(0);
for (var i = 0; i < pairCount; i++)
{
Console.WriteLine("Pair found: {0},{1}", array[i, 0], array[i, 1]);
}
Console.WriteLine();
}
}
internal static class IntPairArrayParser
{
public static int[,] Parse(string input)
{
if (string.IsNullOrWhiteSpace(input)) throw new ArgumentOutOfRangeException("input");
// parse array length from string
var length = ParseLength(input);
// create the array that will hold all the parsed elements
var result = new int[length, 2];
// parse array elements from input
ParseAndStoreElements(input, result);
return result;
}
private static void ParseAndStoreElements(string input, int[,] array)
{
// get the length of the first dimension of the array
var expectedElementCount = array.GetLength(0);
// parse array elements
var elementMatches = Regex.Matches(input, #"{\s*(\d+)\s*,\s*(\d+)\s*}");
// validate that the number of elements present in input is corrent
if (expectedElementCount != elementMatches.Count)
{
var errorMessage = string.Format("Array should have {0} elements. It actually has {1} elements.", expectedElementCount, elementMatches.Count);
throw new ArgumentException(errorMessage, "input");
}
// parse array elements from input into array
for (var elementIndex = 0; elementIndex < expectedElementCount; elementIndex++)
{
ParseAndStoreElement(elementMatches[elementIndex], elementIndex, array);
}
}
private static void ParseAndStoreElement(Match match, int index, int[,] array)
{
// parse first and second element values from the match found
var first = int.Parse(match.Groups[1].Value);
var second = int.Parse(match.Groups[2].Value);
array[index, 0] = first;
array[index, 1] = second;
}
private static int ParseLength(string input)
{
// get the length from input and parse it as int
var lengthMatch = Regex.Match(input, #"(\d+)\s*:");
return int.Parse(lengthMatch.Groups[1].Value);
}
}
}
Not to do your work for you, you will first have to parse the whole string to find the individual integers, either using regular expressions or, as I would do it myself, the string.Split method. Then parse the substrings representing the individual integers with the int.Parse or the int.TryParse methods.
I doubt you're going to get a serious parsing answer for your custom format. If you NEED to have the value inputted that way, I'd look up some info on regular expressions. If that's not powerful enough for you, there are some fairly convienient parser-generators you can use.
Alternatively, the much more realistic idea would be something like this:
(NOTE: Haven't tried this at all... didn't even put it in VS... but this is the idea...)
int rows = 0;
string rowsInput = "";
do {
Console.Write("Number of rows:");
rowsInput = Console.ReadLine();
} while (!Int32.TryParse(rowsInput, out rows);
int columns = 0;
string columnsInput = "";
do {
Console.Write("Number of columns:");
string columnsInput = Console.ReadLine();
} while (!Int32.TryParse(columnsInput, out columns);
List<List<int>> values = new List<List<int>>();
for (int i = 0; i < rows; i++)
{
bool validInput = false;
do {
Console.Write(String.Format("Enter comma-delimited integers for row #{0}:", i.ToString()));
string row = Console.ReadLine();
string[] items = row.split(',');
int temp;
validInput = (items.Length == columns) && (from item in items where !Int32.TryParse(item, out temp) select item).count() == 0;
if (validInput)
{
values.add(
(from item in items select Convert.ToInt32(item)).ToList()
);
}
} while (!validInput);
}