So I currently have 2 values x and y and I want x to be decremented/incremented by y until it gets to 0 without going over.
float x = 9;
float y = 4;
if (x != 0) {
if (x > 0) {
x -= y;
}
else if (x < 0) {
x += y;
}
}
If this was to run x would be subtracted by y 3 times leaving the value of x at -2 in which the next frame it will run again and add y which will again go over.
You could change the implementation as follows by introducing clipping at 0 after the subtraction or addition.
if (x != 0) {
if (x > 0) {
x -= y;
x = Math.Max(x, 0.0f);
}
else if (x < 0) {
x += y;
x = Math.Min(x, 0.0f);
}
}
Not sure if I understand correctly, but if you want x to be decremented/incremented by y until it gets to 0 without going over, this should do it:
for( ; x>=0; x = x - y);
x = x + y;
This function will give you this results in comments, for wrong parameters it will avoid going to infinity and return X:
//[9, 4] = 1
//[-9, -4] = -1
private static float Unnamed(float x, float y)
{
float tmp = x;
float result = x;
while (true)
{
tmp -= y;
if (y > 0)
{
if (tmp > 0 && tmp < x)
result = tmp;
else
break;
}
else
{
if (tmp < 0 && tmp > x)
result = tmp;
else
break;
}
}
return result;
}
Okay so based on #Codor's answer I got this
private float Approach(float value, float targetValue, float step) {
float result;
if (value < targetValue) {
result = Mathf.Min (value + step, targetValue);
} else {
result = Mathf.Max (value - step, targetValue);
}
return result;
}
which worked fine and does exactly what I wanted and will never go past the target value. And then I came across an already built in function that does exactly what I wanted as well Mathf.MoveTowards(value, targetValue, step).
You can do this using something like this :
if ( x != 0 )
{
x = x < 0 ? Math.Min(x + y, 0) : Math.Max(x - y, 0);
}
Related
Find x in 2^x = n.
This is what I am trying to do.(It is not for any specific purpose. It just looks good.)
This is what I wrote but it doesn't work.
public double f(double x)
{
double result = 0;
double increaser = 1;
double subtract = result - increaser;
double add = result + increaser;
while(true)
{
if((Math.Pow(2,result) == x) || increaser == 0.0001)
{
break;
}
double sP = Math.Abs(Math.Pow(2,subtract) - x);
double aP = Math.Abs(Math.Pow(2,add) - x);
double nP = Math.Abs(Math.Pow(2,result) - x);
if((sP < nP) && (sP < aP))
{
result -= increaser;
}
else if((aP < nP) && (aP < sP))
{
result += increaser;
}
else if((nP < sP) && (nP < aP))
{
increaser = increaser / 10;
}
}
return result;
}
This function is called the logarithm:
return Math.Log2(n);
For the general case, you can use two formulae for this:
if bx = n, then x = logbn; and
logba = logxa/logxb.
Since what you're looking for is x in 2x = n, that is x = log2n = logen/loge2, something that can be done with:
public double f(double x) {
return Math.Log(x) / Math.Log(2);
}
Of course, that's for the case where you have a limited set of logarithm bases (such as 10 or e). Since C# provides a call that will handle any base, you can bypass the division operation:
public double f(double x) {
return Math.Log(x, 2);
}
or even use the base-2 one:
public double f(double x) {
return Math.Log2(x);
}
I'm trying to implement a tile-based platforming system for a 2D game demo from this C++ code into C#,
This is what I have written, It doesn't compile though due to the var variable usage.
class GameLogic
{
// Level storage
String sLevel;
int nLevelWidth;
int nLevelHeight;
// Player Properties
float fPlayerPosX = 1.0f;
float fPlayerPosY = 1.0f;
float fPlayerVelX = 0.0f;
float fPlayerVelY = 0.0f;
bool bPlayerOnGround = false;
// Camera properties
float fCameraPosX = 0.0f;
float fCameraPosY = 0.0f;
public GameLogic()
{
var GetTile = (ref int x, ref int y) =>
{
if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
return sLevel[y * nLevelWidth + x];
else
return "";
};
var SetTile = (ref int x, ref int y, string c)=>
{
if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
sLevel[y * nLevelWidth + x] = c;
};
}
}
What do you suggest I should do here, to implement this functionality. Thank you for your time.
It doesn´t compile because of the var statement.
When you use LambdaExpressions and you want to save it to a variable you have to define the delegate Type.
But you can´t use ref variables here. But that is ok, because you don´t change the value of x or y.
You need a Delegate that describes the type of your function.
You could build you own delegate type but in C# there are two built in types for that case.
Action & Action<T1-16> -> always returns void
Func<T1-17> you can define the return type
The GetTile function takes two int and returns a string.
So you can use Func<int, int, string>.
The SetTitle function has one string parameter more but no return type.
That would be Action<int, int, string>.
internal class GameObject
{
private int nLevelWidth;
private int nLevelHeight;
public GameLogic()
{
Func<int, int, string> GetTile = (int x, int y) =>
{
if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
return sLevel[y * nLevelWidth + x];
else
return "";
};
Action<int, int, string> SetTile = (int x, int y, string c)=>
{
if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
sLevel[y * nLevelWidth + x] = c;
};
}
}
That´s a good article about delegates.
As other answers have correctly noted:
You can't use var with a lambda in C# because the type is ambiguous. You have to state the delegate type explicitly.
Your use of ref indicates that you have misunderstood how outer variable capture works in both C++ and C#. You don't need to make these ref, and the outer variables will be captured automatically.
However none of the answers given so far have told you the better solution to this problem, which is to not use lambdas at all! Just use a local function.
public GameLogic()
{
... other code here ...
string GetTile(int x, int y)
{
if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
return sLevel[y * nLevelWidth + x];
else
return "";
}
No lambdas required.
Note that this solution requires C# 7.0 or higher.
(An even better solution would be to put all this code into a class; make a custom data type that does this work for you. But you asked specifically about how to port this code directly, not how to refactor it.)
Lambda Expressions doesn't have a compile time type, but is convertible to any matching delegate or expression type. That's why according to MSDN lambda expressions can't be implicitly typed (also check this answer by Eric Lippert
So:
Func<int, int, string> GetTile = (int x, int y) =>
{
if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
return sLevel[y * nLevelWidth + x];
else
return "";
};
Action<int, int, string> SetTile = (int x, int y, string c)=>
{
if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
sLevel[y * nLevelWidth + x] = c;
};
You can declare two delegates like below:
delegate void ActionRef(ref int x, ref int y, string c);
delegate string FuncRef(ref int x, ref int y);
And instead of using var, you can these delegates as the type of function.
public GameLogic()
{
FuncRef GetTile = (ref int x, ref int y) =>
{
if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
return sLevel[y * nLevelWidth + x];
else
return "";
};
ActionRef SetTile = (ref int x, ref int y, string c) =>
{
if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
sLevel[y * nLevelWidth + x] = c;
};
}
I am working on an edge points extraction algorithm.
I have a List of points representing a blob (a group of connected pixels) and I want to extract edge points.
I have an example algorithm below, but I am wondering if there is a faster way.
I am using class for BlobPoint, because there is more to it than shown in the example below.
BlobPoint index value represent index value in the original image (image is 1D array of pixels, hence required width information).
This algorithm is build on idea that if a pixel on right or bottom or left or top does not exist in the list, then this point is an edge point.
The list will usually contain between 20 000 to 1 000 000 elements.
yr and yl are added for clarity.
public static List<BlobPoint> GetEdgePoints(this List<BlobPoint> points, int width)
{
int length = points.Count;
List<BlobPoint> temp = new List<BlobPoint>();
for (int i = 0; i < length; i++)
{
BlobPoint point = points[i];
int x = point.X;
int y = point.Y;
int xr = x + 1;
int yr = y;
int xb = x - width;
int yb = y - 1;
int xl = x - 1;
int yl = y;
int xt = x + width;
int yt = y + 1;
if (!points.Any(p => p.X == xb && p.Y == yb) || !points.Any(p => p.X == xl && p.Y == yl) || !points.Any(p => p.X == xr && p.Y == yr) || !points.Any(p => p.X == xt && p.Y == yt))
{
temp.Add(point);
}
}
return temp;
}
public class BlobPoint
{
public int X = 0;
public int Y = 0;
public int Index = 0;
public BlobPoint(int x, int y, int index)
{
X = x;
Y = y;
Index = index;
}
}
My solution:
Ok, I have done some testing and the method above is way too slow for my needs.
I will leave question as this might be of use to someone who looks for faster iteration method.
This is a solution I came up with, but it is still a bit slow:
public static Dictionary<int, List<BlobPoint>> GetEdgePoints(BlobPoint[] points, int[] labels, int image_width, int image_height)
{
int length = labels.Length;
if (image_height * image_width != length) throw new ArgumentException("image_width x image_height does not match labels.Length");
if (length == 0) throw new ArgumentException("label array cannot be empty!");
if (points.Length != length) throw new ArgumentException("points array length cannot be different from labels array length!");
var dict = new Dictionary<int, List<BlobPoint>>();
for (int i = 0; i < length; i++)
{
int label = labels[i];
if (label <= 0) continue;
BlobPoint point = points[i];
int x = point.X;
int y = point.Y;
int width_offset = image_width - 1;
int height_offset = image_height - 1;
if (x > 0 && x < width_offset && y > 0 && y < height_offset)
{
if (labels[i + 1] == label && labels[i - 1] == label && labels[i + image_width] == label && labels[i - image_width] == label)
{
continue;
}
}
if (dict.ContainsKey(label))
dict[label].Add(point);
else
dict.Add(label, new List<BlobPoint>() { point });
}
return dict;
}
Personally, I'd use a two-dimensional Boolean array representing the image for this, in which the indices for the points you have are set to true. In exchange for some memory, and a single loop over the points in advance, this allows lightning-fast checks of whether a point is inside the list, removing all internal iterations for lookups on the points list. There is not a single .Contains or .Any or .All performed here. Just two loops over the main list, and eight very simple checks inside the second loop.
public static List<BlobPoint> GetEdgePoints(this List<BlobPoint> points, Int32 imageWidth, Int32 imageHeight)
{
Boolean[,] pointInList = new Boolean[imageHeight, imageWidth];
foreach (BlobPoint p in points)
pointInList[p.Y, p.X] = true;
List<BlobPoint> edgePoints = new List<BlobPoint>();
Int32 lastX = imageWidth - 1;
Int32 lastY = imageHeight - 1;
foreach (BlobPoint p in points)
{
Int32 x = p.X;
Int32 y = p.Y;
// Image edge is obviously a blob edge too.
// Coordinates checks are completely safe after the edge checks.
if (x == 0 || y == 0 || x == lastX || y == lastY
|| !pointInList[y - 1, x]
|| !pointInList[y, x - 1]
|| !pointInList[y, x + 1]
|| !pointInList[y + 1, x])
edgePoints.Add(p);
}
return edgePoints;
}
This technically works without the image width and height, but then you need to do another loop in advance to get the maximum x and y present in your points, so you can make a Boolean[,] array that can contain all coordinates. If you have that image data, though, it's obviously a lot more efficient to just use it.
Not sure why you bother with the BlobPoint class over the standard Point struct, though. The index in the original array is just p.Y * stride + p.X anyway.
I tried this:
static int myPow(int x)
{
int power = x + 1;
int num = 0;
for (int i = 0; i < power; i++)
{
num = x * i;
x = x + num;
}
return num;
}
how can I factorize the int x by x+1 without using Math.Pow?
The idea is to multiply X by X in a loop by X+1 times.
Follow the steps:
find the power (x + 1)
start the variable result with the x value (result = x)
loop i from 1 to power and for each loop multiply result by x, witch means x * x * x * x power times.
static int myPow(int x) {
int power = x + 1;
int result = x;
for (int i = 1; i < power; i++)
{
result *= x;
}
return result;
}
Take a look on the implementation it did on rextester
FYI factorization in math is this. Just for fun, the result can be calculated with Exponentiation by squaring:
static int myPow(int x, int y)
{
if (y < 0) { throw new ArgumentException("y has to be nonnegative"); }
int result = 1;
while (y > 0)
{
if ((y & 1) == 1)
{
result *= x;
}
x = x * x;
y >>= 1;
}
return result;
}
You can use a technique called exponentiation by squaring, which is quite beautiful and is also faster, it takes O(lg k) time, where k is exponent:
static int square(int n){
return n * n;
}
static int pow(int n, int k){
if(k == 1) return n;
if(k % 2 == 1) return n * pow(n, k-1);
return square(pow(n, k/2));
}
then, if you want to get x^(x+1), you just need yo call pow(x, x+1).
small, fast and simple as that :)
screenshot of debug: http://img1.uploadscreenshot.com/images/orig/12/36121481470-orig.jpg
note how x, y have values (i have no idea why x and y stopped on 69 in the for loop - x should've went up to 86 and y to 183) yet r has no value at all. (the variable doesn't exist? what?) how should I fix this?
code if you want to read:
public float[] cht(int[,] matrix)
{
float[] xyrd = new float[4];
int xthreshold, ythreshold;
float slope;
double dir;
float zone;
int[] limitsStorage = new int[3] { matrix.GetLength(0), matrix.GetLength(1), matrix.GetLength(0) / 2 - 10 };
short[,,] accumulator = new short[limitsStorage[0]+1, limitsStorage[1]+1,limitsStorage[2]+1];
for (int x = 0; x < limitsStorage[0]; x++)
{ //first dimension loop of matrix 100
for (int y = 0; y < limitsStorage[1]; y++)
{ //second dimension loop of matrix 120
if (matrix[x, y] == 225)
{//the data at the for loop location is a 1 and not 0 hit.
xthreshold = x - limitsStorage[0] / 2;
ythreshold = y - limitsStorage[1] / 2;
//forget angle, search slope: float angle = xthreshold > 0 ? ((float)Math.Atan2(xthreshold, ythreshold)) : ((float)Math.Atan2(xthreshold, ythreshold) + 180);
slope = xthreshold / ythreshold;
//initiate if loops.
dir = 180 + Math.Round(Math.Atan2(ythreshold, xthreshold) * 57.2957 / 45, 0) * 45 + 45 * (Math.Round(((Math.Atan2(ythreshold, xthreshold) * 57.2957) % 45) / 45));
if (slope > .404 || slope < -.404)
{
if (slope < 2.3558 || slope > -2.3558)
{
if (xthreshold > 0)
{
if (ythreshold > 0)
{
//+x+y zone
zone = 45 + 180;
}
else
{
//+x-y zone
zone = 180 - 45;
}
}
else
{
if (ythreshold > 0)
{
//-x+y zone
zone = 360 - 45;
}
else
{
//-x-y zone
zone = 45;
}
}
}
else if (ythreshold > 0)
{
//+y zone
zone = 360 - 90;
}
else
{
//-y zone
zone = 90;
}
}
else if (xthreshold > 0)
{
//+x zone
zone = 180;
}
else
{
//-x zone
zone = 0;
}
for (int R = 6; R < limitsStorage[2]; R++)
{ //Radius loop for scan 44
float delta = (float)((1 / R) * 57.2957);
for (float Theta = zone - 25; Theta < zone + 25; Theta += delta)
{
accumulator[(int)(((R * Math.Cos(Theta / 57.2957)) < 0 || (R * Math.Cos(Theta / 57.2957)) > limitsStorage[0]) ? 0 : R * Math.Cos(Theta / 57.2957)), (int)(((R * Math.Sin(Theta / 57.2957)) < 0 || (R * Math.Sin(Theta / 57.2957)) > limitsStorage[1]) ? 0 : R * Math.Sin(Theta / 57.2957)),R]++;
//btw, 0,0,R is always the non-center area.
}
}
}
}
}
for (int x = 1; x < limitsStorage[0]; x++)
{
for (int y = 1; y < limitsStorage[1]; y++)
{
for (int r = 6; r < limitsStorage[2]; r++)
{
if (xyrd[3] > accumulator[x, y, r])
{
xyrd[0] = x;
xyrd[1] = y;
xyrd[2] = r;
xyrd[3] = accumulator[x, y, r];
}
}
}
}
if (accPrint)
{
//do something for debugging?
accPrint = false;
}
return xyrd;
}
I just noticed that the x and y have the little lock symbol under them indicating that you have private variables named x and y in the class in which this method is executing. Those are the x and y that you are seeing in the debugger.
r is appropriately out of scope as you've exited the loop in which it is declared.
By the way, x and y are ridiculously bad member variable names, and are ridiculously bad names for for loop variables of type int, especially if they are contained in a class with member variables named x and y.
The only place you declare r is in the for statement, right? That means r goes out of scope as soon as the loop ends. So naturally if you inspect variables at he end of the function, r won't be there.
Confessing I don't know why x and y are in scope based on the comments. They could be class variables, but the asker says not. That's the only explanation I can think of, though.
The behaviour is not weird -- you actually get exactly what you expect.
Please note that the watch window can only accurately show you values that are in scope at the breakpoint.
At the highlighted breakpoint, only accumulator[x, y, r] is in scope, and you see exactly the values you expected.