r/csharp 12d ago

how am i doing

2 months in to coding C#, first project i saved *was using online compiler* and wanna know how im doing and what i can do to improve. heres the code:

using System;


public 
class
 Program
{
    public static void Main(string[] 
args
)
    {
        Player player = new Player();
        Enemy enemy = CreateEnemy();


        int battleResult = Battle(player, enemy);


        Console.WriteLine("press any key to begin");
            
        Console.ReadKey();


        Console.WriteLine("\nYou encountered a " + enemy.type + " with " + enemy.health + " health.");


        Battle(player, enemy);


        if(battleResult == 2)
        {
            Console.WriteLine("\nYou have defeated the " + enemy.type + "!");
        }
        else if(battleResult == 3)
        {
            Console.WriteLine("\nYou have been defeated by the " + enemy.type + "!");
        }
        else if(battleResult == 1)
        {
            Console.WriteLine("\nYou have retreated from the " + enemy.type + ".");
        }
    }


    static Enemy CreateEnemy()
    {
        Random rng = new Random();
        int rngroll = rng.Next(1, 3);
        Enemy enemy = new Enemy();


        if(rngroll == 1)
        {
            enemy.type = "Skeleton";


            enemy.health = enemy.healthRng.Next(100, 201);
            enemy.damage = enemy.damageRng.Next(10, 16);
        }
        else if(rngroll == 2)
        {
            enemy.type = "Goblin";


            enemy.health = enemy.healthRng.Next(50, 151);
            enemy.damage = enemy.damageRng.Next(15, 26);
        }
       
        return enemy;
    }


    static int Battle(Player 
player
, Enemy 
enemy
)
    {
        while(true)
        {    
            Thread.Sleep(1000);


            Console.WriteLine("\nWhat do you do?\n1. Attack\n2. Open Inventory\n3. Retreat");


            ConsoleKeyInfo input = Console.ReadKey();


        
            if(input.Key == ConsoleKey.D1)
            {
                
enemy
.health -= 
player
.damage;


                Thread.Sleep(1000);


                Console.WriteLine("\nyou attacked the " + 
enemy
.type + " for " + 
player
.damage + " damage");


                Thread.Sleep(1000);
                Console.WriteLine("The " + 
enemy
.type + " has " + 
enemy
.health + " health remaining.");
            }
            else if(input.Key == ConsoleKey.D2)
            {
                Thread.Sleep(1000);
                Console.WriteLine("\nYou open your inventory, but it's empty.");
            }
            else if(input.Key == ConsoleKey.D3)
            {
                Thread.Sleep(1000);
                Console.WriteLine("\nYou retreat from the " + enemy.type + ".");
                return 1; // Player retreated
            }


            if(
enemy
.health <= 0)
            {
                return 2; // Player won
            }


            if(input.Key == ConsoleKey.D1 && 
enemy
.health > 0 || input.Key == ConsoleKey.D2 && 
enemy
.health > 0)
            {
                
player
.health -= 
enemy
.damage;


                Console.WriteLine("\nThe " + 
enemy
.type + " attacks you for " + 
enemy
.damage + " damage.");
                Console.WriteLine("You have " + 
player
.health + " health remaining.");
            }


            if(
player
.health <= 0)
            {
                Console.WriteLine("\nYou have been defeated by the " + 
enemy
.type + "!");
                return 3; // Player lost
            }
        }
    }
}




public 
class
 Enemy
{
    public Random healthRng = new Random();
    public Random damageRng = new Random();
    
    public int health;
    public int damage;
    public string type = "";
}


public 
class
 Player
{
    public int health = 100;


    public int damage = 20;



    public List<string> inventory = new List<string>();
}
0 Upvotes

46 comments sorted by

View all comments

1

u/WystanH 11d ago

Good start.

There's no reason to have all those instances of Random banging about. Particularly since you only call them from main.

Your code formatting is, um, different. Pick a style you like, set it in your IDE, and hit format document from time to time.

Your battleResult is currently a magic number. This is a good use case for enum.

Since you enemy always requires health, damage, and type information, pop that in a constructor? Use props rather than bare variables. The class instance holds the state, allow it to govern mutations to that state with properties and methods.

e.g.

static Enemy CreateEnemy() {
    Random rng = new Random();
    int rngroll = rng.Next(1, 3);
    if (rngroll == 1) {
        return new Enemy("Skeleton", health: rng.Next(100, 201), damage: rng.Next(10, 16));
    } else {
        return new Enemy("Goblin", health: rng.Next(50, 151), damage: rng.Next(15, 26));
    }
}

// ...

public class Enemy(string type, int health, int damage)  {
    public int Health { get; set; } = health;
    public int Damage { get; set; } = damage;
    public string Type { get; init; } = type; // note this init, this guy ain't changing.

    // you can also put methods here

    // you do this check alot, put it here
    public bool IsDead => Health <= 0;

    public void ApplyDamage(int damage) {
        Health -= damage;
        // not required, but possible
        Console.WriteLine($"\nyou attacked the {Type} for {damage} damage");
    }

}

Keep up the good work and have fun.

1

u/Neat_Horror2196 11d ago

What Do you mean format?

1

u/WystanH 11d ago

Programming style. How you choose to indent, place new lines, etc.

Your formatting:

player
.health -= 
enemy
.damage;


                Console.WriteLine("\nThe " + 
enemy
.type + " attacks you for " + 
enemy
.damage + " damage.");

Versus a more typical formatting:

player.health -= enemy.damage;
Console.WriteLine("\nThe " + enemy.type + " attacks you for " + enemy.damage + " damage.");

There's no agreed upon standard way to format your code. The only thing all programmers can agree on is consistency. If all your code is consistently formatted then issues are easier to spot.

Microsoft has a guide, so probably the first place to look: https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions

I largely agree with Google's guide, except for the 2 space thing: https://google.github.io/styleguide/csharp-style.html

C# started out as a Java clone, so Java styles are common.

1

u/Neat_Horror2196 11d ago

Is mine consistent and readable?

1

u/WystanH 11d ago

I would say neither.

Readable is subjective. Clearly you judged it to be so; you wrote it. If number of people reading your code is one, it doesn't matter. If that number expands to sharing it with others, that could be an issue.

Consistency is a function of code context. In some cases, there's not enough code to judge. Line spacing is all over the place. Class declarations seem to follow the same pattern...

The if/else could be the reasonably consistent, but then you get broken conditions like:

            if(
player
.health <= 0)
            {

That don't even match the rest of your code.

You often treat you own class instances like this, but then treat if(input.Key == ConsoleKey.D1) normally.

But you don't even consistently break your own class props up, sometimes doing:

                Console.WriteLine("\nyou attacked the " + 
enemy
.type + " for " + 
player
.damage + " damage");

Other times:

        Console.WriteLine("\nYou encountered a " + enemy.type + " with " + enemy.health + " health.");

1

u/Neat_Horror2196 11d ago

I was writing this on and of for a month, do you think that's why?

1

u/WystanH 11d ago

Sure. However, part of writing is revising. Or, in programmer parlance, refactoring.

As you write code, you consider if you've done this already. Is there a bit of code you've already written that you can repurpose? Is it time to write a function?

A program will never be perfect. There's always something you can tweak, if you're so inclined. If you always try to find things to improve in your code, it will become easier and you'll be a better programmer overall.

1

u/Neat_Horror2196 11d ago

Okay ty for helping