public static void duel(String user, String user1, String user2)
{
int[] value = null;
String winner;
for (int i = 0; i < 2; i++)
{
Random rand = new Random((int)DateTime.Now.Ticks);
int numIterations = 0;
numIterations = rand.Next(2, 12);
value[i] = numIterations;//This is line 286
}
if (value[0] > value[1])
{
winner = user1;
}
else
{
winner = user2;
}
Console.WriteLine(user + " Started a duel against " + user1 + " and " + user2 + "!");
Console.WriteLine(user1 + " rolled " + value[0] + " and " + user2 + " rolled " + value[1] + "!");
Console.WriteLine(winner + " is the winner!");
}
What exactly is wrong here? When I set int[] value = null it compiles but if I remove the null it says Use of unassigned local variable 'value' Line 286
Well yes, you have to assign a value to the value variable before you use it - but when you've set it to null, you will get a NullReferenceException when you try to use it. It looks like you want a two element array, so use
int[] value = new int[2];
However, with the code you've written you'll almost certainly end up with the two values being the same, as you're creating two instances of Random at almost exactly the same time. See my article on Random for more information.
I would pass a Random instance into the method, and rewrite it like this - without the somewhat-pointless loop:
public static void Duel(Random rng, String user, String user1, String user2)
{
// Using Next(2, 12) doesn't really mimic 2 dice of 1-6; it actually mimics
// a single 10-sided die with values 2 to 11 inclusive.
int score1 = rng.Next(1, 7) + rng.Next(1, 7);
int score2 = rng.Next(1, 7) + rng.Next(1, 7);
// Note: this is biased in favour of user2 in case of equality
string winner = score1 > score2 ? user1 : user2;
Console.WriteLine("{0} started a duel between {0} and {1}!",
user, user1, user2);
Console.WriteLine("{0} rolled {1} and {2} rolled {3}!", user1, score1,
user2, score2);
Console.WriteLine("{0} is the winner!", winner);
}
Things to note here:
Our method depends on something which it can't necessarily create correctly itself (the Random) so that is injected.
Simulate rolling two dice (which is what I assume the aim is) by rolling two single dice, not picking a single number in the range [2, 12] uniformly.
The second parameter to Random.Next is an exclusive upper bound (I got that wrong until I was checking it over)
Use of the conditional operator when you want to pick one expression or another based on a condition, and do the same thing with the result either way
Use of composite format strings to make it easier to format strings than simple concatenation
Following .NET naming conventions (Duel, not duel)
Change the line to:
int[] value = new int[2];
You need to create an empty array so that you can use it later.
If you don't set it to anything you get the Use of unassigned local variable, because you've declared the variable, but haven't given it a value.
If you set it to null then that's giving it a value, but you're also not putting anything in that variable. Your code further down expects to be able to use elements 0 and 1, however although you declared that value is an array you've not created an array to put into the variable, so you get the error when trying to access the elements of a non-existent array.
The code above fixes this by setting the variable to an array with 2 element, which would contain the default for the type in the array (int), which in this case would be 0 until you set them equal to something.
Bad analogy time:
Imagine i'm planning on putting a bookshelf in my bedroom. I make space for it (declare the variable), but i don't put a bookshelf in that space (set the variable it to null, or don't set it at all).
If i go to get something on the 2nd shelf i'm obviously going to have a problem as although i've made space (a variable) in my room (my program) i've not put a bookshelf there (declared an array to go in the variable).
For more info, see the Arrays Tutorial on MSDN.
You are referencing value[i], but you haven't actually intialized value[] yet.
You need to do something like
value = new int[2];
You haven't assigned your int[] an instance. If you know there will always be 2 values, you can use:
int[] value = new int[2];
If you don't know that you'll only ever have 2 values, consider using a List:
List<int> value = new List<int>();
In c# you need to initialize your variables to some value or it will not compile. To fix your runtime error, you need to initialize value into an array (instead of null). Since you are looping through value twice I assume you need to do something like this:
int[] value = new int[2];
You need to create your array somewhere :
int[] value = new int[2];
If you just declare the array in the beginning you should be safe.
int[] value = new int[2];
Related
So I'm a complete newb to unity and c# and I'm trying to make my first mobile incremental game. I know how to format a variable from (e.g.) 1000 >>> 1k however I have several variables that can go up to decillion+ so I imagine having to check every variable's value seperately up to decillion+ will be quite inefficient. Being a newb I'm not sure how to go about it, maybe a for loop or something?
EDIT: I'm checking if x is greater than a certain value. For example if it's greater than 1,000, display 1k. If it's greater than 1,000,000, display 1m...etc etc
This is my current code for checking if x is greater than 1000 however I don't think copy pasting this against other values would be very efficient;
if (totalCash > 1000)
{
totalCashk = totalCash / 1000;
totalCashTxt.text = "$" + totalCashk.ToString("F1") + "k";
}
So, I agree that copying code is not efficient. That's why people invented functions!
How about simply wrapping your formatting into function, eg. named prettyCurrency?
So you can simply write:
totalCashTxt.text = prettyCurrency(totalCashk);
Also, instead of writing ton of ifs you can handle this case with logarithm with base of 10 to determine number of digits. Example in pure C# below:
using System.IO;
using System;
class Program
{
// Very simple example, gonna throw exception for numbers bigger than 10^12
static readonly string[] suffixes = {"", "k", "M", "G"};
static string prettyCurrency(long cash, string prefix="$")
{
int k;
if(cash == 0)
k = 0; // log10 of 0 is not valid
else
k = (int)(Math.Log10(cash) / 3); // get number of digits and divide by 3
var dividor = Math.Pow(10,k*3); // actual number we print
var text = prefix + (cash/dividor).ToString("F1") + suffixes[k];
return text;
}
static void Main()
{
Console.WriteLine(prettyCurrency(0));
Console.WriteLine(prettyCurrency(333));
Console.WriteLine(prettyCurrency(3145));
Console.WriteLine(prettyCurrency(314512455));
Console.WriteLine(prettyCurrency(31451242545));
}
}
OUTPUT:
$0.0
$333.0
$3.1k
$314.5M
$31.5G
Also, you might think about introducing a new type, which implements this function as its ToString() overload.
EDIT:
I forgot about 0 in input, now it is fixed. And indeed, as #Draco18s said in his comment nor int nor long will handle really big numbers, so you can either use external library like BigInteger or switch to double which will lose his precision when numbers becomes bigger and bigger. (e.g. 1000000000000000.0 + 1 might be equal to 1000000000000000.0). If you choose the latter you should change my function to handle numbers in range (0.0,1.0), for which log10 is negative.
Newb/hobbiest here trying to increase my understanding of arrays and to that end i'm trying to build a little meal calculator which will store user data in an array which would hold three strings and one double (The Users First Name, The Users Last Name, the Name of the Resturant, and a DOUBLE which is the cost of the meal). I know there are far easier ways to do this then the way I'm trying to do this, but my purpose is to increase my understand of how arrays work now that i'm starting to understand loops and methods (I get lost/am scared of arrays so i'm forcing myself to work with arrays all weekend long starting tonight - long weekend and i hope it will a worthwhile weekend of learning :D )
I am currently working on a method to populate the array which would work as follows:
Call GetUserData(question asked);
GetUserData asks the user for a specific type of data (string unless last position [3] then it's a double which I'll do math on later)
GetUserData Loop calls arrQuestions[] to ask user question
GetUserData reads user answer into corresponding position in arrUserData[]
arrUserData[] is populated (at this point with four strings, i'll have to convert the four string to a double when i do math which should be feasible i hope)
So in a nutshell, i'm trying to build a method that asks a series of questions from one array and stores the answers in another array that i can then use to do all sorts of wacky things with as i try to get a better understanding of arrays and how to use them and what they are good for and what they aren't good for.
And I promise all of you I've already tried to Google an answer to this, I've read up on arrays at several places including http://msdn.microsoft.com/en-us/library/ttw7t8t6.aspx and stackOverflow, but the answers I've thus found aren't written in a way someone of my skill level understands/my understanding isn't such that I can divine the answer from what i have been able to read thus far.
The following code all sits within the 'program' class
public void Play()
{
GetString("+ + + Meal Calculator Exercise + + +");
String command = "";
String[] arrQuestions = new String[3];//questions asked
arrQuestions [0] = "First Name: ";//string back
arrQuestions [1] = "Last Name: ";//string back
arrQuestions [2] = "Restaurant Name: ";//string back
arrQuestions [3] = "Cost of Meal: ";//I want a double back for this question
String[] arrUserData = new String[3];/user answers stored
arrUserData[0] = " ";//string
arrUserData[1] = " ";//string
arrUserData[2] = " ";//string
arrUserData[3] = " ";//figure out how to convert to double
do {
GetString("+ + + Meal Calculator Exercise + + +");
GetUserData(arrQuestions[i]);//run loop, ask questions populate arrUserData array
GetString("Again? ");
command = Console.ReadLine().ToLower().Trim();
Console.Clear();
}
while (command == "y" || command == "yes");
GetString("+ + + Thank you + + + Have a wonderful time + + + Goodbye! + + +");
}
public String GetString(String strTxt) {
Console.WriteLine(strTxt);return Console.ReadLine();}
public Array GetUserData(String strTxt)
{
for (int i = 0; i < arrUserData.Length; i++)
Console.WriteLine(arrQuestion[i]);
return Console.ReadLine(arrUserData[i]);
}
static void Main(string[] args){
Program myProgram = new Program();
myProgram.Play();}
In looking at your code I'll try to recommend something that I think uses some of the existing knowledge you've shown.
I won't delve right in to code but I'll try to explain it:
I could count how many questions are in the array, (array.length) and store that. Then I would do a while loop that checks if the number of questions answered is equal to the array length. In this loop you could use console readline to put the questions one by one in to the array and increment your counter variable, then use the variable that you are incrementing to insert the answer in to the user data array.
Does that make sense? Let me know if you want any clarification or if this isn't what you were looking for.
So a little more research, head scratching and help from the kind folks here lead me to this:
class Program
{
String[] arrUserData = new String[4];// Must specify 4 in brackets for array length, not the same as an index
// it will fill up as items are added to it starting from position 0 automatically
// should also be at class level for multiple method access
public void Play()
{
String command; // doesn't need to have an empty string value, only be declared
String[] arrQuestions = new String[4];//questions asked
arrQuestions[0] = "First Name: ";
arrQuestions[1] = "Last Name: ";
arrQuestions[2] = "Restaurant Name: ";
arrQuestions[3] = "Cost of Meal: ";
do {
GetString("+ + + Meal Calculator Exercise + + +"); // I removed the one in the top of the method, or else it does it twice
// pass in array of questions to satisfy necessary array argument in GetUserData();
GetUserData(arrQuestions);//run loop, ask questions populate arrUserData array
command = GetString("Again? "); // your GetString method returns whatever the console reads,
// so it can be assigned to your command variable at the same time, or else the user has to put in y or yes twice
Console.Clear();
}
while (command == "y" || command == "yes");
GetString("+ + + Thank you + + + Have a wonderful time + + + Goodbye! + + +");
}
public String GetString(String strTxt)
{
Console.WriteLine(strTxt); return Console.ReadLine().ToLower().Trim();
}
// changed it to a void to it just simply assigns the values to the class level array
public void GetUserData(string[] thisArray)
{
for (int i = 0; i < thisArray.Length; i++)//use the passed in array to determine loop length
{// missing curly braces
Console.WriteLine(thisArray[i]); // write question with corresponding index to console
arrUserData[i] = Console.ReadLine(); // use Console.ReadLine to get input and assign it to corresponding index in userData
if (i == 3) // check for the last index to convert to double
{// here's the basic way, can cause a lot of errors if user input is not a double
Convert.ToDouble(arrUserData[3]);
// here's the way trapping all possible errors, and giving a nice message for each
// remove the other Convert.ToDouble method and uncomment this to try giving some false values to see how it works
/*
try
{
Convert.ToDouble(arrUserData[3]);
}
catch (FormatException)
{
Console.WriteLine("Unable to convert " + arrUserData[3] + " to a Double.");
}
catch (OverflowException)
{
Console.WriteLine(arrUserData[3] + " is outside the range of a Double.");
}
* */
}
}
SeeUserData(thisArray); // to display the user data, demonstrates nesting methods that can
// operate off of one single variable pass in your Play method
// you could also move it to your play method and change it to SeeUserData(arrQuestions); and it would work the same
}
public void SeeUserData(string[] sameArrayAgain)
{
Console.WriteLine("Here's the data for " + arrUserData[0]);
for (int i = 0; i < sameArrayAgain.Length; i++)
{
Console.WriteLine("Your " + sameArrayAgain[i] + " " + arrUserData[i]);
}
}
static void Main(string[] args) { Program myProgram = new Program(); myProgram.Play(); }
}
I just have two simple arrays of double Values! I get the input from the user and the size of the arrays are equal (always). The thing is, I am multiplying them using:
int sizeof_secondarray = entArray.Length;
for (int i = 0; i <sizeof_secondarray; i++)
{
prod = freqArray[i] * entArray[i];
Console.WriteLine("PROD= " + prod.ToString("#.##"));
}
So, the user gives input for array (freqArray) 50 & 60
and for the array (entArray) 0.52 & 0.47
but the product it gives me is:
PROD=
PROD= 23.5
PROD=
I am totally new to c# and missing something badly here, can somebody help me please?
Based on your partial code and your inputs, I see three points here:
1- The length of your arrays are 3, since you have three outputs, while you mentioned providing only 2 numbers per array. Thus there are some errors when you fill the arrays.
2- Since prod.ToString("#.##") returned empty strings in first and third printout, it means that entArray[0]*freqArray[0] and entArray[2]*freqArray[2] are zeros (x.ToString("#.##") returns empty string when x=0).
3- Based on 1 and 2, my blind guess is that your arrays are filled like this: {0,50,60} and
{0.52,0.47,0}, leading to the shown result.
Conclusion: Fix the section of the code where you get inputs from the user. There is absolutely no problem with the code section you provided here.
Change the for loop to below and try
for (int i = 0;i <sizeof_secondarray - 1; i++)
Update :
Sorry i overlooked into the question and gave wrong suggestion. I have tested the scenario using below code and it gave me correct answer. Are you declaring the variables, specifically "prod" in the below manner? Below code may give some hint to you.
static void Main(string[] args)
{
double[] entArray = new double[] { 0.52, 0.47 };
int sizeof_secondarray = entArray.Length;
double prod;
double[] freqArray = new double[] { 50, 40};
for (int i = 0; i < sizeof_secondarray; i++)
{
prod = freqArray[i] * entArray[i];
Console.WriteLine("PROD= " + prod.ToString("#.##"));
}
Console.Read();
}
Answer :
PROD= 26
PROD= 18.8
okay so, I have been asked to write a console application for a theater ticket system. A user will type in the number of seats required, and the area of the theater chosen (using the code number 1-4 to represent the seating area chosen) The program should work out and display the cost of the tickets, based on the pricing plan shown below
Area Code price
Stalls 1 £24
Grand circle 2 £30
Upper circle 3 £27
Gallery 4 £20
I've so far came up with the following, But it's got an error to do with string + Int conversions under the IF Statements section, this is probably very easy to fix, but I'm new to programming so i'm unsure how to resolve it:
//Declare variables and constants
int iSeatNum;
int iArea;
int iCost;
int iTotalCost;
//Ask the user how many seats they require
Console.WriteLine("How many seats would you like to purchase?");
iSeatNum = Convert.ToInt32(Console.ReadLine());
//Ask the user what area they would like to be in
Console.WriteLine("Where would you like to sit? Please enter 1 for Stalls, 2 for Grand Circle, 3 for Upper Circle or 4 for Gallery");
iArea = Convert.ToInt32(Console.ReadLine());
**if (iArea = "1")**
{
iCost = 24;
}
//Clarify information & work out
Console.WriteLine("You are buying " + iSeatNum + " Seats at " + iArea);
iTotalCost = iSeatNum * iCost;
Console.WriteLine("Your total ticket cost is " + iTotalCost);
//Prevent from closing
Console.WriteLine("Press any key to close");
Console.ReadKey();
if (iArea = "1")
iArea is an integer, "1" is a string. So you cannot compare those two. You should compare with the integer 1 instead. Also note that a single equals symbol (=) is an asignment, and not a comparison. You will want to use two there: ==
if (iArea == 1)
now it displays a further error, when I put iTotalCost = iSeatNum * iCost; it comes up the error of "Use of unassigned local variable iCost" Any idea how I fix this?
The problem is that you declare the variable iCost at the beginning, but never safely assign any value to it before using it. You do assign a value when iArea equals to 1, but for all other cases, the variable remains uninitialized. Of course the compiler doesn’t know that you will end up typing in 1 when the program runs for testing, and that’s not a safe thing anyway. So it requires you to initialize your variable with anything instead.
So at the beginning, you can just say int iCost = 0; to fix this.
Well "1" is a string, not int.
if (iArea == 1)
Because you have already converted you string (the Console.ReadLine() return a string) into number using:
iArea = Convert.ToInt32(Console.ReadLine());
you can compare it as number using:
if (iArea == 1)
note the == instead of =, the single is used for assignment, the double for comparison.
if (iArea = "1")
This doesn't make sense. First of all you're using the assignment equals operator. You're attempting to assign iArea the value of "1". Instead, you need the logical equality operator == which will return true or false depending on whether the first operand is equal to the second operand.
Second, you have already converted the string value read from the console to a strongly typed integer. So you need to write your if statement as follows:
if (iArea == 1)
String strArea =Console.ReadLine();
if (strArea.Equals("1"))
{
iCost = 24;
}
or
int iArea = Convert.ToInt32(Console.ReadLine());
if (iArea == 1))
{
iCost = 24;
}
Today I came a cross an article by Eric Lippert where he was trying to clear the myth between the operators precedence and the order of evaluation. At the end there were two code snippets that got me confused, here is the first snippet:
int[] arr = {0};
int value = arr[arr[0]++];
Now when I think about the value of the variable value, I simply calculate it to be one. Here's how I thought it's working.
First declare arr as an array of int
with one item inside of it; this
item's value is 0.
Second get the value of arr[0] --0 in
this case.
Third get the value of arr[the value
of step 2] (which is still 0) --gets
arr[0] again --still 0.
Fourth assign the value of step 3
(0) to the variable value. --value =
0 now
Add to the value of step 2 1 --Now
arr[0] = 1.
Apparently this is wrong. I tried to search the c# specs for some explicit statement about when the increment is actually happening, but didn't find any.
The second snippet is from a comment of Eric's blog post on the topic:
int[] data = { 11, 22, 33 };
int i = 1;
data[i++] = data[i] + 5;
Now here's how I think this program will execute --after declaring the array and assigning 1 to i. [plz bear with me]
Get data[i] --1
Add to the value of step 1 the value
5 --6
Assign to data[i] (which is still 1)
the value of step 2 --data[i] = 6
Increment i -- i = 2
According to my understanding, this array now should contain the values {11, 27, 33}. However, when I looped to print the array values I got: {11, 38, 33}. This means that the post increment happened before dereferencing the array!
How come? Isn't this post increment supposed to be post? i.e. happen after everything else. What am I missing guys?
The postincrement operation occurs as part of evaluating the overall expression. It's a side effect which occurs after the value is evaluated but before any other expressions are evaluated.
In other words, for any expression E, E++ (if legal) represents something like (pseudo-code):
T tmp = E;
E += 1;
return tmp;
That's all part of evaluating E++, before anything else is evaluated.
See section 7.5.9 of the C# 3.0 spec for more details.
Additionally, for assignment operations where the LHS is classified as a variable (as in this case), the LHS is evaluated before the RHS is evaluated.
So in your example:
int[] data = { 11, 22, 33 };
int i = 1;
data[i++] = data[i] + 5;
is equivalent to:
int[] data = { 11, 22, 33 };
int i = 1;
// Work out what the LHS is going to mean...
int index = i;
i++;
// We're going to assign to data[index], i.e. data[1]. Now i=2.
// Now evaluate the RHS
int rhs = data[i] + 5; // rhs = data[2] + 5 == 38
// Now assign:
data[index] = rhs;
The relevant bit of the specification for this is section 7.16.1 (C# 3.0 spec).
For the first snippet, the sequence is:
Declare arr as you described:
Retrieve the value of arr[0], which is 0
Increment the value of arr[0] to 1.
Retrieve the value of arr[(result of #2)] which is arr[0], which (per #3) is 1.
Store that result in value.
value = 1
For the second snippet, the evaluation is still left-to-right.
Where are we storing the result? In data[i++], which is data[1], but now i = 2
What are we adding? data[i] + 5, which is now data[2] + 5, which is 38.
The missing piece is that "post" doesn't mean "after EVERYTHING else." It just means "immediately after I retrieve the current value of that variable." A post increment happening "in the middle of" a line of code is completely normal.
data[i++] // => data[1], then i is incremented to 2
data[1] = data[2] + 5 // => 33 + 5
I would expect the post-increment operator to increment the variable after its value is used.
In this case, the variable is incremented before the second reference to the variable.
If it would not be so, you could write
data[i++] = data[i++] + data[i++] + data[i++] + 5
If it would be like you say, then you could remove the increment operator because it doesn't do actually anything, in the instruction I reported.
You have to think of assignments in three steps:
Evaluate left hand side (=get address where the value should be stored)
Evaluate right hand side
Assign the value from step 2 to the memory location from step 1.
If you have something like
A().B = C()
Then A() will run first, then C() will run, and then the property setter B will run.
Essentially, you have to think of your statement as
StoreInArray(data, i++, data[i] + 5);
The cause might be that some compilers optimize i++ to be ++i. Most of the time, the end result is the same, but it seems to me to be one of those rare occasions when the compiler is wrong.
I have no access to Visual Studio right now to confirm this, but try disabling code optimization and see if the results will stay the same.