SQL Banker's Rounding Function

The Banker's Rounding, also known as the Gaussian Rounding or Rounding to Even, rounds a given number if its fraction is half to the nearest even number.

The bellow SQL function rounds any given decimal number to a number of given digits and returns the rounded decimal number. It reads the number from right to left depending on the number of digits required and then rounds it. If the fraction is not half, then common rounding takes place.

CREATE FUNCTION [dbo].[BankersRounding]
(
	@value DECIMAL(28, 10),
	@digits INT
)

RETURNS DECIMAL (28, 10)
AS
BEGIN

	DECLARE @roundedValue DECIMAL(28, 10)
	DECLARE @roundingType INT 
	
		IF (ABS(@value - ROUND(@value, @digits, 1)) * POWER(10, @digits + 1) = 5)
			BEGIN
			
				IF (ROUND(ABS(@value) * POWER(10, @digits), 0, 1) % 2 = 0)
					BEGIN
						SET @roundingType = 1 
					END
				ELSE
					BEGIN
						SET @roundingType = 0
					END
						
				SET @roundedValue = ROUND(@value, @digits, @roundingType)
			END
				
		ELSE
			BEGIN
				SET @roundedValue = ROUND(@value, @digits)
			END
						
	RETURN @roundedValue
END

In C# there's the Round method inside the Math class that can take an enumeration overload called MidpointRounding.ToEven that does the exact same thing.

Here's an example:

using System;

namespace BankersRoundingProject
{
    public class BankersRounding
    {
        public static decimal GetRoundedValue(decimal value, int digits)
        {
            return Math.Round(value, digits, MidpointRounding.ToEven);
        }
    }
}

Temperature converting

In this post I'll try to explain you how to convert temperatures from Celsius to Fahrenheit or vice versa. I will create a small WinForms application that actually does that.

I used two doubles to store the temperature's values (one for Celsius and one for Fahrenheit), two labels (of which one will be displayed after the actual transformation takes places and will contain the transformed value), one combobox and one textbox. Oh... and almost forgot about the button that triggers the transformation and displays the result.

One more thing you will notice is that I've used Math.Round with two decimals to get a nice transformation result and I've used the String.Format method to display the transformed value instead of the usual concatenation.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace TemperatureTrasformer
{
    public partial class mainForm : Form
    {
        double celsius;
        double fahrenheit;

        ComboBox cboxTempType;
        TextBox txtTemp;
        Label lblInitial;
        Label lblResult;
        Button btnConvert;

        public mainForm()
        {
            InitializeComponent();

            //Set up the form's proprieties
            this.Text = "Temperature Converter";
            this.ClientSize = new Size(250, 150);
            this.MaximizeBox = false;
            this.StartPosition = FormStartPosition.CenterScreen;
            this.FormBorderStyle = FormBorderStyle.FixedSingle;

            //Set up the form's controls
            lblInitial = new Label();
            lblInitial.Location = new Point(10, 10);
            lblInitial.AutoSize = true;
            lblInitial.Text = "Enter the temperature you want to convert:";

            txtTemp = new TextBox();
            txtTemp.Location = new Point(10, lblInitial.Bottom + 5); 
            txtTemp.Width = 100;

            cboxTempType = new ComboBox();
            cboxTempType.Location = new Point(txtTemp.Right + 10, lblInitial.Bottom + 5);
            cboxTempType.Width = 100;
            cboxTempType.DropDownStyle = ComboBoxStyle.DropDownList;
            cboxTempType.Items.Add("Celsius");
            cboxTempType.Items.Add("Fahrenheit");
            cboxTempType.SelectedIndex = 0;

            btnConvert = new Button();
            btnConvert.Text = "Convert";
            btnConvert.Location = new Point(10, txtTemp.Bottom + 10);
            btnConvert.AutoSize = true;
            btnConvert.Click += new EventHandler(btnConvert_Click);

            lblResult = new Label();
            lblResult.Location = new Point(10, btnConvert.Bottom + 10);
            lblResult.AutoSize = true;

            this.Controls.Add(lblInitial);
            this.Controls.Add(cboxTempType);
            this.Controls.Add(txtTemp);
            this.Controls.Add(btnConvert);
        }

        void btnConvert_Click(object sender, EventArgs e)
        {
            //Convert to Fahrenheit
            if (cboxTempType.SelectedIndex == 0)
            {
                celsius = Convert.ToDouble(txtTemp.Text);
                fahrenheit = Math.Round((celsius * 9) / 5 + 32, 2);
                lblResult.Text = String.Format("The temperature in Fahrenheit is {0} degrees", fahrenheit);
                this.Controls.Add(lblResult);
            }
            //Convert to Celsius
            else if (cboxTempType.SelectedIndex == 1)
            {
                fahrenheit = Convert.ToDouble(txtTemp.Text);
                celsius = Math.Round((fahrenheit - 32) / 9 * 5, 2);
                lblResult.Text = String.Format("The temperature in Celsius is {0} degrees", celsius);
                this.Controls.Add(lblResult);
            }
        }
    }
}

Installing IIS 5.1 (for Win XP) and enabling .aspx pages

Windows XP can only accept IIS 5.1, but IIS 5.1 does not accept by default .aspx pages. This is because .aspx pages were introduced with the Framework 2.0 while IIS 5.1 predates this framework.

Installing IIS 5.1 on Windows XP:

1. Go to Control Panel
2. Open Add/Remove Programs
3. Select the Add/Remove Windows Components Tab
4. Select Internet Information Services (IIS) from the list
5. Click Next and follow the wizard

Once the installation is complete you can open your web browser and navigate to http://localhost/. IF IIS was installed correctly you should see its homepage. You will notice on the IIS homepage the page formats that it supports, but .aspx pages will not be present. To enable these pages on IIS you will need to have at least .NET Framework 2.0 installed.

Enabling .aspx pages on ISS 5.1:

1. Navigate to C:\Windows\Microsoft .NET\Framework
2. Enter the framework directory (v4.0.30319 for .NET 4.0 as example)
3. Search for a file named aspnet_regiis.exe
4. Run this program with the “ -i” command line parameter

You should see how IIS is reconfigured to use the latest framework. Now that everything should is set up, all you’ll have to do is to copy the website in the C:\Inetpub\wwwroot directory. On the local machine you can run the website by navigating to http://localhost/ or from any computer on the intranet by accessing your machine’s IP.

NOTE that IIS 5.1 can host only one site.

WPF - how to add text in a richtextbox

You mighyt have noticed that the RichTextBox control in WPF does not have a Text or Content method. so you will have to use something a little bit different. This method is usefull when you use a read only richtextbox and you want formated text in it.

First you'll have to initialize a paragraph, then add the string inside the paragraph and lastly add the paragraph to the richtextbox.

In the bellow example I will show you how to add a specific text in a richtextbox when a button is clicked.

private void btnAddText_Click(object sender, RoutedEventArgs e)
        {
//we want to clear all text inside the richtextbox, or else each time we click the button the same text will be added over and over again

            txtRichTextBox.Document.Blocks.Clear(); 

//We initialize 3 paragraphs

            Paragraph textTitle = new Paragraph();
            Paragraph textSubTitle = new Paragraph();
            Paragraph textDescription = new Paragraph();

//We will add the strings to the paragraphs as well as bolding the first and justifying the 3rd

            textTitle.Inlines.Add("This is a bolded title");
            textTitle.FontWeight = FontWeights.Bold;
            textSubTitle.Inlines.Add("This is a subtitle");
            textDescription.Inlines.Add("This is a long text so in case you'll copy paste this code you will notice how the text is justified. Just remember not to make the richtextbox too big.");
            textDescription.TextAlignment = TextAlignment.Justify;

//And here we add all 3 paragraphs to the rich text box

            txtRichTextBox.Document.Blocks.Add(textTitle);
            txtRichTextBox.Document.Blocks.Add(textSubTitle);
            txtRichTextBox.Document.Blocks.Add(textDescription);        
}

Basic Pong Game

In this post I will try to give you a basic idea on how to create a very basic pong-like game in C# and Winforms in .NET 4.0.

To start, create a new C# Winforms project and call it whatever you want.

For this project we will need 3 PictureBoxes, 1 Timer, 5 ints and 3 sizes right above the constructor. The pictureboxes represent the ball (picBoxBall) and the 2 paddles (one for the player and one for the AI - picBoxPlayer and picBoxAI). Two of the 5 ints are constant and represent the form's width and height (SCREEN_WIDTH and SCREEN_HEIGHT). Another 2 int are for the ball's speed on the X and Y axis (ballSpeedX and ballSpeedY) and last int is for the Timer's interval (gameTimeInterval). We will call the timer gameTime and the 3 sizes (sizePlayer, sizeAI sizeBall) represent the size of the 3 pictureboxes.

PictureBox picBoxPlayer, picBoxAI, picBoxBall;
        Timer gameTime;

        const int SCREEN_WIDTH = 800;
        const int SCREEN_HEIGHT = 600;
        
        Size sizePlayer = new Size(25, 100);
        Size sizeAI = new Size(25, 100);
        Size sizeBall = new Size(20, 20);

        int ballSpeedX = 3;
        int ballSpeedY = 3;
        int gameTimeInterval = 1;

In the constructor we will need to intilize our controls and the timer's Tick event which I've set the interval to 1. Also, we are going to give the position, size and color of each control.

public gameArea()//gameArea is the form's name
        {
            InitializeComponent();

            picBoxPlayer = new PictureBox();//
            picBoxAI = new PictureBox();//Initializes the PictureBoxes
            picBoxBall = new PictureBox();//

            gameTime = new Timer();//Initializes the Timer

            gameTime.Enabled = true;//Enables the Timer
            gameTime.Interval = gameTimeInterval;//Set the timer's interval

            gameTime.Tick += new EventHandler(gameTime_Tick);//Creates the Timer's Tick event

            this.Width = SCREEN_WIDTH;//sets the Form's Width
            this.Height = SCREEN_HEIGHT;//sets the Form's Height
            this.StartPosition = FormStartPosition.CenterScreen;//opens the form in center of the screen

            picBoxPlayer.Size = sizePlayer;//sets the size of the picturebox
            picBoxPlayer.Location = new Point(picBoxPlayer.Width / 2, ClientSize.Height / 2 - picBoxPlayer.Height / 2);//sets it's location (centered)
            picBoxPlayer.BackColor = Color.Blue;//fills the picturebox with a color
            this.Controls.Add(picBoxPlayer);//adds the picture box to the form

            picBoxAI.Size = sizeAI;
            picBoxAI.Location = new Point(ClientSize.Width - (picBoxAI.Width + picBoxAI.Width / 2), ClientSize.Height / 2 - picBoxPlayer.Height / 2);
            picBoxAI.BackColor = Color.Red;
            this.Controls.Add(picBoxAI);

            picBoxBall.Size = sizeBall;
            picBoxBall.Location = new Point(ClientSize.Width / 2 - picBoxBall.Width / 2, ClientSize.Height / 2 - picBoxBall.Height / 2);
            picBoxBall.BackColor = Color.Green;
            this.Controls.Add(picBoxBall);
        }

Next, in the Timer's tick event we will need to update the ball's position by adding the ballSpeedX and ballSpeedY ints to its original location and we will call 4 methods (2 for movement and 2 for collisions) that I will explain later.

void gameTime_Tick(object sender, EventArgs e)
        {
            picBoxBall.Location = new Point(picBoxBall.Location.X + ballSpeedX, picBoxBall.Location.Y + ballSpeedY);
            gameAreaCollisions();//Checks for collisions with the form's border
            padlleCollision();//Checks for collisions with the padlles
            playerMovement();//Updates the player's position
            aiMovement();//Updates the ai's position
        }

The gameAreaCollisions method basically checks to see if the ball hits form's sides. If it hits the upper or lower side of the form it inverts the Y speed and if it hist the left or right side of the form in resets the ball bu using a new method called resetBall (explained later). You will notice that I've used to different "else if", for collision with the left or right side of the form, although we could have used only one with and "or" approach. I did this because I am planning to elaborate on this approach in a later more advanced tutorial.

private void gameAreaCollisions()
        {
            if (picBoxBall.Location.Y > ClientSize.Height - picBoxBall.Height || picBoxBall.Location.Y < 0)
            {
                ballSpeedY = -ballSpeedY;
            }
            else if (picBoxBall.Location.X > ClientSize.Width)
            {
                resetBall();
            }
            else if (picBoxBall.Location.X < 0)
            {
                resetBall();
            }
        }
The resetBall method is called when the ball hits the left or right side of the form and when it does it send the ball back to the center of the screen, reseting the position. In this method you could add score incrementation for example.
private void resetBall()
        {
            picBoxBall.Location = new Point(ClientSize.Width / 2 - picBoxBall.Width / 2, ClientSize.Height / 2 - picBoxBall.Height / 2);
        }
Next is the playerMovement method which moves the player's padlle according to the cursor position. The movement on the X axis is constant and only the Y position changes.
private void playerMovement()
        {
            if (this.PointToClient(MousePosition).Y >= picBoxPlayer.Height / 2 && this.PointToClient(MousePosition).Y <= ClientSize.Height - picBoxPlayer.Height / 2)
            {
                int playerX = picBoxPlayer.Width / 2;
                int playerY = this.PointToClient(MousePosition).Y - picBoxPlayer.Height / 2;

                picBoxPlayer.Location = new Point(playerX, playerY);
            }
        }
Next is the aiMovement method which moves the AI paddles to the ball's position on Y axis (the X is always the same) whenever the ball is moving towards him. The ball comes towards the AI's paddle only when it's speed on the X axis is positive as the paddle is located in the right side of the form where the X increases.
private void aiMovement()
        {
            if (ballSpeedX > 0)
            {
                picBoxAI.Location = new Point(ClientSize.Width - (picBoxAI.Width + picBoxAI.Width / 2), picBoxBall.Location.Y - picBoxAI.Height / 2);
            }
        }
Last we have the padlleCollision method which verifies the collision with the paddles. We verify this by using the Bounds.IntersectsWith method the the PicturBox control has. As we did in the gameAreaCollisions method all we have to do is invert the speed, but this time on the X axis. I've used two ifs, although I could have used only one for the next tutorial. You can use only one with the "or" aproach.
private void padlleCollision()
        {
            if (picBoxBall.Bounds.IntersectsWith(picBoxAI.Bounds))
            {
                ballSpeedX = -ballSpeedX;
            }

            if (picBoxBall.Bounds.IntersectsWith(picBoxPlayer.Bounds))
            {
                ballSpeedX = -ballSpeedX;
            }
        }

Now press F5 and play the game. Of course, you will notice that you can't beat the AI as its paddle always moves at the ball's position. This tutorial was meant to give you a basic and general idea on how to create a pong rip off. In a later tutorial, whenever the time will allow it, I will try to show you how to create a basic AI, add some graphics, some sounds and gameplay logics (lives, score, difficulty).