Two Picture Boxes that cycle through images on each button click - c#

When I say I'm a beginner, I really am as fresh as you can get so apologies up front!
What I am trying to do is in a form have two picture boxes and a button. When I click on the button it picks 2 new images from my image folder and it will do this a total of 5 times
Any ideas how I approach this - Here's what I have so far for the button click
private void button1_Click(object sender, EventArgs e)
{
pictureBox1.Load(#"C:\Resources\PICT01.JPG");
pictureBox2.Load(#"C:\Resources\PICT02.JPG");
}
Any answers really need to be basic as I am just learning ! Thanks in advance

You need to create a global int to keep track of how often you have switched pictures, and handle that number in your button1_click.
I'm no expert myself but here's how i would do it. A switch is ideal here because you need to check 5 different possibilities.
//global int
int count = 0;
private void button1_Click(object sender, EventArgs e)
{
count++;
switch(count)
{
case 1:
//load image 1 and 2
break;
case 2:
//load image 3 and 4
break;
case 3:
//load image 5 and 6
break;
case 4:
//load image 7 and 8
break;
case 5:
//load image 9 and 10
break;
default:
break;
}
}

This sample program will create a list of all jpg-files in MyPictures folder and pick random pictures from the list, when the list is empty it will raise an exception.
public Form1()
{
// Reading pictures from My Pictures:
string path = Environment.GetFolderPath(Environment.SpecialFolders.MyPictures);
DictionaryInfo myPictures = new DictionaryInfo(path);
FPictureFiles = myPictures.GetFiles("*.jpg", SearchOption.AllDirectories).ToList();
}
private List<FileInfo> FPictureFiles;
private Random FRandom = new Random();
private void button1_Click(object sender)
{
pictureBox1.Load(PickFile());
pictureBox2.Load(PickFile());
}
private string PickFile()
{
if (FPictureFiles.Count == 0) throw new Exception("No more picture files");
int index = FRandom.Next(FPictureFiles.Count);
string filename = FPictureFiles[index].FullName;
FPictureFiles.RemoveAt(index);
return filename;
}
I hope this will help you in your quest.

You may try to create a new List<string> which lists all files having a specific extension of your selection. Then, initialize a new Random class which gets a random number within a specific range considering that the range will not be more than our List<string>.Count value.
Example
Assuming that CurrentClicks identifies a new integer and MaximumClicks is our maximum value
public Form1()
{
InitializeComponent();
button1.Click += new EventHandler(button1_Click); //Link the Click event of button1 to button1_Click
}
const int MaximumClicks = 5; //Initialize a new constant int of value 5 named MaximumClicks
int CurrentClicks = 0; //Initialize a new variable of name CurrentClicks as an int of value 0
the following may apply
private void button1_Click(object sender, EventArgs e)
{
if (CurrentClicks < MaximumClicks) //Continue if CurrentClicks is less than 5
{
string FilesPath = #"D:\Resources\International"; //Replace this with the targeted folder
string FileExtensions = "*.png"; //Applies only to .png file extensions. Replace this with your desired file extension (jpg/bmp/gif/etc)
List<string> ItemsInFolder = new List<string>(); //Initialize a new Generic Collection of name ItemsInFolder as a new List<string>
foreach (string ImageLocation in Directory.GetFiles(FilesPath, FileExtensions)) //Get all files in FilesPath creating a new string of name ImageLocation considering that FilesPath returns a directory matching FileExtensions considering that FileExtensions returns a valid file extension within the targeted folder
{
ItemsInFolder.Add(ImageLocation); //Add ImageLocation to ItemsInFolder
}
Random Rnd = new Random(); //Initialize a new Random class of name Rnd
int ImageIndex = Rnd.Next(0, ItemsInFolder.Count); //Initialize a new variable of name ImageIndex as a random number from 0 to the items retrieved count
pictureBox1.Load(ItemsInFolder[ImageIndex]); //Load the random image based on ImageIndex as ImageIndex belongs to a random index in ItemsInFolder
CurrentClicks++; //Increment CurrentClicks by 1
}
else
{
//Do Something (MaximumClicks reached)
}
}
This will get the file locations within the provided folder matching a specified extension. Then, loads a random file from the file locations gathered into a PictureBox of name pictureBox1.
This will however not avoid files that were added previously to the PictureBox. If you would like to avoid duplicates, you may create a new int array or List<int> and add every ImageIndex that was applied to the PictureBox but it's recommended to go with List<int> because it seems easier to manage
Example
List<int> AlreadyAdded = new List<int>();
redo:
Random Rnd = new Random();
int ImageIndex = Rnd.Next(0, ItemsInFolder.Count);
if (AlreadyAdded.Contains(ImageIndex)) //Continue within this block if the item already exists in AlreadyAdded
{
goto redo;
}
AlreadyAdded.Add(ImageIndex); //Add ImageIndex to AlreadyAdded
Thanks,
I hope you find this helpful :)

Related

Random Number Generator using C#

I'm needing to create random numbers based on the number of random numbers needed by a user.
The user can then save those random numbers to a file when the save to file button is clicked.
After that, the program allows the user to open the same file, but this time, the file opened needs to display how many random numbers within a specific range were created.
The ranges are: (0-19, 20-39, 40-59, 60-79, and 80-99).
So far I'm able to create one random number and list the same number over the number of times entered by the user, but unfortunately:
The random numbers created need to all be random through the number of iterations created by the user.
I don't know how to display the numbers within their respective range.
I can't display the numbers properly.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void RandNumbtextBox_TextChanged(object sender, EventArgs e)
{
}
private void saveFileButton_Click(object sender, EventArgs e)
{
double randomNumber = double.Parse(RandNumbtextBox.Text);
Random r = new Random();//random number object
int random = r.Next(1, 10);// random number 1
if (saveFileDialog.ShowDialog()== DialogResult.OK)
{
StreamWriter outputFile;
outputFile = File.CreateText(saveFileDialog.FileName + ".txt");
for(int i = 0; i < randomNumber; i++)
{
outputFile.WriteLine(random.ToString());
}
outputFile.Close();
}
else
{
MessageBox.Show("op cancelled");
}
}
private void openFileButton_Click(object sender, EventArgs e)
{
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
StreamReader inputFile;
inputFile = File.OpenText(openFileDialog.FileName);
int sum = 0;
while (!inputFile.EndOfStream)
{
sum += int.Parse(inputFile.ReadLine());
}
inputFile.Close();
MessageBox.Show(sum.ToString());
}
else
{
MessageBox.Show("op cancelled");
}
}
}
Thanks to John I was able to figure out the first issue of the question. Generating the random number issue and write them to file.
I'm still unable to:
*Display the numbers within their respective range.
I can't display the numbers properly.
OP, you are assigning the random number once:
int random = r.Next(1, 10);// random number 1
And then writing it out randomNumber times:
for(int i = 0; i < randomNumber; i++)
{
outputFile.WriteLine(random.ToString());
}
I think your code needs to read:
for(int i = 0; i < randomNumber; i++)
{
outputFile.WriteLine(r.Next(1, 10).ToString());
}
As for counting numbers in ranges: A simple approach might be to create "count" variables for each range, and implement branching logic to increment the correct one depending on the number you're looking at. A more dynamic approach may involve a dictionary, or an array of classes which contain the range and a count value.

How do I load the dataGridView1 with the contents of an array at runtime

Note: in converting my long untidy code into pseudo-code I have not explained that I want to return an array/list that contains the data that as been loaded into arFiles.
That is what line...
// look at the contents of each file and store selected information in
means.
I have simple form with a button to load a directory of files
and scan them and load an array with the selected data at runtime.
How do I load the dataGridView1 with the contents of an array?
I have searched the web and cannot find a method to do it at runtime.
The examples I have seen assume one is loading static data.
Please be gentle with me as I have not coded for approx 10 years.
private void btnReadLogFiles_Click(object sender, EventArgs e)
{
string[,] arFiles;
arFiles = this.getFileInfo();
// watch window shows arFiles is loaded correctly
// how do I load a dataGridView1 with the data from the array at runtime?
}
private string[,] getFileInfo()
{
string[] oFiles = Directory.GetFiles(sPath, "*.csv");
nColumns = 4;
nRows = Directory.GetFiles(sPath, "*.csv").Length;
// create an array of rows that matches the files in the directory
string[,] arFiles = new string[nRows, 4];
// look at the contents of each file and store selected information in arFiles.
return arFiles;
}
Unfortunately if you just assign an array of strings into DataGridView the result might not be the one you expect. Therefore, you can workaround this via converting the array of strings into list of anonymous objects and then assign it to the DataGridView
Example:
private void button1_Click(object sender, EventArgs e)
{
this.dataGridView1.DataSource = GetFileInfo();
}
private List<object> GetFileInfo()
{
string[] allPaths = Directory.GetFiles(#"C:\Program Files (x86)\Microsoft Visual Studio 10.0", "*.txt", SearchOption.AllDirectories);
List<object> list = new List<object>();
foreach (var path in allPaths)
{
// Create a new anonymous object
list.Add(new { File = Path.GetFileName(path) });
}
return list;
}
Result:
The following code will put the files into 4 columns
private List<List<string>> getFileInfo()
{
List<List<string>> arFiles = new List<List<string>>();
string[] oFiles = Directory.GetFiles(sPath, "*.csv");
nColumns = 4;
List<string> newRow = null;
for(int index = 0; index < oFiles.Count(); index++)
{
if ((index % nColumns) == 0)
{
newRow = new List<string>();
arFiles.Add(newRow);
}
newRow.Add(oFiles[index]);
}
return arFiles;
}

slot machine game c# image Values

im doing a slot machine game , its a simple one , that basically it will roll the image in the picurebox into a random image. using this code
PictureBox[] PictureboxArray = new PictureBox[5];
the 5 picureboxes are assigned using this line of code
PictureboxArray[0] = pbxK;
PictureboxArray[1] = pbxQueen;
PictureboxArray[2] = pbxKing;
PictureboxArray[3] = pbxJoker;
PictureboxArray[4] = pbxAce;
Images are assigned like that
Image[] Rollimage = new Image[5];
Rollimage[0] = Properties.Resources.K;
Rollimage[1] = Properties.Resources.Queen;
Rollimage[2] = Properties.Resources.King;
Rollimage[3] = Properties.Resources.Joker;
Rollimage[4] = Properties.Resources.Ace;
and the intial image of the picturebox are assigned like that
pbxK.Image = Rollimage[0];
pbxQueen.Image = Rollimage[1];
pbxKing.Image = Rollimage[2];
pbxJoker.Image = Rollimage[3];
pbxAce.Image = Rollimage[4];
the actual code for the image rolling is as follows
for (int i = 0; i <= 4; i++)
{
if (PictureboxArray[i].Enabled == true)
{
Roll[i] = Rnd.Next(0, 4);
}
PictureboxImage(PictureboxArray[i], Roll[i]);
}
rnd is a new random
Random Rnd = new Random();
Roll in an int for saving the index of the roll
int[] Roll = new int[5];
everything works fine and the pictures rolls different image every second of the time , as I predefined that, now what im trying to do is to assign this
int[] PictureValues = new int[]{100, 225, 550, 775, 1000};
to the images
Image[] Rollimage = new Image[5];
meaning that the first roll image which is Properties.Resources.K;has the actual value of 100
and so on , is there a way to do that ?
So.. if I understand your issue correctly, once the image is selected, you need a way to reverse it back to associate it with a value. One method could be the following:
Note: It appears that each picturebox that is showing, is named king / joker etc.. so if you are looking at the front of the 'slot machine' you see 5 boxes which are named pbxk, pbxQueen, pbxKing, pbxJoker, pbxAce but they don't necessarily display the image associated with their name..
int total = 0;
for(int i=0;i<Rollimage.Length;i++)
{
if(pbxk.Image.Equals(Rollimage[i]))
{
total += PictureValues[i];
}
if(pbxQueen...)
{
//Do the same thing for each pbx
}
}
The only thing I'm not 100% on is the comparison method. Additionally, you could use the picturebox's ImageLocation property to store the path to the image whenever you assign it, and then compare that against a filename to figure out what image is showing.
Example on how to compare images: Stack Overflow Image Compare
Given that example, you may want to try == using your current Image array.. if that doesn't work, you may need to define an array of bitmaps to compare against. Seems like a waste of memory to me, but it should work.
Edit
The following code sums the values of the images correctly. I just put together a quick sample program with 2 pictureboxes, a control button and a label, with two resources. This should demonstrate all of the techniques required to perform what you are needing.
public partial class Form1 : Form
{
PictureBox[] PictureboxArray = new PictureBox[2];
Image[] Rollimage = new Image[2];
int[] pictureValues = new int[2];
public Form1()
{
InitializeComponent();
pictureValues[0] = 100;
pictureValues[1] = 200;
Rollimage[0] = Properties.Resources.TitleBar;
Rollimage[1] = Properties.Resources.Untitled;
PictureboxArray[0] = this.pictureBox1;
PictureboxArray[1] = this.pictureBox2;
PictureboxArray[1].Image = Rollimage[0];
PictureboxArray[0].Image = Rollimage[0];
}
private void button1_Click(object sender, EventArgs e)
{
int total = 0;
for(int i = 0;i<Rollimage.Length;i++)
{
foreach(var box in PictureboxArray)
{
if(box.Image == Rollimage[i])
{
total += pictureValues[i];
}
}
}
label1.Text = total.ToString();
}
}

Application only works correctly if I have messagebox in the code

I have a button event in which generates some random numbers based upon the number typed into a textbox (for example, if I type 5, it should generate 5 different random numbers). When I type in a number into the textbox, and click the btnGenerateScores button, it generates a single number and puts that number in the listbox 5 times (or however many times based upon the number in the textbox). This behavior is not correct, it should generate 5 different numbers and list each in the listbox. If I put a MessageBox.Show (I was using it for debugging) command anywhere in the code block, it works correctly. Commenting out the MessageBox.show breaks the code. Does anyone see any reason why it would not work correctly when I don't show the message box? The code is below:
private void btnGenerateScores_Click(object sender, EventArgs e)
{
strInput = txtInputNumber.Text;
intRandCount = Convert.ToInt16(strInput);
scoresArray = new int[intRandCount];
intArrayCount = scoresArray.Length;
btnGenerateScores.Enabled = false;
// Loop to generate random number
for (intRndCount = 0; intRndCount < intRandCount; intRndCount++)
{
GetRand(intRandCount);
scoresArray[intCount] = intRandomNum;
intGenRandom = intRandomNum;
intArrScores = scoresArray[intCount];
lstRdmScores.Items.Add(Convert.ToString(intArrScores));
insertionSortArray = new int[intArrayCount];
Array.Copy(scoresArray, insertionSortArray, intArrayCount);
// Instantiate an instance of the class
arraySort mySort = new arraySort();
// Get the number of elements to store in the array
string s = Convert.ToString(intCount);
mySort.x = Int16.Parse(s);
// Get array elements
for (int i = 0; i < mySort.x; i++)
{
intInsertionSort = insertionSortArray[intCount];
string s1 = Convert.ToString(intInsertionSort);
mySort.a[i] = Int16.Parse(s1);
}
// Sort the array and display in the second list box
mySort.sortArray();
intSortScores = insertionSortArray[intCount];
lstSortScores.Items.Add(Convert.ToString(intSortScores));
// This is the the MessageBox.Show command in question:
MessageBox.Show("The random number generated is: "); //+ Convert.ToString(intGenRandom));
}
}
ignore the fact that the array does not sort correctly, I will get to that later. I want to work on one thing at a time.
I am using VS 2013 and the code was originally created in VS 2005.
As your requirement, and view the source, I rewrite the app for short:
private void btnGenerateScores_Click_1(object sender, EventArgs e)
{
int genTimes;
if (Int32.TryParse(txtInputNumber.Text, out genTimes))
{
var ints = new List<int>();
for (var i = 0; i < genTimes; i++)
{
var r = new Random(Guid.NewGuid().GetHashCode());
var rInt = r.Next(0, int.MaxValue); //for ints
ints.Add(rInt);
}
var copyInts = ints.ToList();
copyInts.AddRange(this.listBox1.Items.Cast<int>());
copyInts = copyInts.Distinct().OrderBy(x => x).ToList();
this.listBox1.Items.Clear();
this.listBox1.Items.AddRange(copyInts.Cast<object>().ToArray());
MessageBox.Show("The random number generated is: " + String.Join(",", ints));
}
}
}
Hope this help.

how to fill int array that has unique numbers in every index? [duplicate]

This question already has answers here:
Random number generator in C# - unique values
(5 answers)
Closed 9 years ago.
I'm creating a bingo game and I'm using Random to generate random numbers in an int array but my problem here is that sometimes a number is used again in an index. How can I make the numbers in index unique?
Here is my work:
namespace Bingo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Random randNum1 = new Random();
int[] random1 = new int[5];
int qwe = 0;
int i = 0;
private void button1_Click(object sender, EventArgs e)
{
Class1 class1 = new Class1();
class1.checker(this);
if (label1.Text == label2.Text || label3.Text == label4.Text) {
label2.Text = randNum1.Next(1, 15).ToString();
label4.Text = randNum1.Next(1, 15).ToString();
}
if (label5.Text == label1.Text || label5.Text == label2.Text) {
label5.Text = randNum1.Next(1, 15).ToString();
}
}
private void Form1_Load(object sender, EventArgs e)
{
Class1 class1 = new Class1();
class1.SetTwo(this);
for (int i = 0; i < random1.Length; i++)
{
random1[i] = randNum1.Next(1, 15);
label1.Text = random1[0].ToString();
label2.Text = random1[1].ToString();
label3.Text = random1[2].ToString();
label4.Text = random1[3].ToString();
label5.Text = random1[4].ToString();
}
}
}
The problem with looping until you found an unused one is that as the game progresses, you'll take longer and longer to find a valid number. It's theoretically possible that your loop will never end (infinitessimally likely, but still...)
The easiest thing to do is what happens in a real Bingo game. Start from a limited set, and actually remove the item from the set each time you draw. Fill a List or any other dynamic indexed container with your initial possibilities, randomly choose an index from 0 to the size of the list, and then remove the selection out of the list.
This will guarantee that every selection produces a unique result, with no looping.
I figured an illustration of Scott Mermelstein's answer may help:
List<int> AvailableNumbers;
Random random;
private void Form1_Load(object sender, EventArgs e)
{
//Create a list of numbers, 1-14
AvailableNumbers = Enumerable.Range(1, 14).ToList();
random = new Random();
label1.Text = GetNextNumber().ToString();
label2.Text = GetNextNumber().ToString();
label3.Text = GetNextNumber().ToString();
label4.Text = GetNextNumber().ToString();
label5.Text = GetNextNumber().ToString();
}
private int GetNextNumber()
{
//Get a random index within the bounds of AvailableNumbers
var nextIndex = random.Next(0, AvailableNumbers.Count);
var nextNumber = AvailableNumbers[nextIndex];
AvailableNumbers.RemoveAt(nextIndex);
return nextNumber;
}
Another approach is to shuffle the sorted list of numbers:
var numbers = Enumerable.Range(1, 15).OrderBy(i => Guid.NewGuid()).ToArray();
How does this work?
start with a list of integers (Enumerable.Range(1, 15) => [1, 2, 3, ..., 15])
reorder them (OrderBy)
with a "random" index Guid.NewGuid()
Obviously, this will only work, if Guid.NewGuid() doesn't produce consecutive GUIDs, but, I think the default doesn't, since that was a security issue with the first implementations of the GUID algorithm.
(I got the shuffling with GUIDs tip from here:
Randomize a List<T>)
You can use other, more efficient methods to shuffle the "deck", but for Bingo style applications, this should work just fine.
Another idea:
var rand = new Random();
var numbers = Enumerable.Range(1, 15).OrderBy(i => rand.Next()).ToArray();
Since the elements in the starting list are unique, the result is guaranteed to reproduce that property.
everytime you grab a new number, just surround it with this :
int num;
do
{
num = randNum1.Next(1, 15);
}
while(random1.Contains(num))
random1[i] = num;
to guarantee it is unique

Categories

Resources