Replacing C# Switch Statement into a More Readable/Intuitive Format - c#

I was desiring to clean up my code a bit for a battleship program that I was creating. There is a 2D array gameboard that holds char values pertaining to each of the ships found on the board, i.e. a battleship on the gameboard would be represented as 'BBBB'.
The program already runs, but the portion which checks whether the user's selected coordinate contains a char value that pertains to a ship seems messy, and I do not know of a way to make it look cleaner. Before this, it was implemented as a bunch of if else-if statements, and that didn't really look too clean either. Any help or pointers to guide me in the right direction would be great. Thanks.
switch (board.Grid[userSelectedRow, userSelectedCol])
{
case 'C':
carrier_C_HitCounter++;
hitCounter++;
if (carrier_C_HitCounter != shipList[0].Length)
{
Console.WriteLine("You struck a ship!\n");
}
else
Console.WriteLine("You sunk their carrier!\n");
break;
case 'B':
battleship_HitCounter++;
hitCounter++;
if (battleship_HitCounter != shipList[1].Length)
{
Console.WriteLine("You struck a ship!\n");
}
else
Console.WriteLine("You sunk their battleship!\n");
break;
case 'S':
submarine_S_HitCounter++;
hitCounter++;
if (submarine_S_HitCounter != shipList[2].Length)
{
Console.WriteLine("You struck a ship!");
}
else
Console.WriteLine("You sunk their submarine!");
break;
case 's':
submarine_s_HitCounter++;
hitCounter++;
if (submarine_s_HitCounter != shipList[3].Length)
{
Console.WriteLine("You struck a ship!");
}
else
Console.WriteLine("You sunk their submarine!");
break;
case 'D':
destroyer_D_HitCounter++;
hitCounter++;
if (destroyer_D_HitCounter != shipList[4].Length)
{
Console.WriteLine("You struck a ship!");
}
else
Console.WriteLine("You sunk their destroyer!");
break;
case 'd':
destroyer_d_HitCounter++;
hitCounter++;
if (destroyer_d_HitCounter != shipList[5].Length)
{
Console.WriteLine("You struck a ship!");
}
else
Console.WriteLine("You sunk their destroyer!");
break;
default:
Console.WriteLine("No ships were hit.");
break;
}
// Change the hit location to 'X'
board.SetChar(userSelectedRow, userSelectedCol, 'X');

The code that is being repeated the most is your check for what ship it is and generating the associated message:
if (carrier_C_HitCounter != shipList[0].Length)
{
Console.WriteLine("You struck a ship!\n");
}
else
Console.WriteLine("You sunk their carrier!\n");
You could define an enum and a function to generate the messages like so to clean up the switch statement a bit:
enum Ship
{
"carrier",
"battleship",
"submarine",
"destroyer"
}
public void getMessage(int number, int counter){
if (counter != shipList[number].Length)
{
Console.WriteLine("You struck a ship!");
}
else
Console.WriteLine("You sunk their " + (Ship)number + " !");
}
Then call it from the switch like:
switch (board.Grid[userSelectedRow, userSelectedCol])
{
case 'C':
carrier_C_HitCounter++;
hitCounter++;
getMessage(0,carrier_C_HitCounter);
break;
case 'B':
battleship_HitCounter++;
hitCounter++;
getMessage(1,battleship_HitCounter);
break;
case 'S':
submarine_S_HitCounter++;
hitCounter++;
getMessage(2,submarine_S_HitCounter);
break;
case 's':
submarine_s_HitCounter++;
hitCounter++;
getMessage(2,submarine_s_HitCounter);
break;
case 'D':
destroyer_D_HitCounter++;
hitCounter++;
getMessage(3,destroyer_D_HitCounter);
break;
case 'd':
destroyer_d_HitCounter++;
hitCounter++;
getMessage(3,destroyer_d_HitCounter);
break;
default:
Console.WriteLine("No ships were hit.");
break;
}
// Change the hit location to 'X'
board.SetChar(userSelectedRow, userSelectedCol, 'X');
I'm assuming shipList is global but otherwise modify the function header to pass that in too. The most important thing in making you code look cleaner is to look for large repeating chunks and try to find a way to "reroute" it. Hope this helps Derek :) Welcome to SO

Related

How to exit the program if exit option is selected? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
Good evening.
Apologies for the noob question, I am new to C# so I'm still getting to grips with a few things. I am trying to write a simple program as shown below, but I'm struggling to get the coding correct for the exit function. How can I write this code to exit to program if the exit option is input, as 'if choice ==4' does not seem to work?
// Demonstrate branching and loops.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Fundamentals
{
class Program
{
static void Main(string[] args)
{
do
{
// Example: Switch.
Console.WriteLine("Main Menu");
Console.WriteLine("1 - Play. ");
Console.WriteLine("2 - Options. ");
Console.WriteLine("3 - Help. ");
Console.WriteLine("4 - Exit. ");
Console.WriteLine(" ");
int choice = Convert.ToInt32(Console.ReadLine());
switch (choice)
{
case 1:
Console.WriteLine("Playing the game.");
Console.WriteLine("");
// Example: do... while loop.
double ans;
do
{
Console.Write("What is: 10 x 10 = ");
ans = Convert.ToInt32(Console.ReadLine());
} while (ans != 100);
Console.WriteLine("\nCorrect!\n");
break;
case 2:
Console.WriteLine("Game settings.\n");
break;
case 3:
Console.WriteLine("Game Help.\n");
break;
case 4:
Console.WriteLine("Exiting...\n");
break;
default:
break;
}
if (choice == "4")
{
Environment.Exit(0);
}
} while (true);
}
}
}
choice is an int and you're comparing it to a string - so
if (choice == 4)
{
Environment.Exit(0);
}
for the code you posted- but you could just put the exit code in the case:
case 4:
{
Console.WriteLine("Exiting...\n");
Environment.Exit(0);
break;
}
You would've saved yourself from having this problem by putting your Environment.Exit() call inside the switch statement that is correctly comparing two int's, rather than re-evaluating a condition after evaluating the conditions...
Those that said int is never equal to string are on the money, but if I may suggest an even more correct solution you shouldn't have that if statement at all.
switch (choice)
{
case 1:
Console.WriteLine("Playing the game.");
Console.WriteLine("");
// Example: do... while loop.
double ans;
do
{
Console.Write("What is: 10 x 10 = ");
ans = Convert.ToInt32(Console.ReadLine());
} while (ans != 100);
Console.WriteLine("\nCorrect!\n");
break;
case 2:
Console.WriteLine("Game settings.\n");
break;
case 3:
Console.WriteLine("Game Help.\n");
break;
case 4:
Console.WriteLine("Exiting...\n");
Environment.Exit(0); //// Just exit from here...
default:
break;
}

Switch Statement C#

Can someone please tell me why my switch statement is not working? In my program I have a text box with the choices of 'Billing', 'Tech Support', 'Retention', 'Customer Service'. My switch statement is saying if that text box is = xxx then show a form I build and hide everything else.
Currently only the billing and other option works?!
<
private void cbDept_SelectedIndexChanged(object sender, EventArgs e)
{
string reason = cbDept.Text;
switch (reason)
{
case "Billing":
gbBilling.Show();
gbTechSupport.Hide();
gbCS.Hide();
gbRetention.Hide();
lbOtherReason.Hide();
txtOther.Hide();
break;
case "Tech Support":
gbTechSupport.Show();
gbBilling.Hide();
gbCS.Hide();
gbRetention.Hide();
lbOtherReason.Hide();
txtOther.Hide();
break;
case "Retention":
gbRetention.Show();
gbBilling.Hide();
gbTechSupport.Hide();
gbCS.Hide();
lbOtherReason.Hide();
txtOther.Hide();
break;
case "Customer Service":
gbCS.Show();
gbBilling.Hide();
gbTechSupport.Hide();
gbRetention.Hide();
lbOtherReason.Hide();
txtOther.Hide();
break;
case "Other":
txtOther.Show();
lbOtherReason.Show();
gbCS.Hide();
gbBilling.Hide();
gbTechSupport.Hide();
gbRetention.Hide();
break;
default:
gbCS.Hide();
gbBilling.Hide();
gbTechSupport.Hide();
gbRetention.Hide();
break;
}
}
>
It seems to me that there is some misspelling in the other options. Check the values of reason before reaching the switch.

C# 2D Game multiple keys doesnt work

I know this question is asked many times but i havent found the right answer for my problem.
My problem is i have a WinForm and i like to press multiple keys to make something xD but if i try to press numpad7, 8 and 4 or any other combination
then it wont work it shows just nothing but i have pressed all this keys
i have tried this
private void GameScreen_KeyDown(object sender, KeyEventArgs e) {
try {
switch (e.KeyCode) {
case Keys.NumPad0:
Console.WriteLine(e.KeyData);
changeButtonsColor();
break;
case Keys.NumPad1:
gb_7.BackColor = Color.MediumSpringGreen;
Console.WriteLine(e.KeyData);
break;
case Keys.NumPad2:
gb_8.BackColor = Color.MediumSpringGreen;
Console.WriteLine(e.KeyData);
break;
case Keys.NumPad3:
gb_9.BackColor = Color.MediumSpringGreen;
Console.WriteLine(e.KeyData);
break;
case Keys.NumPad4:
gb_4.BackColor = Color.MediumSpringGreen;
Console.WriteLine(e.KeyData);
break;
case Keys.NumPad5:
gb_5.BackColor = Color.MediumSpringGreen;
Console.WriteLine(e.KeyData);
break;
case Keys.NumPad6:
gb_6.BackColor = Color.MediumSpringGreen;
Console.WriteLine(e.KeyData);
break;
case Keys.NumPad7:
gb_1.BackColor = Color.MediumSpringGreen;
Console.WriteLine(e.KeyData);
break;
case Keys.NumPad8:
gb_2.BackColor = Color.MediumSpringGreen;
Console.WriteLine(e.KeyData);
break;
case Keys.NumPad9:
gb_3.BackColor = Color.MediumSpringGreen;
Console.WriteLine(e.KeyData);
break;
}
} catch (Exception) {
Console.WriteLine("fail");
}
}
please help me...
This cannot be fixed. Because of how keyboards work, you can press 2 keys at the same time, but as soon as you start pressing 3 at a time, only certain combinations will work. There is no way you can modify the coding to fix this, unless you change what keys you are pressing.

C# How do I make a switch ignore invalid input?

I am trying to make a simple console game that starts with a title screen. The user inputs 'N' for a new game, 'L' to load a game, or 'E' to exit. I have this set up as a switch, but I need to know how to make the program ignore any input other than the aforementioned keys. I've Googled this question but didn't find an answer. Please help if you can.
I don't see much point in posting the code as 10 lines of a simple switch probably wouldn't be terribly helpful to solving the problem. Also, if there would be an easier / more efficient way than a switch, I would love to know.
Thanks.
You can use a default: statement to handle the other (unknown) cases:
switch(inputString.ToLower())
{
case "n":
// Handle new
break;
//.. handle known cases
default:
Console.WriteLine("Unknown option chosen. Please enter valid option:");
// Re-read values, etc?
break;
}
Anything not specified in one of your other cases will fall into the default case, which you can then use to prompt for valid input.
If you want to actually ignore all keys other than valid ones you could do something like this:
public static char ReadKey(IEnumerable<char> validKeys)
{
var validKeySet = new HashSet<char>(validKeys);
while (true)
{
var key = Console.ReadKey(true);
if (validKeySet.Contains(key.KeyChar))
{
//you could print it out if you wanted.
//Console.Write(key.KeyChar);
return key.KeyChar;
}
else
{
//you could print an error message here if you wanted.
}
}
}
When you use ReadKey(true) the true indicated that it will intercept that key and not display it on the console. This gives you the option of determining if it's valid or invalid.
If a switch statement does not have a default block, and if the expression being switched on does not match any of the case blocks, the switch statement does nothing.
When you have only 3 cases, a switch isn't much more efficient than just a simple if-else construct.
if (input == "N")
{
// New game
}
else if (input == "L")
{
// Load game
}
else if (input == "E")
{
// Exit game
}
// if none of the cases match, the input is effectively ignored.
If you insist on using a switch, then your construct is very similar:
switch (input)
{
case "N":
//New Game
break;
case "L":
//Load Game
break;
case "E":
//Exit Game
break;
default:
//Do nothing (ignore unmatched inputs)
break;
}
Thanks for the replies, guys. I managed to solve the problem by doing the following:
static void titleInput()
{
ConsoleKeyInfo titleOption = Console.ReadKey(true);
switch (titleOption.Key)
{
case ConsoleKey.N:
Console.Clear();
break;
case ConsoleKey.L:
break;
case ConsoleKey.E:
Environment.Exit(0);
break;
default:
titleInput();
break;
}
}
I'm not sure how 'proper' this is, but it does what I need it to do. Any keys other than 'N', 'L', and 'E' no longer do anything.

switch and if in C#

Why does the following work (compile):
public void SaveCurrentTab(string currentTabIndex)
{
if (currentTabIndex == MainInfoPnl.ClientID)
PartialSave1();
else if (currentTabIndex == ContactInfoPnl.ClientID)
PartialSave2();
else if (currentTabIndex == BankInfoPnl.ClientID)
PartialSave3();
else if (currentTabIndex == ServicesPnl.ClientID)
PartialSave4();
else if (currentTabIndex == AttachmentsPnl.ClientID)
PartialSave5();
}
But, the following does not?
public void SaveCurrentTab(string currentTabIndex)
{
switch (currentTabIndex)
{
case MainInfoPnl.ClientID:
PartialSave1();
break;
case ContactInfoPnl.ClientID:
PartialSave2();
break;
case BankInfoPnl.ClientID:
PartialSave3();
break;
case ServicesPnl.ClientID:
PartialSave4();
break;
case AttachmentsPnl.ClientID:
PartialSave5();
break;
}
}
Presumably because MainInfoPnl.ClientID isn't a compile-time constant. It may be public static readonly for example, which isn't the same as const. If that doesn't help, show us more about the code and the error message you're getting.
The case statements must be constant strings for a switch - an if condition has no such restriction.
A switch in C# only works with constant values. For values determined at runtime, use a if-else construction.
Try this:
public void SaveCurrentTab(string currentTabIndex)
{
switch (Convert.ToInt32(currentTabIndex))
{
case (int)MainInfoPnl.ClientID:
PartialSave1();
break;
case (int)ContactInfoPnl.ClientID:
PartialSave2();
break;
case (int)BankInfoPnl.ClientID:
PartialSave3();
break;
case (int)ServicesPnl.ClientID:
PartialSave4();
break;
case (int)AttachmentsPnl.ClientID:
PartialSave5();
break;
}
}

Categories

Resources