Is it possible to create loop which create instance of classes? - c#

I want to create console app which read userinput value and create multiple instances of one class and then run void say() in all class instances.
Code below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
int botsnumber = 0;
Console.WriteLine("Type number: ");
botsnumber = Int32.Parse(Console.ReadLine());
for (int i = 0; i < botsnumber; i++)
{
//Here generate bots: Bot b1 = new Bot(); Bot b2 = new Bot();
// Bot b = new Bot();
}
b.say();// b1.say(); b2.say(); b3.say(); ...
}
}
class Bot
{
public static void say()
{
Console.WriteLine("Hello!");
}
}
}

Put the instances into a list, fill it, after that, loop the list and call say
botsnumber = Int32.Parse(Console.ReadLine());
var list = new List<Bot>();
for (int i = 0; i < botsnumber; i++)
{
Bot b = new Bot();
list.Add(b);
}
list.ForEach(b => b.say());
And you don't need to put static in your method say
class Bot
{
public void say()
{
Console.WriteLine("Hello!");
}
}

Like this i guess
public static List<Bot> bots = new List<Bot>();
...
for (int i = 0; i < botsnumber; i++)
{
bots.Add(new Bot);
}
...
bots[0].Say();
bots[1].Say();

I think you want to call say() inside the loop, and make it a non-static method:
for (int i = 0; i < botsnumber; i++)
{
Bot b = new Bot();
b.Say();
}
class Bot
{
public void Say()
{
Console.WriteLine("Hello!");
}
}
Although note that in many ways there's no point in creating a stateless object instance that you immediately discard, so ... in real usage I would either expect some state, or I'd expect it to be a static method.
Alternatively, you could create all the bots first, accumulate them in a list, then loop over that - again, whether this is sensible depends on context, but:
var bots = new List<Bot>(botsnumber);
for (int i = 0; i < botsnumber; i++)
{
bots.Add(new Bot());
}
// ...
foreach(var bot in bots)
{
bot.Say();
}

You could either immediately call say, or call them all after creating all the bots
for (int i = 0; i < botsnumber; i++)
{
//Here generate bots: Bot b1 = new Bot(); Bot b2 = new Bot();
Bot b = new Bot();
b.say();
}
// or
var bots = new List<Bot>();
for (int i = 0; i < botsnumber; i++)
{
//Here generate bots: Bot b1 = new Bot(); Bot b2 = new Bot();
bots.Add(new Bot());
}
foreach (var bot in bots)
{
bot.say();
}

Related

Lucky Dip Program

I was trying to make a lucky dip program where 6 random numbers,1-59, are chosen then printed out in an array. I managed to get this to work, however you needed to use an IndexOf method so that no same number was printed twice by checking if the new number is already in the array.
using System;
namespace LuckyDip
{
class Program
{
static void Main(string[] args)
{
int[] luckyNumbers = new int[6];
Random random = new Random();
for (int x = 0; x<6; x++)
{
num[x] = random.Next(1,59);
Console.WriteLine(num[x]);
}
Console.ReadLine();
}
}
}
It prints out numbers, but sometimes they are the same.
You state that you want to use IndexOf, but that method is used for strings (see docs). Your example has an int array so the solution below uses Contains. This solution adds a check within your loop and generates a new number if this number already exists within your array. If you really need to use IndexOf, create a string array and convert the numbers using String.valueOf(randomNumber)
using System;
using System.Linq;
public class Program
{
public static void Main(string[] args)
{
int[] luckyNumbers = new int[6];
Random random = new Random();
for (int x = 0; x<6; x++)
{
int randomNumber = random.Next(1,59);
while (luckyNumbers.Contains(randomNumber))
{
randomNumber = random.Next(1,59);
}
luckyNumbers[x] = randomNumber;
Console.WriteLine(luckyNumbers[x]);
}
}
}
Another possible solution would be:
using System;
using System.Collections;
using System.Linq;
public class Program
{
public static void Main()
{
int arraySize = 6;
int[] luckyNumbers = Enumerable.Range(1,59).OrderBy(g => Guid.NewGuid()).Take(arraySize).ToArray();
for (int x = 0; x < luckyNumbers.Length; x++)
{
Console.WriteLine(luckyNumbers[x]);
}
}
}

Concurrent increment g = g + 1 of a static variable appears atomic, but shouldn't be?

Can't find why code below with commented Monitor works like synchronized while writing to to g and always returns g=50. I was expecting some discrepancy an result less than 50.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace _7_monitor
{
class Program
{
static object sync = new object();
static int g = 0;
static Barrier b = new Barrier(6, (b) => { Console.WriteLine("barier reached"); } );
public static void tjob(object obj)
{
int t = (int)obj;
for (int i = 0; i < 10; i++)
{
//Monitor.Enter(sync);
g = g + 1;
//Monitor.Exit(sync);
Console.WriteLine("thr {0} iter={1}", t , i);
}
b.SignalAndWait();
}
static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
Thread d = new Thread(tjob);
d.Start(i);
}
Console.WriteLine("waiting");
b.SignalAndWait();
Console.WriteLine("g={0}",g);
Console.ReadLine();
}
}
}
As others have pointed out, a loop of 10 will complete so quickly that there's a good chance that the other threads haven't even started yet, so you've likely got sequential access to the global static variable g, in any event, hence the apparantly observed consistent result.
With a longer loop (I've taken some of the fluff out) with no protection around g, we do get something resembling a random number generator.
var threads = new List<Thread>();
for (var i = 0; i < 5; i++)
{
var d = new Thread(x => {
for (var loop = 0; loop < 100000; loop++)
{
// unsynchronized mutation
g = g + 1;
}
});
d.Start(i);
threads.Add(d);
}
foreach (var t in threads)
{
t.Join();
}
Console.WriteLine("g={0}", g); // 158609, 173331, 127983, ... (i7 with 4 HT Cores)
As per #Jurgis' comment, instead of a Monitor or lock, Interlocked.Increment has been provided to .Net
Replacing g = g + 1 with Interlocked.Increment(ref g); returns the expected:
g=500000
(and obviously, in the real world, there would be absolutely no point in parallelizing work which would just contend for a shared variable)

Why does an integer with value greater than loop limit gets passed to lambda

The code is to generate random numbers in 100 files numbered from 0..99.
What I couldn't get was why this code ended up creating a file called 100.txt and I even got an exception saying that 100.txt was being written by another process.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RandomNumbersFileGenerator
{
class Program
{
static Random Random = new Random();
static void Main(string[] args)
{
List<Task> tasks = new List<Task>();
for(int fileNumber = 0; fileNumber < 100; ++fileNumber)
{
tasks.Add(Task.Run(()=>GenerateFileWithRandomNumbers(Path.Combine($"c:\\FilesWithRandomNumbers\\{fileNumber}.txt"), 10000000)));
}
Task.WaitAll(tasks.ToArray());
}
static void GenerateFileWithRandomNumbers(string path, int numberOfNumbers)
{
List<string> listOfNumbers = new List<string>();
for(;numberOfNumbers > 0; --numberOfNumbers)
{
listOfNumbers.Add(Random.Next().ToString());
}
File.WriteAllLines(path, listOfNumbers);
}
}
}
It is related to closures and captured variables. Change
for(int fileNumber = 0; fileNumber < 100; ++fileNumber)
{
tasks.Add(Task.Run(()=>GenerateFileWithRandomNumbers(Path.Combine($"c:\\FilesWithRandomNumbers\\{fileNumber}.txt"), 10000000)));
}
To
for(int fileNumber = 0; fileNumber < 100; ++fileNumber)
{
int tmp = fileNumber;
tasks.Add(Task.Run(()=>GenerateFileWithRandomNumbers(Path.Combine($"c:\\FilesWithRandomNumbers\\{tmp}.txt"), 10000000)));
}
See also http://csharpindepth.com/articles/chapter5/closures.aspx

c# best way to match yahtzee

In my project that i'm working on I have to match 5 numbers for yahtzee. So all these numbers have to be the same. Now I have thought about how to do this but i'm not sure about what the best and easiest way is. Sure I can write it all out but there has to be a shorter way.
I haven't written the code for the part that checks if yahtzee has been thrown. This is because I only can come up with one way and that is to write it all out.
Here's my code so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Opdr3
{
class Program
{
struct YahtzeeGame
{
public int[] dobbelstenen;
public Random rnd;
public void Gooi()
{
for (int i = 0; i < 5; i++)
{
dobbelstenen[i] = Int32.Parse(rnd + "");
}
}
public bool Yahtzee()
{
Here it has to check if all dobbelstenen[int]
are the same
}
}
static void Main(string[] args)
{
// maak YahtzeeGame (struct) aan
YahtzeeGame yahtzeeGame;
// initialiseer struct-members
yahtzeeGame.rnd = new Random();
yahtzeeGame.dobbelstenen = new int[5];
// probeer yahtzee te gooien
int aantalPogingen = 0;
do
{
// gooi alle dobbelstenen
yahtzeeGame.Gooi();
aantalPogingen++;
} while (!yahtzeeGame.Yahtzee());
// vermeld aantal pogingen voor yahtzee
Console.WriteLine("Aantal pogingen nodig: {0}", aantalPogingen);
// wacht op gebruiker
Console.ReadKey();
}
}
}
You'll need a little loop:
public bool Yahtzee()
{
// check if all dobbelstenen[int] are the same
for(int i = 1; i < 5; i++) // start with second dobbelstenen
{
if(dobbelstenen[i] != dobbelstenen[0]) return false;
}
return true;
}
It simply compares second, third, ... against the first.

Why can't I Selection Sort this library?

I'm trying to use Selection Sort for a library of books so that it sorts them alphabetically, however I can't get it to work.
SelectionSort(library); doesn't work but SelectionSort(titles); does, any ideas? Thanks :)
Here is the full code:
using System;
using System.Collections.Generic;
using System.Text;
namespace BookSortingEx
{
class Program
{
static void swap<T>(ref T x, ref T y)
{
//swapcount++;
T temp = x;
x = y;
y = temp;
}
static void printArray(string[] a)
{
for (int i = 0; i < a.Length; i++)
{
Console.Write(a[i] + ",");
}
Console.WriteLine();
}
static bool IsInOrder<T>(T[] a) where T : IComparable
{
for (int i = 0; i < a.Length - 1; i++)
{
if (a[i].CompareTo(a[i + 1]) > 0)
return false;
}
return true;
}
static void Main(string[] args)
{
string[] array1 = { "Fred", "Zoe", "Angela", "Umbrella", "Ben" };
string[] titles = {"Writing Solid Code",
"Objects First","Programming Gems",
"Head First Java","The C Programming Language",
"Mythical Man Month","The Art of Programming",
"Coding Complete","Design Patterns",
"Problem Solving in Java"};
string[] authors = { "Maguire", "Kolling", "Bentley", "Sierra", "Richie", "Brooks", "Knuth", "McConnal", "Gamma", "Weiss" };
string[] isbns = { "948343", "849328493", "38948932", "394834342", "983492389", "84928334", "4839455", "21331322", "348923948", "43893284", "9483294", "9823943" };
Book[] library = new Book[10];
for (int i = 0; i < library.Length; i++)
{
library[i] = new Book(isbns[i], titles[i], authors[i]);
}
**DOESNT WORK - // SelectionSort(library);**
SelectionSort(titles);
printArray(titles);
foreach (Book book in library)
{
Console.WriteLine(" {0} ", book);
}
Console.WriteLine();
Console.ReadKey();
}
static public void SelectionSort(string[] a)
{
for (int i = 0; i < a.Length - 1; i++)
{
int smallest = i;
for (int j = i + 1; j < a.Length; j++)
{
if (a[j].CompareTo(a[smallest]) < 0)
smallest = j;
}
swap(ref a[i], ref a[smallest]);
}
}
}
}
Your method expects a string[], but you're giving it a Book[]
You'll want to change the implementation of SelectionSort to support Comparable Collections, as well as have Book implement the IComparable interface.
public class Book : IComparable
{
// Implementation
public int CompareTo(Book otherBook)
{
// Implementation
}
}
static public void SelectionSort<T>(IList<T> a) where T : IComparable
{
// Implementation
}
The advantage of this approach, is that you won't have to create a different version of SelectionSort for every kind of object collection you'll want to sort.
Because SelectionSort takes as an argument an array of type string and you are passing it an array of type Book. SelectionSort(titles) works because titles is an array of type string.
You need to write a method that takes an array of type Book
static public void SelectionSort(Book[] books)
and if you haven't done this already you probably need to define a CompareTo method in your Book class, so your sorting algorithm can figure out how to sort books.

Categories