I've written an event handler for a C# windows form project that simulates 100 rolls of two dice and returns the sum of the two dice for each roll. The code does three things for each of these sums, it places it in a RichTextBox called "rollDisplay", it writes the sum to a text file, and it adds the sum to a list of integers called "rolls". All of that is working fine, but now I need to count the frequency of each of the sums, and show these frequencies in a ListBox. As the code below indicates, I'm using eleven different counter variables, and eleven distinct strings to add to the ListBox. What I have below works, but it's really quite ugly, and seems to me like a really inefficient way of doing this.
My question is. Can anyone suggest a cleaner way of doing this? The assignment requires that I have eleven separate counters to identify the frequency of the dice rolls, so I can't use Linq as I saw suggested by several other questions, but I'm really quite uncertain that this is the best way to accomplish what I need.
private void Roll_Click(object sender, EventArgs e)
{
int roll = 0, hitTwo = 0, hitThree = 0, hitFour = 0, hitFive = 0, hitSix = 0, hitSeven = 0, hitEight = 0,
hitNine = 0, hitTen = 0, hitEleven = 0, hitTwelve = 0;
String freq1, freq2, freq3, freq4, freq5, freq6, freq7, freq8, freq9, freq10, freq11;
StreamWriter file = new StreamWriter("dicerolls.txt", true);
List<int> rolls = new List<int>();
for (int i = 0; i < 100; i++)
{
dieUno.setSide(dieUno.roll());
dieDuo.setSide(dieDuo.roll());
int diceTotal = dieUno.getSide() + dieDuo.getSide();
rolls.Add(diceTotal);
rollDisplay.AppendText(diceTotal.ToString() + "\u2028");
try
{
file.WriteLine(diceTotal.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
file.Close();
for (int i = 0; i < rolls.Count; i++)
{
roll = rolls[i];
if(roll==2)
{ hitTwo++; }
else if(roll==3)
{ hitThree++; }
else if(roll==4)
{ hitFour++; }
else if(roll==5)
{ hitFive++; }
else if(roll==6)
{ hitSix++; }
else if(roll==7)
{ hitSeven++; }
else if(roll==8)
{ hitEight++; }
else if(roll==9)
{ hitNine++; }
else if (roll == 10)
{ hitTen++; }
else if (roll == 11)
{ hitEleven++; }
else if (roll == 12)
{ hitTwelve++; }
}
freq1 = " 2 Occurs: " + hitTwo + " times"; freq2 = " 3 Occurs: " + hitThree + " times"; freq3 = " 4 Occurs: " + hitFour + " times";
freq4 = " 5 Occurs: " + hitFive + " times"; freq5 = " 6 Occurs: " + hitSix + " times"; freq6 = " 7 Occurs: " + hitSeven + " times";
freq7 = " 8 Occurs: " + hitEight + " times"; freq8 = " 9 Occurs: " + hitNine + " times"; freq9 = " 10 Occurs: " + hitTen + " times";
freq10 = " 11 Occurs: " + hitEleven + " times"; freq11 = " 12 Occurs: " + hitTwelve + " times";
frequency.Items.Add(freq1); frequency.Items.Add(freq2); frequency.Items.Add(freq3); frequency.Items.Add(freq4); frequency.Items.Add(freq5);
frequency.Items.Add(freq6); frequency.Items.Add(freq7); frequency.Items.Add(freq8); frequency.Items.Add(freq9); frequency.Items.Add(freq10);
frequency.Items.Add(freq11);
}
Roll_Click does way too much work.
First, create a GatherSamples function.
int[] GatherSamples()
{
var rolls = new List<int>();
// roll dice ...
return rolls.ToArray();
}
Then a DisplayRolls method
void DisplayRolls(int[] rolls)
{
// output to your control
}
... and a WriteToDisk method
void WriteToDisk(int[] rolls, string file)
{
using (var writer = new StreamWriter(file)) // research C# using if you don't understand this
{
...
}
}
... then do your frequency analysis
string[] AnalyzeRolls(int[] rolls)
{
// though I don't approve of 11 counters, use them here
return new [] { "2 occurs " ... };
}
... then call it like so:
foreach(var analysis in AnalyzeRolls(rolls))
{
frequency.Items.Add(analysis);
}
Here you go. One 6-sided dice roller. It knows nothing about user interface. It exposes almost nothing about its internal implementation.
class SixSidedDiceRoller
{
private static readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
private SortedDictionary<int,int> frequencyTable;
private List<Tuple<int,int,int>> rollHistory;
public int Count { get { return rollHistory.Count; } }
public IEnumerable<Tuple<int , int , int>> RollHistory
{
get { return rollHistory.AsReadOnly(); }
}
public IEnumerable<Tuple<int,int>> FrequencyTable
{
get
{
return frequencyTable.Select(
x => new Tuple<int,int>(x.Key,x.Value)
) ;
}
}
public SixSidedDiceRoller()
{
rollHistory = new List<Tuple<int , int , int>>();
// initialize the frequency table
for ( int i = 2 ; i <= 12 ; ++i )
{
frequencyTable[i] = 0;
}
return;
}
public int RollDice()
{
int d1 = RollDie();
int d2 = RollDie();
int n = d1 + d2;
rollHistory.Add( new Tuple<int , int , int>( d1 , d2 , n ) );
++frequencyTable[n];
return n;
}
private int RollDie()
{
byte[] octets = new byte[1];
rng.GetBytes( octets );
int die = 1 + ( octets[0] % 6 );
return die;
}
}
Shouldn't be too hard to wire that up to a windows app, wpf app, web app, console app, etc.
Related
I'm making a simple game in C# where the player fights until they have no more health:
public void FightLoop(int currentHealth) {
bool death = false;
do{
hit = false;
if(currentHealth == 0){
death = true;
}
turn = turn + 1;
string turnRecord = turn.ToString();
string firstPlayerChoiceString = GetPlayerInput();
string secondPlayerChoiceString = GetRandomWeapon ();
string gameResult = DetermineWinner(firstPlayerChoiceString, secondPlayerChoiceString, currentHealth, turnRecord);
if(hit == true){
currentHealth = currentHealth - 1;
}
FightRecord();
AddRecord(firstPlayerChoiceString, secondPlayerChoiceString, gameResult, turnRecord, turn);
}while (death == false);
DisplayFightHistory ();
}
At the end of each fight, a summary of the whole thing should be shown (array with turns, attacks and results).
public void FightRecord(int recordSize = 100)
{
try
{
fightRecordSize = recordSize;
fightRecord = new string[fightRecordSize, 4];
}
catch (OverflowException e)
{
System.Console.WriteLine("OverflowException during FightRecord initialization: \"{0}\"\nrecordSize given was [{1}]\nSetting recordSize to 10", e.Message, recordSize);
fightRecordSize = 100;
fightRecord = new string[fightRecordSize, 4];
}
fightRecordCurrentSize = fightRecordCurrentSize++;
}
public void AddRecord(string playerOneChoice, string playerTwoChoice, string gameResult, string turnRecord, int turn)
{
// Insert the record data
fightRecord[fightRecordCurrentIndex, 0] = playerOneChoice;
fightRecord[fightRecordCurrentIndex, 1] = playerTwoChoice;
fightRecord[fightRecordCurrentIndex, 2] = gameResult;
fightRecord[fightRecordCurrentIndex, 3] = turnRecord;
// Increment the fight index counter and current history size
fightRecordCurrentIndex = (fightRecordCurrentIndex + 1) % fightRecordSize;
if (fightRecordCurrentSize < fightRecordSize)
{
fightRecordCurrentSize++;
}
}
public void DisplayFightHistory () {
System.Console.WriteLine ("\nPodsumowanie:");
for (int i = 0; i < fightRecordCurrentSize; i++){
System.Console.WriteLine ("Tura #{0}:\t{1}\t-\t{2},\t{3} {4}",
fightRecord[i,3], fightRecord[i,0], fightRecord[i,1], fightRecord[i,2], i);
}
}
However, every time I get only the last value, like this:
Summary:
Turn #: - ,
Turn #: - ,
Turn #: - ,
Turn #: - ,
Turn #: - ,
Turn #: - ,
Turn #8: Sword - Spear, You lose
By following the whole process of creating the array, it seems like the values are being put in it correctly at first, but with each new turn, only the last value remains.
Does anyone have any idea why it's happening?
Use the loop variable as the index.
Change
fightRecord[displayRecordIndex,3], fightRecord[displayRecordIndex,0], fightRecord[displayRecordIndex,1], fightRecord[displayRecordIndex,2], displayRecordIndex);
To
fightRecord[i,3], fightRecord[i,0], fightRecord[i,1], fightRecord[i,2], i);
I generating millions of bmp by Imagemagick in linux with multi-threaded code but for some reason I get one of these errors(without stack trace) which I can't handle:
dotnet: MagickCore/pixel.c:138: ClonePixelChannelMap: Assertion 'channel_map != (PixelChannelMap *) NULL' failed.
or
dotnet: MagickCore/semaphore.c:452: UnlockSemaphoreInfo: Assertion 'semaphore_info != (SemaphoreInfo *) NULL' failed.
or
dotnet: MagickCore/option.c:2137: CloneImageOptions: Assertion 'clone_info->signature == MagickCoreSignature' failed.
My try - catch block doesn't handle these errors so my program closes immediately.
The errors are very random because the same input for Imagemagick in another attempt passes without error.
I use Include="Magick.NET-Q16-x64" Version="7.11.0.0"
I also try "Magick.NET-Q8-x64" and previous versions of imagemagic with the same results.
Linux 4.18.0-3-amd64 #1 SMP Debian 4.18.20-2 (2018-11-23) x86_64 GNU/Linux
Here is code from thread(I run app with 9 threads)
public virtual void GeneratePictureForCurrSpin()
{
do
{
GenerateInternal();
} while (!isAllPicturesGenerated());
}
public override void GenerateInternal()
{
symbols = symbolParser.ParseSymbols(config, spins[currLocalSpin].symbols);
img = (MagickImage)SpinGenerator.rl.emptyImg.Clone();
bgImg = SpinGenerator.rl.bg;
img.Composite(bgImg, new PointD(config.BgX, config.BgY),ImageMagick.CompositeOperator.Over);
reelsBgImg = SpinGenerator.rl.reelsBg;
img.Composite(reelsBgImg, CompositeOperator.Over);
PointD startPoint = new PointD(config.StartOffsetX, config.StartOffsetY);
MagickImage sym;
for(int i = 0; i < symbols.Count; i++)
{
List<int> symbolsOnReel = symbols[i];
for(int j = 0; j < symbolsOnReel.Count; j++)
{
var newPoint = new PointD(startPoint.X + i * (config.SymbolWidth + config.OffsetX), startPoint.Y + j * (config.SymbolHeight + config.OffsetY));
sym = SpinGenerator.rl.symbols[symbolsOnReel[j]-1];
img.Composite(sym, newPoint, ImageMagick.CompositeOperator.Over);
}
}
bool isFreeSpin = (spins[currLocalSpin].betValue == 0)?true:false;
GenerateBottomBar(isFreeSpin);
ShowTokensValue(spins[currLocalSpin].coins);
ResizeImage();
int fileNr = spins[currLocalSpin].spinNr;
String dir = "Resources/Result/" + GAME_NAME + "/" + betValue;
SaveImg(dir , fileNr);
img.Dispose();
IncrementSpinValues();
}
public virtual void GenerateBottomBar(bool isFreeSpin)
{
var pos = (isFreeSpin)?1:0;
bottomBar = SpinGenerator.rl.bottomBars[pos];
PointD startPoint = new PointD(0,config.BgHeight);
img.Composite(bottomBar,startPoint);
}
private void ShowTokensValue(int tokens)
{
if(tokens < 10)
{
var tokenValueImg = SpinGenerator.rl.tokensValues[tokens];
tokenValueImg.Resize(90,60);
img.Composite(tokenValueImg, new PointD(tokenValueStartX + tokenValueImgWidth, tokenValueStartY),ImageMagick.CompositeOperator.Over);
}
else{
int a = tokens / 10;
int b = tokens % 10;
var tokenValueImgA = SpinGenerator.rl.tokensValues[a];
tokenValueImgA.Resize(90,55);
img.Composite(tokenValueImgA, new PointD(tokenValueStartX, tokenValueStartY),ImageMagick.CompositeOperator.Over);
var tokenValueImgB = SpinGenerator.rl.tokensValues[b];
tokenValueImgB.Resize(90,55);
img.Composite(tokenValueImgB, new PointD(tokenValueStartX+ tokenValueImgWidth, tokenValueStartY),ImageMagick.CompositeOperator.Over);
}
var tokensTxtImg = SpinGenerator.rl.tokensTxt;
img.Composite(tokensTxtImg, new PointD(tokenTxtStartX, tokenTxtStartY),ImageMagick.CompositeOperator.Over);
}
internal void ResizeImage()
{
img.Format = ImageMagick.MagickFormat.Bmp3;
img.Depth = 16;
img.Resize(new MagickGeometry("600, 450!"));
//img.Quality = 100;
}
internal void SaveImg(String dir , int fileNr)
{
System.IO.Directory.CreateDirectory(dir);
img.Write(dir + "/" +"s" + fileNr + ".bmp");
ClearImg();
}
internal virtual void IncrementSpinValues()
{
currLocalSpin++;
currSpin++;
}
I am currently working on a CNN that can tell the difference between a dog and a cat. This is the code I have worked out so far:
public bool trained = false;
public BasicNetwork network;
public Form1()
{
InitializeComponent();
}
[..]
private void trainNN()
{
double[][] input = LoadImages();
double[][] ideal = LoadIdeal();
var trainingSet = new BasicMLDataSet(input, ideal);
var train = new ResilientPropagation(network, trainingSet);
network = CreateNetwork();
}
private double[][] LoadImages()
{
status.Text = "Loading images...";
String[] dogimgs = Directory.GetFiles(Directory.GetCurrentDirectory() + "\\dog_img\\", "*", SearchOption.TopDirectoryOnly);
String[] catimgs = Directory.GetFiles(Directory.GetCurrentDirectory() + "\\cat_img\\", "*", SearchOption.TopDirectoryOnly);
int dogimgscount = dogimgs.Length;
int catimgscount = catimgs.Length;
int totalimgscount = dogimgscount + catimgscount;
double[][] images = new double[totalimgscount][];
for (int dogloop = 0; dogloop < dogimgscount; dogloop++)
{
status.Text = "Loading images... [" + (dogloop + 1) + "/" + totalimgscount + "]";
images[dogloop] = Image2Matrix(new Bitmap(dogimgs[dogloop]));
}
for (int catloop = 0; catloop < catimgscount; catloop++)
{
status.Text = "Loading images... [" + (catloop + dogimgscount) + "/" + totalimgscount + "]";
images[catloop + dogimgscount - 1] = Image2Matrix(new Bitmap(catimgs[catloop]));
}
status.Text = "Images loaded.";
return images;
}
private double[][] LoadIdeal()
{
String[] dogimgs = Directory.GetFiles(Directory.GetCurrentDirectory() + "\\dog_img\\", "*", SearchOption.TopDirectoryOnly);
String[] catimgs = Directory.GetFiles(Directory.GetCurrentDirectory() + "\\cat_img\\", "*", SearchOption.TopDirectoryOnly);
int dogimgscount = dogimgs.Length;
int catimgscount = catimgs.Length;
int totalimgscount = dogimgscount + catimgscount;
double[][] ideal = new double[totalimgscount][];
for (int dogloop = 0; dogloop < dogimgscount; dogloop++)
{
ideal[dogloop] = new[] { 0.0, 1.0 };
}
for (int catloop = 0; catloop < catimgscount; catloop++)
{
ideal[catloop + dogimgscount - 1] = new[] { 1.0, 0.0 };
}
return ideal;
}
I know this might not be the smartest way to load the images, but I just want to see the concept work before I start boosting performance. My problem is the following: If I put 4 images, 2 in dog_img, 2 in cat_img, the program loads the images fine and both the input and the ideal array have a length of 4 and they both are filled with double values. But on the line
var trainingSet = new BasicMLDataSet(input, ideal);
the program throws a NullPointerException Error. Both arrays are clearly initialised and not null or empty, yet it still throws the error. Any help is appreciated. Thank you.
FritzFurtz
Encog does not support CNN's, all input to Encog neural networks are 1D vectors. So, if you want to feed an image to Encog, you need to squash it to a 1D vector and wrap it in a BasicMLData object. Encog is probably not the best solution for computer vision/CNN. For C#, I would look at CNTK.
This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 8 years ago.
Many times I had to create lists of structures to store my data in C#. But this time, I have an error, "Index Out of Range". I don't quite understand why, since I already did similar projects, but I would be very appreciated if someone could help me.
class mng
{
int day = 0;
List<Despesas> dias = new List<Despesas>();
public struct Despesas
{
public double transportes;
public double alimentacao;
public double vestuario;
public double agua;
public double luz;
public double educacao;
}
public mng ()
{
}
(This is where I get the error)
public void showMessage()
{
for (int i = 0; i < 31; i++)
{
MessageBox.Show("Água: " + dias[i].agua + "\nTransportes: " + dias[i].transportes);
}
}
and on Form1:
double transportes = Convert.ToDouble(txtTransportes.Text);
double agua = Convert.ToDouble(txtAgua.Text);
mng mngV = new mng(transportes, agua, educacao);
if (day < 31)
{
button1.Enabled = false;
//this is the button that enables the ShowMessage() Method.
}
else
{
button1.Enabled = true;
}
I never execute the method showMessage() before the List has 31 values, so why is it out of Index? I tried to search on the site first but couldn't find any questions with a similar problem although there are a lot with the same error.
I changed the overload constructor to:
public mng(double transportes, double agua)
{
Despesas dia = new Despesas();
dia.transportes = transportes;
dia.agua = agua;
dias.Add(dia);
MessageBox.Show("Added: " + dias.Count);
day++;
}
and guess what, the dias.Count is always 1. I don't understand why...
Try changing your method to:
public void showMessage()
{
for (int i = 0; i < dias.Count; i++)
{
MessageBox.Show("Água: " + dias[i].agua + "\nTransportes: " + dias[i].transportes);
}
}
What about trying this:
public void showMessage()
{
for (int i = 0; i < dias.Count; i++)
{
MessageBox.Show("Água: " + dias[i].agua + "\nTransportes: " + dias[i].transportes);
}
}
or even better:
public void showMessage()
{
foreach(var d in dias)
{
MessageBox.Show(... + d.agua + .... + d.transportes);
}
}
Just change your code this way:
for (int i = 0; i < dias.Count; i++)
And you can check it under the debugger to verify how many items are there in the array when the loop is running.
make sure that dias has 31 values.you can use foreach instead of for as it will give the the same result with much better performance
foreach(var item in dias )
{
MessageBox.Show("Água: " + item.agua + "\nTransportes: " + item.transportes);
}
if you are using for- than problem is because your list might not filled properly have less items
I'm very much a vb person, but have had to use this id number class in c#. I got it from http://www.codingsanity.com/idnumber.htm :
namespace Utilities
{
[Serializable]
public class IdentityNumber
{
public enum PersonGender
{
Female = 0,
Male = 5
}
public enum PersonCitizenship
{
SouthAfrican = 0,
Foreign = 1
}
static Regex _expression;
Match _match;
const string _IDExpression = #"(?<Year>[0-9][0-9])(?<Month>([0][1-9])|([1][0-2]))(?<Day>([0-2][0-9])|([3][0-1]))(?<Gender>[0-9])(?<Series>[0-9]{3})(?<Citizenship>[0-9])(?<Uniform>[0-9])(?<Control>[0-9])";
static IdentityNumber()
{
_expression = new Regex(_IDExpression, RegexOptions.Compiled | RegexOptions.Singleline);
}
public IdentityNumber(string IDNumber)
{
_match = _expression.Match(IDNumber.Trim());
}
public DateTime DateOfBirth
{
get
{
if(IsUsable == false)
{
throw new ArgumentException("ID Number is unusable!", "IDNumber");
}
int year = int.Parse(_match.Groups["Year"].Value);
// NOTE: Do not optimize by moving these to static, otherwise the calculation may be incorrect
// over year changes, especially century changes.
int currentCentury = int.Parse(DateTime.Now.Year.ToString().Substring(0, 2) + "00");
int lastCentury = currentCentury - 100;
int currentYear = int.Parse(DateTime.Now.Year.ToString().Substring(2, 2));
// If the year is after or at the current YY, then add last century to it, otherwise add
// this century.
// TODO: YY -> YYYY logic needs thinking about
if(year > currentYear)
{
year += lastCentury;
}
else
{
year += currentCentury;
}
return new DateTime(year, int.Parse(_match.Groups["Month"].Value), int.Parse(_match.Groups["Day"].Value));
}
}
public PersonGender Gender
{
get
{
if(IsUsable == false)
{
throw new ArgumentException("ID Number is unusable!", "IDNumber");
}
int gender = int.Parse(_match.Groups["Gender"].Value);
if(gender < (int) PersonGender.Male)
{
return PersonGender.Female;
}
else
{
return PersonGender.Male;
}
}
}
public PersonCitizenship Citizenship
{
get
{
if(IsUsable == false)
{
throw new ArgumentException("ID Number is unusable!", "IDNumber");
}
return (PersonCitizenship) Enum.Parse(typeof(PersonCitizenship), _match.Groups["Citizenship"].Value);
}
}
/// <summary>
/// Indicates if the IDNumber is usable or not.
/// </summary>
public bool IsUsable
{
get
{
return _match.Success;
}
}
/// <summary>
/// Indicates if the IDNumber is valid or not.
/// </summary>
public bool IsValid
{
get
{
if(IsUsable == true)
{
// Calculate total A by adding the figures in the odd positions i.e. the first, third, fifth,
// seventh, ninth and eleventh digits.
int a = int.Parse(_match.Value.Substring(0, 1)) + int.Parse(_match.Value.Substring(2, 1)) + int.Parse(_match.Value.Substring(4, 1)) + int.Parse(_match.Value.Substring(6, 1)) + int.Parse(_match.Value.Substring(8, 1)) + int.Parse(_match.Value.Substring(10, 1));
// Calculate total B by taking the even figures of the number as a whole number, and then
// multiplying that number by 2, and then add the individual figures together.
int b = int.Parse(_match.Value.Substring(1, 1) + _match.Value.Substring(3, 1) + _match.Value.Substring(5, 1) + _match.Value.Substring(7, 1) + _match.Value.Substring(9, 1) + _match.Value.Substring(11, 1));
b *= 2;
string bString = b.ToString();
b = 0;
for(int index = 0; index < bString.Length; index++)
{
b += int.Parse(bString.Substring(index, 1));
}
// Calculate total C by adding total A to total B.
int c = a + b;
// The control-figure can now be determined by subtracting the ones in figure C from 10.
string cString = c.ToString() ;
cString = cString.Substring(cString.Length - 1, 1) ;
int control = 0;
// Where the total C is a multiple of 10, the control figure will be 0.
if(cString != "0")
{
control = 10 - int.Parse(cString.Substring(cString.Length - 1, 1));
}
if(_match.Groups["Control"].Value == control.ToString())
{
return true;
}
}
return false;
}
}
}
}
Can someone please tell the syntax for how I pass an id number to the class?
You'll have to use the constructor.
var someNumber = new IdentityNumber("123456");
Then, you can use the properties of that class to find out the specifics of that Id number.
Console.WriteLine (someNumber.DateOfBirth);
Console.WriteLine (someNumber.Gender);
Console.WriteLine (someNumber.Citizenship);
Console.WriteLine (someNumber.IsValid);
Console.WriteLine (someNumber.IsUsable);
IdentityNumber number = new IdentityNumber("123456");
All you need is to use provided Constructor like
IdentityNumber someNumber = new IdentityNumber("006834");