Posts de rafaelsol

arte-educador e bonequeiro

AngryAnt/UnityHacks

https://github.com/AngryAnt/UnityHacks

Anúncios

Obscure C# Coding Features

Introduction

C# is a multi-paradigm programming language encompassing strong typing, imperative, declarative, functional, generic, object-oriented (class-based) and component-oriented programming disciplines. It was developed by Microsoft within its .NET initiative, and later approved as a standard by Ecma International (ECMA-334) and ISO (ISO/IEC 23270:2006). C# is one of the programming languages designed for the Common Language Infrastructure.

C# is intended to be a simple, modern, general-purpose, object-oriented programming language. Anders Hejlsberg leads its development team, and the most recent version is C# 5.0, which was released on August 15, 2012.

There are several hidden features of C#—tricks many C# fans, addicts and experts don’t even know—including the modulus (%) and null-coalescing (??) operators, goto statement, DefaultValue attribute, and the var type.

The following sections will describe these hidden features, and include example code to demonstrate each of them.

Modulus (%) Operator

The Modulus (%) operator computes the remainder after dividing its first operand by its second. All numeric types have predefined remainder operators. In the following snippet if myNumber is an even number, then its remainder is 0 when applying the Modulus operator. If myNumber is an odd number, then its remainder would be 1 when applying the Modulus operator.

number % 2

Null-coalescing (??) Operator

The null-coalescing (??) operator returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand.

In the following code snippet the variable useNumber is set equal to number if number is NOT null.  If number is null, then useNumber is set equal to -99.

var useNumber = number ?? -99;

Goto Statement

The goto statement transfers the program control directly to a labeled statement.

A common use of goto is to transfer control to a specific switch-case label or the default label in a switch statement.

The goto statement is also useful to get out of deeply nested loops.

In the code snippet below, goto is used to direct the control flow of the program to the even: label if useNumber is an even number; and to the odd: label if useNumber is an odd number, as determined by the Modulus operation.

IfUsePic

DefaultValue Attribute

The DefaultValue specifies the default value for a property.  It is useful when one wants to have a known default value for a property.

Var Type

Variables that are declared at method scope can have an implicit type var. An implicitly typed local variable is strongly typed—just as if you had declared the type yourself, but the compiler determines the type.

Use of the var type makes code easier to read.  In the following code snippet the variable _two would be of integer type.

var _two = 2;

Example

The following code block demonstrates a code block that contains three goto statements. In this code block the integer (number) passed in is tested for whether it is null using the null-coalescing (??)operator. If it is null, the goto myEnd: statement passes control to the myEnd: label and the function returns  “You passed a null value to this function” to the calling program.

If the integer is not null, the number is tested for evenness using the modulus operator (%). If it has no remainder from the modulus operation, the goto even: statement passes control to the even: label and the function returns “You are an EVEN number” to the calling program.

If the number has a remainder from using the modulus operator (%), the goto odd: statement passes control to the odd: label and returns “You are an ODD number” to the calling program.

The code block contains a property decorated with the DefaultValue Attribute with a value of 2.

PublicClassPic

Conclusion

Knowing and understanding obscure C# coding features allows you to solve more business problems.

– See more at: http://www.teamscs.com/2014/10/obscure-c-coding-features/#sthash.dNoGzYGB.dpuf

Mappy

Using this tutorial as a basis, I have a basic map going for my little Roguelike.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using libtcod;

namespace RLtest
{

    public class Program
        {

        static int ScreenX = 20;
        static int ScreenY = 15;
        static int nPlayerX = 10;
        static int nPlayerY = 10;

        const int MAP_X = 20;
        const int MAP_Y = 15;
        const int TILE_FLOOR = 0;
        const int TILE_WALL = 1;

        static int[,] nMapArray = new int[MAP_Y, MAP_X]
        {
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
    { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 },
    { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 },
    { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 },
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
        };

        static void screenInit()
            {
                libtcod.TCODConsole.initRoot(ScreenX, ScreenY, "RLTest", false);
            }

        static void DrawMap()
        {
            for (int x = 0; x < MAP_X; x++)
            {
                for (int y = 0; y < MAP_Y; y++)
                {
                    switch (nMapArray[y, x])
                    {
                        case TILE_FLOOR:
                            TCODConsole.root.putCharEx(x, y, '.', TCODColor.desaturatedRed, TCODColor.black);
                            break;

                        case TILE_WALL:
                            TCODConsole.root.putCharEx(x, y, '#', TCODColor.grey, TCODColor.black);
                            break;
                    }
                }
            }
        }

        static void HandleKeys()
        {
                //Output 

                TCODConsole.root.print(nPlayerX, nPlayerY, "@");
                TCODConsole.flush();

                //Input
                TCODKey Key = TCODConsole.checkForKeypress();
                if (Key.KeyCode == TCODKeyCode.KeypadOne)
                {
                    if (IsPassable(nPlayerX - 1, nPlayerY + 1))
                    {
                        nPlayerY++;
                        nPlayerX--;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadTwo)
                {
                    if (IsPassable(nPlayerX, nPlayerY + 1))
                    {
                        nPlayerY++;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadThree)
                {
                    if (IsPassable(nPlayerX + 1, nPlayerY + 1))
                    {
                        nPlayerY++;
                        nPlayerX++;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadFour)
                {
                    if (IsPassable(nPlayerX - 1, nPlayerY))
                    {
                        nPlayerX--;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadSix)
                {
                    if (IsPassable(nPlayerX + 1, nPlayerY))
                    {
                        nPlayerX++;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadSeven)
                {
                    if (IsPassable(nPlayerX - 1, nPlayerY - 1))
                    {
                        nPlayerY--;
                        nPlayerX--;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadEight)
                {
                    if (IsPassable(nPlayerX, nPlayerY-1))
                    {
                        nPlayerY--;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadNine)
                {
                    if (IsPassable(nPlayerX + 1, nPlayerY - 1))
                    {
                        nPlayerY--;
                        nPlayerX++;
                    }
                }
        }
        static bool IsPassable(int x, int y)
        {
            //Check co-ords are valid
            if (x < 0 || x >= MAP_X || y < 0 || y >= MAP_Y)
                return false;
            //Store value specified
            int nTileValue = nMapArray[y, x];
            //Return true if tile is passable
            if (nTileValue == TILE_FLOOR)
                return true;

            return false;

        }

        [STAThread]
        static void Main(string[] args)
        {
            screenInit();
            while (true)
            {
                DrawMap();
                HandleKeys();
                TCODConsole.root.clear();

            }
        }
        }
}

Running this code gives the following little screen, which allows movement of the @ symbol and also prevents the player walking through walls or off the screen.

rltest_map

Of course I want to have random dungeon generation rather than just a single, hard-coded map, but this is a good starting point to learn how the map is created and drawn. I suppose the next step is to try and change a value from floor to wall using a for loop.

There seem to be several different ways of approaching the programming of a Roguelike, and I will need to learn more about programming to know which way is best. One thing I have seen is the directional values defined as strings like ‘NORTH’ instead of (x, y-1). I might put this in next time.

I particularly need to learn more about how to use methods and functions – I guess a bit of theory is in order! I may write down my understanding of the terms, to clarify them in my mind, and also to be corrected if anyone more knowledgeable that I happens past this blog.

Posted in Code | Leave a comment

Sidetracking

My next subject to work on was making a dungeon for my little guy to walk about in, but I got sidetracked while messing around with a small tutorial, which involved colouring a character. I eventually want to use Libtcod in my RL, so I decided I had better get used to programming with it. With some Googling, fiddling around and peeking at source code, I managed to get the last program running using Libtcod rather than the system library. Some of the libraries included aren’t actually being used at this stage, I’ll have to clear that up.

I had a bit of confusion about  TCODConsole.Flush() , thinking that it did the same as Console.Clear() for some reason. Turns out what I was looking for was TCODConsole.root.clear(). Flush updates the characters and any colour changes, while clear…well, clears the console. While I remember, I also had a problem running the keyboard input through the switch -turns out that second equals sign is very important!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using libtcod;

namespace RLtest
{

    public class Program
        {

        static int ScreenX = 60;
        static int ScreenY = 50;
        static int nPlayerX = 40;
        static int nPlayerY = 12;

        static void screenInit()
            {

                libtcod.TCODConsole.initRoot(ScreenX, ScreenY, "RLTest", false);
            }
        static void HandleKeys()
        {
                //Output 

                TCODConsole.root.print(nPlayerX, nPlayerY, "@");
                TCODConsole.flush();

                //Input
                TCODKey Key = TCODConsole.checkForKeypress();
                if (Key.KeyCode == TCODKeyCode.KeypadOne)
                {
                    if (nPlayerX > 1 && nPlayerY < (ScreenY - 2))
                    {
                        nPlayerY++;
                        nPlayerX--;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadTwo)
                {
                    if (nPlayerY < (ScreenY - 2))
                    {
                        nPlayerY++;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadThree)
                {
                    if (nPlayerX < (ScreenX - 2) && nPlayerY < (ScreenY - 2))
                    {
                        nPlayerY++;
                        nPlayerX++;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadFour)
                {
                    if (nPlayerX > 1)
                    {
                        nPlayerX--;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadSix)
                {
                    if (nPlayerX < (ScreenX - 2))
                    {
                        nPlayerX++;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadSeven)
                {
                    if (nPlayerX > 1 && nPlayerY > 1)
                    {
                        nPlayerY--;
                        nPlayerX--;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadEight)
                {
                    if (nPlayerY > 1)
                    {
                        nPlayerY--;
                    }
                }

                else if (Key.KeyCode == TCODKeyCode.KeypadNine)
                {
                    if (nPlayerX < (ScreenX - 2) && nPlayerY > 1)
                    {
                        nPlayerY--;
                        nPlayerX++;
                    }
                }
        }

        [STAThread]
        static void Main(string[] args)
        {
            screenInit();
            while (true)
            {
                HandleKeys();
                TCODConsole.root.clear();

            }
        }
        }
}
Posted in Code | Tagged , , , | Leave a comment

Initial Forays

I have spent a lot of time going over the C# references linked in the last post, I am beginning to get some grasp of how the language works. The logical nature of programming appeals to the scientific side of my mind, which hasn’t had much exercise since I finished high school, although it is still much easier for me to look at examples in terms of game mechanics, and probably always will be.

I have looked with interest over several <1KB Roguelikes, and they seem to be a good starting point to understand the code of the most basic elements of the genre. As RLs tend to be very complicated, and have many, many features, it is difficult to look at the source code and know where to start. The 1KRL that was hosted at http://nrkn.com/1kRl/, which seems to be down at the moment, was the one I chose to dissect first. As the code is heavily abbreviated, I went through and substituted all the letters for the words they stand for, to make it easier to understand. I am not sure of the name of the author of this RL, if you know, tell me in the comments.

You can download the original VS solution here, and the expanded solution (VS2010)here.

I have also been looking with interest at some name generation code, that I would eventually like to play with myself. My understanding of different parts of the code is dubious at the moment, but it is a great way to get direction for my learning. I have uploaded some interesting sites to the reference page, if you are interested.

Anyway, on to actually learning to code something. Based on “How to write a Roguelike in 15 Steps”, and a couple of RL coding tutorials I have looked at, getting my little @ to move around the screen is the first thing to do. I am using this tutorial, although it is in C++, it is easy enough to convert it to C# with some Googling and browsing reference sites.

I’ll document what I did here, because this is my blog and I want to. Here is the first part…

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RLtest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Clear();

            int nPlayerX, nPlayerY;

            nPlayerX = 40;
            nPlayerY = 12;

            while (true)
            {
                Console.SetCursorPosition(nPlayerX, nPlayerY);
                Console.Write("@");

            }
        }
    }
}

What this does, which is very exciting for me, and extremely boring for anyone else, is to draw an @ in the middle of the console screen. My first step towards a roguelike!


Cue epic guitar solo!

The next step is to get the symbol to move when the appropriate key is pressed. I prefer using the numpad for input, so I’m going with that. I had a bit of trouble figuring out how to use Console.ReadKey, but I got the solution from that 1KRL I have been studying – if you append .KeyChar to the end of the method, it will grab a char for you rather than the data type it gets by default, which is something like System.ConsoleKeyInfo.

namespace RLtest
{
    class Program
    {
        static void Main(string[] args)
        {

            int nPlayerX, nPlayerY;

            nPlayerX = 40;
            nPlayerY = 12;
            char input;

            while (true)
            {
                //Output
                Console.Clear();
                Console.SetCursorPosition(nPlayerX, nPlayerY);
                Console.Write("@");

                //Input
                input = (char)Console.ReadKey(true).KeyChar;

                //Processing
                switch(input)
                {
                case '8':
                        nPlayerY--;
                        break;
                case '4':
                        nPlayerX--;
                        break;
                case '6':
                        nPlayerX++;
                        break;
                case '2':
                        nPlayerY++;
                        break;
                }
            }
        }
    }
}

So now we have… an @ walking around a screen! Joy! As suggested in the tutorial, I can now add a little extra code to make it impossible to walk off the edge of the screen and crash the program. The values here for the window size are the default window size, which is 80×25, but we may want to change that in the future, so I am going to add some variables so that I can change that easily later. The numbers used here I chose arbitrarily to test if the movement code would work. As well as this, I added the ability to move diagonally as suggested in the tutorial.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RLtest
{
    class Program
    {
        static void Main(string[] args)
        {

            int nPlayerX, nPlayerY, ScreenX, ScreenY;

            ScreenX = 100;
            ScreenY = 30;
            nPlayerX = 40;
            nPlayerY = 12;

            System.Console.WindowWidth = ScreenX;
            System.Console.WindowHeight = ScreenY;

            char input;

            while (true)
            {
                //Output
                Console.Clear();     
                Console.SetCursorPosition(nPlayerX, nPlayerY);
                Console.Write("@");

                //Input
                input = (char)Console.ReadKey(true).KeyChar;

                //Processing
                switch(input)
                {
                case '1':
                        if (nPlayerX > 1 && nPlayerY < (ScreenY - 2))
                        {
                            nPlayerY++;
                            nPlayerX--;
                        }
                        break;

                case '2':
                        if (nPlayerY < (ScreenY-2))   
                            nPlayerY++;  
                        break;

                case '3':
                        if (nPlayerX < (ScreenX - 2) && nPlayerY < (ScreenY - 2))
                        {
                            nPlayerY++;
                            nPlayerX++;
                        }
                        break;

                case '4':
                        if (nPlayerX > 1)
                            nPlayerX--;
                        break;

                case '6':
                        if (nPlayerX < (ScreenX-2))
                            nPlayerX++;
                        break;

                case '7':
                        if (nPlayerX > 1 && nPlayerY > 1)
                        {
                            nPlayerY--;
                            nPlayerX--;
                        }
                        break;

                case '8':
                        if (nPlayerY > 1)
                            nPlayerY--;
                        break;

                case '9':
                        if (nPlayerX < (ScreenX - 2) && nPlayerY > 1)
                        {
                            nPlayerY--;
                            nPlayerX++;
                        }
                        break;

                }            
            }
        }
    }
}

I’ll leave this for now, the next step is to deal with map generation.

Calculate Fibonacci Series

 

This is one of the most asked question in interviews, calculating and printing Fibonacci series.

Let’s first try the iterative approach that is simple and prints all the Fibonacci series by passing the length.

Please note that we are starting the series from 0 (instead of 1).

public static voidFibonacci_Iterative(int len)

        {

            int a = 0, b = 1, c = 0;

            Console.Write(“{0} {1}”, a,b);

 

            for (int i = 2; i < len; i++)

            {

                c= a + b;

                Console.Write(” {0}”, c);

                a= b;

                b= c;

            }

       }

 

Test Results:

Input: Fibonacci_Iterative(9);

Output:

 

We can also use the recursive way to print the series against the length as below.

public static voidFibonacci_Recursive(int len)

        {

           Fibonacci_Rec_Temp(0, 1, 1, len);

       }

 

private static voidFibonacci_Rec_Temp(int a, int b, int counter,int len)

        {

            if (counter <= len)

            {

                Console.Write(“{0} “, a);

               Fibonacci_Rec_Temp(b, a + b, counter+1, len);

            }

       }

 

Here we have used two functions just to pass only the length as an input parameter. In the second method 4 parameters are required since we need to continue changing the variable’s position (in other words a -> b and b -> a + b).

We also need to increment the counter in each recursion call and to compare it with the length and continue the loop until it exceeds the length parameter. 

Test Results:

Input: Fibonacci_Recursive(11);

Output:

 

Calculate nth Fibonacci number:

Calculating the nth Fibonacci number is not difficult, we just need to pass the value with the right index.

We will first have a look at an iterative approach.

Here we are using an integer array to keep the Fibonacci numbers until n and returning the nth Fibonacci number.

public static int GetNthFibonacci_Ite(int n)

        {

            int number = n – 1; //Need to decrement by 1 since we are starting from 0

            int[] Fib = new int[number + 1];

            Fib[0]= 0;

            Fib[1]= 1;

 

            for (int i = 2; i <= number;i++)

            {

               Fib[i] = Fib[i – 2] + Fib[i – 1];

            }

            return Fib[number];

        }

 

Test Results:

Input: GetNthFibonacci_Ite(4);

Output:

 

We can also look for a recursive version of that. The only thing to consider is, here we need to pass a number less than 1 to get the nth Fibonacci number.

For example if we want the 8th Fibonacci number then we need to pass 8-1 (in other words 7) as an input (we can also create a pass-through method alternatively).

public static int GetNthFibonacci_Rec(int n)

        {

            if ((n == 0) || (n == 1))

            {

                return n;

            }

            else

                returnGetNthFibonacci_Rec(n – 1) + GetNthFibonacci_Rec(n – 2);

       }

 

 Test Results:

Input: GetNthFibonacci_Rec(8-1);

Output:

 

Please inform me of your comments/suggestions or if you have any better way to do it. J