Character frequency switch statement increasing wrong index - c#

public int MaxNumberOfBalloons(string text)
{
// arr = {b, a, l, o, n}
int[] arr = new int[5];
foreach (char ch in text)
{
switch (ch)
{
case 'b':
Console.WriteLine(ch);
arr[0]++;
break;
case 'a':
arr[1]++;
break;
case 'l':
arr[2]++;
break;
case 'o':
arr[3]++;
break;
case 'n':
arr[4]++;
break;
default:
break;
}
}
int counter = 0;
Console.WriteLine("Before");
displayArr(arr);
while (checkArr(arr))
{
foreach (int i in arr)
{
if (i == 2 || i == 3)
{
arr[i] -= 2;
}
else
{
arr[i]--;
}
}
counter++;
}
Console.WriteLine("After");
displayArr(arr);
return counter;
}
public bool checkArr(int[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
if (i == 2)
{
if (arr[i] > 1)
continue;
else
return false;
}
if (i == 3)
{
if (arr[i] > 1)
continue;
else
return false;
}
if (arr[i] == 0)
return false;
}
return true;
}
Test results for input string: text = "bb"
Console output before the while loop:
b
b
Before
0
2
2
2
2
After the while loop:
After
0
2
2
2
2
counter returned 1.
Question: Why is the switch statement not working as expected?
Observation: Is increasing all the other index except for the one that is supposed to. I wrote a Console.WriteLine in the case that is suppose to land twice and it did, but it increased all the other index except for that one.
The display method is very straight forward: A simple iterator that outputs the content of each index in the array passed to it.
In the main, I just simply call the MaxNumberOfBalloons method and pass it a string.

I think the issue is with displayArr.
If I change it to:
for (int i = 0; i < arr.Length; i++)
{
Console.WriteLine(arr[i]);
}
You are not printing the array but the index of the array based on the value of the array.
It works correctly.
So instead of printing arr[0], which is 2; you are printing arr[arr[0]] which is the same as arr[2], which is 0.
foreach (int i in arr)
{
Console.WriteLine(i);
}
This is a very interesting bug and took me a while to see.

Related

C# Menu and SubMenu on Console-Troubles on Menu Return

I am new at programming and I'm trying to create a Menu that has inside Submenus. The main Menu has all the options to procede while the submenu has a CRUD for each options inserted.
However the submenu I've done(Animals)doesn't work neither of the visualize by id methods and it goes like this to the following crud methods for the submenus. Also when a submenu complets its tasks it should return to the initial Submenu options, allowing to return to main Menu by pressing zero. Which is not happening, though I tryied doing things differently. I'm not sure if it's the switch statement which wrong or if it's the methods call.
Sorry if the code is a little bigger than usual:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace menu
{
class Program
{
public static int id = 1;
enum animalHeader { id, name, client_name, type_animal };
enum clientHeader { id, name, client_surname, adrress };
static void Main(string[] args)
{
string[,] animal = new string[20, 4];
string[,] client = new string[20, 6];
do { MenuOptions(animal); } while (true);
}
static void MenuOptions(string[,] animal)
{
int userChoice;
do
{
Console.Clear();
Console.WriteLine("\nChoose one of the following options:\n");
Console.WriteLine("[ 1 ] Animals");
Console.WriteLine("[ 2 ] Clients");
Console.WriteLine("[ 0 ] Quit application\n");
} while (!int.TryParse(Console.ReadLine(), out userChoice) || userChoice < 0 || userChoice > 2);
Console.Clear();
switch (userChoice)
{
case 1:
menuAnimal(animal);
menuReturn(animal);
break;
case 2:
//menuClient(client);
mainMenu();
break;
case 0:
Environment.Exit(0);
break;
default:
Console.WriteLine("Try again!!");
break;
}
}
static void menuAnimal(string[,] animal)
{
int optAnimal;
do
{
Console.Clear();
Console.WriteLine("\nInsert one of the following options:\n");
Console.WriteLine("[ 1 ] Insert animal");
Console.WriteLine("[ 2 ] See animal");
Console.WriteLine("[ 3 ] Alter animal");
Console.WriteLine("[ 4 ] Erase animal");
Console.WriteLine("[ 5 ] List animals");
Console.WriteLine("[ 0 ] Return to main menu\n");
} while (!int.TryParse(Console.ReadLine(), out optAnimal) || optAnimal < 0 || optAnimal > 5);
Console.Clear();
switch (optAnimal)
{
case 1:
insertData(animal);
menuReturn(animal);
break;
case 2:
visualizeByid(animal);
menuReturn(animal);
break;
case 3:
updateById(animal);
menuReturn(animal);
break;
case 4:
deleteByid(animal);
menuReturn(animal);
break;
case 5:
listData(animal);
menuReturn(animal);
break;
}
}
static void mainMenu()
{
Console.Clear();
Console.ReadKey();
}
static void menuReturn(string[,] animal)
{
Console.Clear();
do { menuAnimal(animal); } while (true);
}
static int generateId()
{
return id++;
}
static int getInsertIndex(string[,] matrix)
{
for (int j = 0; j < matrix.GetLength(0) - 1; j++)
{
if (string.IsNullOrEmpty(matrix[j, 0])) return j;
}
return -1;
}
static void insertData(string[,] matrix)
{
int id = generateId();
int n = getInsertIndex(matrix);
matrix[n, 0] = Convert.ToString(id);
for (int j = 1; j < matrix.GetLength(1); j++)
{
do
{
Console.Write($"Insert {Enum.GetName(typeof(animalHeader), j)}: ");
matrix[n, j] = Console.ReadLine();
} while (String.IsNullOrEmpty(matrix[n, j]));
}
}
static int searchId(string[,] matrix)
{
int choosenId, index = -1;
do
{
Console.Write("Insert ID to continue: ");
} while (!int.TryParse(Console.ReadLine(), out choosenId));
for (int i = 0; i < matrix.GetLength(0); i++)
{
if (Convert.ToString(choosenId) == matrix[i, 0])
{
index = i;
}
}
return index;
}
static void visualizeByid(string[,] matrix)
{
int pos = searchId(matrix);
if (pos != -1)
{
for (int i = pos; i < pos + 1; i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
Console.Write($"{matrix[i, j]}\t");
}
Console.WriteLine();
}
}
else { Console.WriteLine("Wrong Id"); }
}
static void updateById(string[,] matrix)
{
int pos = searchId(matrix);
if (pos != -1)
{
for (int i = pos; i < pos + 1; i++)
{
for (int j = 1; j < matrix.GetLength(1); j++)
{
Console.Write($"Insert {Enum.GetName(typeof(animalHeader), j)}: ");
matrix[i, j] = Console.ReadLine();
}
Console.WriteLine();
}
}
else { Console.WriteLine("Id does not exist"); }
}
static void deleteByid(string[,] matrix)
{
int pos = searchId(matrix);
if (pos != -1)
{
for (int i = pos; i < pos + 1; i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
matrix[i, j] = null;
}
}
}
else { Console.WriteLine("Id does not exist"); }
}
static void listData(string[,] matrix)
{
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
Console.Write($"\t{matrix[i, j]}\t");
}
Console.WriteLine("\n\t");
}
}
}
}
The first problem I can spot is in the menuAnimal method. Check what happens when you enter 0, for example by stepping through the code with debugger.
When user enters 0, the first do-while condition passes (as 0 is a number and is not smaller than 0 and not larger than 5), but in the following switch statement you do not have a case for 0, so the method stops executing and just redraws, because execution continues to menuReturn(animal); in MenuOptions.
The next main problem here is the menuReturn method. Observe that once you get in this method, you can never "escape". It always redraws the animals menu whatever happens and while(true) ensures that it will happened indefinitely. Because there is no break condition inside, it will just keep on going.
Different approach
I will suggest a different approach here, although there are many options you have, so you are free to use a different solution that suits you.
First get rid of the menuReturn method and put this "menu output loop within the menu methods themselves. In pseudo code this would be:
static void MenuMethod()
{
while (true)
{
userInput = read user input for example using do..while as in original code
goBack = false
switch (userInput)
{
case optionA:
doSomething();
goBack = true; //set go back to true if you want go up a level
break;
case optionSubmenu:
submenu(); //go to a submenu, which will start its own loop
//after submenu is closed (goBack = true), execution will return to this level
break;
}
if (goBack) return; //end execution of this menu
}
}
So briefly in your case it could look like this:
static void MenuOptions(string[,] animal)
{
while (true)
{
int userChoice;
do
{
Console.Clear();
Console.WriteLine("\nChoose one of the following options:\n");
Console.WriteLine("[ 1 ] Animals");
Console.WriteLine("[ 2 ] Clients");
Console.WriteLine("[ 0 ] Quit application\n");
} while (!int.TryParse(Console.ReadLine(), out userChoice) || userChoice < 0 || userChoice > 2);
Console.Clear();
switch (userChoice)
{
case 1:
menuAnimal(animal);
break;
case 2:
//menuClient(client);
break;
case 0:
Environment.Exit(0);
break;
default:
Console.WriteLine("Try again!!");
break;
}
}
}
Similar goes for animals menu:
static void MenuAnimal(string[,] animal)
{
while ( true )
{
int optAnimal;
do
{
Console.Clear();
Console.WriteLine("\nInsert one of the following options:\n");
Console.WriteLine("[ 1 ] Insert animal");
Console.WriteLine("[ 2 ] See animal");
Console.WriteLine("[ 3 ] Alter animal");
Console.WriteLine("[ 4 ] Erase animal");
Console.WriteLine("[ 5 ] List animals");
Console.WriteLine("[ 0 ] Return to main menu\n");
} while (!int.TryParse(Console.ReadLine(), out optAnimal) || optAnimal < 0 || optAnimal > 5);
Console.Clear();
bool goBack = false;
switch (optAnimal)
{
case 1:
insertData(animal);
break;
case 2:
visualizeByid(animal);
break;
case 3:
updateById(animal);
break;
case 4:
deleteByid(animal);
break;
case 5:
listData(animal);
break;
}
if ( goBack ) return;
}
}

why is the output in lottery code isn't working?

I'm supposed to make a code in c# (microsoft visual studio 2017) that lets the user input six numbers, and then compare them to an array of six randomly generated numbers(with no duplicates).
If the user has one match, he's supposed to get a message saying he had one match, and different messages for two or three matches, and so on.
This is what I got so far:
static bool isValueInArray(int value, int[] a)
{
for (int i = 0; i < a.Length; i++)
{
if (a[i] == value)
{
return true;
}
}
return false;
}
static void Main(string[] args)
{
int min = 0;
int max = 6;
Random randnum = new Random();//random number generator
int[] numbers = new int[6];// generates six numbers
for (int i = 0; i < numbers.Length; i++)
{
numbers[i] = randnum.Next(min, max);//sets the numbers between 0 to 6
if(isValueInArray( i, numbers))
{
numbers[i] = randnum.Next(min, max);
}
}
try
{
Console.WriteLine("Hello and Welcome to our little game of lottery! lets see just how much luck you got!"); // greetings and instructions
Console.WriteLine("You'll now get to choose 6 different numbers between 0 to 6 to play with.");
Console.WriteLine("Go ahead and type them in.");
int[] lottery = new int[6];
for (int i = 0; i < lottery.Length; i++)
{
lottery[i] = int.Parse(Console.ReadLine()); // array to catch six numbers input
if (lottery[i] > 6)//checking if the numbers fit between 0 and 6
{
Console.WriteLine("whoops! the number you enetered isn't in range! please try again ^^");
break;
}
int x = 6;
for (int a = 0; a < lottery.Length; a++)
{
for (int b = 0; b < numbers.Length; b++)
{
if (lottery[a] == numbers[b])
{
a++;
x--;
if (x == 6)
{
Console.WriteLine("six match");
break;
}
else if (x == 5)
{
Console.WriteLine("five match");
break;
}
else if (x == 4)
{
Console.WriteLine("four match");
break;
}
else if (x == 3)
{
Console.WriteLine("three match");
break;
}
else if (x == 2)
{
Console.WriteLine("two match");
break;
}
else if (x == 1)
{
Console.WriteLine("one match");
break;
}
}
}
}
}
}
catch (FormatException)// checking if the input is in char format
{
Console.WriteLine("only numbers please!");
}
}
My problem is with the output. The program seems to go over all of the "else if" options and print all of them, instead of picking and printing just one of them.
You have everything mixed together. Write out the steps:
Generate numbers
Get input from user
Count number of matches
Print results
Each step should be performed separately.
// These should be the min/max lottery numbers
int min = 1;
int max = 100;
int numberOfLotteryNumbers = 6;
// Renamed for clarity
int[] lotteryNumbers = new int[numberOfLotteryNumbers];
int[] userNumbers = new int[numberOfLotteryNumbers];
// Step 1 - generate numbers
for (int i = 0; i < lotteryNumbers.Length; i++) {
int randomNumber;
do {
randomNumber = randnum.Next(min, max);
} while (isValueInArray(randomNumber, lotteryNumbers));
lotteryNumbers[i] = randomNumber;
}
// Step 2 - get numbers from user
for (int i = 0; i < lottery.Length; i++) {
int userInput;
do {
userInput = int.Parse(Console.ReadLine());
} while (userInput < min || userInput > max || isValueInArray(userInput, userNumbers));
userNumbers[i] = userInput;
}
// Step 3 - calc matches
int matches = 0;
for (int i = 0; i < userNumbers.Length; i++) {
if (isValueInArray(userNumbers[i], lotteryNumbers) {
matches += 1;
}
}
// Step 4 - print results
Console.WriteLine("There are {0} matches.", matches);
You may have to rearrange the code blocks in a way to get user input first, calculate the number of matches first, then display results as following code:
Note: Your approach to guarantee unique numbers in the randomly generated number ain't going to work as you expect to, you are passing "i" where you may want to pass "numbers[i]" instead to the isValueInArray" function. Let aside the idea that you will always end with values 0-5 in the array since you want 6 numbers.
int min = 0;
int max = 6;
Random randnum = new Random();//random number generator
int[] numbers = new int[6];// generates six numbers
for (int i = 0; i < numbers.Length; i++)
{
numbers[i] = randnum.Next(min, max);//sets the numbers between 0 to 6
if (isValueInArray(i, numbers))
{
numbers[i] = randnum.Next(min, max);
}
}
try
{
Console.WriteLine("Hello and Welcome to our little game of lottery! lets see just how much luck you got!"); // greetings and instructions
Console.WriteLine("You'll now get to choose 6 different numbers between 0 to 6 to play with.");
Console.WriteLine("Go ahead and type them in.");
int[] lottery = new int[6];
int x = 0;
//read user numbers
for (int i = 0; i < lottery.Length; i++)
{
lottery[i] = int.Parse(Console.ReadLine()); // array to catch six numbers input
while (lottery[i] > 6)//checking if the numbers fit between 0 and 6
{
Console.WriteLine("whoops! the number you enetered isn't in range! please try again ^^");
lottery[i] = int.Parse(Console.ReadLine()); // array to catch six numbers input
}
}
//count number of matches
for (int a = 0; a < lottery.Length; a++)
{
for (int b = 0; b < numbers.Length; b++)
{
if (lottery[a] == numbers[b])
{
//a++;
x++;
break;
}
}
}
//display results
if (x == 6)
{
Console.WriteLine("six matches");
}
else if (x == 5)
{
Console.WriteLine("five matches");
}
else if (x == 4)
{
Console.WriteLine("four matches");
}
else if (x == 3)
{
Console.WriteLine("three matches");
}
else if (x == 2)
{
Console.WriteLine("two matches");
}
else if (x == 1)
{
Console.WriteLine("one match");
}
}
catch (FormatException)// checking if the input is in char format
{
Console.WriteLine("only numbers please!");
}
Console.Read();
}
You can use a counter to achieve your goal. Just increment counter value on match:
int counter = 0;
for (int i = 0; i < lottery.Length; i++)
{
// ..
if (x == number)
{
counter++;
break;
}
// ..
}
Console.WriteLine("You have " + counter + " matches");

Compare lexicographically two char arrays

Can you help with this?
I need to compare lexicographically two arrays: if one of them is shorter than other, it is lexicographically first. If their length are same, they had to be compared element by element. If an element is before the other in the alphabet, this array is lexicographically first.
Here is my code:
using System;
internal class CompareTwoCharArraysLexicographically
{
private static void Main()
{
char[] firstArray = {'a', 'b', 'c', 'z'};
int firstArrayLength = firstArray.Length;
char[] secondArray = {'a', 'b', 'c', 'd'};
int secondArrayLength = secondArray.Length;
int length = Math.Min(firstArray.Length, secondArray.Length);
if (firstArray.Length > secondArray.Length)
{
Console.WriteLine("Second array is earlier.");
}
else if (firstArray.Length == secondArray.Length)
{
for (int i = 0; i < length; i++)
{
if (firstArray[i] > secondArray[i])
{
Console.WriteLine("2 array is earlier.");
break;
}
else if (secondArray[i] > firstArray[i])
{
Console.WriteLine("1 array is earlier.");
break;
}
else
{
Console.WriteLine("Two arrays are equal.");
}
}
}
else
{
Console.WriteLine("First array is earlier.");
}
}
}
How I can avoid three time repeated message "Two arrays are equal."?
Yet another structured way to do it:
class LexicographicCharArrayComparer : Comparer<char[]>
{
public override int Compare(char[] x, char[] y)
{
if (x == null || y == null)
return Default.Compare(x, y);
int lengthComp = x.Length.CompareTo(y.Length);
if (lengthComp != 0)
return lengthComp;
return StringComparer.Ordinal.Compare(new string(x), new string(y));
}
}
Usage:
char[] firstArray = { 'a', 'b', 'c', 'z', };
char[] secondArray = { 'a', 'b', 'c', 'd', };
var comparer = new LexicographicCharArrayComparer();
var result = comparer.Compare(firstArray, secondArray);
if (result < 0)
Console.WriteLine("1st array is earlier");
else if (result == 0)
Console.WriteLine("The two arrays are equal");
else
Console.WriteLine("2nd array is earlier");
Your own approach can be repaired, of course. Correct the middle block to something like:
else if (firstArray.Length == secondArray.Length)
{
bool resolved = false;
for (int i = 0; i < length; i++)
{
if (firstArray[i] > secondArray[i])
{
Console.WriteLine("2 array is earlier.");
resolved = true;
break;
}
if (secondArray[i] > firstArray[i])
{
Console.WriteLine("1 array is earlier.");
resolved = true;
break;
}
}
if (!resolved)
{
Console.WriteLine("Two arrays are equal.");
}
}
I think you will need to use a tracking variable to know whether or not the arrays are equal. Currently you are saying they are equal each time two items in the same index are equal. Instead, consider the following code:
else if (firstArray.Length == secondArray.Length)
{
var largerArray = 0;
// Compare each item in the array
for (int i = 0; i < length; i++)
{
// As soon as two items are not equal, set the comparison value and break
if (firstArray[i] > secondArray[i])
{
largerArray = 1;
break;
}
else if (secondArray[i] > firstArray[i])
{
largerArray = 2
break;
}
}
// Check the largerArray value. If it was never changed, the arrays are equal
// Otherwise, display a message based on the value of the largerArray.
if (largerArray == 0)
{
Console.WriteLine("Two arrays are equal.");
}
else
{
Console.WriteLine("{0} array is earlier.", largerArray);
}
}
Here is my suggestion:
Console.Write("Enter a positive number for length of the first array: ");
int n = int.Parse(Console.ReadLine());
Console.Write("Enter a positive number for length of the second array: ");
int m = int.Parse(Console.ReadLine());
// Declare and create the arrays
char[] firstArray = new char[n];
char[] secondArray = new char[m];
Console.WriteLine("Enter values of the arrays: ");
for (int i = 0; i < firstArray.Length; i++)
{
firstArray[i] = char.Parse(Console.ReadLine());
}
Console.WriteLine();
for (int i = 0; i < m; i++)
{
secondArray[i] = char.Parse(Console.ReadLine());
}
Console.WriteLine();
// Print them on the console
for (int i = 0; i < n; i++)
{
Console.Write(" " + firstArray[i]);
}
Console.WriteLine();
for (int i = 0; i < m; i++)
{
Console.Write(" " + secondArray[i]);
}
Console.WriteLine();
int minLength = Math.Min(firstArray.Length, secondArray.Length);
bool equalValues = true;
// Search which of the arrays is lexicographically earlier
for (int i = 0; i < minLength; i++)
{
if (firstArray[i] == secondArray[i])
{
continue;
}
else if (firstArray[i] < secondArray[i])
{
Console.WriteLine("The first array is earlier.");
break;
}
else if (firstArray[i] > secondArray[i])
{
Console.WriteLine("The second array is earlier.");
break;
}
}
for (int i = 0; i < minLength; i++)
{
if (firstArray[i] != secondArray[i])
{
equalValues = false;
}
}
// This is to indicate the values of the two arrays till the element of index minLength-1 are equal
for (int i = 0; i < minLength; i++)
{
if (equalValues && n < m)
{
Console.WriteLine("The first array is earlier.");
break;
}
else if (equalValues && n > m)
{
Console.WriteLine("The second array is earlier.");
break;
}
else if (equalValues && n == m)
{
Console.WriteLine("The two arrays aree equal.");
break;
}
}
Here is a relatively simple implementation using the sums of the ASCII values of the array characters as a lexicographical comparison criteria:
/* Method: compareLexicographically(a, b);
Compare lexicographically the two arrays passed as parameters and print result.
Comparison criteria:
1. Arrays lengths.
2. Accumulated ASCII values of the array characters.
*/
static void compareLexicographically(char[] a, char[] b)
{
if (a.Length == b.Length) // same lengths
{
int suma = 0;
int sumb = 0;
for (int i = 0; i < a.Length; i++)
{
suma += a[i];
sumb += b[i];
}
if (suma == sumb)
{
Console.WriteLine("Two arrays are lexicographically equal.\n");
}
else
{
if (suma < sumb)
{
Console.WriteLine("First array lexicographically smaller than second.\n");
}
else
{
Console.WriteLine("First array lexicographically greater than second.\n");
}
}
}
else // different lengths
{
if (a.Length < b.Length)
{
Console.WriteLine("First array lexicographically smaller than second.\n");
}
else
{
Console.WriteLine("First array lexicographically greater than second.\n");
}
}
}
I think that this fixes your problem :)
Hope I helped you as well u helped me find an answer of an exercise
using System;
internal class CompareTwoCharArraysLexicographically
{
private static void Main()
{
char[] firstArray = { 'a', 'b', 'c', 'z' };
int firstArrayLength = firstArray.Length;
char[] secondArray = { 'a', 'b', 'c', 'd' };
int secondArrayLength = secondArray.Length;
int length = Math.Min(firstArray.Length, secondArray.Length);
bool same = false;
if (firstArray.Length > secondArray.Length)
{
Console.WriteLine("Second array is earlier.");
}
else if (firstArray.Length == secondArray.Length)
{
for (int i = 0; i < length; i++)
{
if (firstArray[i] != secondArray[i])
{
same = false;
if (firstArray[i] > secondArray[i])
{
Console.Clear();
Console.WriteLine("2 array is earlier.");
break;
}
if (secondArray[i] > firstArray[i])
{
Console.Clear();
Console.WriteLine("1 array is earlier.");
break;
}
}
else same = true;
if (same == true)
{
Console.Clear();
Console.WriteLine("Two arrays are equal.");
}
else
{
Console.WriteLine("First array is earlier.");
}
}
}
}
}

Hangman in C# Looping Issue

So i got The following Code Here... I have to provide 5 User provided words, randomize on the 5 and give any one of them up for a guess, the tries = word length + 2. The main problem i Am having is looping the entire check to fill in the 2nd, 3rd guess etc. The 1st guess is fine. How would i go about looping and keeping the characters which were guessed right while still keeping the ones that were not guessed as a "_" character.
Example - Word was "Heaven" - User Enters "e" - Produces - _ e _ _ e _ No Spaces.
The tries would then be equal to 6(Word Length) + 2 = 8 Tries
int tries = 0;
Random rand = new Random();
int randomword = rand.Next(1, 5);
string word = "";
Console.WriteLine("Please Enter 5 Words into the System");
Console.WriteLine();
for (int i = 0; i < 5; i++)
{
words.Add(Console.ReadLine());
Console.Clear();
}
Console.WriteLine("For Display Purposes. Here are Your 5 Words");
Console.WriteLine("===========================================");
Console.WriteLine();
foreach (var item in words)
{
Console.WriteLine(item);
}
Console.WriteLine();
Console.WriteLine("Now Guess The word given Below");
Console.WriteLine();
switch (randomword)
{
case 1:
//Gets the List index 0 - 1st word in the list
word = words[0];
tries = word.Length;
break;
case 2:
word = words[1];
tries = word.Length;
break;
case 3:
word = words[2];
tries = word.Length;
break;
case 4:
word = words[3];
tries = word.Length;
break;
case 5:
word = words[4];
tries = word.Length;
break;
default:
break;
}
//Default + addition to the Length
tries += 2;
Console.WriteLine();
Console.WriteLine("You Have {0} + tries",tries );
//Works for the 1st Guess
do
{
char guess = char.Parse(Console.ReadLine());
if (word.Contains(guess))
{
foreach (char item in word)
{
if (item == guess)
{
Console.Write(item);
}
else
{
Console.Write("_");
}
}
}
Console.WriteLine();
}
//If my word contains A "_" i will keep looping
while (word.Contains("_"));
Console.ReadKey();
Your main problem is that you're only keeping track of the current guess, not all the previous ones. You can use a HashSet to keep track of your previous guesses. So define a variable HashSet<char> guessedLetters before your do loop, and then as the 2nd line in your loop after you parse "guess" do guessedLetters.Add(guess). Then substitute if(item==guess) with if(guessedLetters.Contains(item)). Viola, only three lines code change!
Finally your exit condition can be while (word.Any(c=>!guessedChars.Contains(c)) && --tries != 0);.
How about:
static void Main(string[] args)
{
string[] words = new string[] { "Apple", "Banana", "Pear", "Pineapple", "Melon"};
Random random = new Random();
string wordToGuess = words[random.Next(5)].ToLower();
char[] currentLetters = new char[wordToGuess.Length];
for (int i = 0; i < currentLetters.Length; i++) currentLetters[i] = '_';
int numTries = currentLetters.Length + 1;
bool hasWon = false;
do
{
string input = Console.ReadLine().ToLower();
if (input.Length == 1) //guess a letter
{
char inputChar = input[0];
for (int i = 0; i < currentLetters.Length; i++)
{
if (wordToGuess[i] == inputChar)
{
currentLetters[i] = inputChar;
}
}
if (!currentLetters.Contains('_'))
{
hasWon = true;
}
else
{
Console.WriteLine(new string(currentLetters));
}
}
else
{
if (input == wordToGuess)
{
hasWon = true;
}
else
{
Console.WriteLine("Incorrect!");
Console.WriteLine(new string(currentLetters));
}
}
numTries--;
} while (new string(currentLetters) != wordToGuess && numTries > 0 && !hasWon);
if (hasWon)
{
Console.WriteLine("Congratulations, you guessed correctly.");
}
else
{
Console.WriteLine("Too bad! Out of tries");
}
}
you need to store the guessing result and check that for your loop (change your do while loop to as below):
string resultword = word;
do
{
char guess = char.Parse(Console.ReadLine());
if (word.Contains(guess))
{
resultword = resultword.Replace(guess, ' ');
for (int i = 0; i < resultword.Count(); i++)
{
if (resultword[i] == ' ')
{
Console.Write(word[i]);
}
else
{
Console.Write("_");
}
}
}
Console.WriteLine();
}
while (tries-- != 0 && resultword.Trim() != string.Empty);
How about, using your existing code;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
internal class Program
{
private static void Main(string[] args)
{
List<string> words = new List<string>();
int tries = 0;
Random rand = new Random();
var currentLetters = new List<char>();
int randomword = rand.Next(1, 5);
string word = "";
Console.WriteLine("Please Enter 5 Words into the System");
Console.WriteLine();
for (int i = 0; i < 5; i++)
{
words.Add(Console.ReadLine());
Console.Clear();
}
Console.WriteLine("For Display Purposes. Here are Your 5 Words");
Console.WriteLine("===========================================");
Console.WriteLine();
foreach (var item in words)
{
Console.WriteLine(item);
}
Console.WriteLine();
Console.WriteLine("Now Guess The word given Below");
Console.WriteLine();
switch (randomword)
{
case 1:
//Gets the List index 0 - 1st word in the list
word = words[0];
tries = word.Length;
break;
case 2:
word = words[1];
tries = word.Length;
break;
case 3:
word = words[2];
tries = word.Length;
break;
case 4:
word = words[3];
tries = word.Length;
break;
case 5:
word = words[4];
tries = word.Length;
break;
default:
break;
}
//Default + addition to the Length
tries += 2;
Console.WriteLine();
Console.WriteLine("You Have {0} + tries", tries);
//Works for the 1st Guess
do
{
char guess = char.Parse(Console.ReadLine());
if (!currentLetters.Contains(guess))
{
currentLetters.Add(guess);
foreach (var l in word.ToCharArray().Intersect(currentLetters).ToArray())
{
word = word.Replace(l, '_');
}
}
Console.WriteLine(word);
} //If my word contains A "_" i will keep looping
while (word.Contains("_"));
Console.ReadKey();
}
}
}
Working example:
List<string> words = new List<string>();
int tries = 0;
Random rand = new Random();
int randomword = rand.Next(1, 5);
string word = "";
Console.WriteLine("Please Enter 5 Words into the System");
Console.WriteLine();
for (int i = 0; i < 5; i++)
{
words.Add(Console.ReadLine());
Console.Clear();
}
Console.WriteLine("For Display Purposes. Here are Your 5 Words");
Console.WriteLine("===========================================");
Console.WriteLine();
foreach (var item in words)
{
Console.WriteLine(item);
}
Console.WriteLine();
Console.WriteLine("Now Guess The word given Below");
Console.WriteLine();
switch (randomword)
{
case 1:
//Gets the List index 0 - 1st word in the list
word = words[0];
tries = word.Length;
break;
case 2:
word = words[1];
tries = word.Length;
break;
case 3:
word = words[2];
tries = word.Length;
break;
case 4:
word = words[3];
tries = word.Length;
break;
case 5:
word = words[4];
tries = word.Length;
break;
default:
break;
}
//Default + addition to the Length
tries += 2;
Console.WriteLine();
Console.WriteLine("You Have {0} + tries", tries);
List<char> guesses = new List<char>();
string guessedWord = "";
for(int i=0;i<word.Length;i++)
{
guessedWord += "_";
}
//Works for the 1st Guess
do
{
char guess = char.Parse(Console.ReadLine());
if (word.Contains(guess))
{
guesses.Add(guess);
}
foreach (char storedGuess in guesses)
{
if(word.Contains(storedGuess))
{
int index = word.IndexOf(storedGuess);
while(index > -1)
{
StringBuilder sb = new StringBuilder(guessedWord);
sb[index] = storedGuess;
guessedWord = sb.ToString();
index = word.IndexOf(storedGuess, index+1);
}
}
}
Console.WriteLine(guessedWord);
}
while (guessedWord.Contains("_"));
Console.ReadKey();
You mention the number of tries, but you never use it in the code after it is used. Presumably, you want to do the following:
Pick a random word (in your case, you are picking one of the five words supplied by the user)
Set the number of guesses (tries?) equal to the length of the word plus 2. If they guess a letter that is present, then it is free. If the letter is not present, then they lose one of their guesses.
Before each guess, display the word with all the unguessed letters replaced by "_".
When the user guesses a letter that is present, replace the "_" in the displayed word by the letter.
Here is some sample code that should work (untested):
string displayword = String.Copy(word);
for (int j = 0; j < displayword.length; j++) displayword[j]='_';
do {
// Display the word so far.
Console.WriteLine("Word is {0}", displayword);
// Get a guess from the user
char guess = char.Parse(Console.ReadLine());
if (word.Contains(guess)) {
for (j=0; j<word.length; j++) {
if (word[j] == guess) displayword[j]=guess;
}
} else {
// Decrease the tries.
tries--;
}
} while (displayword.Contains("_") && (tries > 0));
You need to distinguish the input word from the result so-far. Initialize the result with underscores, and then add the letters to the result as people guess them. It's a little easier if you make result a char array instead of a string.
var result = new string('_', word.Length).ToCharArray();
do
{
char guess = char.Parse(Console.ReadLine());
for (var i = 0; i < word.Length; ++i)
{
if(word[i] == guess)
{
result[i] = guess;
}
}
Console.WriteLine(new string(result));
}
//If my word contains A "_" i will keep looping
while (result.Contains('_') && --tries != 0);

How to reset or restart nested loops

loop one
{
looptwo
{
if(condition=true)
{
reset values//restart both loops
}
}
}
and possibilities for reset values is 3
basically i want to compair two matrices
a= 1 2 3 4
1 2 3 4
b= 3 4 5 6
4 6 7 8
and when row 1 of a[] is matched with row 1 of b[].....i will add these rows and a[]
become = 2 4 6 8
for(i=0;i<rows;i++)
for(j=0;j<columns;j++)
{
a[i]=a[i]+b[i,j]
}
and again find my maches from restart with new a[] Matrix
and i have to insure that all rows of b[] matrix are checked with a[] which are 3 in this case
You have to use goto to break out of multiple loop levels in C#. For example:
RESTART:
while (a) {
while (b) {
if (that_other_thing)
goto RESTART;
}
}
Well, you don't have to use goto but the alternative might be using a bunch of flag variables to indicate that a restart is required. And that code will probably be pretty hard to follow.
The best choice here is to move the loops into their own method, and return from inside the inner loop. Example:
public void MyMehod(){
loop one{
looptwo{
if(condition=true){
return;
}
}
}
}
If this is not possible for some reason, you can use a bool value that you set in the inner loop to bail out of all of them, but this is a bit more messy:
bool endloop = false;
while(!endloop){
while(!endloop){
if(condition){
endloop = true;
}
}
}
For a while loop it looks ok, but even more messy for a for loop or a foreach loop.
Start:
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
if(j == 5)
goto Start;
}
}
Although structuring your code in a way to not use a goto is a much better approach...
If you can guarantee that you will have a condition that will tell you that you don't need to restart, you could wrap the whole thing in one more loop.
bool keepLooping = true;
while (keepLooping)
{
keepLooping = false;
for (int x = 0; x < maxx; x++)
{
for (int y = 0; y < maxy; y++)
{
if (DoSomething(x, y))
{
keepLooping = true;
break;
}
}
if (keepLooping)
{
break;
}
}
}
If you are checking a list for duplicates and modifying them do make all entries unique, you might do something like this (assuming string values):
List<string> a = GetNamesFromeSomewhere();
bool duplicateFound = true;
while (duplicateFound )
{
duplicateFound = false;
for (int x = 0; x < a.Length; x++)
{
for (int y = x + 1; y < a.Length; y++)
{
if (a[x].Equals(a[y]))
{
//Change a[y], but now we have to recheck for duplicates...
a[y] += "_";
duplicateFound = true;
break;
}
}
if (duplicateFound)
{
break;
}
}
}
if you use numeric loop variables like i and j you can just reset the values
e.g.
for (i=0; i<10; i++) {
for (j=0; j<10; j++) {
if (var[i][j] == 'x') {
i=0; j=0; break;
}
}
}
you can also use the method approach as suggested earlier
void someFunction(params) {
for (i=0; i<10; i++) {
for (j=0; j<10; j++) {
if (var[i][j] == 'x') {
someFunction(params)
return;
}
}
}
}

Categories

Resources