Showing the path of a projectile

Posted on

Problem

I’m trying to dive deeper into C#, and so I’ve been experimenting with some code. I’m creating a console application that shows the path of a projectile depending on the angle, and it works great! You can check it out here actually. It’s not perfect, but I like it.

Is there a better way to use my for loops? I’m using 3 inside eachother, and I’m not sure if that should be an issue. If you could take a look at the code in the link, it’d be great.

I realized my code might not have shown up. The code snippet won’t work if you try to do it as you’re missing a couple functions I’ve devised, but you should be able to get the idea just by looking at it.

using System.IO;
using System;
using System.Threading;
class Program
{

static void Main()
{
    Console.Clear();

    DoArc();
}

static void DoArc() {

            int tempVal = 0;
            string displayLine = "";
    //HERE
    for(int a = 0; a < 90; a+= 2) {

        Console.Clear();
        //HERE
        for(int y = 0; y < 16; y++) {
            //HERE
            for(int x = 0; x < 40; x++) {
                tempVal = Mathf.RoundToInt(Physics.HeightAtPoint(x, a, 15f, 0));
                tempVal = Mathf.Clamp(tempVal, 0, 16);

                if(Mathf.CloseTo(16 - y, tempVal, 1)) 
                displayLine += " X";
                else
                displayLine += " .";

            }
        Console.WriteLine(displayLine);
        displayLine = "";
        }
        Console.WriteLine("Angle: " + a);
        Thread.Sleep(500);

    }
}
}

Solution

I don’t see anything particularly wrong with the loops themselves, but, as far as coding style goes:

  • tempVal and displayLine should be declared as close as possible to the place where they’re first used.
  • the values returned by Math.RoundToInt and Mathf.Clamp don’t seem to have anything in common, so they should be assigned to different variables. Don’t reuse tempVal for different and unrelated things.
  • tempVal, x, y and a should be given more meaningful names.
  • You should use a StringBuilder to build strings, instead of using string concatenation.
  • Your indentation is all over the place.
  • In C#, it is common practice to put the opening bracket { on its own line – although one could argue that this is a matter of personal preference and doesn’t really matter as long as you’re consistent throughout the codebase.

    for(int y = 0; y < 16; y++)
    {
        var sb = new StringBuilder();
    
        //HERE
        for(int x = 0; x < 40; x++)
        {
            int height = Mathf.RoundToInt(Physics.HeightAtPoint(x, a, 15f, 0));
            int clamp = Mathf.Clamp(height, 0, 16);
    
            if(Mathf.CloseTo(16 - y, clamp, 1)) 
                sb.Append(" X");
            else
                sb.Append(" .");
    
        }
        Console.WriteLine(sb.ToString());
    }
    

Adding to the answers already provided I’d like to say that it’s a bad practice to use all kinds of so called magic numbers/strings like 90, 14, 16… give them a meaning

var rightAngle = 90;
var maxHeight = 40;

for(int x = 0; x < maxHeight; x++) 
{
}

or whatever the numbers represent.

Since your output is calculated directly from the values in your for statements, I would say that this is fine.

If you were using the for loops to iterate over collections, then you would have different options.

You could take a different approach by populating collections with numeric values using Enumerable.Range, projecting the results of your computations to a new collection (like a two-dimensional array of bools where true indicates the projectile is present at that position), but it’s probably only worth attempting as an academic exercise.

If you went a functional route, you could completely remove your dependence on collections by returning a function to print each row. However, if you wanted to not call any console methods from inside your functions you would have to represent the row some way (either a collection or perhaps a Tuple containing 2 values, length and position). I should note that C# is probably not the best fit for this option.

Leave a Reply

Your email address will not be published. Required fields are marked *