Iterating through an array of strings i want it to write a specific line if one of the elements coresponds to the condition. The problem is with the else condition. It is written as many times as the length of the array and i only need it written once
public static void FindSandy(params string[] ocean)
{
for (int i = 0; i < ocean.Length; i++)
{
if (ocean[i] == "Sandy")
{
Console.WriteLine("We found Sandy on position {0}", i);
}
else
{
Console.WriteLine("He was not here");
}
}
}
static void Main(string[] args)
{
{
FindSandy("Bob","Bella", "Sandy", "Nemo", "Dory");
}
}
What about if you just return if you found it?
public static void FindSandy(params string[] ocean)
{
for (int i = 0; i < ocean.Length; i++)
{
if (ocean[i] == "Sandy")
{
Console.WriteLine("We found Sandy on position {0}", i);
// Found, you can return from method.
return;
}
}
// Not found, write the 'not found' message.
Console.WriteLine("He was not here");
}
The simplest way to change your code to handle this is to create a variable that tracks the index where Sandy is found, initialize it to an invalid value (like -1), and then set it to the actual value in your if block (and we can also add a break; statement to exit the loop as soon as we find him).
Then, we output a string based on the value of the position variable:
public static void FindSandy(params string[] ocean)
{
int position = -1;
for (int i = 0; i < ocean?.Length; i++)
{
if (ocean[i] == "Sandy")
{
position = i;
break;
}
}
if (position > -1)
{
Console.WriteLine("We found Sandy on position {0}", position);
}
else
{
Console.WriteLine("He was not here");
}
}
The code can be simplified a little with the System.Linq extension methods Select (to select the name and then index) and FirstOrDefault which returns the first item that meets a condidion, or the default for the type (which is null):
public static void FindSandy(params string[] ocean)
{
var position = ocean?.Select((name, index) => new {name, index})
.FirstOrDefault(item => item.name == "Sandy");
Console.WriteLine(position == null
? "He was not here"
: $"We found Sandy on position {position.index}");
}
You can use the keyword break to exit the for loop :
public static void FindSandy(params string[] ocean)
{
for (int i = 0; i < ocean.Length; i++)
{
if (ocean[i] == "Sandy")
{
Console.WriteLine("We found Sandy on position {0}", i);
break;
}
else if (i == ocean.Length - 1)
{
Console.WriteLine("He was not here");
break;
}
}
}
To solve your issue, you could add a new boolean variable (e.g. weFoundSandy): if you find an occurrence, set this variable to true, use the break statement (to reduce the iterations of the for) and, at the end, use this boolean variable to determine which message to display.
public static void FindSandy(params string[] ocean) {
bool weFoundSandy = false;
for (int i = 0; i < ocean.Length; i++) {
if (ocean[i] == "Sandy") {
Console.WriteLine("We found Sandy on position {0}", i);
weFoundSandy = true;
break;
}
}
if (!weFoundSandy) {
Console.WriteLine("Sandy was not here");
}
}
or, you could simply use the C# Array.IndexOf method, e.g.:
public static void FindSandy(params string[] ocean) {
int indexOfSandy = Array.IndexOf(ocean, "Sandy");
if (indexOfSandy >= 0) {
Console.WriteLine("We found Sandy on position {0}", indexOfSandy);
} else {
Console.WriteLine("Sandy was not here");
}
}
Related
My assignment is to create a string list that has at least two matching values and then to prompt the user to input one of those values and then I am to display the index or indices of that value entered.
I seem to have figured out how to get the desired indices to show, but I also need to have a statement in the event the value entered is not in the list and when I do an else, it messes things up. Looking for some help on this!
So this does what I want but without the else statement:
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
List<string> mprovinces = new List<string> { "Nova Scotia", "New Brunswick", "Prince Edward Island", "Nova Scotia" };
Console.WriteLine("Enter one of the following maritime provinces: \nNova Scotia, \nNew Brunswick, \nPrince Edward Island\n");
string input2 = Console.ReadLine();
for (int i = 0; i < mprovinces.Count; i++)
{
bool match = mprovinces[i] == input2;
if (match)
{
Console.WriteLine(i);
}
}
}
}
But when I add an else statement and I enter a value that is in the list it provides more data than I want:
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
List<string> mprovinces = new List<string> { "Nova Scotia", "New Brunswick", "Prince Edward Island", "Nova Scotia" };
Console.WriteLine("Enter one of the following maritime provinces: \nNova Scotia, \nNew Brunswick, \nPrince Edward Island\n");
string input2 = Console.ReadLine();
for (int i = 0; i < mprovinces.Count; i++)
{
bool match = mprovinces[i] == input2;
if (match)
{
Console.WriteLine(i);
}
else
{
Console.WriteLine("Sorry, this is not in the list");
}
}
}
}
Since the "Sorry" message is inside of the for loop you will show it for EVERY index that does not exactly match your input2. You need to pull the match value out of the for loop and check it once.
var matchIndex = -1; // can never get a -1 so it's a good default to check for later
for (int i = 0; i < mprovinces.Count; i++)
{
if (mprovinces[i] == input2)
{
matchIndex = i;
break; // break out of loop
}
}
if (matchIndex >= 0) // again a valid index will never be below 0
{
Console.WriteLine("Index: " + matchIndex);
}
else
{
Console.WriteLine("Sorry, this is not in the list");
}
I'm not sure exactly what you want to show. If you only want to show the FIRST index that matches then the above code will work. If you want to show EVERY index that matches then this would work.
EDIT: I have changed this function to not use a string to keep track of the list. It just shows the matching indexes as they appear.
bool matchExists = false;
for (int i = 0; i < mprovinces.Count; i++)
{
if (mprovinces[i] == input2)
{
matchExists = true;
Console.WriteLine(i);
}
}
if (matchExists == false)
{
Console.WriteLine("Sorry, this is not in the list");
}
I have assignment to make Hangman game with methods, so far everything is going ok until I realized that the word that I input by char when has two consecutive characters it can't get the following if statement
if (correctGuesses.Count == randomWord.Length)
{
Console.WriteLine("You won the word is: {0}", randomWord);
break;
}
and thus I can never finish the game if the word is something like Green
I was trying to use List.Contains('*') if contains it to continue if not to break and to write the Word thus to win, but it fails if I put '!' in front or if I don't put it, it becomes a endless loop . Could you please help me if there is a way to use Contains in a way that will not search only for one symbol but will check for every single one until there is no more.
I will post the code here.
static string GeneratingRandomWords()
{
Random r = new Random();
List<string> words = new List<string>() { /*"Cat", "Dog", "Eagle", "Lion", "Shark",*/ "Green" };
string word = words[r.Next(0, words.Count)];
return word;
}
static char Input()
{
char inputt = char.Parse(Console.ReadLine());
return inputt;
}
static char[] TransformingCharToInvisible(string randomWord)
{
char[] charFromString = randomWord.ToCharArray();
for (int i = 0; i < randomWord.Length; i++)
{
charFromString[i] = '*';
}
Console.WriteLine(charFromString);
return charFromString;
}
static int CorrectGuesses(char input, string randomWord, int correct)
{
if (randomWord.Contains(input))
{
Console.WriteLine("Next");
correct++;
}
return correct;
}
static int Lives(string randomWord, char input, int lives)
{
if (!randomWord.Contains(input))
{
Console.WriteLine("Try another one");
lives--;
}
return lives;
}
static List<char> CorrectWord(List<char> correctGuesses, string randomWord, char input)
{
if (randomWord.Contains(input))
{
correctGuesses.Add(input);
char[] charFromString = randomWord.ToCharArray();
for (int i = 0; i < randomWord.Length; i++)
{
charFromString[i] = '*';
if (correctGuesses.Contains(randomWord[i]))
{
charFromString[i] = randomWord[i];
}
}
Console.WriteLine(charFromString);
}
return correctGuesses;
}
static void Main(string[] args)
{
string randomWord = GeneratingRandomWords();
TransformingCharToInvisible(randomWord);
List<char> correctGuesses = new List<char>();
int lives = 10;
int correct = 0;
//bool won = true;
while (true)
{
Console.WriteLine("Write a char");
char input = Input();
correct = CorrectGuesses(input, randomWord, correct);
lives = Lives(randomWord, input, lives);
if (correctGuesses.Contains(input))
{
Console.WriteLine("You've already tried '{0}', and it was correct!", input);
continue;
}
correctGuesses = CorrectWord(correctGuesses, randomWord, input);
if (lives == 0)
{
Console.WriteLine("You lose sorry, try againg next time ");
break;
}
if (correctGuesses.Count == randomWord.Length)
{
Console.WriteLine("You won the word is: {0}", randomWord);
break;
}
}
}
Here a simplified version of your code where i did not add all the error checking but the basics use the required Contains to check if letters are found
static void Main(string[] args)
{
var lives = 10;
var correctGuesses = new List<char>();
var word = "green";
while (true)
{
Console.WriteLine("Guess a letter? ");
// deliberatly just check for 1 character for simplicity reasons
var input = Console.ReadLine()[0];
// if already guessed give a chance to the user to retry
if (correctGuesses.Contains(input))
{
Console.WriteLine("Letter already guessed");
}
else
{
// if the word contains the letter
if (word.Contains(input))
{
// add as a correct guess
correctGuesses.Add(input);
Console.WriteLine("Letter found");
}
else
{
// letter dont exist remove a life
lives--;
Console.WriteLine("Letter not found");
}
}
// check if the user still have lives
if (lives == 0)
{
Console.WriteLine("You lost");
break;
}
// check if the amount of distinct character in the word match
// the amount found. This mean the word is completly guessed
else if (word.Distinct().Count() == correctGuesses.Count())
{
Console.WriteLine("You won you found the word");
break;
}
}
Console.ReadKey();
}
I didn't understand you very well
but I modified your code like this :
private static bool IsCorrectGuess(char input, string actualWord)
{
return actualWord.Contains(input);
}
private static void WriteCorrectGuesses(ICollection<char> correctGuesses, string randomWord)
{
char[] charFromString = randomWord.ToCharArray();
for (var i = 0; i < randomWord.Length; i++)
{
charFromString[i] = '*';
if (correctGuesses.Contains(randomWord[i]))
charFromString[i] = randomWord[i];
}
Console.WriteLine(charFromString);
}
private static string GeneratingRandomWords()
{
var r = new Random();
var words = new List<string>
{
/*"Cat", "Dog", "Eagle", "Lion", "Shark",*/ "Green"
};
return words[r.Next(0, words.Count)];
}
private static char Input()
{
return char.Parse(Console.ReadLine() ?? throw new InvalidOperationException());
}
private static void Main(string[] args)
{
string randomWord = GeneratingRandomWords();
var correctGuesses = new List<char>();
WriteCorrectGuesses(correctGuesses, randomWord);
var lives = 10;
var correct = 0;
//bool won = true;
while (true)
{
Console.WriteLine("Write a char");
char input = Input();
if (IsCorrectGuess(input, randomWord))
{
// correct letter
int score = randomWord.ToCharArray().Count(item => item == input);
for (var i = 0; i < score; i++)
{
correctGuesses.Add(input);
correct++;
}
WriteCorrectGuesses(correctGuesses, randomWord);
if (correctGuesses.Count == randomWord.Length)
{
Console.WriteLine("You won the word is: {0}", randomWord);
Console.Read();
break;
}
Console.WriteLine("Next");
}
else
{
// wrong letter
Console.WriteLine($"Try another one. You still have {lives} to try.");
lives--;
}
if (lives == 0)
{
Console.WriteLine("You lose sorry, try again next time ");
break;
}
}
}
I'm having problem with my code and cannot find my error. Why only the first try is working and on every other tries it prints me false?
Even when I enter 323, which is true, for example, and prints "true" after that everything is false even empty scapes.
class Program
{
public static void Main()
{
string inputedString = Console.ReadLine();
string reversedString = string.Empty;
while (true)
{
if (inputedString == "END")
{
break;
}
for (int i = inputedString.Length - 1; i >= 0; i--)
{
reversedString += inputedString[i];
}
if (reversedString == inputedString)
{
Console.WriteLine("true");
}
else
{
Console.WriteLine("false");
}
}
}
}
You read the first string outside the loop and never reread the string inside the loop. You also don't clear the reversedString so each subsequent time in the loop its wrong.
public static void Main()
{
string inputedString;
string reversedString;
while (true)
{
inputedString = Console.ReadLine();
reversedString = string.Empty;
if (inputedString == "END")
{
break;
}
for (int i = inputedString.Length - 1; i >= 0; i--)
{
reversedString += inputedString[i];
}
if (reversedString == inputedString)
{
Console.WriteLine("true");
}
else
{
Console.WriteLine("false");
}
}
}
}
The part of the code below should be inside the 'while" loop
string inputedString = Console.ReadLine();
string reversedString = string.Empty;
I wrote this little program that catches five integer numbers that are entered consecutively at the console.
This works as expected - except for one thing:
I did not find a way to accept 0 as one of the numbers being entered.
Of course, a solution with another collection type is easy.
But the challenge here is to do it with an array of five integers.
I tried to set a boolean flag "zeroEntered", tried with a counter, tried to count j backwwards. It all does not work.
Perhaps this is not possible? Would somebody know for sure?
Here is the code:
class Program
{
static void Main(string[] args)
{
#region Catch5IntegerInArrayOfInt[5]
// I try to catch five integers in an array of int[5]
// This works as expected except I cannot catch 0 as one of the numbers
// Cannot wrap my head around this one it seems
// because all ints are initialized with 0
Console.WriteLine("Please enter five unique numbers consecutively.");
int[] fiveNumbers = new int[5]; // do it using an array just the same (as collections were not part of the lectures so far)
for (int i = 0; i < fiveNumbers.Length; i++)
{
Console.WriteLine("Please enter your {0} number:", (Countables)i);
CatchUsersNumbers(fiveNumbers, i);
}
DisplayResult(fiveNumbers);
Console.WriteLine("\n");
}
#endregion
#region HelperMethods
private static bool CheckWhetherInteger(string userInput)
{
bool result = Int32.TryParse(userInput, out myInteger);
if (result == false)
{
Console.Clear();
Console.WriteLine("You did not enter an integer.");
}
return result;
}
private static bool CheckUniqueness(int[] fiveNumbers, int userInput)
{
for (int i = 0; i < fiveNumbers.Length; i++)
{
if (userInput == 0)
{
for (int j = i ; j <fiveNumbers.Length; j--)
{
if (j == 0)
break;
if (fiveNumbers[j] == 0)
{
return false;
}
}
}
else if (fiveNumbers[i] == userInput)
{
return false;
}
}
return true;
}
private static void CatchUsersNumbers(int[] fiveNumbers, int i)
{
while (true)
{
userInput = Console.ReadLine().Trim();
if (CheckWhetherInteger(userInput) && CheckUniqueness(fiveNumbers, myInteger))
{
fiveNumbers[i] = myInteger;
break;
}
else
Console.Clear();
Console.WriteLine("You did not enter a unique integer number, try again...");
}
}
private static void DisplayResult(int[] fiveNumbers)
{
Console.Clear();
Array.Sort(fiveNumbers);
Console.WriteLine("These are the five interger numbers you entered \nand that were stored in the array:\n");
for (int i = 0; i < fiveNumbers.Length; i++)
{
if (i != fiveNumbers.Length - 1)
Console.Write(fiveNumbers[i] + ", ");
else
Console.Write(fiveNumbers[i]);
}
}
#endregion
#region Class Variables
private static int myInteger = 0;
private static string userInput;
private enum Countables
{
first = 0,
second,
third,
fourth,
fifth
}
#endregion
}
Thank you.
It is possible, but your array of 5 ints will be initialized to 5 zeroes, so when scanning for uniqueness, your check fails, especially because of this piece of code:
if (fiveNumbers[j] == 0)
{
return false;
}
So instead of looping through the entire array, you should keep a counter to keep track of how many items you already have in your array. Then, when performing the check, only check upto that index, and don't include the other items in the check, because they contain 0, but you should treat them as uninitialized.
You could also solve this using other data types. For instance, you could create an array of nullable integers, so you can actually check whether an item already got a value. Or (maybe the best solution) you could use a List instead of array.
Your Only error here is that int.TryParse() takes 0 as invalid you could make another if statement to handle the exception but this looks less clean
private static bool CheckWhetherInteger(string userInput)
{
if (userInput == "0")
{
myInteger = 0;
return true
}
else
{
bool result = Int32.TryParse(userInput, out myInteger);
if (result == false)
{
Console.Clear();
Console.WriteLine("You did not enter an integer.");
}
}
return result;
}
I just post the solution - using nullable integers - as suggested by Golez Trol. Here it is, should somebody be interested:
class Program
{
static void Main(string[] args)
{
#region Catch5IntegerInArrayOfInt[5]
// The solution to catching five integers in an array of int[5]
// is to use nullable integers.
// Keeping a counter when entering an integer to the array does not appeal to me.
// With normal integers I cannot catch 0 as one of the numbers
// because all ints are initialized with 0
Console.WriteLine("Please enter five unique numbers consecutively.");
var fiveNumbers = new int?[5]; // do it using an array just the same (as collections were not part of the lectures so far)
for (int i = 0; i < fiveNumbers.Length; i++)
{
Console.WriteLine("Please enter your {0} number:", (Countables)i);
CatchUsersNumbers(fiveNumbers, i);
}
DisplayResult(fiveNumbers);
Console.WriteLine("\n");
}
#endregion
#region HelperMethods
private static void CatchUsersNumbers(int?[] fiveNumbers, int i)
{
while (true)
{
userInput = Console.ReadLine().Trim();
if (CheckWhetherInteger(userInput) && CheckUniqueness(fiveNumbers, myInteger))
{
fiveNumbers[i] = myInteger;
break;
}
else
{
Console.Clear();
Console.WriteLine("You did not enter a unique integer number, try again...");
}
}
}
private static bool CheckWhetherInteger(string userInput)
{
bool result = Int32.TryParse(userInput, out myInteger);
if (result == false)
{
Console.Clear();
Console.WriteLine("You did not enter an integer.");
}
return result;
}
private static bool CheckUniqueness(int?[] fiveNumbers, int userInput)
{
for (int i = 0; i < fiveNumbers.Length; i++)
{
if (fiveNumbers[i] == userInput)
{
return false;
}
}
return true;
}
private static void DisplayResult(int?[] fiveNumbers)
{
Console.Clear();
Array.Sort(fiveNumbers);
Console.WriteLine("These are the five interger numbers you entered \nand that were stored in the array:\n");
for (int i = 0; i < fiveNumbers.Length; i++)
{
if (i != fiveNumbers.Length - 1)
Console.Write(fiveNumbers[i] + ", ");
else
Console.Write(fiveNumbers[i]);
}
}
#endregion
#region Class Variables
private static int myInteger = 0;
private static string userInput;
private enum Countables
{
first = 0,
second,
third,
fourth,
fifth
}
#endregion
}
Thank you for your hints - I was truly stuck.
Code example:
using System;
public class Test {
public static void Main() {
int a = 0;
if(a++ == 0){
Console.WriteLine(a);
}
}
}
In this code the Console will write: 1. I can write this code in another way:
public static void Main() {
int a = 0;
if(a == 0){
a++;
Console.WriteLine(a);
}
}
These two examples work exactly the same (from what I know about postfix).
The problem is with this example coming from the Microsoft tutorials:
using System;
public class Document {
// Class allowing to view the document as an array of words:
public class WordCollection {
readonly Document document;
internal WordCollection (Document d){
document = d;
}
// Helper function -- search character array "text", starting
// at character "begin", for word number "wordCount". Returns
//false if there are less than wordCount words. Sets "start" and
//length to the position and length of the word within text
private bool GetWord(char[] text, int begin, int wordCount,
out int start, out int length) {
int end = text.Length;
int count = 0;
int inWord = -1;
start = length = 0;
for (int i = begin; i <= end; ++i){
bool isLetter = i < end && Char.IsLetterOrDigit(text[i]);
if (inWord >= 0) {
if (!isLetter) {
if (count++ == wordCount) {//PROBLEM IS HERE!!!!!!!!!!!!
start = inWord;
length = i - inWord;
return true;
}
inWord = -1;
}
} else {
if (isLetter) {
inWord = i;
}
}
}
return false;
}
//Indexer to get and set words of the containing document:
public string this[int index] {
get
{
int start, length;
if(GetWord(document.TextArray, 0, index, out start,
out length)) {
return new string(document.TextArray, start, length);
} else {
throw new IndexOutOfRangeException();
}
}
set {
int start, length;
if(GetWord(document.TextArray, 0, index, out start,
out length))
{
//Replace the word at start/length with
// the string "value"
if(length == value.Length){
Array.Copy(value.ToCharArray(), 0,
document.TextArray, start, length);
}
else {
char[] newText = new char[document.TextArray.Length +
value.Length - length];
Array.Copy(document.TextArray, 0, newText, 0, start);
Array.Copy(value.ToCharArray(), 0, newText, start, value.Length);
Array.Copy(document.TextArray, start + length, newText,
start + value.Length, document.TextArray.Length - start - length);
document.TextArray = newText;
}
} else {
throw new IndexOutOfRangeException();
}
}
}
public int Count {
get {
int count = 0, start = 0, length = 0;
while (GetWord(document.TextArray, start + length,
0, out start, out length)) {
++count;
}
return count;
}
}
}
// Class allowing the document to be viewed like an array
// of character
public class CharacterCollection {
readonly Document document;
internal CharacterCollection(Document d) {
document = d;
}
//Indexer to get and set character in the containing
//document
public char this[int index] {
get {
return document.TextArray[index];
}
set {
document.TextArray[index] = value;
}
}
//get the count of character in the containing document
public int Count {
get {
return document.TextArray.Length;
}
}
}
//Because the types of the fields have indexers,
//these fields appear as "indexed properties":
public WordCollection Words;
public readonly CharacterCollection Characters;
private char[] TextArray;
public Document(string initialText) {
TextArray = initialText.ToCharArray();
Words = new WordCollection(this);
Characters = new CharacterCollection(this);
}
public string Text {
get {
return new string(TextArray);
}
}
class Test {
static void Main() {
Document d = new Document(
"peter piper picked a peck of pickled peppers. How many pickled peppers did peter piper pick?"
);
//Change word "peter" to "penelope"
for(int i = 0; i < d.Words.Count; ++i){
if (d.Words[i] == "peter") {
d.Words[i] = "penelope";
}
}
for (int i = 0; i < d.Characters.Count; ++i) {
if (d.Characters[i] == 'p') {
d.Characters[i] = 'P';
}
}
Console.WriteLine(d.Text);
}
}
}
If I change the code marked above to this:
if (count == wordCount) {//PROBLEM IS HERE
start = inWord;
length = i - inWord;
count++;
return true;
}
I get an IndexOutOfRangeException, but I don't know why.
Your initial assumption is incorrect (that the two examples work exactly the same). In the following version, count is incremented regardless of whether or not it is equal to wordCount:
if (count++ == wordCount)
{
// Code omitted
}
In this version, count is ONLY incremented when it is equal to wordCount
if (count == wordCount)
{
// Other code omitted
count++;
}
EDIT
The reason this is causing you a failure is that, when you are searching for the second word (when wordCount is 1), the variable count will never equal wordCount (because it never gets incremented), and therefore the GetWord method returns false, which then triggers the else clause in your get method, which throws an IndexOutOfRangeException.
In your version of the code, count is only being incremented when count == wordCount; in the Microsoft version, it's being incremented whether the condition is met or not.
using System;
public class Test {
public static void Main() {
int a = 0;
if(a++ == 0){
Console.WriteLine(a);
}
}
}
Is not quite the same as:
public static void Main() {
int a = 0;
if(a == 0){
a++;
Console.WriteLine(a);
}
}
In the second case a++ is executed only if a == 0. In the first case a++ is executed every time we check the condition.
There is your mistake:
public static void Main() {
int a = 0;
if(a == 0){
a++;
Console.WriteLine(a);
}
}
It should be like this:
public static void Main() {
int a = 0;
if(a == 0){
a++;
Console.WriteLine(a);
}
else
a++;
}
a gets alwasy increased. This means, that in your code example count will get only increased when count == wordCount (In which case the method will return true anyway...). You basicly never increasing count.