Using a 2d array of buttons implemented and placed on a form.
Button[,] tmpButton = new Button[x, y];
private void DrawGrid()
{
int ButtonWidth = 48;
int ButtonHeight = 48;
int start_x = 88;
int start_y = 200;
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
tmpButton[i, j] = new Button();
tmpButton[i, j].Top = start_x + (i * ButtonHeight);
tmpButton[i, j].Left = start_y + (j * ButtonWidth);
tmpButton[i, j].Width = ButtonWidth;
tmpButton[i, j].Height = ButtonHeight;
tmpButton[i, j].Click += new EventHandler(BTN_Grid_Click);
this.Controls.Add(tmpButton[i, j]);
}
}
}
If a random location (x,y) is set true within the grid with the intention of guessing (by clicking on the surrounding grid buttons) it's location. If the location is !true it should return left right up down pointing to the random location we set earlier. If the true location is up and left, it should return whichever it is closest too.
What would be the best way to implement something like this?
This is getting close, but something I can't see is off a bit ...
public String GetDirection()
{
int xd = Guess.X - Clue.X;
int yd = Guess.Y - Clue.Y;
if(Math.Abs(xd) <= Math.Abs(yd))
return (xd <= 0) ? "Left" : "Right";
else
return (yd <= 0) ? "Down" : "Up";
}
Here is a visual representation of what is happening ...
Alright so you had most of it right however you made a easy mistake. When you create the buttons you're rendering from left to right then top to bottom which creates the height as the x position then the width as the y position. So when you go and correlate the guess to the correct position you forget that you did this and assume x is the width.
Here's my implementation which fixed this:
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 UpDownLeftRight {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
this.Load += new System.EventHandler(this.Form1_Load);
}
public int[] winner = new int[2];
public Button[,] tmpButton = new Button[10, 10];
private void Form1_Load(object sender, EventArgs e) {
Random r = new Random();
int ButtonWidth = 48;
int ButtonHeight = 48;
int start_x = 0;
int start_y = 0;
winner = new int[] { r.Next(0, 10), r.Next(0, 10) };
this.Size = new Size((ButtonWidth * 11), (ButtonHeight * 11));
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
tmpButton[i, j] = new Button();
tmpButton[i, j].Left = start_x + (i * ButtonWidth);
tmpButton[i, j].Top = start_y + (j * ButtonHeight);
tmpButton[i, j].Width = ButtonWidth;
tmpButton[i, j].Height = ButtonHeight;
tmpButton[i, j].Font = new Font(FontFamily.GenericMonospace, 17);
tmpButton[i, j].Click += new EventHandler(BTN_Grid_Click);
this.Controls.Add(tmpButton[i, j]);
}
}
}
public void BTN_Grid_Click(object o, EventArgs e) {
int[] guess = new int[2];
for (int i = 0; i != tmpButton.GetLength(1); i++) {
for (int j = 0; j != tmpButton.GetLength(0); j++) {
if (tmpButton[i, j] == o) {
guess = new int[] { i, j };
}
}
}
int xDist = guess[0] - winner[0];
int yDist = guess[1] - winner[1];
string possible = "˂˃˄˅";
if (xDist > 0) { possible = possible.Replace("˃", ""); }
if (xDist < 0) { possible = possible.Replace("˂", ""); }
if (xDist == 0) { possible = possible.Replace("˂", ""); possible = possible.Replace("˃", ""); }
if (yDist > 0) { possible = possible.Replace("˅", ""); }
if (yDist < 0) { possible = possible.Replace("˄", ""); }
if (yDist == 0) { possible = possible.Replace("˄", ""); possible = possible.Replace("˅", ""); }
((Button)o).Text = possible;
}
}
}
Related
I'm working on writing a Mendelbrot renderer in C# to practice multithreading, but am having an issue where my calculation code maxes out at 2 iterations. I don't really understand why since the online references I've been looking at seem to calculate it the same way as me. No matter what coordinates of pixels I provide, it always returns 2 (aside from 0,0 and 0,1).
`
using System;
using System.Numerics;
using SkiaSharp;
namespace Mandelbrot
{
internal class Program
{
const int MaxIterations = 100;
static void Main(string[] args)
{
int size = 250;
int[,] grid = Run(size, 0, 0, 1);
// Console.WriteLine("Please specify a square size for the image.");
// try
// {
// Console.Write("Length: ");
// height = Int32.Parse(Console.ReadLine());
// }
// catch (FormatException e)
// {
// Console.WriteLine(e);
// throw;
// }
using (var surface = SKSurface.Create(width: size, height: size, SKColorType.Rgba8888, SKAlphaType.Premul))
{
SKCanvas canvas = surface.Canvas;
canvas.DrawColor(SKColors.Coral);
for (int i = 0; i < grid.GetLength(0); i++)
{
for (int j = 0; j < grid.GetLength(1); j++)
{
if (grid[i, j] >= MaxIterations)
canvas.DrawPoint(new SKPoint(i, j), SKColors.Black);
}
}
canvas.DrawPoint(new SKPoint(250, 250), SKColors.Chartreuse);
OutputImage(surface);
}
Console.WriteLine("Program successfully completed.");
}
public static int[,] Run(int size, int fromX, int fromY, int h)
{
int[] oulltput = new int[size * size];
int[,] output = new int[size, size];
for (int i = 0; i < output.GetLength(0); i += 1)
{
for (int j = 0; j < output.GetLength(1); j += 1)
{
float x = fromX + i * h;
float y = fromY + j * h;
output[i, j] = IterCount(x, y, MaxIterations);
}
}
return output;
}
public static int IterCount(float constX, float constY, int maxIterations)
{
const float maxMagnitude = 2f;
const float maxMagnitudeSquared = maxMagnitude * maxMagnitude;
int i = 0;
float x = 0.0f, y = 0.0f;
float xSquared = 0.0f, ySquared = 0.0f;
while (xSquared + ySquared <= maxMagnitudeSquared && i < maxIterations)
{
xSquared = x * x;
ySquared = y * y;
float xtmp = xSquared - ySquared + constX;
y = 2.0f * x * y + constY;
x = xtmp;
i++;
}
return i;
}
private static void OutputImage(SKSurface surface)
{
Console.WriteLine("Attempting to write .png to disk...");
using (var image = surface.Snapshot())
using (var data = image.Encode(SKEncodedImageFormat.Png, 80))
using (var stream = File.OpenWrite("out.png"))
{
// save the data to a stream
data.SaveTo(stream);
Console.WriteLine("Success!");
}
}
}
}
`
I tried to use breakpoints and writeline statements to debug but I can't figure out where my math is going wrong. I keep getting 2 for my iteration count.
Im doing school project. My task is to write a small Winform application that represents the Bezier Curve, but with some constraints.
I did almost everything, just one more step is ahead of me.
The whole program starts with an empty canvas, then the user can click on it, and a circle is drawn. After every 4th click, the bezier curve appears to that polygon. Now comes my problem.
What I am stuck with is that I have to controll somehow where the 5th click is going to be. It must be on a line that comes from 2 points: the 3rd and 4th points.
Can anybody help me with this? I have really no idea how to even start.
So far, this is my code.
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 grafika_beadando_kettesert
{
public partial class MainForm : Form
{
Graphics g;
int counter = 0;
Pen PenBlack = Pens.Black; //ezzel a tollal rajzolom a vonalat
Pen PenCurve = new Pen(Color.Blue, 3f); //ezzel a tollal rajzolom a görbét
Brush PenPoint; //Ezzel töltöm ki a pontot
int size = 4; // a lerakott pont mérete
int found = -1;
List<PointF> Points = new List<PointF>(); //ebbe a listába tárolom a pontokat
PointF p0, p1;
public MainForm()
{
InitializeComponent();
PenPoint = new SolidBrush(canvas.BackColor);
this.DoubleBuffered = true;
}
private void canvas_Paint(object sender, PaintEventArgs e)
{
g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
for (int i = 0; i < Points.Count - 1; i++) // mindig meg kell rajzolni az eddig meghúzott vonalakat a polygonból újra
g.DrawLine(PenBlack, Points[i], Points[i + 1]);
if (counter == 4)
{
DrawBeziergorbe();
counter = 0;
}
for (int i = 0; i < Points.Count; i++) // ezzel rajzolom meg az eddig felrakott pontokat újra
{
g.FillEllipse(PenPoint, Points[i].X - size, Points[i].Y - size, 2 * size, 2 * size);
g.DrawEllipse(PenBlack, Points[i].X - size, Points[i].Y - size, 2 * size, 2 * size);
}
}
private void canvas_MouseUp(object sender, MouseEventArgs e)
{
found = -1;
}
private void canvas_MouseMove(object sender, MouseEventArgs e)
{
if (found != -1)
{
Points[found] = e.Location;
canvas.Invalidate();
}
}
private void canvas_MouseDown(object sender, MouseEventArgs e)
{
for (int i = 0; i < Points.Count; i++)
{
if (Math.Abs(Points[i].X - e.X) <= size && Math.Abs(Points[i].Y - e.Y) <= size)
{
found = i;
break;
}
}
if (found == -1)
{
Points.Add(e.Location); //ha nincs túl közel a lerakott pont egy jelenlegihez, akkor hozzáadja a
//"Points" listához, hogy innen kiolvasva újra belehessen rajzolni
found = Points.Count - 1;
counter++;
canvas.Invalidate();
}
}
private void DrawBeziergorbe() //Mivel n-ed fokú bezier görbe kell, ezért használom a binomiálisos megoldást
{
int n = Points.Count - 1;
double t = 0;
double h = 1.0 / 500.0;
double b = 0.0;
p0 = new PointF(0, 0);
for (int i = 0; i <= n; i++)
{
b = B(n, i, t);
p0.X += (float)(b * Points[i].X);
p0.Y += (float)(b * Points[i].Y);
}
while (t < 1)
{
t += h;
p1 = new PointF(0, 0);
for (int i = 0; i <= n; i++)
{
b = B(n, i, t);
p1.X += (float)(b * Points[i].X);
p1.Y += (float)(b * Points[i].Y);
}
g.DrawLine(PenCurve, p0, p1);
p0 = p1;
}
}
private double B(int n, int i, double t)
{
return Binom(n, i) * (Math.Pow(1 - t, n - i) * Math.Pow(t, i));
}
private uint Binom(int n, int k)
{
if (n == 0) return 0;
else if (k == 0 || k == n) return 1;
else return Binom(n - 1, k - 1) + Binom(n - 1, k);
}
}
}
You can simply project the click position on the desired line.
If c is the click position and A and B are the two last control points, then the projected position p is:
d = B - A
p = A + dot(c - A, d) / dot(d, d) * d
I have a problem with my terrain.
When I want to set the altitude it works, but the terrain is always displayed larger than the 2D array I use for the altitude. In this example, my array and terrain are 200x157. So why do I have this overhang in my display?
using MoonSharp.Interpreter;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using System;
using System.Text;
using System.IO;
[MoonSharpUserData]
public class PrefabCreator : MonoBehaviour
{
/// <summary>
/// Classmembers for PrefabCreator
/// </summary>
private int terrainDepth;
private int terrainWidth;
private int terrainHeight;
private float terrainScale;
private float maxHeight;
public void CreateTerrain(int[][] mapData)
{
MapScale(mapData);
Terrain terrain = Resources.Load<Terrain>("TerrainObject") as Terrain;
Terrain prefabTerrain = Instantiate(terrain, new Vector3(0, 0, 0), Quaternion.identity);
prefabTerrain.terrainData = GenerateTerrain(prefabTerrain.terrainData, mapData);
}
private void MapScale(int[][] mapData)
{
terrainWidth = 0;
terrainHeight = 0;
terrainDepth = 10;
maxHeight = 0;
bool firstRun = true;
for (int i = 0; i < mapData.GetLength(0); i++)
{
terrainHeight++;
for (int j = 0; j < mapData[i].Length; j++)
{
if(mapData[i][j] > maxHeight)
{
maxHeight = mapData[i][j];
}
if (firstRun)
{
terrainWidth++;
}
}
firstRun = false;
}
Debug.Log("MAXHEIGHT: " + maxHeight);
}
private TerrainData GenerateTerrain(TerrainData terrainData, int[][] mapData)
{
if(terrainWidth >= terrainHeight)
{
terrainData.heightmapResolution = terrainWidth + 1;
}
else
{
terrainData.heightmapResolution = terrainHeight + 1;
}
terrainData.size = new Vector3(terrainWidth, terrainDepth, terrainHeight);
Debug.Log("Test" + terrainData.heightmapHeight);
Debug.Log("Test" + terrainData.heightmapWidth);
Debug.Log("Test" + terrainData.heightmapScale);
terrainData.SetHeights(0, 0, GenerateHeights(mapData));
return terrainData;
}
private float[,] GenerateHeights(int[][] mapData)
{
Debug.Log("Breite " + terrainWidth);
Debug.Log("Höhe " + terrainHeight);
float[,] heights = new float[terrainHeight, terrainWidth];
//Debug.Log("Test" + mapData[2][4]);
for (int x = 0; x <= terrainHeight - 1; x++)
{
//Debug.Log("X = " + x);
for (int y = 0; y <= terrainWidth - 1; y++)
{
//Debug.Log("Y = " + y);
float value = 0.0f + mapData[x][y];
heights[x, y] = (value / maxHeight);
//heights[x, y] = (float)value ;
Debug.Log(heights[x, y]);
}
}
return heights;
}
}
See the picture in the appendix. I don't understand why the overhangs exist at the edges?
Many thanks in advance People
I wrote a code that reads an image and calculates the normal vector for every pixel out of the RGB-Values. The Problem is even if I choose a 256x256 image c# will take too long to operate and sometimes it shuts down. Can someone show me another method or a different solution?
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Aufgabe17NormalMapping
{
public partial class Form1 : Form
{
public delegate void TextManagerDelegate(string text);
TextManagerDelegate TextHandler;
Bitmap img;
public Form1()
{
InitializeComponent();
TextHandler = new TextManagerDelegate(TextManager);
}
public void TextManager(string txt)
{
textBox1.AppendText(txt + Environment.NewLine);
}
public void RunProcess()
{
string filePath = #"C:\Users\USerName\Documents\Visual Studio 2017\Projects\Aufgabe17NormalMapping\images.jpg";
using (img = new Bitmap(filePath))
{
var height = img.Height;
var width = img.Width;
double[,] ArrayR = new double[width, height];
double[,] ArrayG = new double[width, height];
double[,] ArrayB = new double[width, height];
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
Color pixel = img.GetPixel(i, j);
ArrayR[i, j] = (((double)Convert.ToDouble(pixel.R.ToString())) + 0.5) * 2;
ArrayG[i, j] = (((double)Convert.ToDouble(pixel.G.ToString())) + 0.5) * 2;
ArrayB[i, j] = (((double)Convert.ToDouble(pixel.B.ToString())) + 0.5) * 2;
Debug.WriteLine(ArrayR[i, j].ToString(), "Array R");
//Debug.Print(ArrayR[i, j].ToString(), "Array Rsdsd");
BeginInvoke(TextHandler, ArrayR[i, j].ToString());
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
Task T = new Task(RunProcess);
T.Start();
}
}
}
Your code is really fast, it is the "reporting" that takes a long time. Remove the Debug.WriteLine and TextHandler and I got the following time (in debug mode)
ImgSize 532x1280
Lasted: 0:00:01,181845
Code snippet:
static void Main(string[] args)
{
var watch = Stopwatch.StartNew();
RunProcess();
Console.WriteLine($"Lasted: {watch.Elapsed.ToString("g")}");
}
public static void RunProcess()
{
var str = new StringBuilder();
string filePath = #"C:\Users\Wouter\Desktop\gamez.jpg";
using (var img = new Bitmap(filePath))
{
var height = img.Height;
var width = img.Width;
Console.WriteLine($"ImgSize {width}x{height}");
double[,] ArrayR = new double[width, height];
double[,] ArrayG = new double[width, height];
double[,] ArrayB = new double[width, height];
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
Color pixel = img.GetPixel(i, j);
ArrayR[i, j] = (((double)Convert.ToDouble(pixel.R.ToString())) + 0.5) * 2;
ArrayG[i, j] = (((double)Convert.ToDouble(pixel.G.ToString())) + 0.5) * 2;
ArrayB[i, j] = (((double)Convert.ToDouble(pixel.B.ToString())) + 0.5) * 2;
str.AppendLine(ArrayR[i, j].ToString());
}
}
}
BeginInvoke(TextHandler, str.ToString());
}
Try working with a StringBuilder and once you've got the entire image processed, update the UI once.
I'm trying to create a chess game purely for my learning C# and chess. Just to start off with, I would like to create an 8x8 grid of buttons through code rather than the designer. This would save me hard coding each button individually.
A button array would seem a good way to start but I have no idea how to implement this.
You can create a "square" class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
class Square:PictureBox
{
private bool color;
private char piece;
}
and define an array to make place for 8x8 squares.
public partial class Form1 : Form
{
Square[,] square = new Square[8, 8];
public Form1()
{
InitializeComponent();
int i, j;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
this.square[i, j] = new Square();//Creating the chess object//
this.square[i, j].BackColor = System.Drawing.SystemColors.ActiveCaption;
this.square[i, j].BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.square[i, j].Location = new System.Drawing.Point(57 + i * 40, 109 + j * 40);
this.square[i, j].Name = "chessBox1";
this.square[i, j].Size = new System.Drawing.Size(40, 40);
this.square[i, j].TabIndex = 2;
this.square[i, j].TabStop = false;
this.Controls.Add(this.square[i, j]);
}
}
}
}
int ButtonWidth = 40;
int ButtonHeight = 40;
int Distance = 20;
int start_x = 10;
int start_y = 10;
for (int x = 0; x < 8; x++)
{
for (int y = 0; y < 8; y++)
{
Button tmpButton = new Button();
tmpButton.Top = start_x + (x * ButtonHeight + Distance);
tmpButton.Left = start_y + (y * ButtonWidth + Distance);
tmpButton.Width = ButtonWidth;
tmpButton.Height = ButtonHeight;
tmpButton.Text = "X: " + x.ToString() + " Y: " + y.ToString();
// Possible add Buttonclick event etc..
this.Controls.Add(tmpButton);
}
}
May be you ca use the code below to solve your problem. This code is of Windows Form application in C#. And for the control Button.
for (int i = 0; i< 8; i++)
{
for (int j = 0; j < 8; j++)
{
Button BtnNew = new Button;
BtnNew.Height = 80;
BtnNew.Width = 80;
BtnNew.Location = new Point(80*i, 80*j);
this.Controls.Add(BtnNew);
}
}