Naughts and Crosses (Tic Tac Toe), subroutine query - c#

So I'm at the final stage of my Noughts and Crosses project and I'm quite dearly stuck, I have done move validation subroutine as well as a subroutine that is solely based on changing the blank space in the box into an " X " or an " O ",
yet my code seems to tell me that some part of my code does not exist in the current context and I am completely baffled
The code is:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string[,] grid = new string[3, 3] {{" "," "," "},
{" "," "," "},
{" "," "," "}};
string board = System.IO.File.ReadAllText("E:\\BoardGame.txt");
Console.WriteLine(board);
int player = 0;
var XCoordinate = 0;
var YCoordinate = 0;
int x, y;
GetMoveCoordinates(ref XCoordinate, ref YCoordinate);
if (player == 0)
{
grid[XCoordinate, YCoordinate] = " X ";
player++;
}
else
{
grid[XCoordinate, YCoordinate] = " O ";
player--;
}
UpdateGrid(grid, box);
if (player == 1)
{
}
}
public static void GetMoveCoordinates(ref int XCoordinate, ref int YCoordinate)
{
int CommaLocation;
bool GameHasBeenWon = false;
string CoordinatesInput;
string XChar, YChar;
while (GameHasBeenWon == false)
{
try
{
Console.Write("Enter your coordinates: (x,y) ");
CoordinatesInput = Console.ReadLine();
CommaLocation = CoordinatesInput.IndexOf(",".ToString());
XChar = CoordinatesInput.Substring(CommaLocation - 1, CommaLocation);
YChar = CoordinatesInput.Substring(CommaLocation + 1);
XCoordinate = int.Parse(XChar);
YCoordinate = int.Parse(YChar);
}
catch
{
Console.WriteLine("Invalid Input- Please Try Again");
}
}
}
public static bool CheckValidMove(int XCoordinate, int YCoordinate, string[,] Board)
{
if ((XCoordinate >= 1) || (XCoordinate <= 3))
{
if ((YCoordinate >= 1) || (YCoordinate <= 3))
{
if ((Board[XCoordinate, YCoordinate]) == " ")
{
return true;
}
else return false;
}
else return false;
}
else return false;
}
public static void UpdateGrid(string[,] grid, string box)
{
Console.Clear();
for (int x = 0; x < grid.GetLength(0); x++)
{
for (int y = 0; y < grid.GetLength(1); y++)
{
box = box.Replace((x + 1) + "," + (y + 1), grid[y, x]);
}
}
// In the case not required as clearning the console default the cursor back to 0,0, but left in
// as an example
Console.SetCursorPosition(0, 0);
Console.WriteLine(box);
}
}
}
Yet the problem I seem to have is under Main, under the if statement where the code seems to tell me that box in the Update(grid,box), does not exist in the current context, yet it should do in the last subroutine? Am I supposed to do it as a ref statement or am I missing something? Also if you have any tips on how to tidy up the code I'd gladly appreciate it (yes I will add win parameters but I'd like to draw my symbols first).
This is what the grid looks like this:
+---+---+---+
| | | |
+---+---+---+
| | | |
+---+---+---+
| | | |
+---+---+---+

There are several bugs here. First, the following won't compile:
UpdateGrid(grid, box);
As Andrew Whitaker indicated in the comments, there is no "box" variable in your main method (you never declared or initialized it). Define what that variable is and initialize it properly and that'll compile again.
Next, a quick stylistic note on the following:
while (GameHasBeenWon == false)
Don't explicitly compare to true and false - the correct way to do this is
while (!GameHasBeenWon)
The next line to comment on has several bugs:
(XCoordinate >= 1) || (XCoordinate <= 3)
This means that XCoordinate >= 1 OR it's less than or equal to 3, which isn't at all what you meant. Actually, by this logic, any integer is valid because it's either greater than 1, equal to 1, less than 3, or equal to 3. (Think about it - for what integers could a statement like this possibly be false?) Also, 3 is specifically not a valid index, but 0 is. Keep in mind that arrays are zero-indexed. Thus, this should actually be
(XCoordinate >= 0) && (XCoordinate < 3)
In terms of your if statements:
if ((Board[XCoordinate, YCoordinate]) == " ")
{
return true;
}
else return false;
returns true exactly when (Board[XCoordinate, YCoordinate]) == " " is true and false exactly when that statement is false. You could just do
return (Board[XCoordinate, YCoordinate]) == " ";
In fact, you could do that for the whole "if" statement. (I'm not sitting in front of an IDE right now so I apologize if my syntax isn't perfect here).
return ((XCoordinate >= 0) && (XCoordinate < 3) &&
((YCoordinate >= 0) && (YCoordinate < 3)) &&
((Board[XCoordinate, YCoordinate]) == " "));

Related

Get iterative output from for loop in C# windows forms constructor

my homework is to create a windows forms(.net framework) program in C# that outputs all numbers less than N except those that are divisible by 3 or 7 using constructors. Making this in console is easy. but in windows forms I don't know how to make the TextBox read all of the iterations in the constructor.
This is my code in the constructor:
class NumLess
{
public string s;
public NumLess (int N)
{
for (int i = 1; i < N; i++)
{
if (i % 3 == 0)
{
break;
}
if (i % 7 == 0)
{
break;
}
s = i + ",";
}
}
}
And this is the code in the windows forms button:
private void btnCalc_Click(object sender, EventArgs e)
{
NumLess num = new NumLess(int.Parse(txtN.Text));
txtResult.Text = "" + num.s;
}
It only outputs the last iteration, I dont know what to do now.
Also, I've read something about this being easier with listbox and collections (not sure if I'm wording that the right way), but my teacher asked us to do it with Textbox and basic control structures, as you can see we are only starting to learn.
Thanks in advance
The problem is in the constructor:
public NumLess (int N)
{
for (int i = 1; i < N; i++)
{
if (i % 3 == 0)
{
break;
}
if (i % 7 == 0)
{
break;
}
s = i + ","; //will reset s every time
}
}
As you can see, the operator= overwrites what exists in s. There are many ways to fix this. For me to fix it, all I did was replace = with += which will concatenate the current s with the new value. Replace:
s = i + ","; //will reset s every time
With:
s += i + ",";
You can also do these options:
s = string.Concat(s, string.Concat(i, ","));
s = s + i + ",";
Stringbuilders, as explained here: https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder?view=net-5.0, are another option.
Also, as devcrp pointed out in the comments:
also you'd want to use continue; instead of break;, otherwise you'll only collect the numbers until one of them is divisible by 3 or 7
Try this version of NumLess class.
class NumLess
{
public string s;
public NumLess (int N)
{
for (int i = 1; i < N; i++)
{
if (i % 3 == 0)
{
continue;
}
if (i % 7 == 0)
{
continue;
}
s = string.Concat(s, string.Concat(i, ","));
}
}
}

Read characters from a single line including whitespaces rather than from a new line

IN C# i am trying to solve a problem :
Write a program that checks whether the product of the odd elements is equal to the product of the even elements.
The only thing left is:
On the second line you will receive N numbers separated by a whitespace.
I am unable to get this working. I have tried with Split but it keeps breaking. Can someone help?
Example:
Input
5
2 1 1 6 3
Output
yes 6
static void Main(string[] args)
{
long N = long.Parse(Console.ReadLine());
long[] array = new long[N];
long ODD = 1;
long EVEN = 1;
for (int i = 0; i < N; i++)
{
array[i] = int.Parse(Console.ReadLine());
if ((i + 1) % 2 == 0)
{
EVEN *= array[i];
}
else
{
ODD *= array[i];
}
}
if (EVEN == ODD)
{
Console.WriteLine("yes" + " " +
ODD);
}
else
{
Console.WriteLine("no" + " " + ODD + " " + EVEN);
}
}
Read from console input and keep it to an string array, Then convert each array element to long and apply the Odd Even logic like below:
static void Main(string[] args)
{
string input = Console.ReadLine();
string[] inputArray = input.Split(' ');
long element;
long odd = 1;
long even = 1;
foreach (var i in inputArray)
{
element = long.Parse(i);
if (element % 2 == 0)
{
even *= element;
}
else
{
odd *= element;
}
}
Console.WriteLine("\nOdd product = " + odd + ", Even product = " + even);
if (odd == even)
{
Console.WriteLine("ODD == EVEN \n");
Console.WriteLine("Yes" + " " + odd);
}
else
{
Console.WriteLine("ODD != EVEN \n");
Console.WriteLine("No" + " " + odd + " " + even);
}
Console.ReadKey();
}
long[] nums = input.Split(' ').Select(x => long.Parse(x))..ToArray(); //split numbers by space and cast them as int
int oddProduct = 1, evenProduct = 1; // initial values
foreach(long x in nums.Where(a => a%2 == 1))
oddProduct *= x; // multiply odd ones
foreach(long x in nums.Where(a => a%2 == 0))
evenProduct *= x; // multiply even ones

using radio buttons to do some basic maths

i am making a program that will calculate how much someone needs to pay if they have had there vehicle parked. I am trying to use radio buttons to select the type of vehicle. when cars(radiobutton1) is selected the algorithm works but when trucks (radiobutton2)is selected it will not work. here is my code
// cars
if (radioButton1.Checked == true)
{
int hac = Convert.ToInt16(txthrs.Text);
int h1c = 5;
int h2c = 3;
if (txthrs.Text == "1") ;
money.Text = h1c.ToString();
if (hac < 1) ;
money.Text = (h1c + (hac - 1) * h2c).ToString();
// end of cars
// trucks
if (radioButton2.Checked == true)
{
int hat = Convert.ToInt16(txthrs.Text);
int h1t = 6;
decimal h2t = 3.5m;
if (txthrs.Text == "1") ;
money.Text = h1t.ToString();
if (hat < 1) ;
money.Text = (h1t + (hat - 1) * h2t).ToString();
}
}
}
}
}
when trucks (radiobutton2)is selected it will not work.
Firstly, you have some logical mistakes because if (hac < 1) ; and (hat < 1) ; doesn't do anything at all, it's just an expression on its own. With that in mind, i have updated your code to remove those logical errors.
Secondly, don't use == to compare strings, rather use Equals() method.
Thirdly, the radioButton2 condition is nested within the radioButton1 condition hence it causes the unexpected behaviour. You can solve it by separating them like this:
if (radioButton1.Checked == true)
{
int hac = Convert.ToInt16(txthrs.Text);
int h1c = 5;
int h2c = 3;
if (txthrs.Text.ToString().Equals("1"))
money.Text = h1c.ToString();
if (hac < 1)
money.Text = (h1c + (hac - 1) * h2c).ToString();
}
if (radioButton2.Checked == true)
{
int hat = Convert.ToInt16(txthrs.Text);
int h1t = 6;
decimal h2t = 3.5m;
if (txthrs.Text.ToString().Equals("1"))
money.Text = h1t.ToString();
if (hat < 1)
money.Text = (h1t + (hat - 1) * h2t).ToString();
}
You have nested your if statements, the second if statement will only execute if radio button one is checked. Move the second if block out of the first.

Testing if a list of integer is odd or even

Trying to determine if my list of integer is made of odd or even numbers, my desired output is a list of true an/or false. Can I perform the following operation on the list lst or do I need to create a loop? A is the output.
List <int> lst = new List <int>();
A = IsOdd(lst);
You could try using Linq to project the list:
var output = lst.Select(x => x % 2 == 0).ToList();
This will return a new list of bools such that {1, 2, 3, 4, 5} will map to {false, true, false, true, false}.
Just use the modulus
loop through the list and run the following on each item
if(num % 2 == 0)
{
//is even
}
else
{
//is odd
}
Alternatively if you want to know if all are even you can do something like this:
bool allAreEven = lst.All(x => x % 2 == 0);
There's at least 7 different ways to test if a number is odd or even. But, if you read through these benchmarks, you'll find that as TGH mentioned above, the modulus operation is the fastest:
if (x % 2 == 0)
//even number
else
//odd number
Here are a few other methods (from the website) :
//bitwise operation
if ((x & 1) == 0)
//even number
else
//odd number
//bit shifting
if (((x >> 1) << 1) == x)
//even number
else
//odd number
//using native library
System.Math.DivRem((long)x, (long)2, out outvalue);
if ( outvalue == 0)
//even number
else
//odd number
#region even and odd numbers
for (int x = 0; x <= 50; x = x + 2)
{
int y = 1;
y = y + x;
if (y < 50)
{
Console.WriteLine("Odd number is #{" + x + "} : even number is #{" + y + "} order by Asc");
Console.ReadKey();
}
else
{
Console.WriteLine("Odd number is #{" + x + "} : even number is #{0} order by Asc");
Console.ReadKey();
}
}
//order by desc
for (int z = 50; z >= 0; z = z - 2)
{
int w = z;
w = w - 1;
if (w > 0)
{
Console.WriteLine("odd number is {" + z + "} : even number is {" + w + "} order by desc");
Console.ReadKey();
}
else
{
Console.WriteLine("odd number is {" + z + "} : even number is {0} order by desc");
Console.ReadKey();
}
}
--simple codes--
#region odd / even numbers order by desc
//declaration of integer
int TotalCount = 50;
int loop;
Console.WriteLine("\n---------Odd Numbers -------\n");
for (loop = TotalCount; loop >= 0; loop--)
{
if (loop % 2 == 0)
{
Console.WriteLine("Even numbers : #{0}", loop);
}
}
Console.WriteLine("\n---------Even Numbers -------\n");
for (loop = TotalCount; loop >= 0; loop--)
{
if (loop % 2 != 0)
{
Console.WriteLine("odd numbers : #{0}", loop);
}
}
Console.ReadLine();
#endregion

How can I solve the Collatz conjecture algorithm in C#?

I was able to solve the Collatz conjecture algorithm (no, i didn't try to prove it) in about 5 minutes using Java.
Now that I'm learning C# to make web apps, I'm running into trouble doing the same thing.
I simply want the user to enter a number, click a button, and print the output to a text box.
Here is the button Click event handler method I'm using:
protected void Button3_Click(object sender, EventArgs e)
{
string x = TextBox1.Text; //user entered a number
string y =collatz(x); //this function is below and returns a string
chatbox.Text = y; //output
}
And here is the Collatz method:
public static string collatz(string y)
{
if (y == null)
return null;
double x = double.Parse(y); //x is my "n"
y = x.ToString(); //output string
double large = x; //keep track of biggest number
// the algorithm
// the redundancies (like x==1.. x!= 1) are part of troubleshooting :/
while (x > 1)
{
if (x % 2 == 0)
{
x = x / 2;
if (x > large)
large = x;
if (x != 1)
y = y+" "+ x.ToString();
if (x == 1)
{
y = y + " " + x.ToString();
y = y + " largest number was " + large;
}
}
if (x % 2 != 0)
{
if (x == 1)
{
y = y+" "+ x.ToString();
y = y + " largest number was " + large;
}
x = (3 * x) + 1;
if (x > large)
large = x;
y = y+" "+ x.ToString();
}
}
return y;
}
EDIT
when I use the VS.net debugger and enter a number like 2, I get NO output and NO error. I'm just left waiting forever. If it were an infinite loop, I would get an error eventually, right?
and no, this is not a homework problem (it was 2 years ago when I did it in JAVA though :).) I'm learning C# independently.
You had an infinite loop. Try this:
public static string collatz(string y)
{
if (y == null)
{
return null;
}
int x = int.Parse(y); //x is my "n"
var results = new StringBuilder();
results.Append(x.ToString());
int largest = x; //keep track of biggest number
// the algorithm
// the redundancies (like x==1.. x!= 1) are part of troubleshooting :/
while (x > 1)
{
if (x % 2 == 0)
{
x = x / 2;
if (x > largest)
{
largest = x;
}
if (x != 1)
{
results.Append(" " + x.ToString());
}
if (x == 1)
{
results.Append(" " + x.ToString());
results.Append(" largest number was " + largest.ToString());
return results.ToString();
}
}
if (x % 2 != 0)
{
if (x == 1)
{
results.Append(" " + x.ToString());
results.Append(" largest number was " + largest.ToString());
return results.ToString();
}
x = (3 * x) + 1;
if (x > largest)
{
largest = x;
}
results.Append(" " + x.ToString());
}
}
return results.ToString();
}
Two notes:
When you're doing string concatenation in a loop, it's a good habit to use a StringBuilder rather than s = s + t. Lots, lots less memory allocations.
A lot of times you can't rely on == when it comes to double values. It seems to work in this case, but it might not when you get to higher numbers where there's less precision. Since all the numbers are going to be int's anyway, might as well use those.
if (x == 1)
{
y = y+" "+ x.ToString();
y = y + " largest number was " + large;
}
This part here (odd x) is redundant. For if x is 1, it will never enter the while loop. Your code seems logically. Maybe try using integer instead.
x = x / 2;
if (x > large)
large = x;
Redundant code again for even x part. How do you expect x to be bigger than large after division by 2? Just check it in the 3n+1 part will do.
if (x == 1)
{
y = y + " " + x.ToString();
y = y + " largest number was " + large;
}
You can just leave this part out and let the while loop handle this check.
public static string collatz(string y)
{
if (y == null)
return null;
double x = double.Parse(y);
y = x.ToString();
double large = x;
while (x > 1) {
if (x % 2 == 0) {
x = x / 2; // x reassigned
if (x > large)
large = x;
if (x != 1)
y = y + " " + x.ToString();
if (x == 1) {
y = y + " " + x.ToString();
y = y + " largest number was " + large;
}
}
// Infinite loop goes because of that
if (x % 2 != 0) { // double check on reassigned variable, use “else” instead
if (x == 1) {
y = y + " " + x.ToString();
y = y + " largest number was " + large;
}
x = (3 * x) + 1;
if (x > large)
large = x;
y = y + " " + x.ToString();
}
}
return y;
}
I tried it with fixed code (using else) and it works fine.
Also, you don't need double type since Collatz works with natural numbers. The following is a quick refactoring to add more .NET-ty to your code:
public static string collatz(string input)
{
int current = 0;
if (string.IsNullOrEmpty(input) || !int.TryParse(input, out current) || current < 1) {
return "Empty, not a number or less then 1";
}
int max = current;
while (current > 1) {
if (current % 2 == 0) {
current = current / 2; // current reassigned
if (current > max)
max = current;
if (current != 1)
input = input + " " + current.ToString();
if (current == 1) {
input = input + " " + current.ToString();
input = input + " largest number was " + max;
}
} else {
if (current == 1) {
input = input + " " + current.ToString();
input = input + " largest number was " + max;
}
current = (3 * current) + 1;
if (current > max)
max = current;
input = input + " " + current.ToString();
}
}
return input;
}
View Equation:
if the number is even: n/2
if the number is odd: 3n+1
Step One:
Add a method called Collazt which returns a collection of objects of type int of class List<?>
public static List<int> Collazt(int n) {
List<int> data = new List<int>();
data.Add(n);
int resul = 0;
while (true) {
if (n == 1) {
break;
}
if ((n % 2) == 0)
{
resul = n / 2;
n = resul;
}
else {
resul = (n * 3) + 1;
n = resul;
}
data.Add(n);
}
return data;
}
Step Two:
We call the method in our main class.
static void Main(string[] args)
{
Console.Write("N: ");
int r = int.Parse(Console.ReadLine());
List<int> result = Collazt(r);
Console.WriteLine("Lista:");
Console.WriteLine("[");
for (int i= 0; i<result.Count; i++) {
Console.Write(result[i]+"\n");
}
Console.WriteLine("]");
}
string restart;
do
{
Console.WriteLine("Type a Whole Number");
double n = Convert.ToDouble(Console.ReadLine());
do
{double a = n;
if (n % 2 == 0)
{
Console.WriteLine("Even");
n = a / 2;
Console.WriteLine(n);
}
else
{
Console.WriteLine("Odd");
n = (3*a) + 1;
Console.WriteLine(n);
}
}
while (n != 1);
Console.WriteLine("Yo Wanna Restart? Type y and press enter");
restart = Console.ReadLine();
Console.Clear();
}
while (restart == "y");
Console.ReadKey(true);
(not a professional programmer, made it for fun, i know there are better ways)

Categories

Resources