Задача "Кривaя Дрaкона"
Решаю задачу "Кривaя Дрaкона", которая находится здесь. Я решил её следующим образом, и проверка была пройдена:
using System;
namespace Fractals
{
internal static class DragonFractalTask
{
public static void Calc(double x, double y, double angle, int randomise , out double c, out double d)
{
var dx = (x * Math.Cos(angle) - y * Math.Sin(angle)) / Math.Sqrt(2) + randomise ;
d = (x * Math.Sin(angle) + y * Math.Cos(angle)) / Math.Sqrt(2);
c = dx;
}
public static void DrawDragonFractal(Pixels pixels, int numOfIterations, int seed)
{
double c = 1, d = 0;
var random = new Random(seed);
while (numOfIterations-- > 0)
{
var randomise = random.Next(2);
var angle = Math.PI / 4 + Math.PI / 2 * randomise ;
Calc(c, d, angle, randomise , out c, out d);
pixels.SetPixel(c, d);
}
}
}
}
Однако преподаватель выделил слово void в 7 строчке с замечанием "Лучше возвращать значение". Я исправил на этот вариант:
using System;
namespace Fractals
{
internal static class DragonFractalTask
{
public static (double c, double d) Calc(double x, double y, double angle, int randomise)
{
var dx = (x * Math.Cos(angle) - y * Math.Sin(angle)) / Math.Sqrt(2) + randomise ;
var d = (x * Math.Sin(angle) + y * Math.Cos(angle)) / Math.Sqrt(2);
var c = dx;
}
public static void DrawDragonFractal(Pixels pixels, int numOfIterations, int seed)
{
double c = 1, d = 0;
var random = new Random(seed);
while (numOfIterations-- > 0)
{
var randomise = random.Next(2);
var angle = Math.PI / 4 + Math.PI / 2 * randomise ;
Calc(c, d, angle, randomise);
pixels.SetPixel(c, d);
}
}
}
}
Теперь задание не проходит на проверку, видимо из-за того, что необходимо использовать возвращаемое значение, как это написать? Спасибо
Ответы (1 шт):
По моему, Ваш преподаватель имел в виду следующее: вместо out double c, out double d он хочет, чтобы функция возвращала значение.
Но есть трудность. Вам нужно вернуть 2 числа, а функция возвращает одно значение.
Эту проблему можно решить созданием класса или структуры, который состоит из двух double чисел. Тогда решение будет таким:
internal static class DragonFractalTask
{
public class TmpPair
{
public double c;
public double d;
}
public static TmpPair Calc(double x, double y, double angle, int randomise)
{
var dx = (x * Math.Cos(angle) - y * Math.Sin(angle)) / Math.Sqrt(2) + randomise;
var d = (x * Math.Sin(angle) + y * Math.Cos(angle)) / Math.Sqrt(2);
var c = dx;
TmpPair return_val = new TmpPair();
return_val.c = c;
return_val.d = d;
return return_val;
}
public static void DrawDragonFractal(Pixels pixels, int numOfIterations, int seed)
{
double c = 1, d = 0;
var random = new Random(seed);
while (numOfIterations-- > 0)
{
var randomise = random.Next(2);
var angle = Math.PI / 4 + Math.PI / 2 * randomise;
TmpPair pair = Calc(c, d, angle, randomise);
pixels.SetPixel(pair.c, pair.d);
}
}
}
Небольшое дополнение.
Вообще то, в C# уже существует тип, очень подходящий для возврата нескольких значений из функции. Этот тип называется Tuple<>, и с ним решение становится короче:
internal static class DragonFractalTask
{
public static Tuple<double, double> Calc(double x, double y, double angle, int randomise)
{
var dx = (x * Math.Cos(angle) - y * Math.Sin(angle)) / Math.Sqrt(2) + randomise;
var d = (x * Math.Sin(angle) + y * Math.Cos(angle)) / Math.Sqrt(2);
var c = dx;
Tuple<double, double> ret_val = new Tuple<double, double>(c, d);
return ret_val;
}
public static void DrawDragonFractal(Pixels pixels, int numOfIterations, int seed)
{
double c = 1, d = 0;
var random = new Random(seed);
while (numOfIterations-- > 0)
{
var randomise = random.Next(2);
var angle = Math.PI / 4 + Math.PI / 2 * randomise;
Tuple<double, double> pair = Calc(c, d, angle, randomise);
pixels.SetPixel(pair.Item1, pair.Item2);
}
}
}
И наконец, есть прекрасный еще более короткий вариант, который мне в комментариях подсказал EvgeniyZ: (а также, он предлагает понятный пример про использование кортежей)
internal static class DragonFractalTask
{
public static (double, double) Calc(double x, double y, double angle, int randomise)
{
var dx = (x * Math.Cos(angle) - y * Math.Sin(angle)) / Math.Sqrt(2) + randomise;
var d = (x * Math.Sin(angle) + y * Math.Cos(angle)) / Math.Sqrt(2);
var c = dx;
return (c, d);
}
public static void DrawDragonFractal(Pixels pixels, int numOfIterations, int seed)
{
double c = 1, d = 0;
var random = new Random(seed);
while (numOfIterations-- > 0)
{
var randomise = random.Next(2);
var angle = Math.PI / 4 + Math.PI / 2 * randomise;
(double r_c, double r_d) = Calc(c, d, angle, randomise);
pixels.SetPixel(r_c, r_d);
}
}
}