I stumbled upon problems with controll testing string in my Mastermind application - c#

well first of all I'm quite new to programing so please keep that in mind. I'm currently working on a MasterMind game, done in C# console application. I stumbled upon a problem while testing my diffrent methods. I wrote all test methods responds in the system.debug and the method that I've recived a fault from is the method "isValidKey(string key)"
I've got a "true" response form the "createSecretKey()" and the MasterMind constructor;
So I assume they are fine.
So if you could please help me find whats wrong with the "isVaildKey(string key" method I would really appreciate it.
So here is my code:
namespace MasterMind
{
class MasterMindModel
{
private string _secretKey;
public MasterMindModel()
{
_secretKey = createSecretKey();
}
private static string createSecretKey()
{
string secretKey;
string[] t_secretKey = new string[4];
Random rnd = new Random();
string symbols = "1234567";
for (int i = 0; i < 4; i++)
{
char ch = symbols[rnd.Next(symbols.Length)];
t_secretKey[i] += ch;
}
secretKey = t_secretKey[0] + t_secretKey [1] + t_secretKey[2] + t_secretKey[3];
return secretKey;
}
public static bool SelfTest()
{
bool ok = true;
for (int i = 0; i < 1000 && ok; ++i)
{
ok = isValidKey(createSecretKey());
}
System.Diagnostics.Debug.WriteLine("CreateSecretKey: " + ok);
MasterMindModel model = new MasterMindModel();
ok = isValidKey(model._secretKey);
System.Diagnostics.Debug.WriteLine("MasterMindModel constructor: " + ok);
ok = isValidKey("2361") && !isValidKey("2368")
&& !isValidKey("ABCD") && !isValidKey("+-*=")
&& !isValidKey("2301") && !isValidKey("23611")
&& !isValidKey("231");
System.Diagnostics.Debug.WriteLine("MasterMindModel isValidKey " + ok);
return ok;
}
public static bool isValidKey(string key)
{
Random rnd = new Random();
string symbols = "1234567";
for (int i = 0; i < 4; i++)
{
char ch = symbols[rnd.Next(symbols.Length)];
key += ch;
}
if (key != "2368" && key != "ABCD" && key != "+-*=" && key != "2301" && key != "23611" && key != "231")
{
key = t_key[0] + t_key[1] + t_key[2] + t_key[3];
}
return true;
}
}
}
The compiler don't give me any errors and I can't seem too figure out what the problem is.
As I said I'm quite new, so any tips on what I should research and what syntaxes I should read more about etc. I would also apprieciate it.
Also please tell me if this post is to vauge and I will delete it and make another one. It's my first post here.
Thanks.

The immediate issue I see in your method is that t_key is not defined anywhere, can't explain why compiler isn't complaining unless you are not showing all the code.

You are mixing test cases in both SelfTest and isValidKey functions. You want to keep them in one place. Also you want to make your code more flexible by not using hard coded values so much. Also don't use static if not needed, you might want to run several instances of your model at once. Below is how I would do what you are trying to achieve:
class MasterMindModel
{
private string createSecretKey(int keyLength, List<char> keyItems)
{
StringBuilder secretKey = new StringBuilder();
for (int i = 0; i < keyLength; i++)
{
secretKey.Append(keyItems[_rnd.Next(keyItems.Count)]);
}
return secretKey.ToString();
}
private bool isValidKey(string key, int keyLength, List<char> keyItems)
{
if (key.Length != keyLength)
{
return false;
}
foreach (char c in key)
{
if (!keyItems.Contains(c))
{
return false;
}
}
return true;
}
public void SelfTest()
{
int keyLength = 4;
List<char> keyItems = new List<char> { '1', '2', '3', '4', '5', '6', '7' };
Debug.Assert(isValidKey(createSecretKey(keyLength, keyItems), keyLength, keyItems));
Debug.Assert(isValidKey(createSecretKey(keyLength, keyItems), 3, keyItems) == false);
Debug.Assert(isValidKey(createSecretKey(keyLength, keyItems), keyLength, new List<char> { '0', '8', '9' }) == false);
}
private static Random _rnd = new Random();
}

Related

New to c#, not understanding online compiler

so I wrote some C# code and I am trying to test it incrementally, do to something that would take a while to explain, but bottom line, I'm new to c# and not understanding the online compiler error messages. Here is the error message I get when I try and compile, but the strings look good to me.
string solutionSet = "white|black|beige|pink|green|blue|red|yellow|orange|cyan|purple|brown";
string[] solutionSetArray = new string[12];
string ret = "";
string delimeter = "|";
int tempPos = 0;
int counter = 0;
int successFlag = 0;
int patternLength = 5;
for (int index = 0; index < solutionSet.Length; index++)
{
if (solutionSet[index] == delimeter)
{
solutionSetArray[counter] = solutionSet.Substring(tempPos, index);
tempPos = index + 1;
counter++;
}
if (solutionSet.Length - index == 1)
{
solutionSetArray[solutionSetArray.Length-1] = solutionSet.Substring(tempPos, solutionSet.Length);
}
}
for (int i = 0; i < patternLength; i++)
{
Random rnd = new Random();
int randIndex = rnd.Next(solutionSetArray.Length);
if (i != patternLength - 1)
{
ret += solutionSetArray[randIndex] + "|";
successFlag++;
}
else
{
ret += solutionSetArray[randIndex];
}
}
if (successFlag == patternLength - 1)
{
Console.WriteLine(ret);
}
else
{
Console.WriteLine("ERROR");
}
The error (which, according to the message, is on line 1, column 11) is being caused by your very first line of code, which begins string.
I can't tell the context from just your post, but my guess is that you are declaring solutionSet in a block that is not inside of a class or function. You should enclose your code in a class or method, e.g.
public class MyClass
{
static public void Main()
{
string solutionSet = "white|black|beige|pink|green|blue|red|yellow|orange|cyan|purple|brown";
//Rest of code goes here
}
}
By the way, if you're trying to convert solutionSet to an array, you can just write
var solutionSetArray = solutionSet.Split("|");
the problem with your code is
solutionSetArray[counter] = solutionSet.Substring(tempPos, index);
after 6 iterations tempPos=34 and index=37 which is running out of bounds of solutionSet. I would suggest to use var solutionSetArray = solutionSet.Split("|"); and also use LinqPad which can be easy for you to debug if possible,.

C# Console App -- Trying to access a list from else statement

This is for a data structures and algorithms class. We're just starting out with bubble sort. The instructions were to generate random, unique integers and sort them using the sorting technique of the lecture. It will be required to add different sorting techniques as well.
To generate the list of random numbers, I generated a list and then shuffled the list using the fisher-yates algorithm. So I have my unique, sorted list of whatever size I choose.
I'm getting stuck because after I generate the random list, I am having problems accessing the list to run it through BubbleSort.
Is there any way I can do this?
class Algorithms
{
static void Main(string[] args)
{
string response = "";
//Main Console Menu
while (response != "exit")
{
Console.WriteLine("Type help for list of commands");
response = Console.ReadLine();
//List<int> toSort = new List<int>();
if (response.StartsWith("exit"))
{
Environment.Exit(0);
}
else if (response.ToLower().StartsWith("help"))
{
Help(response);
}
else if (response.ToLower().StartsWith("generate"))
{
// Shuffle(Generate(response));
// have been using the line above but adding next line for
//an idea of my problem
List<int> toSort = Shuffle(Generate(response));
}
else if (response.ToLower().StartsWith("bubble"))
{
//This doesn't work and I'm trying to figure out how it can
BubbleSort(toSort);
}
}
}
//Displays help information
public static void Help(string input)
{
Console.WriteLine("\ngenerate <integer> -- Generates a data set of intended amount of integers\n"+
"algorithm <algorithm type> -- Choose which algorithm to sort data\nexit -- exit application\n" );
}
//Generates List of integers from 0 to number choosen by user
public static List<int> Generate(string size)
{
int cutString = size.Length - 9;
string sizeSubset = size.Substring(9, cutString);
List<int> numGen = new List<int>();
int dataSetSize = Convert.ToInt32(sizeSubset);
for(int i = 0; i <= dataSetSize; i++)
{
numGen.Add(i);
// Console.WriteLine(numGen[i]);
}
return numGen;
}
//Use Fisher-Yates algorithm to shuffle the list.
static Random randomize = new Random();
public static List<int> Shuffle(List<int>makeRandom)
{
List<int> shuffled = new List<int>();
int n = makeRandom.Count;
while (n > 1)
{
n--;
int k = randomize.Next(n + 1);
int value = makeRandom[k];
makeRandom[k] = makeRandom[n];
makeRandom[n] = value;
shuffled.Add(value);
Console.WriteLine(value);
}
return shuffled;
}
public static void BubbleSort(List<int>input)
{
for(int i = 0; i <= input.Count; i++)
{
for (int j = 0; j <= (input.Count - 1); j++)
{
if (input[j] > input[j + 1])
{
int temp = input[j];
input[j] = input[j + 1];
input[j + 1] = temp;
Console.WriteLine("hello");
}
}
}
}
}
}
You defined list in scope of else if (response.ToLower().StartsWith("generate")) code block, so it is not accessible outside of that block. Move declaration to Main method scope, like this:
static void Main(string[] args)
{
string response = "";
//define your list here.
List<int> toSort = new List<int>();
//Main Console Menu
while (response != "exit")
{
Console.WriteLine("Type help for list of commands");
response = Console.ReadLine();
if (response.StartsWith("exit"))
{
Environment.Exit(0);
}
else if (response.ToLower().StartsWith("help"))
{
Help(response);
}
else if (response.ToLower().StartsWith("generate"))
{
toSort = Shuffle(Generate(response));
}
else if (response.ToLower().StartsWith("bubble"))
{
List<int> sortedList = BubbleSort(toSort);
}
}
}

Cannot permanently replace value in an array

I can't permanently replace the array members. When I change the value of String Clue, the string being displayed only displays the current value of clue. I think the problem us on the initialization of char[]. I tried to put them in other parts of the code but it produces error. Beginner here! Hope you can help me. Thanks! :)
private void clues(String clue)
{
int idx = numb[wordOn]+4;
char[] GuessHide = Words[idx].ToUpper().ToCharArray();
char[] GuessShow = Words[idx].ToUpper().ToCharArray();
for (int a = 0; a < GuessHide.Length; a++)
{
if (GuessShow[a] != Convert.ToChar(clue.ToUpper()))
GuessHide[a] = '*';
else
GuessHide[a] = Convert.ToChar(clue.ToUpper());
}
Guess(string.Join("", GuessHide));
}
Edited - because you initalize GuessHide at each call of calls in your code and you do not store its current state you basically reset it each time. Still, you can make some small changes in your code like this:
private static void clues(string clue, char[] GuessHide, char[] GuessShow)
{
for (int a = 0; a < GuessHide.Length; a++)
{
if (GuessShow[a] == Convert.ToChar(clue.ToUpper()))
{
GuessHide[a] = Convert.ToChar(clue.ToUpper());
}
}
Console.WriteLine(string.Join("", GuessHide));
}
Call it like this:
clues("p", GuessHide, GuessShow);
clues("a", GuessHide, GuessShow);
Initialise GuessShow and GuessHide in the outside code like this:
char[] GuessHide = new string('*', Words[idx].Length).ToCharArray();
char[] GuessShow = Words[idx].ToUpper().ToCharArray();
public class Program
{
static string[] Words;
static string[] HiddenWords;
public static void Main()
{
Words = new string[] { "Apple", "Banana" };
HiddenWords = new string[Words.Length];
for (int i = 0; i < Words.Length; i++)
{
HiddenWords[i] = new string('*', Words[i].Length);
}
Guess('P', 0);
Guess('a', 0);
Guess('A', 1);
Guess('N', 1);
Console.ReadLine();
}
private static void Guess(char clue, int idx)
{
string originalWord = Words[idx];
string upperedWord = Words[idx].ToUpper();
char[] foundSoFar = HiddenWords[idx].ToCharArray();
clue = char.ToUpper(clue);
for (int i = 0; i < upperedWord.Length; i++)
{
if (upperedWord[i] == clue)
{
foundSoFar[i] = originalWord[i];
}
}
HiddenWords[idx] = new string(foundSoFar);
Console.WriteLine(HiddenWords[idx]);
}
}

Why Static method sometimes returns same result for separate call?

In my c# code I have a static method. Here is the code sample:
public class RandomKey
{
public static string GetKey()
{
Random rng = new Random();
char[] chars = new char[8];
for (int i = 0; i < chars.Length; i++)
{
int v = rng.Next(10 + 26 + 26);
char c;
if (v < 10)
{
c = (char)('0' + v);
}
else if (v < 36)
{
c = (char)('a' - 10 + v);
}
else
{
c = (char)('A' - 36 + v);
}
chars[i] = c;
}
string key = new string(chars);
key += DateTime.Now.Ticks.ToString();
return key;
}
}
I am calling this function from another Class's method.
Class SomeClass
{
Void SomeMethod()
{
for(int i=0; i<100; i++)
{
System.Diagnostics.Debug.WriteLine(i + "===>" + RandomKey.GetKey());
}
}
}
But now the problem is sometimes I am getting the same output from the static method though the function was called separately. Is there any wrong with my code?
The reason is that you are initializing the Random object inside the method.
When you call the method in close time proximity (like inside a loop), the Random object is initialized with the same seed. (see Matthew Watson's comment to find out why.)
To prevent that you should declare and initialize the Random object as a static field, like this:
public class RandomKey
{
static Random rng = new Random();
public static string GetKey()
{
// do your stuff...
}
}
You keep reinitializing the Random value. Move that out to a static field. Also you can format numbers in hex using ToString with a formatter.
Also, DateTime.Now is a bad idea. See this answer for a better way to allocate unique, timestamp values.

ShortcutKey from string

I want to provider user with option to set ToolStripMenuItem.ShortcutKeys via configuration file, so I've figured out that I need somehow transform string to Keys.
I've already found how to do that for simple values using Enum.Parse, but it won't recognize formats like:
Ctrl+i (with space at the end)
i
Ctrl+Alt+Esc
Q: Is there any standardized way of parsing stings (Ctrl+i) to Keys?
I'd like to avoid writing my own function that will split text into pieces and then handle each case/special string separately.
The string you see in the Properties window for the ShortcutKeys property is generated by a TypeConverter. You can use that type converter in your own code as well. Like this:
var txt = "Ctrl+I";
var cvt = new KeysConverter();
var key = (Keys)cvt.ConvertFrom(txt);
System.Diagnostics.Debug.Assert(key == (Keys.Control | Keys.I));
Do beware that I or Ctrl+Alt+Escape are not valid short-cut keys. KeysConverter will not complain, you'll get the exception when you assign the ShortCutKeys property. Wrap both with try/except to catch invalid config data.
Yes, you can separate the values with a , - however your string would still need massaged because Ctrl and Esc are not valid Keys values. They still need to be valid values. So consider the following code:
var keys = "Ctrl+Alt+Esc";
keys = keys.Replace("+", ",").Replace("Ctrl", "Control").Replace("Esc", "Escape");
var k = (Keys)Enum.Parse(typeof(Keys), keys);
Further, here is the code in the Enum class that's going to pick that up:
string[] array = value.Split(Enum.enumSeperatorCharArray);
ulong[] array2;
string[] array3;
Enum.GetCachedValuesAndNames(runtimeType, out array2, out array3, true, true);
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i].Trim();
bool flag = false;
int j = 0;
while (j < array3.Length)
{
if (ignoreCase)
{
if (string.Compare(array3[j], array[i], StringComparison.OrdinalIgnoreCase) == 0)
{
goto IL_152;
}
}
else
{
if (array3[j].Equals(array[i]))
{
goto IL_152;
}
}
j++;
continue;
IL_152:
ulong num2 = array2[j];
num |= num2;
flag = true;
break;
}
if (!flag)
{
parseResult.SetFailure(Enum.ParseFailureKind.ArgumentWithParameter, "Arg_EnumValueNotFound", value);
return false;
}
}
The value of enumSeperatorCharArray is:
private static readonly char[] enumSeperatorCharArray = new char[]
{
','
};

Categories

Resources