Program not drawing graphics - c#

I've been following the instructions for an assignment and I can't see any issues with the code (no error messages and the program runs without crashing), but the program does not draw the graphics. It's supposed to random out 200 random numbers between 1-100, and then sort them into a graph with a bubble sort
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp6
{
public partial class Form1 : Form
{
int[] number = new int[200];
Random generator = new Random();
public Form1()
{
InitializeComponent();
}
private void btnGenerate_Click(object sender, EventArgs e)
{
for (int i = 0; i < number.Length; i++)
{
number[i] = generator.Next(1, 101);
}
Invalidate();
}
private void btnSort_Click(object sender, EventArgs e)
{
BubbleSort(number);
Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
//Assigns origo
Point origo = new Point(40,150);
//Draw x and y axes
e.Graphics.DrawLine(Pens.Black, origo.X, origo.Y, origo.X, origo.Y - 100);
e.Graphics.DrawLine(Pens.Black, origo.X, origo.Y, origo.X + 200, origo.Y);
//Draw all points
for(int i = 0; i < number.Length; i++)
{
e.Graphics.FillEllipse(Brushes.Red, origo.X + i, origo.Y - number[i], 2, 2);
}
}
public void BubbleSort(int[] list)
{
for (int m = list.Length - 1; m > 0; m--)
{
for (int n = 0; n < m; n++)
{
if (list[n] > list[n + 1])
{
int temp = list[n];
list[n] = list[n + 1];
list[n + 1] = temp;
}
}
}
}
}
}
The program should draw 200 points when you press the button "Generate" and then sort them into a line/graph when you press "Sort", but the program isn't drawing anything when I press the buttons.

Related

Labels not showing output for random simulation

I have a class project to create a tic tac toe simulations (game is not played by people) where O's and X's automatically generate when the New Game button is clicked. I am having trouble with the code to get the labels to show the output.
Using a 2D array type INT to simulate the game board, it should store a 0 or 1 in each of the 9 elements and produce a O or X. There also needs to be a label to display if X or O wins.
Here is my code so far ( I know there isn't much, I'm completely lost):
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void StartButton_Click(object sender, EventArgs e)
{
Random rand = new Random();
const int ROWS = 3;
const int COLS = 3;
int[,] gameBoard = new int[ROWS, COLS];
for (int row = 0; row < ROWS; row++)
{
for (int col = 0; col < COLS; col++)
{ gameBoard[row, col]= rand.Next(2); }
}
}
private void ExitButton_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
Win Forms labels get populated unless the current event process finishes completely. If you want to update the labels with X and O while you may use the control property InvokeRequired (boolean) and after assigning the value to label call label.Refresh() function. I will suggest fork a thread on hitting start button and do the for loop -> random.next() inside the thread. Try with these changes. All the Best!!
Try following :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
const int ROWS = 3;
const int COLS = 3;
const int WIDTH = 100;
const int HEIGHT = 100;
const int SPACE = 20;
static TextBox[,] gameBoard;
public Form1()
{
InitializeComponent();
gameBoard = new TextBox[ROWS, COLS];
for (int row = 0; row < ROWS; row++)
{
for (int col = 0; col < COLS; col++)
{
TextBox newTextBox = new TextBox();
newTextBox.Multiline = true;
this.Controls.Add(newTextBox);
newTextBox.Height = HEIGHT;
newTextBox.Width = WIDTH;
newTextBox.Top = SPACE + (row * (HEIGHT + SPACE));
newTextBox.Left = SPACE + (col * (WIDTH + SPACE));
gameBoard[row, col] = newTextBox;
}
}
}
}
}

How do I know which card is clicked?

I am making a Memory game in WPF and C#. It is going good till now. When I click (turn) 2 cards, I want my code to register that and when the images don't match then I want the back.png image to come back.
Now my code counts how many times there has been clicked but I don't know how to make the cards "turn" again and to make them go away when 2 images match. I have 16 images, 1 and 9 are pairs, 2 and 10 are pairs, and so on.
My plan was to make a method that is called resetCards().
This is my MainWindow.cs:
public partial class MainWindow : Window
{
private MemoryGrid grid;
public MainWindow()
{
InitializeComponent();
}
private void start_Click(object sender, RoutedEventArgs e)
{
grid = new MemoryGrid(GameGrid, 4, 4);
start.Visibility = Visibility.Collapsed;
}
This is my MemoryGrid.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace SpellenScherm
{
public class MemoryGrid
{
private Grid grid;
private int rows, cols;
public MemoryGrid(Grid grid, int rows, int cols)
{
this.grid = grid;
this.rows = rows;
this.cols = cols;
InitializeGrid();
AddImages();
}
private void InitializeGrid()
{
for (int i = 0; i < rows; i++)
{
grid.RowDefinitions.Add(new RowDefinition());
}
for (int i = 0; i < cols; i++)
{
grid.ColumnDefinitions.Add(new ColumnDefinition());
}
}
private void AddImages()
{
List<ImageSource> images = GetImagesList();
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
Image back = new Image();
back.Source = new BitmapImage(new Uri("/images/back.png", UriKind.Relative));
back.MouseDown += new System.Windows.Input.MouseButtonEventHandler(CardClick);
back.Tag = images.First();
images.RemoveAt(0);
Grid.SetColumn(back, col);
Grid.SetRow(back, row);
grid.Children.Add(back);
}
}
}
static int numberOfClicks = 0;
private void resetCards()
{
}
private void CardClick(object sender, MouseButtonEventArgs e)
{
if (numberOfClicks < 2)
{
Image card = (Image)sender;
ImageSource front = (ImageSource)card.Tag;
card.Source = front;
numberOfClicks++;
}
if (numberOfClicks == 2)
{
resetCards();
numberOfClicks = numberOfClicks -2;
}
}
public List<ImageSource> GetImagesList()
{
List<ImageSource> images = new List<ImageSource>();
List<string> random = new List<string>();
for (int i = 0; i < 16; i++)
{
int imageNR = 0;
Random rnd = new Random();
imageNR = rnd.Next(1, 17);
if (random.Contains(Convert.ToString(imageNR)))
{
i--;
}
else
{
random.Add(Convert.ToString(imageNR));
ImageSource source = new BitmapImage(new Uri("images/" + imageNR + ".png", UriKind.Relative));
images.Add(source);
}
}
return images;
}
}
}
You can try this approach - keep two fields in your MemoryGrid class one for each of the images which show their front faces. (Let's call them Image1 and Image2). Then you can keep a track of which cards are flipped in the whole grid and pass them as arguments to your resetCards method as follows:
private void CardClick(object sender, MouseButtonEventArgs e)
{
if (numberOfClicks < 2)
{
Image card = (Image)sender;
ImageSource front = (ImageSource)card.Tag;
card.Source = front;
if(this.Image1 == null){
Image1 = card;
}
else if(this.Image2 == null){
Image2 = card;
}
numberOfClicks++;
}
if (numberOfClicks == 2)
{
resetCards(Image1, Image2);
numberOfClicks = numberOfClicks -2;
}
}

C# Accessing Dynamic Controls Windows Forms

I am creating a number of comboBoxes based on user input. I create the boxes just fine, but when it comes to wanting to check the text within them I am struggling.
I thought of maybe storing them in a IList but that hasn't seemed to work so far. The goal is to change the text of all of them on a button click, but after several attempts I am becoming frustrated.
IList<ComboBox> comboBoxes = new List<ComboBox>();
private void AddComboBox(int i)
{
var comboBoxStudentAttendance = new ComboBox();
comboBoxStudentAttendance.Top = TopMarginDistance(i);
comboBoxStudentAttendance.Items.Add("");
comboBoxStudentAttendance.Items.Add("Present");
comboBoxStudentAttendance.Items.Add("Absent");
comboBoxStudentAttendance.Items.Add("Late");
comboBoxStudentAttendance.Items.Add("Sick");
comboBoxStudentAttendance.Items.Add("Excused");
comboBoxes.Add(comboBoxStudentAttendance);
this.Controls.Add(comboBoxStudentAttendance);
}
I tried the following but with no success.
private void DistributeAttendanceButton_Click(object sender, EventArgs e)
{
for (int i = 0; i < sampleNum; i++)
{
switch (MasterComboBox.Text)
{
case "Present":
comboBoxes.ElementAt(i).Text = "Present";
break;
}
}
}
Try this
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
const int TOP_MARGIN = 10;
const int LEFT_MARGIN = 10;
const int WIDTH = 200;
const int HEIGHT = 10;
const int SPACE = 15;
const int NUMBER_OF_BOXES = 10;
public Form1()
{
InitializeComponent();
MasterComboBox.Text = "Present";
for (int i = 0; i < NUMBER_OF_BOXES; i++)
{
AddComboBox(i);
}
}
List<ComboBox> comboBoxes = new List<ComboBox>();
private void AddComboBox(int i)
{
var comboBoxStudentAttendance = new ComboBox();
comboBoxStudentAttendance.Top = TOP_MARGIN + i * (SPACE + HEIGHT);
comboBoxStudentAttendance.Left = LEFT_MARGIN;
comboBoxStudentAttendance.Width = WIDTH;
comboBoxStudentAttendance.Height = HEIGHT;
comboBoxStudentAttendance.Items.Add("");
comboBoxStudentAttendance.Items.Add("Present");
comboBoxStudentAttendance.Items.Add("Absent");
comboBoxStudentAttendance.Items.Add("Late");
comboBoxStudentAttendance.Items.Add("Sick");
comboBoxStudentAttendance.Items.Add("Excused");
comboBoxes.Add(comboBoxStudentAttendance);
this.Controls.Add(comboBoxStudentAttendance);
}
private void DistributeAttendanceButton_Click(object sender, EventArgs e)
{
for (int i = 0; i < comboBoxes.Count; i++)
{
switch (MasterComboBox.Text)
{
case "Present":
comboBoxes[i].Text = "Present";
break;
}
}
}
}
}

How to run procedure with parameters in another thread using C#?

I am stuck at trying to call a procedure and use some parameters in a new thread in C#. There is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Random_colored_rectangles
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Thread th;
Random rand;
System.Drawing.Color[] colors = new System.Drawing.Color[5] {Color.Orange, Color.Red, Color.Pink, Color.Black, Color.Gold };
private void DrawColor(Color color)
{
for (int i = 0; i < 100; i++)
{
DrawRectangle(color, 3 , rand.Next(0, this.Width), rand.Next(0, this.Height), 10, 10);
Thread.Sleep(100);
}
MessageBox.Show(color + " done");
}
private void DrawRectangle(Color barva, float width, int pos_x, int pos_y, int size_x, int size_y)
{
Pen myPen = new Pen(barva, width);
Graphics formGraphics;
formGraphics = plocha.CreateGraphics();
formGraphics.DrawRectangle(myPen, new Rectangle(pos_x, pos_y, size_x, size_y));
myPen.Dispose();
formGraphics.Dispose();
}
private void Form1_Load(object sender, EventArgs e)
{
rand = new Random();
}
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.R)
{
th = new Thread(DrawColor);
th.Name = Convert.ToString(threadCount);
threadList.Add(th);
threadCount = threadCount + 1;
th.Start(colors[rand.Next(0, colors.Length)]);
}
}
}
}
This code should (after pressing R) make 100 random colored rectangles (the color is chosen from an array of few colors). But, I am unable to make my thread start the procedure DrawColor with a parameter of the random color select.
Can you please help me?
You could do it by using a Task.
Color theColorToPass = someColor;
Task.Factory.StartNew(color => {
DrawColor(color);
}, theColorToPass);
You could aswell access the array directly from within the Task though. I see no point in passing it to the Thread.
Using the advice of those more familiar with the do's and don'ts of C# (that is not me trying to sound mean or anything), I have devised a way to accomplish what you want without the need of CreateGraphics() or Thread.Sleep(). Unfortunately, this throws an OutOfMemoryException when it hits e.Graphics.DrawRectangle(penToUse, rectanglesToUse[0]);. What does that mean?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace Colors
{
public partial class Form1 : Form
{
Timer timer = new Timer { Interval = 100 };
Random rand = new Random();
Color[] colors = new Color[5]
{
Color.Black,
Color.Blue,
Color.Green,
Color.Purple,
Color.Red
};
List<Pen> usedPens = new List<Pen>();
List<Rectangle> usedRectangles = new List<Rectangle>();
Pen penToUse;
List<Rectangle> rectanglesToUse = new List<Rectangle>();
public Form1()
{
InitializeComponent();
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
penToUse = new Pen(GetRandomColor(), 3);
rectanglesToUse.Clear();
for (int i = 0; i < 100; i++)
rectanglesToUse.Add(GetRandomRectangle());
this.Refresh();
}
}
private Color GetRandomColor()
{
return colors[rand.Next(0, colors.Length)];
}
private Rectangle GetRandomRectangle()
{
return new Rectangle(rand.Next(0, Width), rand.Next(0, Height), 10, 10);
}
protected override void OnPaint(PaintEventArgs e)
{
for (int i = 0; i < usedRectangles.Count; i++)
e.Graphics.DrawRectangle(usedPens[i % 100], usedRectangles[i]);
timer.Tick += delegate
{
if (rectanglesToUse.Count > 0)
{
e.Graphics.DrawRectangle(penToUse, rectanglesToUse[0]);
usedRectangles.Add(rectanglesToUse[0]);
rectanglesToUse.RemoveAt(0);
}
else
{
usedPens.Add(penToUse);
timer.Stop();
}
};
timer.Start();
}
}
}

Assigning indexes to buttons C#

I am working on an application for WP8, in my code I want to assign indexes to buttons like in arrays. Reason is that I want to operate buttons with buttons (i.e one button that is pressed activate other buttons)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace test2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public class LEDButton : Button
{
public const int LEDWidth = 50;
public const int LEDHeight = 30;
public LEDButton()
{
BackColor = Color.Tan;//inner color
//BackColor = Color.FromArgb(0, 64, 0);
ForeColor = Color.Yellow;//outline
FlatStyle = FlatStyle.Popup;//Button style
Size = new Size(LEDWidth, LEDHeight);
UseVisualStyleBackColor = false;
}
}
private void button1_Click(object sender, EventArgs e)
{
LEDButton[,] b = new LEDButton[4, 4];
for (int y = 0; y < b.GetUpperBound(0); y++)
{
for (int x = 0; x < b.GetUpperBound(1); x++)
{
b[y, x] = new LEDButton()
{
//put button properties here
Name = "button" + y.ToString() + x.ToString(),//String.Format("Button{0}{1}", y, x),
TabIndex = 10 * y + x,
Text = y.ToString() + x.ToString(),
Location = new Point(LEDButton.LEDWidth * x + 20, LEDButton.LEDHeight * y + 20)
};
// b[y, x].Click += button_Click;
}
}
// add buttons to controls
for (int y = 0; y < b.GetUpperBound(0); y++)
for (int x = 0; x < b.GetUpperBound(1); x++)
this.Controls.Add(b[y, x]);
}
}
}
If I have understood your question properly, you should rely on an array of delegates. Here you have a correction of your code assigning dynamically 4 different methods to 4 different buttons:
namespace test2
{
public partial class Form1 : Form
{
public delegate void button_click(object sender, EventArgs e);
public static button_click[] clickMethods = new button_click[4];
public Form1()
{
InitializeComponent();
}
public class LEDButton : Button
{
public const int LEDWidth = 50;
public const int LEDHeight = 30;
public LEDButton()
{
BackColor = Color.Tan;//inner color
//BackColor = Color.FromArgb(0, 64, 0);
ForeColor = Color.Yellow;//outline
FlatStyle = FlatStyle.Popup;//Button style
Size = new Size(LEDWidth, LEDHeight);
UseVisualStyleBackColor = false;
}
}
private void Form1_Load(object sender, EventArgs e)
{
clickMethods[0] = buttonGeneric_Click_1;
clickMethods[1] = buttonGeneric_Click_2;
clickMethods[2] = buttonGeneric_Click_3;
clickMethods[3] = buttonGeneric_Click_4;
}
private void buttonGeneric_Click_1(object sender, EventArgs e)
{
}
private void buttonGeneric_Click_2(object sender, EventArgs e)
{
}
private void buttonGeneric_Click_3(object sender, EventArgs e)
{
}
private void buttonGeneric_Click_4(object sender, EventArgs e)
{
}
private void button1_Click_1(object sender, EventArgs e)
{
LEDButton[,] b = new LEDButton[4, 4];
for (int y = 0; y < b.GetUpperBound(0); y++)
{
for (int x = 0; x < b.GetUpperBound(1); x++)
{
b[y, x] = new LEDButton()
{
//put button properties here
Name = "button" + y.ToString() + x.ToString(),//String.Format("Button{0}{1}", y, x),
TabIndex = 10 * y + x,
Text = y.ToString() + x.ToString(),
Location = new Point(LEDButton.LEDWidth * x + 20, LEDButton.LEDHeight * y + 20)
};
if (y <= 3)
{
b[y, x].Click += new System.EventHandler(clickMethods[y]);
}
}
}
// add buttons to controls
for (int y = 0; y < b.GetUpperBound(0); y++)
for (int x = 0; x < b.GetUpperBound(1); x++)
this.Controls.Add(b[y, x]);
}
}
}
--- loop ---
Button abc = new Button();
abc.Name = loopCounter.ToString();
--- loop ---
This will help you to assigning indexes,
Don't use array of Button, it is useless!

Categories