c# at a arbitrary or random time , make a function execute - c#

I want to make a function which has an alarm execute at the arbitrary time on everyday... I use c#.
I can not find proper method or code. I think I could use timer or rand method, but it happens regular time.
Here is the code:
class Program
{
static void Main(string[] args)
{
int i, k;
int j;
Console.WriteLine("가위는 0, 바위는 1, 보는 2 선택 => ");
string ReadValue = Console.ReadLine();
j = Convert.ToInt32(ReadValue);
k = new Random().Next() % 3;
if(k == 0 && j == 1 || k == 1 && j == 2 || k == 2 && j == 0)
{
Console.WriteLine("플레이어 승! \n");
}
else if(k == j)
{
Console.WriteLine("무승부! \n");
}
else{
Console.WriteLine("플레이어 패배! \n");
}
}
}

Your question is vague one. There're many possible implementations depending on what you actually want. The simplest one, IMHO, is to wait:
private static Random random = new Random();
static void Main(string[] args)
{
while (true)
{
// from 10 seconds up to 1 day;
int timeToWait = random.Next(10, 86400) * 1000;
Thread.Sleep(timeToWait);
Alarm();
}
}
static void Alarm()
{
Console.WriteLine("Alarm!");
}

You're using the Random in the wrong way. You should have a Random r = new Random(); outside a loop that is executing your method and inside the loop a k=r.Next();.
Random(seed) with the same seed always return the same value. You either have to do what I said above, or modify the seed every execution, but for this, you need a random value!. I recommend you to read the Random reference: https://msdn.microsoft.com/en-us/library/system.random(v=vs.110).aspx

Related

C# exclude numbers from a list in random generation

I am making a tic tac toe game and I am making it to be unbeatable
but first I have to let the computer know the rules.
I'm stuck in a step that is => when it's the computer's turn and we have just started the game so no win case so it's up to the computer to generate a random number that will be the computer's choice ( the block where he mark X or O )
so I need it to generate a number from 1 to 9 but by excluding the already used blocks ( numbers ).
I tried doing that by making a list and adding a number every time the human player used a block but I can't find a way to use those numbers from the list as exclusion for the random choice of the computer.
Here is what I tried and thnx in advance:
//random
List<int> cas = new List<int>();
if (c1 == true)
{
cas.Add(1);
}
if (c2 == true)
{
cas.Add(2);
}
if (c3 == true)
{
cas.Add(3);
}
if (c4 == true)
{
cas.Add(4);
}
if (c5 == true)
{
cas.Add(5);
}
if (c6 == true)
{
cas.Add(6);
}
if (c7 == true)
{
cas.Add(7);
}
if (c8 == true)
{
cas.Add(8);
}
if (c9 == true)
{
cas.Add(9);
}
for (int i = 0; i < cas.Count; i++)
{
random_except_list(cas[]);
}
public static int random_except_list(int[] x)
{
Random r = new Random();
int result = r.Next(1, 9 - );
for (int i = 0; i < x.Length; i++)
{
if (result < x[i])
return result;
result++;
}
return result;
}
Lets have possible places to use:
List<int> possible = Enumerable.Range(1,9).ToList(); // create a list and add 1-9
and used places:
List<int> used = new List<int>();
Random rnd = new Random();
Now everytime we generate a random number in the range of possible list count as index and remove it from there and move it to used:
int index = rnd.Next(0, possible.Count);
used.Add(possible[index]);
possible.RemoveAt(index);
for user its just enough to check if it exists in the used so the acceptable number should be:
!used.Any(x=> x== NumberUserHaveChosen)
So the first time the random number can be 0-8 (as possible.Count==9) and take from it at random index.
the second time the random number can be 0-7 (as possible.Count==8) and take from it at random index.
and so on... while the possible.Count != 0
in this case there is no need to generate random numbers several times that finally it won't exist in our used List.
Several years ago I was working on a Sudoku algorithm, and what I was trying to achieve was to generate a valid solved sudoku table in minimum time possible, i get to the conclusion that I should replace the algorithm that each time I generate a number I have to check some lists to make sure the number was not generated before, as count of numbers were increasing these comparisons would become more and more. for example when only the number 4 is remaining, I should generate random numbers till I get 4. so I used this approach and the result was amazing.
I think you should do something like this:
public static int random_except_list(List<int> x)
{
Random r = new Random();
int result = 0;
while (true)
{
result = r.Next(1, 10);
if (!x.Contains(result))
return result;
}
}
Just trying to use what you have written (more or less), but changing the method to take a List<int> which is what you are building, I would write the method using LINQ like this (except I would create a static Random variable and keep it between calls):
public static int random_except_list(List<int> x) => Enumerable.Range(1, 9).Where(n => !x.Contains(n)).ToList()[new Random().Next(0, 9 - x.Count)];
However, you can implement the same idea in a more explicit way using procedural code:
public static int random_except_list_explicit(List<int> x) {
// First, generate a list of possible answers by skipping the except positions in x
var possibles = new List<int>();
for (int i = 1; i <= 9; i++)
if (!x.Contains(i))
possibles.Add(i);
// now pick a random member of the possible answers and return it
return possibles[new Random().Next(0, possibles.Count)];
}
I believe it is better to work with positions left. So user or computer select from all open positions:
using System;
using System.Collections.Generic;
class app
{
public static int random_except_list(List<int> openPositions)
{
Random r = new Random();
int index = r.Next(openPositions.Count - 1);
int result = openPositions[index];
openPositions.RemoveAt(index);
return result;
}
static void Main()
{
List<int> openPositions = new List<int>();
for (int i = 1; i < 10; i++)
{
openPositions.Add(i);
}
bool turn = false;
while (openPositions.Count > 0)
{
foreach (int value in openPositions)
{
Console.Write(value + " ");
}
Console.WriteLine();
if (!turn)
{
while (true)
{
Console.WriteLine("Choose your Position");
ConsoleKeyInfo key = Console.ReadKey();
int num = (int)key.KeyChar - 48;
if (openPositions.Contains(num))
{
openPositions.Remove(num);
Console.WriteLine();
break;
}
else Console.Write(" is not Valid: ");
}
}
else
{
int compPos = random_except_list(openPositions);
Console.WriteLine("Computer choose: " + compPos);
}
turn = !turn;
}
Console.WriteLine("No positions left");
Console.ReadKey();
}
}

C# factorial calculator is not working right

My factorial calculator isn't working quite correctly.
It works as expected from 1 to 20, as my professor wants. However, entering 0 should return a factorial of 1; it returns 0
Here is my code:
private void CalculateFactorial(long number)
{
//perform the calculations
long result = number;
for (int i = 1; i < number; i++)
{
result = result * i;
}
//display the calculated Factorial to the user
txt_Factorial.Text = result.ToString("n0");
}
Here is the method which calls the above method, the event handler for the calculate button:
private void btn_Calculate_Click(object sender, EventArgs e)
{
//get the users input
long number = long.Parse(txt_Number.Text);
// make sure the number not invalid. If it is invalid, tell the user
// otherwise, proceed to calculation.
if (number < 0 || number > 20)
txt_Factorial.Text = "Invalid Number";
else
CalculateFactorial(number);
txt_Number.Focus(); // returns the focus to the number box whether or not data was valid
Ideas?
If you step through this in a debugger the problem becomes pretty clear. And as you're just getting started with programming I highly recommend getting used to a debugger as early as you can. It's an absolutely invaluable tool for programming.
Look at your for loop:
for (int i = 1; i < number; i++)
What happens when number is 0? The loop never runs. You can't include 0 in the loop range because that would set every result to 0 by first multiplying it by 0. So you need to add an explicit check for 0 in the function logic:
if (number == 0)
return 1;
// continue with your loop here
Factorial of 0 is 1 by definition, not by calculation, and your code does not reflect that. Add a check before your code:
if (number == 0)
result = 1;
else
// compute factorial
Also think about creating a function that returns an integer value as the result.
You can use this :
if(number == 0){
result = 1;
}
for (int i = 1; i <= number; i++)
result *= i;
}
also your formula is wrong because n! = 1*2*3*.....*n
You can test the following code! tested and works. Recursive Implementation as well as basic implementation
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication50
{
class Program
{
static void Main(string[] args)
{
NumberManipulator manipulator = new NumberManipulator();
Console.WriteLine("Please Enter Factorial Number:");
int a= Convert.ToInt32(Console.ReadLine());
Console.WriteLine("---Basic Calling--");
Console.WriteLine("Factorial of {0} is: {1}" ,a, manipulator.factorial(a));
Console.WriteLine("--Recursively Calling--");
Console.WriteLine("Factorial of {0} is: {1}", a, manipulator.recursively(a));
Console.ReadLine();
}
}
class NumberManipulator
{
public int factorial(int num)
{
int result=1;
int b = 1;
do
{
result = result * b;
Console.WriteLine(result);
b++;
} while (num >= b);
return result;
}
public int recursively(int num)
{
if (num <= 1)
{
return 1;
}
else
{
return recursively(num - 1) * num;
}
}
}
}

The array dont save my numbers

I am trying to learn C# and doing some questions i googeld. This is the task to do:
*"Beginner level:
The task is to make
a dice game where the user throws 3
Each 12-sided dice (numbers
shall be randomly selected and stored in an array / field or list).
Add up the total of the dice and show on the screen.
Create a function / method that accepts a figure
(the total sum of the dice). Function / method
should return the text "Good throw" if the figure
is higher or equal to 20.
In all other cases, the text
"Sorry" is returned.
Call the function / method in the main method
and prints the total and the text.
Advanced level:
This is an extension of the task where you must use a class to simulate a dice. The user shall have the option of writing a x y-sided dice himself.
If the total sum of a roll of the dice generates a score that is> 50% of the maximum score, the words "good throw" is displayed.
This logic can be in your main method.
Create the class described in the class diagram and use appropriate
way in your code."*
The thing is that i cant get it to work, the array in my class do not save my numbers im typing in... I only get the reslut 0. I think i have just done some big misstake i cant see...
This is the Main code:
static void Main(string[] args)
{
List<Dice> _Dice = new List<Dice>();
int a = 0;
int times = int.Parse(Interaction.InputBox("Write how many times you want to repeat the game:"));
while (a != times)
{
int antThrow = int.Parse(Interaction.InputBox("Write how many times you want each dice to get thrown:"));
int xChoice = int.Parse(Interaction.InputBox("Write how many dice you want to throw:"));
int yChoice = int.Parse(Interaction.InputBox("Write how many sides you want each dice should have:"));
_Dice.Add(new Dice(xChoice,yChoice, antThrow));
a++;
}
int e = 1;
foreach (var item in _Dice)
{
Interaction.MsgBox(string.Format("Result of game {0}: {1}", e++, item.Tostring()));
}
}
This is the Dice class:
class Dice
{
static int _xChoice, _yChoice, _throw;
static List<int> sum = new List<int>();
static int w = 0;
static int _sum;
static int[,] dice = new int[_xChoice, _yChoice];
public string Tostring()
{
int half = _sum / 2;
if (half <= _sum/2)
{
return "Good throw!" + _sum;
}
else
{
return "Bad throw!";
}
}
void random()
{
Random rnd = new Random();
while (w != _throw)
{
for (int i = 0; i < dice.GetLength(0); i++)
{
for (int j = 0; j < dice.GetLength(1); j++)
{
dice[i, j] = rnd.Next(1, _yChoice);
_sum += dice[j, i];
sum.Add(_sum);
}
}
w++;
}
}
public Tarning(int Xchoice, int Ychoice, int throw)
{
_throw = thorw;
_xChoice = Xchoice;
_yChoice = Ychoice;
}
}
Your main problem is in the static keyword. Static field means that there's only
one field for all the instances, which is not your case: you need each instance of Dice has its own fields' values.
class Dice {
// no static here
private int _xChoice, _yChoice, _throw;
// no static here
private List<int> sum = new List<int>();
// no static here
private int w = 0;
// no static here
private int _sum;
// no static here
private int[,] dice = new int[_xChoice, _yChoice];
// BUT, you want a random generator for all the instances, that's why "static"
private static Random rnd = new Random();
// When overriding method mark it with "override"
// And Be Careful with CAPitalization:
// the method's name "ToString" not Tostring
public override string ToString() {
...
}
void random() {
// Do not create Random generator each time you call it:
// It makes the random sequences skewed badly!
// Istead use one generator for all the calls, see the code above
// private static Random rnd = new Random();
// Random rnd = new Random();
...
}
...
class Program
{
static void Main(string[] args)
{
var dice = new List<DiceLogic>();
int a = 0;
int times = GetTimes();
while (a != times)
{
int antThrow = GetAntThrow();
int xChoice = GetXChoice();
int yChoice = GetYChoice();
dice.Add(new DiceLogic(xChoice, yChoice, antThrow));
a++;
}
int e = 1;
foreach (var item in dice)
{
Console.WriteLine("Result of game {0}: {1}", e++, item.Tostring());
}
Console.ReadLine();
}
private static int GetTimes()
{
while (true)
{
Console.WriteLine("Write how many times you want to repeat the game:");
int times;
var result = int.TryParse(Console.ReadLine(), out times);
if (result) return times;
Console.WriteLine("Value must be a number.");
}
}
private static int GetAntThrow()
{
while (true)
{
Console.WriteLine("Write how many times you want each dice to get thrown:");
int antThrow;
var result = int.TryParse(Console.ReadLine(), out antThrow);
if (result) return antThrow;
Console.WriteLine("Value must be a number.");
}
}
private static int GetXChoice()
{
while (true)
{
Console.WriteLine("Write how many dice you want to throw:");
int getXChoice;
var result = int.TryParse(Console.ReadLine(), out getXChoice);
if (result) return getXChoice;
Console.WriteLine("Value must be a number.");
}
}
private static int GetYChoice()
{
while (true)
{
Console.WriteLine("Write how many sides you want each dice should have:");
int getXChoice;
var result = int.TryParse(Console.ReadLine(), out getXChoice);
if (result) return getXChoice;
Console.WriteLine("Value must be a number.");
}
}
}
public class DiceLogic
{
public string Tostring()
{
int maxScore = _diceSides*_dices;
if (_result >= maxScore / 2)
{
return "Good throw! " + _result;
}
return "Bad throw! " + _result;
}
private readonly int _dices;
private readonly int _diceSides;
private readonly int _throwDice;
private int _result;
private void CalculateResult()
{
var rnd = new Random();
for (int i = 0; i < _dices; i++)
{
int currentResult = 0;
for (int j = 0; j < _throwDice; j++)
{
currentResult = rnd.Next(0, _diceSides);
}
_result += currentResult;
}
}
public DiceLogic(int dices, int diceSides, int throwEachDice)
{
_dices = dices;
_diceSides = diceSides;
_throwDice = throwEachDice;
CalculateResult();
}
}
This is an example of how you could implement what they are asking, go through te code line by line with the debugger so you understand what is going on.
You never call the method random(). Therefore, the value of your member variable _sum is never changed and remains 0. You need to call the method random() somewhere. You should probably make it public and call it from your main method after you have set up all your dice.
Furthermore, your member variables in the Dice class are all static! That means that the different Dice instances will all share the same values. I think this is not intended. You should make the variables instance variables by removing the static modifier.
Your method Tarning is not called and it takes a reserved word “throw” [I believe it was supposed to be thorw]. The method is not void so it must return a type.
Random() is not invoked and does display anything.
Dice has not constructor that has 3 arguments within its braces but it’s declared as _Dice.Add(new Dice(xChoice,yChoice, antThrow));

Separate functions without duplicating code

I am currently working on a program to traverse through a list of numbers with two different functions to find the sum and a specific value. Here is the code that I have implemented
class Program
{
static int i, sum;
static List<int> store = new List<int>();
static void Main(string[] args)
{
for (i = 0; i < 100; i++)
{
store.Add(i);
}
i = 0;
TraverseList();
Console.ReadLine();
}
static void TraverseList()
{
while (i < store.Count)
{
FindValue();
FindSum();
i++;
}
Console.WriteLine("The sum is {0}", sum);
}
static void FindValue()
{
if (store[i] == 40)
{
Console.WriteLine("Value is 40");
}
}
static void FindSum()
{
sum = sum + store[i];
}
}
I was thinking of separating FindSum and FindValue into two different functions and not calling them in TraverseList. Is there any other way of doing it rather the duplicating the common code of list traversal in those two functions as I have done here
class Program
{
static int i, sum;
static List<int> store = new List<int>();
static void Main(string[] args)
{
for (i = 0; i < 100; i++)
{
store.Add(i);
}
i = 0;
FindValue();
i = 0;
FindSum();
Console.ReadLine();
}
static void FindValue()
{
while (i < store.Count)
{
if (store[i] == 40)
{
Console.WriteLine("Value is 40");
}
i++;
}
}
static void FindSum()
{
while (i < store.Count)
{
sum = sum + store[i];
i++;
}
Console.WriteLine("The sum is {0}", sum);
}
}
To find the sum of a series of numbers you can use the simple LINQ function:
List<int> numbers = new List<int>();
int sum = numbers.Sum();
I am not sure what you mean by find a value. If you want to check if one of the numbers in a series is equal to a certain value you can use the LINQ function Any:
int myValue = 40;
bool hasMyValue = numbers.Any(i => i == myValue);
This uses a lambda expression which executes a function and passes each element in the collection to the function. The function returns true or false to indicate that the element is a match for the Any test.
If instead you want to check for how many numbers in a sequence match a certain value you can instead use the Count function like so:
int numberOfMatches = numbers.Count(i => i == myValue);
First thing - I would use foreach instead of while, regarding the duplicate code (assuming you are not using Linq) - I think it's fine
A taste how Linq can simplify your code:
var FindSum = store.Sum();
var FindValue = store.FindAll(x => x == 40);
I cannot stress enough how bad it is to have i and sum as class members. Especially i. It will make your code very fragile, and hard to work with. Try to make each method as isolated from the rest of the code as possible.
Try something like this instead:
static void Main( string[] args )
{
List<int> store = new List<int>();
for( int i = 0; i < 100; i++ )
store.Add( i );
FindValue( store );
FindSum( store );
Console.ReadLine();
}
static void FindValue( List<int> list )
{
for( int i = 0; i < list.Count; i++ )
{
if( list[i] == 40 )
Console.WriteLine( "Value is 40" );
}
}
static void FindSum( List<int> list )
{
int sum = 0;
for( int i = 0; i < list.Count; i++ )
sum += list[i];
Console.WriteLine( "The sum is {0}", sum );
}
It is perfectly fine (and normal) to duplicate the looping, it's just a single line. You could also use a foreach here.
Also, disregard everyone telling you to use LINQ. You're obviously new to programming and you should learn the basics first.

dice rolling in C# console application giving incorrect totals

I am writing dice roller program in C# console. I am giving two input
Enter the size of the dice and
Enter how times you want to play.
Suppose dice size is 6 and 10 times i have played.
Output is coming:
1 was rolled 2 times
2 was rolled 7 times
3 was rolled 8 times
4 was rolled 7 times
5 was rolled 4 times
6 was rolled 5 times
Total: 33 (its not fixed for every execution this no will be changed)
But my requirement was this total always should be number of playing times. Here I am playing 10 times so the total should be 10 not 33. It should happen for every new numbers... If I play 100 times sum or total should be 100 only not any other number. rest all will be remain same, in my programing not getting the expected sum. Please somebody modify it. Here is my code:
Dice.cs:
public class Dice
{
Int32 _DiceSize;
public Int32 _NoOfDice;
public Dice(Int32 dicesize)
{
this._DiceSize = dicesize;
}
public string Roll()
{
if (_DiceSize<= 0)
{
throw new ApplicationException("Dice Size cant be less than 0 or 0");
}
if (_NoOfDice <= 0)
{
throw new ApplicationException("No of dice cant be less than 0 or 0");
}
Random rnd = new Random();
Int32[] roll = new Int32[_DiceSize];
for (Int32 i = 0; i < _DiceSize; i++)
{
roll[i] = rnd.Next(1,_NoOfDice);
}
StringBuilder result = new StringBuilder();
Int32 Total = 0;
Console.WriteLine("Rolling.......");
for (Int32 i = 0; i < roll.Length; i++)
{
Total += roll[i];
result.AppendFormat("{0}:\t was rolled\t{1}\t times\n", i + 1, roll[i]);
}
result.AppendFormat("\t\t\t......\n");
result.AppendFormat("TOTAL: {0}", Total);
return result.ToString();
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter no of dice size");
int dicesize = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("How many times want to play");
int noofplay=Convert.ToInt32(Console.ReadLine());
Dice obj = new Dice(dicesize);
obj._NoOfDice = noofplay;
obj.Roll();
Console.WriteLine(obj.Roll());
Console.WriteLine("Press enter to exit");
Console.ReadKey();
}
}
It looks to me like you're getting the math backwards... shouldn't it be:
// to capture just the counts
int[] roll = new int[_DiceSize];
for (int i = 0; i < _NoOfDice; i++)
{
roll[rnd.Next(roll.Length)]++;
}
Or if you want the actual rolls:
// to capture individual rolls
int[] roll = new int[_NoOfDice];
for (int i = 0; i < _NoOfDice; i++)
{
roll[i] = rnd.Next(_DiceSize) + 1; // note upper bound is exclusive, so +1
}
You are creating a new Random instance on each iteration. This is not a good thing as it will affect the uniform distribution of results. Keep the Random instance in a field instead of creating a new one every time.
public class Dice {
private Random rnd = new Random();
// ... don't create a new random in `Roll` method. Use `rnd` directly.
}
First of all, the following for-loop is wrong:
for (Int32 i = 0; i < _DiceSize; i++)
{
roll[i] = rnd.Next(1,_NoOfDice);
}
Obviously you switched _DiceSize and _NoOfDice. The correct loop would look like
for (Int32 i = 0; i < _NoOfDice; i++)
{
roll[i] = rnd.Next(1,_DiceSize);
}
Because of that, the line
Int32[] roll = new Int32[_DiceSize];
has to be changed to
Int32[] roll = new Int32[_NoOfDice];
Maybe you should think about renaming these variables, so it's more clearly, which means what.
If you modify your code that way, you will mention that your analisys won't work that way you implemented it. Actually, what you are showing is the result of each throw, which is not what you want, if I understood you right.
UPDATE:
Sorry, I misunderstood you. You do want to show the result for every roll. So, why don't you just move the StringBuilder.AppendFormat to your "rolling-for-loop"?
UPDATE #2:
For me, the following Die-class works exactly the way you want it:
public class Die
{
private int maxValue;
private int numberOfRolls;
private Random random;
public Die(int maxValue, int numberOfRolls)
{
this.maxValue = maxValue;
this.numberOfRolls = numberOfRolls;
this.random = new Random();
}
public string Roll()
{
StringBuilder resultString = new StringBuilder();
for (int i = 0; i < this.numberOfRolls; i++)
{
resultString.AppendFormat("Roll #{0} - Result: {1}" + Environment.NewLine, i + 1, this.random.Next(1, maxValue + 1));
}
return resultString.ToString();
}
}
Hope I could help you.
This is the full code you have to use, according to Mehrdad and Marc Gravell.
Have fun.
public class Dice
{
private Random rnd = new Random();
Int32 _DiceSize;
public Int32 _NoOfDice;
public Dice(Int32 dicesize)
{
if (dicesize <= 0)
{
throw new ApplicationException("Dice Size cant be less than 0 or 0");
}
this._DiceSize = dicesize;
}
public string Roll()
{
if (_NoOfDice <= 0)
{
throw new ApplicationException("No of dice cant be less than 0 or 0");
}
// to capture just the counts
int[] roll = new int[_DiceSize];
for (int i = 0; i < _NoOfDice; i++)
{
roll[rnd.Next(roll.Length)]++;
}
StringBuilder result = new StringBuilder();
Int32 Total = 0;
Console.WriteLine("Rolling.......");
for (Int32 i = 0; i < roll.Length; i++)
{
Total += roll[i];
result.AppendFormat("{0}:\t was rolled\t{1}\t times\n", i + 1, roll[i]);
}
result.AppendFormat("\t\t\t......\n");
result.AppendFormat("TOTAL: {0}", Total);
return result.ToString();
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter no of dice size");
int dicesize = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("How many times want to play");
int noofplay = Convert.ToInt32(Console.ReadLine());
Dice obj = new Dice(dicesize);
obj._NoOfDice = noofplay;
Console.WriteLine(obj.Roll());
Console.WriteLine("Press enter to exit");
Console.ReadKey();
}
}

Categories