Difference between revisions of "If a player presses enter without typing a word it is an invalid move"

From TRCCompSci - AQA Computer Science
Jump to: navigation, search
(Improved + new solution)
Line 1: Line 1:
 +
== Method 01==
 +
 
<syntaxhighlight lang=csharp>
 
<syntaxhighlight lang=csharp>
private static void HaveTurn(string PlayerName, ref string PlayerTiles, ref int PlayerTilesPlayed, ref int PlayerScore, Dictionary<char, int> TileDictionary, ref QueueOfTiles TileQueue, List<string> AllowedWords, int MaxHandSize, int NoOfEndOfTurnTiles)
+
private static void HaveTurn(string PlayerName, ref string PlayerTiles, ref int PlayerTilesPlayed, ref int PlayerScore, Dictionary<char, int> TileDictionary, ref QueueOfTiles TileQueue, List<string> AllowedWords, int MaxHandSize, int NoOfEndOfTurnTiles) {
        {
+
    Console.WriteLine();
            Console.WriteLine();
+
    Console.WriteLine(PlayerName + " it is your turn.");
            Console.WriteLine(PlayerName + " it is your turn.");
+
    DisplayTilesInHand(PlayerTiles);
            DisplayTilesInHand(PlayerTiles);
+
    string NewTileChoice = "2";
            string NewTileChoice = "2";
+
    bool ValidWord = false;
            bool ValidChoice = false;
+
    string Choice = "";
            bool ValidWord = false;
+
 
            string Choice = "";
+
    #region ChoiceChecker
            while (!ValidChoice)
+
    while (true) { // Infinite loop
            {
+
        Choice = GetChoice();
                Choice = GetChoice();
+
       
                if (Choice == "")
+
        if (String.IsNullOrWhiteSpace(Choice)) { // If nothing or whitespace "   " input
                {
+
            Console.WriteLine("You inputted a word with no letters, this is not a good option!");
                    Console.WriteLine("You inputted a word with no letters, this is not a good option!");
+
            Console.WriteLine("Try again please!");
                    Console.WriteLine("Try again please!")
+
        }  else { break;} // On valid input break loop and continue method
                    continue;
+
    }
                }  
+
    #endregion
             }
+
 
         }
+
    // Notice while loop using 'ValidChoice' boolean gone
 +
    if (Choice == "1") {
 +
DisplayTileValues(TileDictionary, AllowedWords);
 +
    } else if (Choice == "4") {
 +
TileQueue.Show();
 +
    } else if (Choice == "7") {
 +
DisplayTilesInHand(PlayerTiles);
 +
    } else if (Choice == "0") {
 +
        FillHandWithTiles(ref TileQueue, ref PlayerTiles, MaxHandSize);
 +
    } else {
 +
if (Choice.Length == 0) {
 +
    ValidWord = false;
 +
} else {
 +
    ValidWord = CheckWordIsInTiles(Choice, PlayerTiles);
 +
}
 +
 
 +
if (ValidWord) {
 +
    ValidWord = CheckWordIsValid(Choice, AllowedWords);
 +
   
 +
             if (ValidWord) {
 +
Console.WriteLine();
 +
Console.WriteLine("Valid word");
 +
Console.WriteLine();
 +
UpdateAfterAllowedWord(Choice, ref PlayerTiles, ref PlayerScore, ref PlayerTilesPlayed, TileDictionary, AllowedWords);
 +
NewTileChoice = GetNewTileChoice();
 +
    }
 +
         } else {
 +
    Console.WriteLine();
 +
    Console.WriteLine("Not a valid attempt, you lose your turn.");
 +
    Console.WriteLine();
 +
}
 +
 
 +
if (NewTileChoice != "4") {
 +
    AddEndOfTurnTiles(ref TileQueue, ref PlayerTiles, NewTileChoice, Choice);
 +
}
 +
 
 +
Console.WriteLine();
 +
Console.WriteLine("Your word was:" + Choice);
 +
Console.WriteLine("Your new score is:" + PlayerScore);
 +
Console.WriteLine("You have played " + PlayerTilesPlayed + " tiles so far in this game.");
 +
    }
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
* This code demonstrates what would happen if a user was to attempt entering a word that does not exist
+
 
* The part of the code used for this function can be found starting line 14, finishing on line 17
+
The above method in question consists of an infinite loop which continually requests a choice and upon the entering of the first valid choice, it stops execution and carries on with the method. The actual-new content appears at the beginning of the infinite loop. The valid choice boolean which is defined in the original method has been removed because I find it un-necessary and I have also removed the while loop sorrounding the choce conditions. Notice in this case because if choice isn't a number it's seen as the users word input, you don't have to re-check the input isn't of length 0 or not again.
* This means that if the user word is equal to nothing, it takes the user back to the choice screen
+
 
* This code avoids potential accidents if a misclick occurs
+
==Method 02==
 +
 
 +
While the above method is perfectly fine, in all honesty it feels somewhat forceful. I feel a much quicker approach in this case would be to use recursion alongside the GetChoice method. As of now, the GetChoice method looks like this.
 +
 
 +
<syntaxhighlight lang=csharp>
 +
private static string GetChoice() {
 +
    string Choice;
 +
    Console.WriteLine();
 +
    Console.WriteLine("Either:");
 +
    Console.WriteLine("    enter the word you would like to play OR");
 +
    Console.WriteLine("    press 1 to display the letter values OR");
 +
    Console.WriteLine("    press 4 to view the tile queue OR");
 +
    Console.WriteLine("    press 7 to view your tiles again OR");
 +
    Console.WriteLine("    press 0 to fill hand and stop the game.");
 +
    Console.Write("> ");
 +
    Choice = Console.ReadLine();
 +
    Console.WriteLine();
 +
    Choice = Choice.ToUpper();
 +
    return Choice;
 +
}
 +
</syntaxhighlight>
 +
 
 +
With a little recursion we can have the same affect as above in 4 lines with no real effort.
 +
 
 +
<syntaxhighlight lang=csharp>
 +
private static string GetChoice() {
 +
    string Choice;
 +
 
 +
    Console.WriteLine();
 +
    Console.WriteLine("Either:");
 +
    Console.WriteLine("    enter the word you would like to play OR");
 +
    Console.WriteLine("    press 1 to display the letter values OR");
 +
    Console.WriteLine("    press 4 to view the tile queue OR");
 +
    Console.WriteLine("    press 7 to view your tiles again OR");
 +
    Console.WriteLine("    press 0 to fill hand and stop the game.");
 +
    Console.Write("> ");
 +
 
 +
    Choice = Console.ReadLine().ToUpper();
 +
    Console.WriteLine();
 +
 
 +
    if (String.IsNullOrWhiteSpace(Choice)) { // Invalid choice
 +
        Console.WriteLine("You inputted a word with no letters, this is not a good option!\nTry Again\n");
 +
        return GetChoice(); // Rerun method again from the top and then return its value when valid
 +
    } else return Choice; // Valid so return
 +
}
 +
</syntaxhighlight>
 +
 
 +
This recursive method functions similair to a synthetic while loop. In fact, you recieve a StackOverflowException precisely when this continually nesting loop runs far too many times (interesting point for any who're interested); For those who worry this may mean this method is unreliable or "Exception-prone", please note that for a StackOverflowException to be thrown the user must enter an invalid choice over 1,000,000 times and for a computer this may be instant but for a user it's highly unlikely. To finish off the program let's return to the above method and modify the one line we need to (also removing the while loop) to complete our task.
 +
 
 +
<syntaxhighlight lang=csharp>
 +
private static void HaveTurn(string PlayerName, ref string PlayerTiles, ref int PlayerTilesPlayed, ref int PlayerScore, Dictionary<char, int> TileDictionary, ref QueueOfTiles TileQueue, List<string> AllowedWords, int MaxHandSize, int NoOfEndOfTurnTiles) {
 +
    // ... Var initalisation region here   
 +
 
 +
    string Choice = GetChoice(); // That's it
 +
 
 +
    // .. If statement stuff here
 +
}
 +
</syntaxhighlight>
 +
 
 +
That's it, just change the choice variable definition to call the variable and you'll get a valid choice of desired length > 0 (including whitespace as 0). Pick and choose whatever solution u prefer.

Revision as of 19:24, 14 November 2017

Method 01

private static void HaveTurn(string PlayerName, ref string PlayerTiles, ref int PlayerTilesPlayed, ref int PlayerScore, Dictionary<char, int> TileDictionary, ref QueueOfTiles TileQueue, List<string> AllowedWords, int MaxHandSize, int NoOfEndOfTurnTiles) {
    Console.WriteLine();
    Console.WriteLine(PlayerName + " it is your turn.");
    DisplayTilesInHand(PlayerTiles);
    string NewTileChoice = "2";
    bool ValidWord = false;
    string Choice = "";

    #region ChoiceChecker
    while (true) { // Infinite loop
        Choice = GetChoice();
        
        if (String.IsNullOrWhiteSpace(Choice)) { // If nothing or whitespace "   " input
            Console.WriteLine("You inputted a word with no letters, this is not a good option!");
            Console.WriteLine("Try again please!");
        }  else { break;} // On valid input break loop and continue method
    }
    #endregion

    // Notice while loop using 'ValidChoice' boolean gone
    if (Choice == "1") {
	DisplayTileValues(TileDictionary, AllowedWords);
    } else if (Choice == "4") {
	TileQueue.Show();
    } else if (Choice == "7") {
	DisplayTilesInHand(PlayerTiles);
    } else if (Choice == "0") {
        FillHandWithTiles(ref TileQueue, ref PlayerTiles, MaxHandSize);
    } else {
	if (Choice.Length == 0) {
	    ValidWord = false;
	} else {
	    ValidWord = CheckWordIsInTiles(Choice, PlayerTiles);
	}

	if (ValidWord) {
	    ValidWord = CheckWordIsValid(Choice, AllowedWords);
	    
            if (ValidWord) {
		Console.WriteLine();
		Console.WriteLine("Valid word");
		Console.WriteLine();
		UpdateAfterAllowedWord(Choice, ref PlayerTiles, ref PlayerScore, ref PlayerTilesPlayed, TileDictionary, AllowedWords);
		NewTileChoice = GetNewTileChoice();
	    }
        } else {
	    Console.WriteLine();
	    Console.WriteLine("Not a valid attempt, you lose your turn.");
	    Console.WriteLine();
	}

	if (NewTileChoice != "4") {
	    AddEndOfTurnTiles(ref TileQueue, ref PlayerTiles, NewTileChoice, Choice);
	}

	Console.WriteLine();
	Console.WriteLine("Your word was:" + Choice);
	Console.WriteLine("Your new score is:" + PlayerScore);
	Console.WriteLine("You have played " + PlayerTilesPlayed + " tiles so far in this game.");
    }
}

The above method in question consists of an infinite loop which continually requests a choice and upon the entering of the first valid choice, it stops execution and carries on with the method. The actual-new content appears at the beginning of the infinite loop. The valid choice boolean which is defined in the original method has been removed because I find it un-necessary and I have also removed the while loop sorrounding the choce conditions. Notice in this case because if choice isn't a number it's seen as the users word input, you don't have to re-check the input isn't of length 0 or not again.

Method 02

While the above method is perfectly fine, in all honesty it feels somewhat forceful. I feel a much quicker approach in this case would be to use recursion alongside the GetChoice method. As of now, the GetChoice method looks like this.

private static string GetChoice() {
    string Choice;
    Console.WriteLine();
    Console.WriteLine("Either:");
    Console.WriteLine("     enter the word you would like to play OR");
    Console.WriteLine("     press 1 to display the letter values OR");
    Console.WriteLine("     press 4 to view the tile queue OR");
    Console.WriteLine("     press 7 to view your tiles again OR");
    Console.WriteLine("     press 0 to fill hand and stop the game.");
    Console.Write("> ");
    Choice = Console.ReadLine();
    Console.WriteLine();
    Choice = Choice.ToUpper();
    return Choice;
}

With a little recursion we can have the same affect as above in 4 lines with no real effort.

private static string GetChoice() {
    string Choice;

    Console.WriteLine();
    Console.WriteLine("Either:");
    Console.WriteLine("     enter the word you would like to play OR");
    Console.WriteLine("     press 1 to display the letter values OR");
    Console.WriteLine("     press 4 to view the tile queue OR");
    Console.WriteLine("     press 7 to view your tiles again OR");
    Console.WriteLine("     press 0 to fill hand and stop the game.");
    Console.Write("> ");

    Choice = Console.ReadLine().ToUpper();
    Console.WriteLine();

    if (String.IsNullOrWhiteSpace(Choice)) { // Invalid choice
        Console.WriteLine("You inputted a word with no letters, this is not a good option!\nTry Again\n");
        return GetChoice(); // Rerun method again from the top and then return its value when valid
    } else return Choice; // Valid so return
}

This recursive method functions similair to a synthetic while loop. In fact, you recieve a StackOverflowException precisely when this continually nesting loop runs far too many times (interesting point for any who're interested); For those who worry this may mean this method is unreliable or "Exception-prone", please note that for a StackOverflowException to be thrown the user must enter an invalid choice over 1,000,000 times and for a computer this may be instant but for a user it's highly unlikely. To finish off the program let's return to the above method and modify the one line we need to (also removing the while loop) to complete our task.

private static void HaveTurn(string PlayerName, ref string PlayerTiles, ref int PlayerTilesPlayed, ref int PlayerScore, Dictionary<char, int> TileDictionary, ref QueueOfTiles TileQueue, List<string> AllowedWords, int MaxHandSize, int NoOfEndOfTurnTiles) {
    // ... Var initalisation region here    

    string Choice = GetChoice(); // That's it

    // .. If statement stuff here
}

That's it, just change the choice variable definition to call the variable and you'll get a valid choice of desired length > 0 (including whitespace as 0). Pick and choose whatever solution u prefer.