I am writing a short program. What I need is that I want to set "correct" parameter in Game.cs, and in my advTry.cs, I want to use this "correct" parameter to determine the output. with my class advTry.cs like:
public bool correct { get; set; }
if (correct)
{
solveButton = new MenuButton(contentManager.Load<Texture2D>("solve"),
buttonCenter, GameState.AnswerNo);
Console.WriteLine("OK");
}
else
{
solveButton2 = new MenuButton(contentManager.Load<Texture2D>("solve"),
buttonCenter, GameState.AnswerYes);
Console.WriteLine("Not OK");
}
While in my GAME.cs, I define correct as:
if (messageString == "18")
{
Console.WriteLine("Main OK");
advTry.correct = true;
}
else
{
advTry.correct = false;
Console.WriteLine("Main not OK");
}
I use the Console.WriteLine to check the passing of boolean parameter "correct". While the result is originally "Not OK", then when I start to input "18", it gives out"Main not OK" first, then "Main OK" (easy to understand, because input"1" then "8").
However, the biggest problem is "OK" never comes out, the state "GameState.AnswerNo" can't be fulfilled, Why is that please? How to fix it please?
Your question is not at all clear. You haven't given any idea of the structure of the code apart from those two conditionals. It's just impossible to answer right now. However, my best guess from what you've written here is that you've set the value of "correct" to true in your advTry class, but you haven't run the code inside that class to output OK to the console. That code won't run automatically just because you set the value of "correct". You need to do something like this in advTry.cs:
private bool _correct;
public bool correct
{
get { return _correct; }
set
{
_correct = value;
output();
}
}
private void output
{
if (_correct)
{
//output "OK"
}
else
{
//output "Not OK"
}
}
Related
Why when I type "gamble" the first time, only the if statement works? It's no use typing anything else, it still adds 10 woods. And why when I type anything else the first time, just the else statement works? It is no use typing "gamble, will continue saying " Write '' gamble '' to hit the tree. " PS: The variable its int = woods; and string gamble;
Console.WriteLine("You have {0} woods", woods);
Console.WriteLine("Write ''gamble'' to hit the tree");
gamble = Console.ReadLine();
bool loop = true;
while (loop)
{
if (gamble.Contains("gamble"))
{
woods = woods + 10;
Console.Clear();
}
else
{
Console.WriteLine("Write ''gamble'' to hit the tree");
}
Console.WriteLine("You have {0} woods", woods);
Console.ReadLine();
}
gamble = Console.ReadLine();
You only set gamble in the beginning. In the loop it is never changed. So it keeps using the first value over and over again.
Add gamble = to the last line of the loop.
If I understand what your are describing, you forgot to read into gamble again
Console.WriteLine("You have {0} woods", woods);
gamble = Console.ReadLine();
}
At the end of the while loop, you are doing Console.ReadLine() but not storing it. You need gamble = Console.ReadLine() to store the scanned string in the "gamble" variable.
Because loop is always true. You should change it to false after if and else statements...
The reason it's adding 10 wood regardless if there is something else than "gamble" in the console line, is because you're writing "gamble" in the returning message.
else {Console.WriteLine("Write ''gamble'' to hit the tree");} is the problem here.
You can fix it by either not writing the word "gamble" inside the returning message, or find a clever way to not have it run in a while(true) loop.
You can, for example, use the main method to have it run the function you're going to run just once.
Something like this.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
// Set a `wood` variable for the class.
protected int wood { get; set; }
static void Main(string[] args)
{
Program program = new Program(); // Making use of non-static methods.
program.Handler();
}
public void Handler()
{
Console.WriteLine("Write \"gamble\" to hit the tree.");
string message = Console.ReadLine();
if (message == "gamble")
{
addWood(); // Call the non-static method.
}
}
public bool addWood()
{
this.wood = this.wood + 10;
Console.WriteLine("You now have {0} wood!", this.wood);
Handler(); // Call the Handler() method again for infinite loop.
return true;
}
}
}
WARNING: The program will exit if there is something else than "gamble" written.
BuildForm Method
public static IForm<FAQConversation> BuildForm()
{
return new FormBuilder<FAQConversation>()
.Field(new FieldReflector<FAQConversation>(nameof(Inquiry))
.SetValidate(AnswerInquiry)
.SetPrompt(new PromptAttribute("Okay, tell me what is your question. Enter \"back\" to go back to Products Selection."))
)
.Build();
}
Validation Method
private static async Task<ValidateResult> AnswerInquiry(FAQConversation state, object value)
{
var result = new ValidateResult();
//somecode here
if(testCase == false)
{
result.isValid = false;
result.Feedback = "Try again";
}
else
{
result.isValid = true;
}
return result;
}
My validation method returns the feedback "Try Again" text when the input on my validating field is invalid. However, it is returning both Original Prompt and the Feedback text.
Question
How do I remove the original prompt on revalidation of a field?
While FormFlow does offer a lot of customizability, the main idea behind it is to automate everything for you, which tends to indicate that at least some things are built in pretty strongly.
I understand that what you want to do is disable the prompt for a field upon "retry," which is to say that if the user was already shown the prompt for a field and they entered something invalid then they shouldn't be shown the prompt again. I can see in the source code that FormFlow doesn't really provide a special case for "retries" and the behavior of prompting when a field remains unknown is one of those built-in things. However, there is still something you can do.
FormFlow offers a (largely undocumented) way to replace what's called the "prompter." You can do this using the Prompter() method, which takes a PromptAsyncDelegate. As a starting point for your new prompter, you can find the default prompter in the FormBuilder source code:
_form._prompter = async (context, prompt, state, field) =>
{
var preamble = context.MakeMessage();
var promptMessage = context.MakeMessage();
if (prompt.GenerateMessages(preamble, promptMessage))
{
await context.PostAsync(preamble);
}
await context.PostAsync(promptMessage);
return prompt;
};
Whereas the default prompter always posts promptMessage, your replacement can surround that line with an if statement. That leaves the question of what your condition should be. We've established that FormFlow doesn't include any concept of a retry, so you'd have to build that in yourself somehow. You could include a Boolean field as a switch in FAQConversation's state, or you could even use PrivateConversationData since the prompter gives you access to the DialogContext. You might think that would be a simple matter of turning off the switch when the prompt gets displayed once or when AnswerInquiryAsync determines that the user input is invalid, but then when would the switch get turned back on? What if the user enters "back" and you want the prompt to be displayed again?
While you might find some way to more accurately represent the logic of "disabling the prompt on retry," the simplest solution I came up with was to keep track of the last message FormFlow produced and then skip the first message that comes after "Try again." It looks like this:
[Serializable]
public class FAQConversation
{
public string Inquiry { get; set; }
private string LastMessage { get; set; }
private const string TRY_AGAIN = "Try again";
public static IForm<FAQConversation> BuildForm()
{
return new FormBuilder<FAQConversation>()
// This is an alternative way of using the Field() method but it works the same.
.Field(nameof(Inquiry),
"Okay, tell me what is your question. Enter \"back\" to go back to Products Selection.",
validate: AnswerInquiryAsync)
.Prompter(PromptAsync)
.Build();
}
private static async Task<ValidateResult> AnswerInquiryAsync(FAQConversation state, object value)
{
var result = new ValidateResult();
bool testCase = Equals(value, "true"); // Enter "true" to continue for testing purposes.
if (testCase == false)
{
result.IsValid = false;
// A constant should be used with strings that appear more than once in your code.
result.Feedback = TRY_AGAIN;
}
else
{
result.IsValid = true;
// A value must be provided or else the Field will not be populated.
result.Value = value;
}
return result;
}
/// <summary>
/// Here is the method we're using for the PromptAsyncDelegate.
/// </summary>
private static async Task<FormPrompt> PromptAsync(IDialogContext context, FormPrompt prompt,
FAQConversation state, IField<FAQConversation> field)
{
var preamble = context.MakeMessage();
var promptMessage = context.MakeMessage();
if (prompt.GenerateMessages(preamble, promptMessage))
{
await context.PostAsync(preamble);
}
// Here is where we've made a change to the default prompter.
if (state.LastMessage != TRY_AGAIN)
{
await context.PostAsync(promptMessage);
}
state.LastMessage = promptMessage.Text;
return prompt;
}
}
I am writing a language of my own called SPL. It has an Input command which reads input from the ISplRuntime.Input property (it is a TextReader). All other commands run on this interface because this way I can write different apps with just one library!
I then wrote another console app to test my language. This is my implementation of ISplRuntime. Focus on the Input and constructor:
public class MyRuntime : ISplRuntime {
protected TextReader reader;
protected bool stopped;
public object Current {
get;
set;
}
public virtual TextReader Input {
get {
return reader;
}
}
public object[] Memory {
get;
protected set;
}
public TextWriter Output {
get {
return Console.Out;
}
}
public bool Stopped {
get {
return stopped;
}
set {
stopped = value;
if (value) {
Console.WriteLine ();
Console.WriteLine ("Program has finished");
}
}
}
public void ShowErrorMessage (string error) {
Console.WriteLine (error);
}
public MyRuntime () {
string s = Console.ReadLine ();
reader = new StringReader (s);
stopped = false;
Memory = new object[20];
}
}
When the runtime is constructed, it asks for input. And use that input to create a StringReader and return it in the Input property. So every time the input will only be one lline.
Then I write a program in SPL that outputs the input. And that is where the problem is! When I input 1 1 1 1 it prints 1 1 1 and threw a FormatException. This is how I read number input:
private bool ReadFromInput (ISplRuntime runtime, out int i) {
char stuffRead = (char)runtime.Input.Peek ();
if (stuffRead == ' ') {
i = 0;
runtime.Input.Read ();
return true;
}
if (char.IsNumber (stuffRead)) {
string numberString = "";
while (char.IsNumber (stuffRead)) {
stuffRead = (char)runtime.Input.Read ();
numberString += stuffRead;
}
i = Convert.ToInt32 (numberString); //This is where the exception occured! (Obviously, because there is no other methods that would throw it)
return true;
} else {
i = 0;
return false;
}
}
The parameter runtime is just the runtime you have just seen. It returns true if it successfully reads a number. And that number is the output parameter i.
After using the "Watch" window in Visual Studio, I found out that number string is "1\uffff" when the exception is thrown. That's why it throws it! I know (think) that '\uffff' is the end of line character. But why would it appear in my input? I know (think) that pressing Ctrl + Z makes a end of line, but I did not! Then I checked runtime.Input in the watch window. This is the result:
I see that there is a field called _s and I think that is the string that I told it to read from. See? _s doesn't even contain '\uffff', how come it reads it?
P.S. I already know the solution. I just need to change the while loop a little and it works. But I want to know why does it reads an end of line.
There is no mistery here - \uffff is produced by your code. All you need is to read the documentation and understand what the methods that you call return.
TextReader.Peek Method
Return Value
Type: System.Int32
An integer representing the next character to be read, or -1 if no more characters are available or the reader does not support seeking.
TextReader.Read Method
Return Value
Type: System.Int32
The next character from the text reader, or -1 if no more characters are available.
Hope you see the relation between -1 (0xffffffff) and \uffff.
Keep getting the error message does not contain a static main method for suitable entry point. Would anyone be able to explain this error to me and possibly help me fix it? Thanks. New to C#
{
class Authenticator
{
private Dictionary<string, string> dictionary = new Dictionary<string, string>();
public void IntialValues()
{
dictionary.Add("username1", "password1");
dictionary.Add("username2", "password2");
dictionary.Add("username3", "password3");
dictionary.Add("username4", "password4");
dictionary.Add("username5", "password5");
}
public bool Authenticate(Boolean authenticated)
{
Console.WriteLine("Please enter a username");
string inputUsername = Console.ReadLine();
Console.WriteLine("Please enter your password");
string inputPassword = Console.ReadLine();
if (dictionary.ContainsKey(inputUsername) && dictionary[inputUsername] == inputPassword)
{
authenticated = true;
}
else
{
authenticated = false;
}
return authenticated;
}
}
}
If all of your code consists only of the block shown above then the error is more than clear. A Main method is required in your program.
The Main method is, by convention, the default point where the code starts executing. You can get here a more in depth explanation
So, for example, you need to add the following code
class Authenticator
{
static void Main(string[] args)
{
Authenticator au = new Authenticator();
au.InitialValues();
if(au.Authenticate())
Console.WriteLine("Authenticated");
else
Console.WriteLine("NOT Authenticated");
Console.WriteLine("Press Enter to end");
Console.ReadLine();
}
// Move the boolen variable inside the method
public bool Authenticate()
{
bool authenticated = false;
Console.WriteLine("Please enter a username");
string inputUsername = Console.ReadLine();
Console.WriteLine("Please enter your password");
string inputPassword = Console.ReadLine();
if (dictionary.ContainsKey(inputUsername) && dictionary[inputUsername] == inputPassword)
{
authenticated = true;
}
else
{
authenticated = false;
}
return authenticated;
}
}
By the way, you should remove the parameter passed in input to the Authenticate method. You should declare it as an internal variable, set it depending on the outcome of the check and return it.
However, you could remove that variable altogether writing
....
return (dictionary.ContainsKey(inputUsername)) &&
(dictionary[inputUsername] == inputPassword)
}
All executable programs must have a Main function somewhere in the project that is compiled to the exe.
If you just want to compile a class (eg to a dll) then you have to set that as the "project type" in visual studio.
The easiest way is to create a new project, but select class library as project type, and then paste your code in there. Alternatively you can use the command line to compile a file to a dll like so:
c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /target:library Authenticator.cs
Evening guys,
This may seem like a stupid question but im having some issues figuring out where i should be placing my user input verification checks. I have checks, for the following:
file exists
Correct extension
Access to the file
Input in 2 NumericUpDown controls
One numericUpDown is always greater than the other.
Assignment to static properties.
Im assuming each one of these should at least be a single method but i then have a single method which has a large number of lines which solely check the result of the method calls to the list above. ie
public void VerifyData()
{
if(VerifyNumber1OnTheList != true)
{
LogError("The file specified is incorrect")
return;
}
if(VerifyNumber2OnTheList != ......
Any suggestions on how i should actually be laying this out would be appreciated.
Thanks
Putting a series of validation methods is ok.
This is user input, so you're doing defensive programming here, not looking for exceptional errors. It seems like you'd want to know why the user input is bad. If so, a simple approach is to use a collecting object to visit each validation method
public void VerifyData(ValidationErrors errors)
{
ValidateFileExists(errors);
ValidateExtension(errors);
ValidateFileAccess(errors);
...
}
private void ValidateFileExists(ValidationErrors errors)
{
if(!File.Exists...)
{
errors.Add("File does not exists.");
}
}
public void CallingMethod(UserInput input)
{
_dataToVerify = input;
var errors = new ValidationErrors();
VerifyData(errors);
if(errors.Count > 0)
ShowErrors(errors);
else
ShowSuccess();
}
I just put the data in an instance variable for purposes of simplicity, you could pass that into your validation method. This approach is simple but allows you to tell the user something about the input and how to correct it.
All right here is a quick sample I wrote up for you. Architecture obviously is your choice here. Modify as needed. I believe this should be a great jumping off point for you.
Cheers
Matt
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//This would simulate the event handler that calls your validation event
List<string> errorList = Validation.VerifyData();
if (errorList.Count != 0)
{
ErrorHandler.HandleError(errorList);
return;
}
//Do stuff if validation actually passed here.
}
}
public static class Validation
{
public static List<string> VerifyData()
{
List<string> errorList = new List<string>();
//File exists
if (true)
errorList.Add("File doesn't exist.");
//File has correct extension
if (true)
errorList.Add("File doesn't exist.");
//Has access to the file
if (true)
errorList.Add("File doesn't exist.");
//INput in 2 NumericUpDownControls
if (true)
errorList.Add("File doesn't exist.");
//One NumericUpDown is always greater than the other
if (true)
errorList.Add("File doesn't exist.");
//Assignment to static properties
if (true)
errorList.Add("File doesn't exist.");
return errorList;
}
}
public static class ErrorHandler
{
public static void HandleError(List<string> errorMessageList )
{
//Display your message here. This could return a dialog result as well for further processing.
}
}
}
Your method above seems like a perfectly fine way of laying out your code.
My only change would be in how you handle your checking. Use well-named methods rather than booleans during your check:
public void VerifyData()
{
if(FileExists())
{
LogError("The file specified is incorrect")
return;
}
if(CorrectExtension())