Using logical operators in shooting robot program [closed] - c#

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 4 years ago.
Improve this question
Here is the c# code that controls an artillery shooting robot.
static bool ShouldFire(bool enemyInFront, string enemyName, int robotHealth)
{
bool shouldFire = true;
if (enemyInFront == true)
{
if (enemyName == "boss")
{
if (robotHealth < 50) shouldFire = false;
if (robotHealth > 100) shouldFire = true;
}
}
else
{
return false;
}
return shouldFire;
}
The code looks awkward somewhat and could be re-written significantly shorter. Can the community at stackoverflow suggest a c# method, that would do the same as in the code above, but using one operation? I kindly ask you to make your proposals. Here is some template of what one is looking for:
static bool ShouldFire2(bool enemyInFront, string enemyName, int robotHealth)
{
return enemyInFront && (...);
}
I would appreciate some explanation, on how to achieve the desired outcome.

My suggestion is this:
static bool ShouldFire2(bool enemyInFront, string enemyName, int robotHealth)
{
return enemyInFront && (enemyName == "boss" ? robotHealth >= 50 : true);
}
You first check in there is an enemy ahead. if yes, check if it is boss and if its hp greater than 50 then return true, otherwise false. If not a boss, always return true. And false if nothing in front of your character.

The line 'if (robotHealth > 100) shouldFire = true;' does nothing. shouldFire is already true unless health is under 50.
So you can reduce that section to:
static bool ShouldFire(bool enemyInFront, string enemyName, int robotHealth)
{
bool shouldFire = true;
if (enemyInFront == true)
{
return !(enemyName != "boss" && robotHealth < 50); }
else
{
return false;
}
return shouldFire;
}
Which could be reduced to:
static bool ShouldFire(bool enemyInFront, string enemyName, int robotHealth)
{
return enemyInFront && (enemyName != "boss" || robotHealth >= 50);
}

Related

Can a return statement returning the result of a ternary expression be made to not return for one branch of the ternary?

Is it possible to write this if statement in ternary operator (shorthand of c# if)? If yes what would it be?
if (condition)
{
return true;
}
else
{
int a = 2;
}
Thanx everyone in advance. Thank you very much.
Sorry guys if I confused you. I am trying to use ternary operator in this if else block of the method.
public static bool CompareDictionary(this Dictionary<Position, char>
dictionary1,
Dictionary<Position, char> dictionary2, out List<string> wordList)
{
string str = "";
wordList = new List<string>();
foreach (var dic1KeyVal in dictionary1)
{
Position d1key = dic1KeyVal.Key;
char d1Pos = dic1KeyVal.Value;
bool isFound = false;
foreach (var dic2KeyVal in dictionary2)
{
Position d2key = dic2KeyVal.Key;
char d2Pos = dic2KeyVal.Value;
if (d1Pos.Equals(d2Pos) && d1key == d2key)
{
isFound = true;
str = str + d1Pos.ToString();
}
}
if (isFound == false)
{
return false;
}
else
{
wordList.Add(str);
str = "";
}
}
return true;
}
Short Answer
No.
Long Answer
First of all this code does not even need an else:
if (condition)
{
return true;
}
else
{
int a = 2;
}
and can be written as:
if (condition)
{
return true;
}
int a = 2;
Now for ternary operator: Both conditions in a ternary operator must return the same thing. You cannot return a bool in one condition and then assign to a variable in another condition. If you were checking the answer to a question, for example, it would be like this:
return answer == 2 ? true : false;
Whether the answer is correct or not, we return a bool. Or it could be like this:
return answer == 2 ? 1: -1;
But not like this:
return answer == 2 ? true : "wrong"; // will not compile
No. The ternary operator just returns one out of two potential values depending on a condition.
What you can do with the ternary operator is, e.g. int a = condition ? 0 : 2 which would assign the variable a value of either 0 or 2 depending on the value of condition.
Given a more complete example of what you intend to do someone here could potentially come up with a nicer syntax.

Parse command line string into a list of strings [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I want to take the following string as input:
first-arg second-arg "third arg with spaces" "arg with \" quotes"
and return this list of strings as output
["first-arg", "second-arg", "third arg with spaces", "arg with \" quotes"]
Are there any nuget packages or built in functions that can do this? I want it to handle edge cases like arguments containing multiple words and arguments containing quotes.
string[] arguments = Environment.GetCommandLineArgs();
For more information see the MSDN website
This class satisfies the requirements. It's not the most effective way, but it returns the right arguments.
public static class ArgumentLineParser
{
public static string[] ToArguments(string cmd)
{
if (string.IsNullOrWhiteSpace(cmd))
{
return new string[0];
}
var argList = new List<string>();
var parseStack = new Stack<char>();
bool insideLiteral = false;
for (int i = 0; i < cmd.Length; i++)
{
bool isLast = i + 1 >= cmd.Length;
if (char.IsWhiteSpace(cmd[i]) && insideLiteral)
{
// Whitespace within literal is kept
parseStack.Push(cmd[i]);
}
else if (char.IsWhiteSpace(cmd[i]))
{
// Whitespace delimits arguments
MoveArgumentToList(parseStack, argList);
}
else if (!isLast && '\\'.Equals(cmd[i]) && '"'.Equals(cmd[i + 1]))
{
//Escaped double quote
parseStack.Push(cmd[i + 1]);
i++;
}
else if ('"'.Equals(cmd[i]) && !insideLiteral)
{
// Begin literal
insideLiteral = true;
}
else if ('"'.Equals(cmd[i]) && insideLiteral)
{
// End literal
insideLiteral = false;
}
else
{
parseStack.Push(cmd[i]);
}
}
MoveArgumentToList(parseStack, argList);
return argList.ToArray();
}
private static void MoveArgumentToList(Stack<char> stack, List<string> list)
{
var arg = string.Empty;
while (stack.Count > 0)
{
arg = stack.Pop() + arg;
}
if (arg != string.Empty)
{
list.Add(arg);
}
}
}
It can be used like this:
var line = #"first-arg second-arg ""third arg with spaces"" ""arg with \"" quotes""";
var args = ArgumentLineParser.ToArguments(line);

Search function LINQ. Use checkbox values as parameters

I have a search function that tales 7 parameters and 6 of them are checkbox values. They are bools like shown down below. I Have a problem with my datetime search. If the user check that box if would like do run a serach function where that a date is not null in the database. My code look like this at the moment. But i would like to get some feedback to how to improve my code for better performance and code structure.
public List<Invoice> GetAllInvoicesBySearch(int merchant, long buyer, bool send, bool paid, bool firstReminder, bool secondReminder, bool invoiceClaim)
{
var sendValue = new InvoiceStatus();
var paidValue = new InvoiceStatus();
var firstRemind = new DateTime();
var secondRemind = new DateTime();
if (buyer <= 0)
{
return null;
}
if (send)
{
sendValue = InvoiceStatus.Sent;
}
if (paid)
{
paidValue = InvoiceStatus.Paid;
}
if (firstReminder)
{
firstRemind = DateTime.Now;
}
if (secondReminder)
{
secondRemind = DateTime.Now;
}
return
Context.Invoices.Where(
i =>
i.InstallationId == merchant && i.Buyer.Msisdn == buyer || i.Status == sendValue || i.Status == paidValue ||
i.FirstReminderDate == firstRemind || i.SecondReminderDate == secondRemind).ToList();
}
So my problem is with the datetime at the moment to get that correctly. Any suggestions on how to solve my problem and improve my code?
You would be better off using a PredicateBuilder and converting to an extension method like this:
public static class ExtensionMethods {
public static IQueryable<Invoice> Search(this IQueryable<Invoice> src, int merchant,
long buyer, bool send, bool paid, bool firstReminder,
bool secondReminder, bool invoiceClaim)
{
var predicate = PredicateBuilder.False<Invoice>();
var sendValue = new InvoiceStatus();
var paidValue = new InvoiceStatus();
var firstRemind = new DateTime();
var secondRemind = new DateTime();
if (buyer <= 0)
{
return src.Where(predicate);
}
predicate=predicate.Or(i=>i.InstallationId == merchant && i.Buyer.Msisdn == buyer);
if (send)
{
predicate=predicate.Or(i=>i.Status == InvoiceStatus.Sent);
}
if (paid)
{
predicate=predicate.Or(i=>i.Status == InvoiceStatus.Paid);
}
if (firstReminder)
{
predicate=predicate.Or(i=>i.FirstReminderDate == DateTime.Today);
}
if (secondReminder)
{
predicate=predicate.Or(i=>i.SecondReminderDate == DateTime.Today);
}
return src.Where(predicate);
}
}
Also, if I understand your code correctly, InvoiceStatus should either be an enum, or at the very least, InvoiceStatus.Sent and InvoiceStatus.Paid should be marked as being static. Reference it like so:
Context.Invoices.Search(...).OrderBy(...)...
It will make further manipulation much easier if you need to do sorting, paging, filtering beyond the original searching.

Simplifying many possibilities in c# indexof condition [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
Is there any way to simplify this code? The input is a string.
private string IfItIsPicture(string URI_obrazku)
{
if (URI_obrazku.IndexOf(".jpg") > -1 ||
URI_obrazku.IndexOf(".png") > -1 ||
URI_obrazku.IndexOf(".bmp") > -1 ||
URI_obrazku.IndexOf(".tiff") > -1 ||
URI_obrazku.IndexOf(".tif") > -1 ||
URI_obrazku.IndexOf(".jpeg") > -1 ||
URI_obrazku.IndexOf(".jpg") > -1 ||
URI_obrazku.IndexOf(".svg") > -1 ||
URI_obrazku.IndexOf(".gif") > -1)
{ ... some code }
return someString;
}
Thanks.
Use Path.GetExtension to get just the extension. Then check whether that extension is in your collection of known extensions.
private string IfItIsPicture(string URI_obrazku)
{
var knownExtensions = new [] { ".jpg",".png",".bmp", "..."};
var extension = Path.GetExtension(URI_obrazku);
if (knownExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
{
// ... some code
}
return "someString";
}
Use Linq:
var types = new List<string> { ".jpg", ".png", ... };
if (types.Any(t => URI_obrazku.IndexOf(t) >= 0))
{
return someString;
}
Yes, use an array
var values = new [] { ".jpg",".png",".bmp", ...};
if(values.Any(x => URI_obrazku.EndsWith(x)))
I don't know if this is better, but I bet it's faster since it isn't doing multiple IndexOfs:
private bool IsPicture(string URI_obrazku)
{
String Extension = Path.GetExtension(URI_obrazku);
switch (Extension)
{
case ".jpg": return true;
case ".png": return true;
// other extensions
default: return false;
}
}

What is an effective way to validate a bunch of variables before moving on?

I've been reading about the ideal size of methods and the single responsibility principle then I go look at some of my code. I feel I can break up a lot (>90%) of my stuff to be small manageable methods but then I get to validating a data or a form. It always seems really large and bloated. I tend to validate my data with nested if statements and try to catch errors or issues at each level. But when I start to get 6, 8, 10+ levels of validation it is very cumbersome. But I'm not sure how to break it up to be more effective.
An example of something I think is cumbersome but not sure how to improve upon it is below.
Each of the levels has a unique action associated with it and only once all the conditions return true can the whole thing return true but this is tough to read, especially after coming back to the program after a month or so.
if (InitialUsageSettings.zeroed || sender.Equals(btnZero))
{
if (InitialUsageSettings.StandardFilterRun || sender.Equals(btnStandard))
{
if (InitialUsageSettings.ReferenceFilterRun || sender.Equals(btnReference) || sender.Equals(btnStandard))
{
if (InitialUsageSettings.PrecisionTestRun || sender.Equals(btnPrecision) || sender.Equals(btnReference) || sender.Equals(btnStandard))
{
if (txtOperatorID.Text.Length > 0 && cboProject.Text.Length > 0 && cboFilterType.Text.Length > 0 && cboInstType.Text.Length > 0)
{
if (txtFilterID.Text.Length > 0 && txtLot.Text.Length > 0)
{
return true;
}
else
{
if (txtFilterID.Text.Length == 0)
{
//E
}
if (txtLot.Text.Length == 0)
{
//D
}
}
}
else
{
if (txtOperatorID.Text.Length == 0)
{
//A
}
if (cboProject.Text.Length == 0)
{
//B
}
if (cboFilterType.Text.Length == 0)
{
//C
}
if (cboInstType.Text.Length == 0)
{
//D
}
//return false;
}
}
else
{
outputMessages.AppendLine("Please correct the folloring issues before taking a reading: X");
}
}
else
{
outputMessages.AppendLine("Please correct the folloring issues before taking a reading: Y");
}
}
else
{
outputMessages.AppendLine("Please correct the folloring issues before taking a reading: Z");
}
}
else
{
outputMessages.AppendLine("Please correct the folloring issues before taking a reading: A");
}
If your main purpose is to break the methods up into manageable chunks, you could encapsulate each if block in its own method. e.g.:
if (InitialUsageSettings.zeroed || sender.Equals(btnZero))
{
ValidateStandardFilter();
}
else
{
outputMessages.AppendLine("Please correct the folloring issues before taking a reading: A");
}
But it seems to me that this method has too many responsibilities: You're trying to make it validate and also output a message. Instead, the method should be solely responsible for validating.
public ValidationResult Validate(Sender sender)
{
if (!(InitialUsageSettings.zeroed || sender.Equals(btnZero)))
{
return ValidationResult.Error("A");
}
if (!(InitialUsageSettings.StandardFilterRun || sender.Equals(btnStandard)))
{
return ValidationResult.Error("Z");
}
// Etc...
if (txtOperatorID.Text.Length == 0)
{
errors.Add("A");
}
if (cboProject.Text.Length == 0)
{
errors.Add("B");
}
if (cboFilterType.Text.Length == 0)
{
errors.Add("C");
}
if (cboInstType.Text.Length == 0)
{
errors.Add("D");
}
if(errors.Count > 0)
{
return ValidationResult.Errors(errors);
}
if (txtFilterID.Text.Length == 0)
{
errors.Add("E");
}
if (txtLot.Text.Length == 0)
{
errors.Add("D");
}
return errors.Count > 0
? ValidationResult.Errors(errors)
: ValidationResult.Success();
}
And then the calling code can worry about the output:
var result = Validate(sender);
if (result.IsError)
{
outputMessages.AppendLine("Please correct...: " + result.Issue);
}
To get an idea of what the ValidationResult class might look like, see my answer here.
Update
The code above could be further refactored to reduce repetition even more:
public ValidationResult Validate(Sender sender)
{
if (!(InitialUsageSettings.zeroed || sender.Equals(btnZero)))
{
return ValidationResult.Error("A");
}
if (!(InitialUsageSettings.StandardFilterRun || sender.Equals(btnStandard)))
{
return ValidationResult.Error("Z");
}
// Etc...
var firstErrorBatch = GetEmptyStringErrors(
new[]{
new InputCheckPair(txtOperatorID, "A"),
new InputCheckPair(cboProject, "B"),
new InputCheckPair(cboFilterType, "C"),
new InputCheckPair(cboInstType, "D"),
})
.ToList();
if(firstErrorBatch.Count > 0)
{
return ValidationResult.Errors(firstErrorBatch);
}
var secondErrorBatch = GetEmptyStringErrors(
new[]{
new InputCheckPair(txtFilterID, "E"),
new InputCheckPair(txtLot, "D"),
})
.ToList();
return secondErrorBatch.Count > 0
? ValidationResult.Errors(secondErrorBatch)
: ValidationResult.Success();
}
private class InputCheckPair
{
public InputCheckPair(TextBox input, string errorIfEmpty)
{
Input = input;
ErrorIfEmpty = errorIfEmpty;
}
public TextBox Input {get; private set;}
public string ErrorIfEmpty{get; private set;}
}
public IEnumerable<string> GetEmptyStringErrors(IEnumerable<InputCheckPair> pairs)
{
return from p in pairs where p.Input.Text.Length == 0 select p.ErrorIfEmpty;
}
Something akin to
if(errorCondition1)
errors.add(message1);
if(errorCondition2)
errors.add(message2);
return errors.Count == 0;
So each condition is not nested
You can invert your if statements and use Guard Clauses instead. See this example.
Reverse the flow. Instead of
If(cond) {
if(someothercond) {
//great sucess!
return true;
} else {
// handle
return false;
}
} else {
// handle
return false;
}
do:
if(!cond1) {
// handle
return false;
}
if(!someothercond) {
// handle
return false;
}
// great sucess!
return true;
One way is to have a validation method that is called prior to executing your other code.
For example:
private String ValidateThis() {
StringBuilder result = new StringBuilder();
if (!cond1) {
result.AppendLine("error on cond1");
}
if (!cond2) {
result.AppendLine("error on cond2");
}
return result.ToString();
}
public void ButtonClick(object sender) {
String isValid = ValidateThis();
if (!String.IsNullOrEmpty(isValid)) {
// set your error message
outputMessages.AppendLine(isValid);
return;
}
// ... perform your other operations.
}
I would try to have each validation defined as a predicate, something like this...
delegate bool Validator(object sender, out string message);
Then you could string as many of those together as you need.
There are a number of ways to tackle this. You really want to limit the amount of repeated code, such as the code that adds an output message, which is nearly identical in four or more places.
If you think of these nested if…else blocks as a sequence, where as soon as one fails you take action and stop further processing, you can create a list and leverage LINQ's FirstOrDefault functionality to process the list of conditions sequentially until one fails, or you get null if they all pass.
Creating an object to encapsulate the conditions will help consolidate and reduce duplication.
Here is an example:
public class Validator
{
public Validator(string code, bool settingsCheck, Button button, object sender)
{
Code = code;
IsValid = sender != null && button != null && sender.Equals(button);
}
public bool IsValid { get; private set; }
public string Code { get; private set; }
}
Now, your method looks more like this:
var validationChecks = new List<Validator>
{
new Validator("A", InitialUsageSettings.zeroed, btnZero, sender),
new Validator("Z", InitialUsageSettings.StandardFilterRun, btnStandard, sender),
new Validator("Y", InitialUsageSettings.ReferenceFilterRun, btnReference, sender),
new Validator("X", InitialUsageSettings.PrecisionTestRun, btnPrecision, sender)
}
var failure = validationChecks.FirstOrDefault(check => !check.IsValid);
if (failure != null)
{
outputMessages.AppendLineFormat(
"Please correct the following issues before taking a reading: {0}", failure.Code);
return;
}
else
{
// further checks; I'm not sure what you're doing there with A-E
}

Categories