Coding a Snake Game for Android



This game will use a different engine to the other games on this site as it will make a pre-determined number of “moves” each second, rather than playing as many frames of animation as possible and then timing each frame for maximum smoothness. The reason for this is we can recreate a authentic blocky/jumpy animation.
One dot for the snake and one dot for Bob waiting to be eaten. Before anyone complains that snakes don’t eat Bobs, they don’t eat apples either. As the game continues and many Bobs are eaten the snake grows in length making it more likely that the player will trap or eat himself.

Let’s start coding.
Coding the Snake Activity

As usual, we will start with an Activity which will control a thread in a class which controls the game and handles input from the player. If you want a more in-depth discussion of the interaction between the Activity and the main class then take a look at the Breakout tutorial.

Create a new project in Android Studio, use the Empty Activity template, and call it Snake. Leave the rest of the settings at their defaults. Call the Activity SnakeActivity and amend its code to be the same as this.
One dot for the snake and one dot for Bob waiting to be eaten. Before anyone complains that snakes don’t eat Bobs, they don’t eat apples either. As the game continues and many Bobs are eaten the snake grows in length making it more likely that the player will trap or eat himself.

import android.app.Activity;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Display;

public class SnakeActivity extends Activity {

    // Declare an instance of SnakeEngine
    // We will code this soon
    SnakeEngine snakeEngine;

}

Here we declare an instance of SnakeEngine called snakeEngine which doesn’t exist yet but it will soon. Now code the onCreate method of the SnakeActivity class to initialize the SnakeEngine object. Obviously there will be errors in our code but if we code SnakeActivity in full we won’t need to keep coming back to it. Add the following code and we will discuss it.

import android.app.Activity;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Display;

public class SnakeActivity extends Activity {

    // Declare an instance of SnakeEngine
    SnakeEngine snakeEngine;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Get the pixel dimensions of the screen
        Display display = getWindowManager().getDefaultDisplay();

        // Initialize the result into a Point object
        Point size = new Point();
        display.getSize(size);

        // Create a new instance of the SnakeEngine class
        snakeEngine = new SnakeEngine(this, size);

        // Make snakeEngine the view of the Activity
        setContentView(snakeEngine);
    }
}
The onCreate method uses the Display class and an object of type Point to get the resolution of the device the game is running on. Our SnakeEngine class will need a reference to the Activity and the resolution so we pass them in to the SnakeEngine constructor. The last thing we do is use snakeEngine to be the View of the SnakeActivity.
Now we can code the onPause and onResume methods. Add the following code. Again. for a full explanation read the Breakout tutorial but basically Android will call these onPause and onResume methods then these methods call the relevant methods inside SnakeEngine to start and stop the thread which handles the entire game.

// Start the thread in snakeEngine
@Override
protected void onResume() {
    super.onResume();
    snakeEngine.resume();
}

// Stop the thread in snakeEngine
@Override
protected void onPause() {
    super.onPause();
    snakeEngine.pause();
}
Making the game fullscreen and landscape

We want to use every pixel that the device has to offer so we will make changes to the app’s AndroidManifest.xml configuration file.

    In the project explorer pane in Android Studio double click on the manifests folder, this will open up the AndroidManifest.xml file in the code editor.
    In the AndroidManifest.xml file, locate the following line of code: android:name=”.SnakeActivity”>
    Place the cursor before the closing > shown above. Tap the enter key a couple of times to move the > a couple of lines below the rest of the line shown above.
    Immediately below ParallaxActivity but BEFORE the newly positioned > type or copy and paste these two lines to make the game run full screen and lock it in the landscape orientation.

android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:screenOrientation="landscape"
1
2
   
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:screenOrientation="landscape"

Add the sound to the project

Download the sounds by right-clicking on the files listed below. Add them to the Snake project by using your operating system’s file browser go to the app\src\main folder of the project and create a new folder called assets. Add your sound files to this folder. Here are my sound effects. Right-click and select Save link as… to download them.

Note: At the moment my Web host seems to be restricting me from uploading .ogg files. Just look at one of my other projects, download the files from them and rename them to suit below.  You could also make your own or download the bonus content (above). Sorry will fix this as soon as I can.

snake_crash

eat_bob

We can now get rid of the errors by moving on to the SnakeEngine class.
Coding SnakeEngine

Add a new class called SnakeEngine and amend the code as shown next so we have all the required imports.
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.graphics.Point;
import android.media.AudioManager;
import android.media.SoundPool;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
import java.util.Random;
import android.content.res.AssetManager;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;


class SnakeEngine extends SurfaceView implements Runnable {
    
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.graphics.Point;
import android.media.AudioManager;
import android.media.SoundPool;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
import java.util.Random;
import android.content.res.AssetManager;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;


class SnakeEngine extends SurfaceView implements Runnable {
    
}

When we extend SurfaceView so that the call to setContentView in the SnakeActivity class works and we implement the Runnable interface so we can later pass this class to the Thread constructor to create a Thread instance. Runnable has one method that we must implement and we will overide run soon.
The SnakeEngine variables

Add all the member variables after the class declaration then they will be ready for use as we proceed through the rest of the code.
// Our game thread for the main game loop
private Thread thread = null;

// To hold a reference to the Activity
private Context context;

// for plaing sound effects
private SoundPool soundPool;
private int eat_bob = -1;
private int snake_crash = -1;

// For tracking movement Heading
public enum Heading {UP, RIGHT, DOWN, LEFT}
// Start by heading to the right
private Heading heading = Heading.RIGHT;

// To hold the screen size in pixels
private int screenX;
private int screenY;

// How long is the snake
private int snakeLength;

// Where is Bob hiding?
private int bobX;
private int bobY;

// The size in pixels of a snake segment
private int blockSize;

// The size in segments of the playable area
private final int NUM_BLOCKS_WIDE = 40;
private int numBlocksHigh;

// Control pausing between updates
private long nextFrameTime;
// Update the game 10 times per second
private final long FPS = 10;
// There are 1000 milliseconds in a second
private final long MILLIS_PER_SECOND = 1000;
// We will draw the frame much more often

// How many points does the player have
private int score;

// The location in the grid of all the segments
private int[] snakeXs;
private int[] snakeYs;

// Everything we need for drawing
// Is the game currently playing?
private volatile boolean isPlaying;

// A canvas for our paint
private Canvas canvas;

// Required to use canvas
private SurfaceHolder surfaceHolder;

// Some paint for our canvas
private Paint paint;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
   
// Our game thread for the main game loop
private Thread thread = null;

// To hold a reference to the Activity
private Context context;

// for plaing sound effects
private SoundPool soundPool;
private int eat_bob = -1;
private int snake_crash = -1;

// For tracking movement Heading
public enum Heading {UP, RIGHT, DOWN, LEFT}
// Start by heading to the right
private Heading heading = Heading.RIGHT;

// To hold the screen size in pixels
private int screenX;
private int screenY;

// How long is the snake
private int snakeLength;

// Where is Bob hiding?
private int bobX;
private int bobY;

// The size in pixels of a snake segment
private int blockSize;

// The size in segments of the playable area
private final int NUM_BLOCKS_WIDE = 40;
private int numBlocksHigh;

// Control pausing between updates
private long nextFrameTime;
// Update the game 10 times per second
private final long FPS = 10;
// There are 1000 milliseconds in a second
private final long MILLIS_PER_SECOND = 1000;
// We will draw the frame much more often

// How many points does the player have
private int score;

// The location in the grid of all the segments
private int[] snakeXs;
private int[] snakeYs;

// Everything we need for drawing
// Is the game currently playing?
private volatile boolean isPlaying;

// A canvas for our paint
private Canvas canvas;

// Required to use canvas
private SurfaceHolder surfaceHolder;

// Some paint for our canvas
private Paint paint;

We can now code the constructor.
Coding the SnakeEngine constructor

Add this code next, be sure to add it inside the closing curly brace of the SnakeEngine class.
public SnakeEngine(Context context, Point size) {
    super(context);

    context = context;

    screenX = size.x;
    screenY = size.y;

    // Work out how many pixels each block is
    blockSize = screenX / NUM_BLOCKS_WIDE;
    // How many blocks of the same size will fit into the height
    numBlocksHigh = screenY / blockSize;

    // Set the sound up
    soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
    try {
        // Create objects of the 2 required classes
        // Use m_Context because this is a reference to the Activity
        AssetManager assetManager = context.getAssets();
        AssetFileDescriptor descriptor;

        // Prepare the two sounds in memory
        descriptor = assetManager.openFd("get_mouse_sound.ogg");
        eat_bob = soundPool.load(descriptor, 0);

        descriptor = assetManager.openFd("death_sound.ogg");
        snake_crash = soundPool.load(descriptor, 0);

    } catch (IOException e) {
        // Error
    }


    // Initialize the drawing objects
    surfaceHolder = getHolder();
    paint = new Paint();

    // If you score 200 you are rewarded with a crash achievement!
    snakeXs = new int[200];
    snakeYs = new int[200];

    // Start the game
    newGame();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
   
public SnakeEngine(Context context, Point size) {
    super(context);

    context = context;

    screenX = size.x;
    screenY = size.y;

    // Work out how many pixels each block is
    blockSize = screenX / NUM_BLOCKS_WIDE;
    // How many blocks of the same size will fit into the height
    numBlocksHigh = screenY / blockSize;

    // Set the sound up
    soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
    try {
        // Create objects of the 2 required classes
        // Use m_Context because this is a reference to the Activity
        AssetManager assetManager = context.getAssets();
        AssetFileDescriptor descriptor;

        // Prepare the two sounds in memory
        descriptor = assetManager.openFd("get_mouse_sound.ogg");
        eat_bob = soundPool.load(descriptor, 0);

        descriptor = assetManager.openFd("death_sound.ogg");
        snake_crash = soundPool.load(descriptor, 0);

    } catch (IOException e) {
        // Error
    }


    // Initialize the drawing objects
    surfaceHolder = getHolder();
    paint = new Paint();

    // If you score 200 you are rewarded with a crash achievement!
    snakeXs = new int[200];
    snakeYs = new int[200];

    // Start the game
    newGame();
}

First, we initialize,  context, screenX and screenY with the values passed in from SnakeActivity. Next, we divide the number of pixels by the final int NUM_BLOCKS_WIDE in order to determine the appropriate number of pixels in the width of blockSize. Now we can use this to work out, based on the number of vertical pixels, how many blocks high the playable area will be.

Next, the sound files are loaded and associated with an appropriately named identifier. They are now ready to play at will with soundPool.playSound.
After this, we initialized the two int arrays. snakeXs will hold the horizontal coordinate of each segment of the snake and snakeYs will hold each vertical coordinate.

The last part of the code we call the newGame method which unsurprisingly starts the game. We will code newGame shortly.
Making the thread run the game loop

All the in the run method, including method calls from the run method, works in a separate thread to the Android UI. This will allow our game to run smoothly at the same time as listening for player input. Add the run method as well as pause and resume and then we will talk about them.
@Override
public void run() {
   
    while (isPlaying) {

        // Update 10 times a second
        if(updateRequired()) {
            update();
            draw();
        }

    }
}   

public void pause() {
    isPlaying = false;
    try {
        thread.join();
    } catch (InterruptedException e) {
        // Error
    }
}

public void resume() {
    isPlaying = true;
    thread = new Thread(this);
    thread.start();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
   
@Override
public void run() {
   
    while (isPlaying) {

        // Update 10 times a second
        if(updateRequired()) {
            update();
            draw();
        }

    }
}   

public void pause() {
    isPlaying = false;
    try {
        thread.join();
    } catch (InterruptedException e) {
        // Error
    }
}

public void resume() {
    isPlaying = true;
    thread = new Thread(this);
    thread.start();
}

The pause and resume methods are called by SnakeActivity when Android or the player causes the app to call onPause or onResume. The resume method creates a new instance of Thread when required and pause stops the it when required. Now our instance of Thread will play nicely with Android.

Everything in, and called by the run method, will now happen in a separate thread.

The run method calls update and then draw. The whole thing is wrapped in a while loop that repeats continuously if isPlaying is set to true and the thread is running.

These calls are also contained within if(updateRequired()). Only if this is true are the update and draw methods called. The updateRequired method can, therefore, control the frame rate of the game ensureing the blocky/authentic motion.
Some more methods

As we saw, the newGame method is called by the constructor it is also called when the snake crashes and a new game is required. Add the newGame method.
public void newGame() {
    // Start with a single snake segment
    snakeLength = 1;
    snakeXs[0] = NUM_BLOCKS_WIDE / 2;
    snakeYs[0] = numBlocksHigh / 2;

    // Get Bob ready for dinner
    spawnBob();

    // Reset the score
    score = 0;

    // Setup nextFrameTime so an update is triggered
    nextFrameTime = System.currentTimeMillis();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
   
public void newGame() {
    // Start with a single snake segment
    snakeLength = 1;
    snakeXs[0] = NUM_BLOCKS_WIDE / 2;
    snakeYs[0] = numBlocksHigh / 2;

    // Get Bob ready for dinner
    spawnBob();

    // Reset the score
    score = 0;

    // Setup nextFrameTime so an update is triggered
    nextFrameTime = System.currentTimeMillis();
}

In the newGame method, the snake is prepared. The length is set to just one block then the head of the snake is set to the center of the screen. The first position of each of the arrays holds the head. It is only the head that we will use when we code the collision detection. Next, Bob is prepared for a terrible demise by calling spawnBob and score is initialized to .

The final bit of code in the newGame method sets nextFrameTime to whatever the current time is. This will cause the update and draw methods run.
Spawning and eating Bob

The spawnBob method uses two random int values within the ranges of zero and NUM_BLOCKS_WIDE, zero and numBlocksHigh, then initializes the horizontal and vertical location of the mouse.
public void spawnBob() {
    Random random = new Random();
    bobX = random.nextInt(NUM_BLOCKS_WIDE - 1) + 1;
    bobY = random.nextInt(numBlocksHigh - 1) + 1;
}
1
2
3
4
5
   
public void spawnBob() {
    Random random = new Random();
    bobX = random.nextInt(NUM_BLOCKS_WIDE - 1) + 1;
    bobY = random.nextInt(numBlocksHigh - 1) + 1;
}

Optimization tip: Instantiating a new instance of Random is slow and could be done in the constructor then just reused each time spawnBob is called. In this context, however it will not affect the smooth running of the game.

The eatBob method is simple too.

The snake’s length is increased by one block, a new mouse is spawned, 1 is added to the score and a sound effect is played.

Here is the code for the eatBob method to add after the spawnBob method.
private void eatBob(){
    //  Got him!
    // Increase the size of the snake
    snakeLength++;
    //replace Bob
    // This reminds me of Edge of Tomorrow. Oneday Bob will be ready!
    spawnBob();
    //add to the score
    score = score + 1;
    soundPool.play(eat_bob, 1, 1, 0, 0, 1);
}
1
2
3
4
5
6
7
8
9
10
11
   
private void eatBob(){
    //  Got him!
    // Increase the size of the snake
    snakeLength++;
    //replace Bob
    // This reminds me of Edge of Tomorrow. Oneday Bob will be ready!
    spawnBob();
    //add to the score
    score = score + 1;
    soundPool.play(eat_bob, 1, 1, 0, 0, 1);
}

The moveSnake method is quite long but doesn’t involve anything too tricky. Add the code and then we can go through it.
private void moveSnake(){
    // Move the body
    for (int i = snakeLength; i > 0; i--) {
        // Start at the back and move it
        // to the position of the segment in front of it
        snakeXs[i] = snakeXs[i - 1];
        snakeYs[i] = snakeYs[i - 1];

        // Exclude the head because
        // the head has nothing in front of it
    }

    // Move the head in the appropriate heading
    switch (heading) {
        case UP:
            snakeYs[0]--;
            break;

        case RIGHT:
            snakeXs[0]++;
            break;

        case DOWN:
            snakeYs[0]++;
            break;

        case LEFT:
            snakeXs[0]--;
            break;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   
private void moveSnake(){
    // Move the body
    for (int i = snakeLength; i > 0; i--) {
        // Start at the back and move it
        // to the position of the segment in front of it
        snakeXs[i] = snakeXs[i - 1];
        snakeYs[i] = snakeYs[i - 1];

        // Exclude the head because
        // the head has nothing in front of it
    }

    // Move the head in the appropriate heading
    switch (heading) {
        case UP:
            snakeYs[0]--;
            break;

        case RIGHT:
            snakeXs[0]++;
            break;

        case DOWN:
            snakeYs[0]++;
            break;

        case LEFT:
            snakeXs[0]--;
            break;
    }
}

The for loop starts at the last block of the snake in snakeXs and snakeYs and advances it into the location previously occupied by the block ahead of it. When the for loop is complete the last position is in the place the block ahead used to be in and the block that was just behind the head is where the head used to be.

Therefore, as long as we handle the head properly all the other blocks will be correctly positioned too.

To move the head we switch based on the current value of heading and add or subtract 1 from either the heads vertical or horizontal position.

In the detectDeath method, we do collision detection. Notice in the code that follows we check for two things. Has the snake’s head bumped into the edge of the screen and has the snake’s head bumped into a block of the snake’s body?
private boolean detectDeath(){
    // Has the snake died?
    boolean dead = false;

    // Hit the screen edge
    if (snakeXs[0] == -1) dead = true;
    if (snakeXs[0] >= NUM_BLOCKS_WIDE) dead = true;
    if (snakeYs[0] == -1) dead = true;
    if (snakeYs[0] == numBlocksHigh) dead = true;

    // Eaten itself?
    for (int i = snakeLength - 1; i > 0; i--) {
        if ((i > 4) && (snakeXs[0] == snakeXs[i]) && (snakeYs[0] == snakeYs[i])) {
            dead = true;
        }
    }

    return dead;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   
private boolean detectDeath(){
    // Has the snake died?
    boolean dead = false;

    // Hit the screen edge
    if (snakeXs[0] == -1) dead = true;
    if (snakeXs[0] >= NUM_BLOCKS_WIDE) dead = true;
    if (snakeYs[0] == -1) dead = true;
    if (snakeYs[0] == numBlocksHigh) dead = true;

    // Eaten itself?
    for (int i = snakeLength - 1; i > 0; i--) {
        if ((i > 4) && (snakeXs[0] == snakeXs[i]) && (snakeYs[0] == snakeYs[i])) {
            dead = true;
        }
    }

    return dead;
}

If either of the collision possibilities happens then detectDeath returns true to the update method which takes further action.
Coding the update method

This method does three things:

    It checks if the head has touched/eaten a mouse. If it has then the eatBob method handles things.
    It calls the moveSnake method which was coded previously.
    It calls the detectDeath method and if it returns true a sound is played and the game begins again.

All this happens ten times per second because of the way updateRequired will work. We will code updateRequired in a minute. Add the code for the update method.
public void update() {
    // Did the head of the snake eat Bob?
    if (snakeXs[0] == bobX && snakeYs[0] == bobY) {
        eatBob();
    }

    moveSnake();

    if (detectDeath()) {
        //start again
        soundPool.play(snake_crash, 1, 1, 0, 0, 1);

        newGame();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
   
public void update() {
    // Did the head of the snake eat Bob?
    if (snakeXs[0] == bobX && snakeYs[0] == bobY) {
        eatBob();
    }

    moveSnake();

    if (detectDeath()) {
        //start again
        soundPool.play(snake_crash, 1, 1, 0, 0, 1);

        newGame();
    }
}

Drawing the game

Add all the code for the draw method and then we will go through it.
public void draw() {
    // Get a lock on the canvas
    if (surfaceHolder.getSurface().isValid()) {
        canvas = surfaceHolder.lockCanvas();

        // Fill the screen with Game Code School blue
        canvas.drawColor(Color.argb(255, 26, 128, 182));

        // Set the color of the paint to draw the snake white
        paint.setColor(Color.argb(255, 255, 255, 255));

        // Scale the HUD text
        paint.setTextSize(90);
        canvas.drawText("Score:" + score, 10, 70, paint);

        // Draw the snake one block at a time
        for (int i = 0; i < snakeLength; i++) {
            canvas.drawRect(snakeXs[i] * blockSize,
                    (snakeYs[i] * blockSize),
                    (snakeXs[i] * blockSize) + blockSize,
                    (snakeYs[i] * blockSize) + blockSize,
                    paint);
        }

        // Set the color of the paint to draw Bob red
        paint.setColor(Color.argb(255, 255, 0, 0));

        // Draw Bob
        canvas.drawRect(bobX * blockSize,
                (bobY * blockSize),
                (bobX * blockSize) + blockSize,
                (bobY * blockSize) + blockSize,
                paint);

        // Unlock the canvas and reveal the graphics for this frame
        surfaceHolder.unlockCanvasAndPost(canvas);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
   
public void draw() {
    // Get a lock on the canvas
    if (surfaceHolder.getSurface().isValid()) {
        canvas = surfaceHolder.lockCanvas();

        // Fill the screen with Game Code School blue
        canvas.drawColor(Color.argb(255, 26, 128, 182));

        // Set the color of the paint to draw the snake white
        paint.setColor(Color.argb(255, 255, 255, 255));

        // Scale the HUD text
        paint.setTextSize(90);
        canvas.drawText("Score:" + score, 10, 70, paint);

        // Draw the snake one block at a time
        for (int i = 0; i < snakeLength; i++) {
            canvas.drawRect(snakeXs[i] * blockSize,
                    (snakeYs[i] * blockSize),
                    (snakeXs[i] * blockSize) + blockSize,
                    (snakeYs[i] * blockSize) + blockSize,
                    paint);
        }

        // Set the color of the paint to draw Bob red
        paint.setColor(Color.argb(255, 255, 0, 0));

        // Draw Bob
        canvas.drawRect(bobX * blockSize,
                (bobY * blockSize),
                (bobX * blockSize) + blockSize,
                (bobY * blockSize) + blockSize,
                paint);

        // Unlock the canvas and reveal the graphics for this frame
        surfaceHolder.unlockCanvasAndPost(canvas);
    }
}

First, we lock the surface which is required by Android. If this works, we clear the screen with drawColor and then change the color of all future objects we will draw by calling setColor. We do this once for the snake and once for Bob. Now we draw the text for the score.

We use a for loop to draw a block/square to represent each block of the snake. The code positions the blocks to screen coordinates by using their grid positions(contained in the array) multiplied by blockSize which was determined in the constructor based on screen resolution.

Now we can draw single block to represent Bob.
Coding updateRequired

We are almost done!

The updateRequired method will let us know if the nextFrameTime variable has been exceeded by the actual current time. If it has then a new time is retrieved and put back in nextFrameTime. The method then returns true allowing draw and update to execute. If not, false is returned and the next frame is delayed until it is time.

You can now add the updateRequired method.
public boolean updateRequired() {

    // Are we due to update the frame
    if(nextFrameTime <= System.currentTimeMillis()){
        // Tenth of a second has passed

        // Setup when the next update will be triggered
        nextFrameTime =System.currentTimeMillis() + MILLIS_PER_SECOND / FPS;

        // Return true so that the update and draw
        // functions are executed
        return true;
    }

    return false;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   
public boolean updateRequired() {

    // Are we due to update the frame
    if(nextFrameTime <= System.currentTimeMillis()){
        // Tenth of a second has passed

        // Setup when the next update will be triggered
        nextFrameTime =System.currentTimeMillis() + MILLIS_PER_SECOND / FPS;

        // Return true so that the update and draw
        // functions are executed
        return true;
    }

    return false;
}

Handling screen touches (player input)

The final code handles the player removing their finger. Holding won’t work. The onTouchEvent method uses motionEvent.getAction to detect MotionEvent.ACTION_UP. This notifies us the player’s finger has left the screen. We then use motionEvent.getX() to determine if that action was on the left or the right of the screen.

If they tap on the left side of the screen then the snake moves to the next direction in the enumeration going anti-clockwise if they tap on the right then it’s clockwise.

It’s meant to be awkward, it is authentic to the original. Add this code to handle touches on the screen.
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {

    switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_UP:
            if (motionEvent.getX() >= screenX / 2) {
               switch(heading){
                   case UP:
                       heading = Heading.RIGHT;
                       break;
                   case RIGHT:
                       heading = Heading.DOWN;
                       break;
                   case DOWN:
                       heading = Heading.LEFT;
                       break;
                   case LEFT:
                       heading = Heading.UP;
                       break;
               }
            } else {
                switch(heading){
                    case UP:
                        heading = Heading.LEFT;
                        break;
                    case LEFT:
                        heading = Heading.DOWN;
                        break;
                    case DOWN:
                        heading = Heading.RIGHT;
                        break;
                    case RIGHT:
                        heading = Heading.UP;
                        break;
                }
            }
    }
    return true;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
   
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {

    switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_UP:
            if (motionEvent.getX() >= screenX / 2) {
               switch(heading){
                   case UP:
                       heading = Heading.RIGHT;
                       break;
                   case RIGHT:
                       heading = Heading.DOWN;
                       break;
                   case DOWN:
                       heading = Heading.LEFT;
                       break;
                   case LEFT:
                       heading = Heading.UP;
                       break;
               }
            } else {
                switch(heading){
                    case UP:
                        heading = Heading.LEFT;
                        break;
                    case LEFT:
                        heading = Heading.DOWN;
                        break;
                    case DOWN:
                        heading = Heading.RIGHT;
                        break;
                    case RIGHT:
                        heading = Heading.UP;
                        break;
                }
            }
    }
    return true;
}

Validating ASP.NET Server Controls on Asp.Net !

By Bill Evjen
Reuters
December 2003
Applies to:
    Microsoft® ASP.NET
    Microsoft Visual Basic® .NET
    Microsoft Visual C#® .NET
Summary: Learn how to use all the available ASP.NET validation server controls that are at your disposal. This paper introduces these new controls and discusses tips and tricks on working with them in practical scenarios. (34 printed pages)
Introduction
Looking at Validation
The RequiredFieldValidator Control
The CompareValidator Control
The RangeValidator Control
The RegularExpressionValidator Control
The CustomValidator Control
The ValidationSummary Control
Conclusion
Introduction

In your studies of ASP.NET, you might have been introduced to a number of different types of controls, whether HTML server controls or Web server controls. This paper focuses on a series of controls that stand out from the rest—validation server controls.
Validation server controls are a series of controls that help you validate the data that the user enters into the other controls that are provided with ASP.NET. They determine whether the form can be processed based upon the rules that you define in the validation server controls.

Looking at Validation
One of the most common elements of Web pages is a form in which the user can input data that is posted back to the server. These forms are made up of different types of HTML elements that are constructed using straight HTML, HTML server controls, or Web server controls. A variety of HTML elements, such as text boxes, check boxes, radio buttons, drop-down lists and more, can be used in forms.
Often when your ASP.NET applications are collecting information from a user, you want to ensure that the data that you collect is valid. Some users are not interested in spending enough time to enter the correct information into a form, and in some cases, users might even intentionally enter false information to gain access or get past a certain step in your application's workflow process.
One of the first steps is to understand what validating data means. Validating, in this case, does not mean that if John Doe types his name into the form field of a text box as Fred Doe the computer sends an alert to inform you that the data is untruthful. No, we still do not have the capability to find out whether a statement is true.
Validation is testing to determine whether the user entered something into the field. After you determine that something was entered, you can then also check to see whether what was entered is a number or a character and if it is in the correct format. From there, you can compare user input in different fields or against values that might be held in other repositories, such as a database. You can check for many types of information, as you learn in the rest of this article.
Data collection on the Internet is one of its most important features, so you must make sure that the data you collect has value and meaning. You ensure this by eliminating any chance that the information collected does not abide by the rules you outline.

Understanding the Difference Between Server-Side and Client-Side Validation
Many people new to ASP.NET don't know the difference between client-side and server-side validation. You must understand these two different ways of validating the data users input into a Web form.
After the user enters data into a Web form, clicks the Submit button, and sends the form data to the server as a request, you can perform server-side validation on the data. If the data is incorrect or not valid, you can send back a response stating this. If, however, when the user clicks the Submit button, a scripting language that is part of the overall HTML page is initiated to check the validity of the data before it is sent to the server, this is client-side validation.
It was a lot easier to understand the difference between these forms of validation when you coded Active Server Pages 3.0 because, as the programmer, you personally performed almost all data validation. You yourself either programmed it to be client-side or server-side.
When you used server-side validation with ASP 3.0, if something the user entered was wrong, you could repost the form and ask the user to correct the information in that particular field of the form. Sometimes, you carried the correct input from the other fields back to the form page, and populated the fields for the users so they didn't have to re-enter the same information again. Some sites on the Internet don't carry this inputted information back to the form page, and the user is then required to enter all the information into the form a second time. Obviously, this may cause people to leave your site for another.
The bad thing about server-side validation is that it requires trips back and forth to the server. This takes a lot of resources and makes for a slower-paced form for the user. Nothing is more annoying to a user who is on a dial-up connection than clicking the Submit button on the form and then waiting for 20 seconds to find out that they didn't enter their password correctly.
The other option for form validation is to put some client-side JavaScript or VBScript at the top of the ASP page that checks if the information in the fields is correct. This takes care of the problem of making unnecessary trips to the server, but it requires another language to learn and manage. JavaScript is a great language, but takes a lot of time to master, and there are always problems getting your JavaScript code to work on different browsers. Listing 1 shows you an example of using client-side JavaScript to perform form validation.

Listing 1: Client-side JavaScript for form validation

<script language="javascript">
<!--
Function CheckForm(form)
{
  for(var intCtr = 0; intCtr <= (form.elements.length - 5); ++intCtr)
  {
    var temp = form.elements[intCtr];
    if(temp.type == "text" && temp.value == "")
    {
    alert("Please Enter All Information!");
      temp.focus();
      return false;
    }
  }
  return true;
}
//-->
</script>

This sample piece of JavaScript does some validation, but it doesn't check for all the in-formation that you might need on the form you are building. This piece of code determines only whether the user entered anything at all in all five fields within the form. It does not determine whether the user entered an actual e-mail address within the e-mail address text box, whether the user entered a number between two given numbers, or whether the password and the confirm password text boxes match. After awhile, you can see that you need many JavaScript functions to obtain the level of form validation required.

.NET to the Rescue!
Developers who used classic Active Server Pages 3.0 to develop Web pages might remember that they used to spend a considerable amount of their time developing validation mechanics in their pages. It was time consuming if you did it right. It was most efficient to do the validation of the form on the client-side to limit the number of requests and responses required to work through an application. As I stated, however, you were never quite sure if the requesting browser would understand the scripting code that you used for the validation. So, it was usually better, especially for critical Web applications, to bring the validation to the server.
ASP.NET has changed this by giving you the capability to use the validation server controls that are provided with the other new controls at your disposal. What makes these validation server controls effective is that when an ASP.NET page containing these controls is requested, it is the ASP.NET engine that decides whether to perform the validation on the client or on the server depending on the browser that is making the request. Therefore, your page's functionality changes depending on the requesting browser—thus enabling you to make your Web pages the best they can possibly be—rather than dummying-down your Web applications for the lowest common denominator.
Validation server controls are the only type of ASP.NET server controls that also generate client-side script. All the other controls work with the idea of making postbacks to the server (a request to the server to get a response).
Presently, six different validation server controls are available for ASP.NET:
  • RequiredFieldValidator
  • CompareValidator
  • RangeValidator
  • RegularExpressionValidator
  • CustomValidator
  • ValidationSummary
You can also customize validation for your own needs. Then, if there are any errors in the form data, these validation server controls enable you to customize the display of error information on the browser.
You place validation server controls on your page as you would any other type of controls. After the user submits the form, the user's form information is sent to the appropriate validation control, where it is evaluated. If the information doesn't validate, the control sets a page property that indicates this. After all the form information is sent to all the validation server controls, if one or more of the validation server controls cannot validate the information sent to it, the entire form input is found to be invalid, and the user is notified.
Table 1 describes each of the six validation server controls.

Table 1: Available validation server controls
Validation Server Control
Description
RequiredFieldValidator
Ensures that the user does not skip a form entry field
CompareValidator
Allows for comparisons between the user's input and another item using a comparison operator (equals, greater than, less than, and so on)
RangeValidator
Checks the user's input based upon a lower- and upper-level range of numbers or characters
RegularExpressionValidator
Checks that the user's entry matches a pattern defined by a regular expression. This is a good control to use to check e-mail addresses and phone numbers
CustomValidator
Checks the user's entry using custom-coded validation logic
ValidationSummary
Displays all the error messages from the validators in one specific spot on the page
Not all button clicks are equal
Normally, in a series of HTML form elements, there is some sort of Button, ImageButton, or LinkButton control on the page that submits the form and causes the validation to initiate. This might not be the functionality that you are always looking for in your Web forms. You may not want each and every button on the ASP.NET page to initiate validation.
For instance, you might have a Cancel or Reset button on the Web page. If the user clicks one of these buttons, you don't want that button click to validate the contents contained in the Web form.
To prevent this, you have to set the CausesValidation property for the control to False.
<asp:Button id="Button1" runat="server" Text="Button"
  CausesValidation="False"></asp:Button>

The RequiredFieldValidator Control
The RequiredFieldValidator server control makes sure that the user enters something into the field that it is associated with in the form. You need to tie the RequiredFieldValidator to each control that is a required field in the form. Although this is the simplest of the validation server controls, you must understand certain things about it.
To see an example of using the RequiredFieldValidator server control, create a Web form that contains a TextBox server control and a Button server control. Next to the button, place a RequiredFieldValidator server control. Your ASP.NET page should look like the code illustrated in Listing 2.

Listing 2: Using the RequiredFieldValidator control
Visual Basic .NET

<%@ Page Language="VB" %>
<script runat="server">

    Sub Button1_Click(sender As Object, e As EventArgs)
       Label1.Text = "Page is valid!"
    End Sub

</script>
<html>
<head>
</head>
<body>
    <form runat="server">
        <p>
            <asp:TextBox id="TextBox1"
             runat="server"></asp:TextBox>
            &nbsp;
            <asp:RequiredFieldValidator
             id="RequiredFieldValidator1" runat="server"
             ErrorMessage="Required!"
             ControlToValidate="TextBox1">
            </asp:RequiredFieldValidator>
        </p>
        <p>
            <asp:Button id="Button1" onclick="Button1_Click"
             runat="server" Text="Button"></asp:Button>
        </p>
        <p>
            <asp:Label id="Label1" runat="server"></asp:Label>
        </p>
    </form>
</body>
</html>

Visual C# .NET
<%@ Page Language="C#" %>
<script runat="server">

    void Button1_Click(Object sender, EventArgs e) {
       Label1.Text = "Page is valid!";
    }

</script>
<html>
<head>
</head>
<body>
    <form runat="server">
        <p>
            <asp:TextBox id="TextBox1"
             runat="server"></asp:TextBox>
            &nbsp;
            <asp:RequiredFieldValidator
             id="RequiredFieldValidator1" runat="server"
             ErrorMessage="Required!"
             ControlToValidate="TextBox1">
            </asp:RequiredFieldValidator>
        </p>
        <p>
            <asp:Button id="Button1" onclick="Button1_Click"
             runat="server" Text="Button"></asp:Button>
        </p>
        <p>
            <asp:Label id="Label1" runat="server"></asp:Label>
        </p>
    </form>
</body>
</html>

Run this page and then omit putting a value in the text box. When you click the button, you get a result similar to that shown in Figure 1.

Figure 1: Causing the RequiredFieldValidator server control to fire
There are a few things to be aware of when using the RequiredFieldValidator server control in your ASP.NET pages. First of all, the most important property of this validation control is the ControlToValidate property. The value assigned to this control needs to be the value of the id property for the control to which you want to link the RequiredFieldValidator control. You can link only one RequiredFieldValidator server control to any other server control on the page. For instance, if you have three required TextBox controls on your ASP.NET page, you need three separate RequiredFieldValidator controls to make sure that they are all required.
The second property of this control is the ErrorMessage property. This is the text that appears where the RequiredFieldValidator control is located on the ASP.NET page if the TextBox is left empty. Instead of using the ErrorMessage property, you can also use the Text property:
<asp:RequiredFieldValidator id="RequiredFieldValidator1"
  runat="server" Text="Required!"
  ControlToValidate="TextBox1">
</asp:RequiredFieldValidator>
Or you can use the following construct:
<asp:RequiredFieldValidator id="RequiredFieldValidator1"
  runat="server" ControlToValidate="TextBox1">
  Required!
</asp:RequiredFieldValidator>

As you run this simple page, notice a few things. First of all, if you are running a client that is considered an upper-level browser (for example, Internet Explorer 4.0 or better), the code generated to perform the validation is client-side. To see this, right-click the page, and then click View Source. You see JavaScript in the code of the page.
The JavaScript in the code of the page means that the required field checking against the text box on the page is done client-side. To test this, simply click the button on the page, and you see the Required! error message displayed. Next, enter a value in the TextBox control, and then press TAB. The RequiredFieldValidator server control is then triggered.
By default, red text is used for the error messages that are shown by these validation server controls. As with most of the ASP.NET server controls, however, you can change the style of the controls by changing the properties of the control in code or within the designer. For instance, you can apply a more complex style as illustrated here:
<asp:RequiredFieldValidator id="RequiredFieldValidator1"
  runat="server" ControlToValidate="TextBox1" BackColor="DarkGray"
  BorderColor="Black" BorderStyle="Solid" BorderWidth="1px"
  ForeColor="White" Font-Bold="True" Font-Names="Verdana"
  Font-Size="X-Small">&nbsp;Enter something&nbsp;
</asp:RequiredFieldValidator>

Using code similar to the preceding, you can get a more elaborate result, as shown in Figure 2.

Figure 2: A RequiredFieldValidator control with a little more style

Note   The RequiredFieldValidation server control works with most HTML form elements except for check boxes. You cannot validate against the CheckBox or CheckBoxList server controls using the RequiredFieldValidator server control. Instead you need to use the CustomValidator server control. An example of this is shown later in this article.
Double-Checking Client-Side Validation
One interesting point is that even though the form data is validated on the client (eliminating the need for additional requests to and responses from the server to validate the data), the data entered is re-verified on the server. After the data is checked on the client and found valid, it is rechecked on the server using the same validation rules. These are rules that you establish to ensure against some tricky programmer out there trying to bypass the validation process by posting the page to the server as if it passed validation.

Using the InitialValue Property with a TextBox Server Control
Another property to be aware of when working with the RequiredFieldValidator server control is the InitialValue property. Instead of being empty, HTML form elements can be populated with default values. In this case, you expect the user to change the value in these elements.
This situation is illustrated in the Listing 3, which shows a TextBox server control with an associated RequiredFieldValidator server control.

Listing 3: A TextBox control with a default value
<asp:TextBox id="TextBox1" runat="server">Hello</asp:TextBox>
  &nbsp;
<asp:RequiredFieldValidator id="RequiredFieldValidator1" 
  runat="server" ErrorMessage="Please change value"
  ControlToValidate="TextBox1" InitialValue="Hello">
</asp:RequiredFieldValidator>

In this example, the single text box has a default value of Hello. The value you place here can be from any source, even a dynamic source. There is also a RequiredFieldValidator server control that is assigned to validate this text box. In this case, you want the user to change the initial value of this control to something other than the default value of the InitialValue property —Hello. You can also populate the value of this property from a dynamic source, just as you can populate the TextBox server control from a dynamic source.
RequiredFieldValidator1.InitialValue = some value

Because of the InitialValue property, if the user tries to submit the form without changing the value in the text box, the RequiredFieldValidator control fires and the form does not post to the server. If the user changes the value in the text box and submits the form, this RequiredFieldValidator control does not fire and the form is posted.

Requiring a Value Change and Disallowing Empty Values at the Same Time
When using the RequiredFieldValidator control against a text-based control such as a TextBox control, you can use the InitialValue property. The form validation fails if the value contained in the associated control is not changed from this value. If you use this kind of construct, however, the user can change the value of the text box in any manner to get past the validation. He or she can even empty the text box of any value, and it still passes the validation process.
In some situations, you can require the user not only to change the initial value of the text box, but also to input some value so that it is not empty. To do this, use two RequiredFieldValidator server controls. The first RequiredFieldValidator server control uses the InitialValue property to ensure that the user changes the default value in the text box that the control is associated with. The second RequiredFieldValidator control validates that the same text box is not left empty, as illustrated in Listing 4.
Listing 4: A single TextBox control with two RequiredFieldValidator controls
<asp:TextBox id="TextBox1" runat="server">Hello</asp:TextBox>
  &nbsp;
<asp:RequiredFieldValidator id="RequiredFieldValidator1"
  runat="server" ErrorMessage="Please change value"
  ControlToValidate="TextBox1" InitialValue="Hello">
</asp:RequiredFieldValidator>
<asp:RequiredFieldValidator id="RequiredFieldValidator2"
  runat="server" ErrorMessage="Do not leave empty"
  ControlToValidate="TextBox1">
</asp:RequiredFieldValidator>

Using the InitialValue Property with a DropDownList Control
A good way of using the InitialValue property is with the DropDownList server control. For instance, a drop-down list might have a default value that is not an empty value (by default, some text appears in it). An example of a drop-down list with the RequiredFieldValidator that uses the InitialValue property is illustrated in Listing 5.
Listing 5: Using the RequiredFieldValidator server control with the Drop-DownList server control
<asp:DropDownList id="DropDownList1" runat="server">
   <asp:ListItem Selected="True">Select a profession</asp:ListItem>
   <asp:ListItem>Programmer</asp:ListItem>
   <asp:ListItem>Lawyer</asp:ListItem>
   <asp:ListItem>Doctor</asp:ListItem>
   <asp:ListItem>Artist</asp:ListItem>
</asp:DropDownList>
  &nbsp;
<asp:RequiredFieldValidator id="RequiredFieldValidator1" 
  runat="server" ErrorMessage="Please make a selection"
  ControlToValidate="DropDownList1"
  InitialValue="Select a profession">
</asp:RequiredFieldValidator>

Using this kind of construct enables you to place a description of the actions required in the drop-down list and also requires the user to make a selection from the choices. To get past the validation process, the user must make a selection other than the Select a profession choice. If the user doesn't enter a profession, an error message is returned (see Figure 3). It takes a lot of code to write your own JavaScript function for this procedure, and that JavaScript also has to be browser-independent. With ASP.NET, the RequiredFieldValidator server control takes care of that.
Figure 3: Validation error based upon the DropDownList control
The CompareValidator Control
The CompareValidator server control compares the value entered into the form field to another field, a database value, or other value that you specify. When comparing against data types, you just set the OperatorDataTypeCheck. After that is done, you can set the Type attribute to String, Integer, Double, Date, or Currency in the CompareValidator control to make sure that the user's input into the field is the specified type.

Validating Against Other Controls on the Web Form
Using the CompareValidator server control, you can make comparisons between different controls within a form on your ASP.NET page. For example, if you want to compare what the user enters in the Password field to the entry in the Confirm Password field to see whether they are the same, you can use the CompareValidator server control. Using these two fields is a common practice when a form asks for a password. It ensures that the user doesn't mistype the password (see Listing 6).

Listing 6: Using the CompareValidator server control
Visual Basic .NET
<%@ Page Language="VB" %>
<script runat="server">

    Sub Button1_Click(sender As Object, e As EventArgs)
       Label1.Text = "Passwords match"
    End Sub

</script>
<html>
<head>
</head>
<body>
    <form runat="server">
        <p>
            Password<br>
            <asp:TextBox id="TextBox1" runat="server"
             TextMode="Password"></asp:TextBox>
             &nbsp;
            <asp:CompareValidator id="CompareValidator1"
             runat="server" ErrorMessage="Passwords do not match!"
             ControlToValidate="TextBox2"
             ControlToCompare="TextBox1"></asp:CompareValidator>
        </p>
        <p>
            Confirm Password<br>
            <asp:TextBox id="TextBox2" runat="server"
             TextMode="Password"></asp:TextBox>
        </p>
        <p>
            <asp:Button id="Button1" onclick="Button1_Click"
             runat="server" Text="Login"></asp:Button>
        </p>
        <p>
            <asp:Label id="Label1" runat="server"></asp:Label>
        </p>
    </form>
</body>
</html>

Visual C# .NET
<%@ Page Language="C#" %>
<script runat="server">

    void Button1_Click(Object sender, EventArgs e) {
       Label1.Text = "Passwords match";
    }

</script>
<html>
<head>
</head>
<body>
    <form runat="server">
        <p>
            Password<br>
            <asp:TextBox id="TextBox1" runat="server"
             TextMode="Password"></asp:TextBox>
             &nbsp;
            <asp:CompareValidator id="CompareValidator1"
             runat="server" ErrorMessage="Passwords do not match!"
             ControlToValidate="TextBox2"
             ControlToCompare="TextBox1"></asp:CompareValidator>
        </p>
        <p>
            Confirm Password<br>
            <asp:TextBox id="TextBox2" runat="server"
             TextMode="Password"></asp:TextBox>
        </p>
        <p>
            <asp:Button id="Button1" onclick="Button1_Click"
             runat="server" Text="Login"></asp:Button>
        </p>
        <p>
            <asp:Label id="Label1" runat="server"></asp:Label>
        </p>
    </form>
</body>
</html>

In this example, the Web form uses two TextBox server controls. One is for the user to enter the password, and the second TextBox control requires the user to enter the password again to ensure they didn't mistype the original. By using the CompareValidator server control, you guarantee that they are equal strings. If they are not equal, the page returns an error message (see Figure 4). If they are equal, your page submits as valid.

Figure 4: In this example, the user mistyped the password and got an error message.
Validating Against Constants
You can also use the CompareValidator server control to make sure that the value typed into the form field by a user is valid when compared against a constant, some dynamic value that you retrieve, or that it adheres to a specific data type. Listing 7 shows an example of this.

Listing 7: Checking to make sure value entered is of a specific data type
Age:
<asp:TextBox id="TextBox1" runat="server" MaxLength="3">
</asp:TextBox>
&nbsp;
<asp:CompareValidator id="CompareValidator1" runat="server"
  ErrorMessage="You must enter a number"
  ControlToValidate="TextBox1" Type="Integer"
  Operator="DataTypeCheck"></asp:CompareValidator>

In this example, the user must enter an integer in the text box; otherwise, the CompareValidator server control fires and displays an error message on the page. By giving the Type property of the CompareValidator server control a value of Integer, you ensure that the value entered in the text box conforms to this .NET Framework data type.
You also have the option of not only comparing values against specific data types, but also ensuring that values are valid when compared against certain constants (see Listing 8).

Listing 8: Comparing values against constants for validity
Age:
<asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
  &nbsp;
<asp:CompareValidator id="CompareValidator1" runat="server"
  Operator="GreaterThan" ValueToCompare="18"
  ControlToValidate="TextBox1" ErrorMessage="You must be older than
  18 to join" Type="Integer"></asp:CompareValidator>

In this case, a few checks are made against any value that the user types in the text box. The first is based on the Type property in the CompareValidator server control. The Type property has the value of Integer, therefore any value placed in the text box needs to conform to this .NET Framework data type. If the user enters a string into the text box, the form submission is invalid. The next property is the Operator property. This property has a value of GreaterThan, meaning that for the form submission to be valid, the value entered in the text box has to be greater than the value that is assigned to the ValueToCompare property. For this CompareValidator server control, the ValueToCompare property has a value of 18. This means that the value entered in the text box on the page must be an integer greater than 18. If it does not meet these criteria, the value is considered invalid, and the CompareValidator server control displays an error message in the browser.
In the situation shown in Listing 8, you are not comparing two fields in the form; instead, you are comparing one field against a value that you have specified in code. The Operator property can contain one of the following values:
  • Equal
  • NotEqual
  • GreaterThan
  • GreaterThanEqual
  • LessThan
  • LessThanEqual
  • DataTypeCheck
The RangeValidator Control
The RangeValidator server control is similar to the CompareValidator server control, but the RangeValidator server control compares what is entered into the form field with two values and makes sure that what was entered by the user is between these two specified values.
For instance, imagine that you have a text box where you want end users to enter their ages. Instead of being greater than or less than a specific constant, you want the values entered to be between a specific range of numbers. For this, you use the RangeValidator server control, as illustrated in Listing 9.

Listing 9: Using the RangeValidator server control to work with a range of numbers
Age:
<asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
  &nbsp;
<asp:RangeValidator id="RangeValidator1" runat="server"
  ControlToValidate="TextBox1" Type="Integer"
  ErrorMessage="You must be between 30 and 40"
  MaximumValue="40" MinimumValue="30"></asp:RangeValidator>

In this case, the user should enter a value between 30 and 40 in the text box. If some number is entered that is outside of this range, the RangeValidator server control fires an error message and considers the form submission invalid.
The Type property enables you to make comparisons against many different .NET Framework types, such as String, Integer, Double, Date, and Currency. These choices enable you to do a number of range comparisons. For instance, you can use the Currency value in the Type property to retrieve monetary-value entries that are within a certain range. You can also use the Date value for the Type property to make sure that the entry is between specific date ranges.
Also, just as you can use the String data type in the CompareValidator server control, you can use the String data type with the RangeValidator server control to make sure that the value entered falls within a specific range of characters. For example, if the user is entering her last name, and you want only people with last names starting with M and P to proceed, you can easily do this by using the RangeValidator server control, as illustrated in Listing 10.

Listing 10: Comparing an entry to a range of characters
Last name:
<asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
  &nbsp;
<asp:RangeValidator id="RangeValidator1" runat="server"
  ControlToValidate="TextBox1"
  ErrorMessage="Your last name needs to be between M and P"
  MaximumValue="Q" MinimumValue="M"></asp:RangeValidator>

In the example in Listing 10, the value is being checked against a range that is specified by using the MaximumValue and MinimumValue properties. Notice, in this example, that the Type property is not specified. In this case, it doesn't need to be specified because the default value of the Type property is String. If not specified, it is considered to have the value of String.

The RegularExpressionValidator Control
The RegularExpressionValidator server control is a validation control that enables you to check the user's input based on a pattern defined by a regular expression. This is a great control to check whether the user has entered a valid e-mail address or telephone number. In the past, these kinds of validations took a considerable amount of JavaScript coding. The RegularExpressionValidator control with ASP.NET saves coding time.
In the Properties window for the RegularExpressionValidator server control, click the button in the ValidationExpression box, and Visual Studio.NET provides you with a short list of expressions to use in your form via the Regular Expression Editor. However, you are not limited to these regular expressions in your ASP.NET applications. The list of prepared expressions is shown in Figure 5.

Figure 5: The Regular Expression Editor
For an example of using the RegularExpressionValidator server control to make sure that a value entered in a text box is an e-mail address, look at Listing 11.

Listing 11: Validating an e-mail address
Email:
<asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
  &nbsp;
<asp:RegularExpressionValidator id="RegularExpressionValidator1"
  runat="server" ControlToValidate="TextBox1"
  ErrorMessage="You must enter an email address"
  ValidationExpression="\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">
</asp:RegularExpressionValidator>

In this example, notice that you place the Internet e-mail address regular expression in your ValidationExpression property. The great thing is that it is pretty simple, and it takes hardly any coding. Figure 6 shows the error message that results if a user enters an incorrect e-mail address in the text box.

Figure 6: Validating whether an e-mail address is entered in a text box
Note   The e-mail address is checked only to see whether it is in the correct format. The e-mail address is not checked in to ensure that it is an actual e-mail address.
A great place on the Internet to find free regular expressions is the RegEx Library at

Using Images for Your Error Messages
One interesting way of showing your error messages when using validation controls is to use images along with text for identifying errors on your ASP.NET pages. This secret is not limited to the RegularExpressionValidator server control, but can be used with all the validation server controls.
To use an image instead of text for your error messages, you create something similar to the code in Listing 13.

Listing 13: Using images for your validation messages
Email:
<asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
  &nbsp;
<asp:RegularExpressionValidator id="RegularExpressionValidator1"
  runat="server" ControlToValidate="TextBox1"
  ErrorMessage='<img src="error.gif">'
  ValidationExpression="\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">
</asp:RegularExpressionValidator>

To use an image instead of text for your error messages, you use an HTML string that points to the image that you want to display for the value of the ErrorMessage property (see Figure 7).

Figure 7: An image is displayed when the incorrect e-mail address is entered.

The CustomValidator Control
You are not limited to the validation controls that have been shown thus far in this article; you also have the CustomValidator server control. The CustomValidator server control enables you to develop your own custom server-side or client-side validations. At times, you may want to compare the user's input to a value in a database, or to determine whether his input conforms to some arithmetic validation that you are looking for (for instance, if the number is even or odd). You can do all this and more by using this type of validation control.

Client-side Validation
One of the cool things about using the validation controls, in general, is that they allow for client-side validation of certain HTML server controls. As I said, you can create your own JavaScript functions that provide you with a higher level of validation capabilities.
Listing 14 illustrates how to use JavaScript and the CustomValidator server control to expand upon the default validation capabilities that are provided to you with the .NET Framework.

Listing 14: Creating your own client-side validation functions
Visual Basic .NET
<%@ Page Language="VB" %>
<script runat="server">

    Sub Button1_Click(sender As Object, e As EventArgs)
       Label1.Text = "VALID NUMBER!"
    End Sub

</script>
<html>
<head>
    <script language="JavaScript">
        function validateNumber(oSrc, args) {
           args.IsValid = (args.Value % 5 == 0);
        }
    </script>
</head>
<body>
    <form runat="server">
        <p>
            Number:
            <asp:TextBox id="TextBox1"
             runat="server"></asp:TextBox>
             &nbsp;
            <asp:CustomValidator id="CustomValidator1"
             runat="server" ControlToValidate="TextBox1"
             ErrorMessage="Number must be divisible by 5"
             ClientValidationFunction="validateNumber">
            </asp:CustomValidator>
        </p>
        <p>
            <asp:Button id="Button1" onclick="Button1_Click"
             runat="server" Text="Button"></asp:Button>
        </p>
        <p>
            <asp:Label id="Label1" runat="server"></asp:Label>
        </p>
    </form>
</body>
</html>

Visual C# .NET
<%@ Page Language="C#" %>
<script runat="server">

    void Button1_Click(Object sender, EventArgs e) {
       Label1.Text = "VALID NUMBER!";
    }

</script>
<html>
<head>
    <script language="JavaScript">
        function validateNumber(oSrc, args) {
           args.IsValid = (args.Value % 5 == 0);
        }
    </script>
</head>
<body>
    <form runat="server">
        <p>
            Number:
            <asp:TextBox id="TextBox1"
             runat="server"></asp:TextBox>
             &nbsp;
            <asp:CustomValidator id="CustomValidator1"
             runat="server" ControlToValidate="TextBox1"
             ErrorMessage="Number must be divisible by 5"
             ClientValidationFunction="validateNumber">
            </asp:CustomValidator>
        </p>
        <p>
            <asp:Button id="Button1" onclick="Button1_Click"
             runat="server" Text="Button"></asp:Button>
        </p>
        <p>
            <asp:Label id="Label1" runat="server"></asp:Label>
        </p>
    </form>
</body>
</html>

The important part of the CustomValidator server control here is the ClientValidationFunction property. The value of this property must be the client-side JavaScript function that is in the page—in this case, the validateNumber function. By simply using this with the ClientValidationFunction property, you have tied the validation process to the custom client-side function that you created, as illustrated in Figure 8.

Figure 8: Performing a custom client-side validation using the CustomValidator server control
You set the args.IsValid property to either True or False in the JavaScript function. The args.Value property is the value from the user that is retrieved from the control that the CustomValidator server control is tied to.
Using the ClientValidationFunction property enables you to incorporate your own JavaScript functions into ASP.NET controls so that they behave like the other validation controls.

Server-side Validation
The other way of performing validation on Web forms using the CustomValidator server control is to use server-side validation. This is just as easy as the client-side validation.
Server-side validation of your Web forms enables you to create rather elaborate validation capabilities. Listing 15 shows you a not-too-elaborate example of server-side checking. Here the code determines whether the number entered in the text box on the ASP.NET page is even.

Listing 15: Creating your own server-side validation functions
Visual Basic .NET
<%@ Page Language="VB" %>
<script runat="server">

    Sub Button1_Click(sender As Object, e As EventArgs)
       If Page.IsValid Then
          Label1.Text = "VALID ENTRY!"
       End If
    End Sub
   
    Sub ValidateNumber(sender As Object, args As ServerValidateEventArgs)
       Try
          Dim num As Integer = Integer.Parse(args.Value)
          args.IsValid = ((num mod 5) = 0)
       Catch ex As Exception
          args.IsValid = false
       End Try
    End Sub

</script>
<html>
<head>
</head>
<body>
    <form runat="server">
        <p>
            Number:
            <asp:TextBox id="TextBox1"
             runat="server"></asp:TextBox>
             &nbsp;
            <asp:CustomValidator id="CustomValidator1"
             runat="server" ControlToValidate="TextBox1"
             ErrorMessage="Number must be divisible by 5"
             OnServerValidate="ValidateNumber"></asp:CustomValidator>
        </p>
        <p>
            <asp:Button id="Button1" onclick="Button1_Click"
             runat="server" Text="Button"></asp:Button>
        </p>
        <p>
            <asp:Label id="Label1" runat="server"></asp:Label>
        </p>
    </form>
</body>
</html>

Visual C# .NET
<%@ Page Language="C#" %>
<script runat="server">

      void Button1_Click(Object sender, EventArgs e) {
         if (Page.IsValid) {
            Label1.Text = "VALID ENTRY!";
         }
      }

      void ValidateNumber(object source, ServerValidateEventArgs args)
      {
         try
         {
            int num = int.Parse(args.Value);
            args.IsValid = ((num%5) == 0);
         }
         catch(Exception ex)
         {
            args.IsValid = false;
         }
      }

</script>
<html>
<head>
</head>
<body>
    <form runat="server">
        <p>
            Number:
            <asp:TextBox id="TextBox1"
             runat="server"></asp:TextBox>
             &nbsp;
            <asp:CustomValidator id="CustomValidator1"
             runat="server" ControlToValidate="TextBox1"
             ErrorMessage="Number must be even"
             OnServerValidate="ValidateNumber"></asp:CustomValidator>
        </p>
        <p>
            <asp:Button id="Button1" onclick="Button1_Click"
             runat="server" Text="Button"></asp:Button>
        </p>
        <p>
            <asp:Label id="Label1" runat="server"></asp:Label>
        </p>
    </form>
</body>
</html>

Performing custom server-side validation with the CustomValidator server controls requires that you use the OnServerValidate property instead of the ClientValidationFunction property. The ClientValidationFunction is used with the CustomValidator server control when working with client-side validation.
In this case, you need to give the OnServerValidate property a value that is equal to the name of the server-side function that you would write in one of the .NET-compliant languages.

Making Validation More Secure
If you are going to use the CustomValidator server control for client-side validation, you should also consider re-evaluating the user's input using a server-side validation function.
It is not too hard for some people to post a form back to your server and bypass or fool the client-side validation. If you re-evaluate the input on the server, you can stop this from occurring, making your ASP.NET applications more secure.

Using the CustomValidator server control to validate the Checkbox server control
If you have been working through the examples so far in this article, note that there wasn't a validation server control in place that was able to validate the CheckBox server control. Don't be too worried. You can use the CustomValidator server control to work through this control. You can use it any time that a validation server control on your page is not using the ControlToValidate property. For an example of this, see Listing 16.

Listing 16: Validating a check box Visual Basic .NET
<%@ Page Language="VB" %>
<script runat="server">

    Sub CustomValidator1_ServerValidate(source As Object, _
       args As ServerValidateEventArgs)

       args.IsValid = (CheckBox1.Checked = True)
    End Sub
   
    Sub Button1_Click(sender As Object, e As EventArgs)
       If Page.IsValid Then
          Label1.Text = "Thank you for your donation!"
       Else
          Label1.Text = ""
       End If
    End Sub

</script>
<html>
<head>
</head>
<body>
    <form runat="server">
        <p>
            Check checkbox if you want to donate $10
        </p>
        <p>
            <asp:CheckBox id="CheckBox1" runat="server"
             Text="Donate $10"></asp:CheckBox>
            &nbsp;
            <asp:CustomValidator id="CustomValidator1"
             runat="server" ErrorMessage="Please donate $10"
             OnServerValidate="CustomValidator1_ServerValidate">
            </asp:CustomValidator>
        </p>
        <p>
            <asp:Button id="Button1" onclick="Button1_Click"
             runat="server" Text="Submit"></asp:Button>
        </p>
        <p>
            <asp:Label id="Label1" runat="server"></asp:Label>
        </p>
    </form>
</body>
</html>

Visual C# .NET
<%@ Page Language="C#" %>
<script runat="server">

   void CustomValidator1_ServerValidate(Object source,
      ServerValidateEventArgs args) {
  
      args.IsValid = (CheckBox1.Checked == true);
   }

   void Button1_Click(Object sender, EventArgs e) {
      if (Page.IsValid) {
         Label1.Text = "Thank you for your donation!"; }
      else {
         Label1.Text = "";
      }
   }

</script>
<html>
<head>
</head>
<body>
    <form runat="server">
        <p>
            Check checkbox if you want to donate $10
        </p>
        <p>
            <asp:CheckBox id="CheckBox1" runat="server"
             Text="Donate $10"></asp:CheckBox>
            &nbsp;
            <asp:CustomValidator id="CustomValidator1"
             runat="server" ErrorMessage="Please donate $10"
             OnServerValidate="CustomValidator1_ServerValidate">
            </asp:CustomValidator>
        </p>
        <p>
            <asp:Button id="Button1" onclick="Button1_Click"
             runat="server" Text="Submit"></asp:Button>
        </p>
        <p>
            <asp:Label id="Label1" runat="server"></asp:Label>
        </p>
    </form>
</body>
</html>

Note that a CheckBox server control appears on the page. Also notice that there isn't a validation server control on the page that has this CheckBox server control tied to it via any property settings. Instead, a CustomValidator server control on the page references a server-side function called CustomValidator1_ServerValidate.
Within this server-side function, validation performed in the code checks whether the CheckBox server control's Checked property has a value of True (meaning that it is checked). If the value of this property is True, the CustomValidator server control is passed a True value—meaning that the input passed the test.
The CustomValidator server control enables you to do almost any type of validations that you can think of. This is a great control to use if you do any database validations on the input that is entered into a form by a user. This control can also apply any complicated logic that you want to include in the validation process.

The ValidationSummary Control
The ValidationSummary server control works with all the validation server controls on the page. It takes all the error messages that the other validation controls send back to the page and puts them all in one spot (that you specify) on the page. These error messages can be displayed in a list, bulleted list, or paragraph.

Showing a Bulleted List of Errors
You can use the ValidationSummary server control in a number of ways, but the example in Listing 17 shows you how to use it in a simple manner. For this example, two text boxes on the page are associated with a RequiredFieldValidator control. When an error is triggered, not only does it display the error next to the text box itself, it also displays it in a summary at the bottom of the ASP.NET page.

Listing 17: Having a summary of errors appear on the screen
<p>First name
   <asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
    &nbsp;
   <asp:RequiredFieldValidator id="RequiredFieldValidator1"
    runat="server" ErrorMessage="You must enter your first name"
    ControlToValidate="TextBox1"></asp:RequiredFieldValidator>
</p>
<p>Last name
   <asp:TextBox id="TextBox2" runat="server"></asp:TextBox>
    &nbsp;
   <asp:RequiredFieldValidator id="RequiredFieldValidator2"
    runat="server" ErrorMessage="You must enter your last name"
    ControlToValidate="TextBox2"></asp:RequiredFieldValidator>
</p>
<p>
   <asp:Button id="Button1" onclick="Button1_Click" runat="server"
    Text="Submit"></asp:Button>
</p>
<p>
   <asp:ValidationSummary id="ValidationSummary1" runat="server"
    HeaderText="You received the following errors:">
   </asp:ValidationSummary>
</p>
<p>
   <asp:Label id="Label1" runat="server"></asp:Label>
</p>

Using this kind of construct, when the validation server control is triggered, error messages similar to the ones shown in Figure 9 appear on the screen.

Figure 9: Validation errors shown using the ValidationSummary server control
By default, the ValidationSummary server control shows the errors in a bulleted list on the page using red text. You have the option to completely alter how output displays in the browser.
To change how the error messages are displayed, you can change the value of the DisplayMode property of the ValidationSummary control. The possible values of this control can be set to the following:
  • BulletList
  • List
  • SingleParagraph
If you use the BulletList value for the DisplayMode property, it appears as shown in Figure 11. If you use List, it appears without bullets. If you use SingleParagraph, the errors appear in a text area all on one line in a single paragraph.

Showing a Dialog Box Containing Error Notifications
One flexible feature of the ValidationSummary server control is that you can easily show the ASP.NET page's errors in a pop-up dialog box. You have the option of showing the summary in the browser and the dialog box together, or just in the dialog box.
The property that controls whether the message appears in the browser is the ShowSummary property. To turn off the display of validation errors in the browser, set the value of the ShowSummary property to False. To show validation errors in a dialog box, set the ValidationSummary control's ShowMessageBox property to True (see Listing 18).

Listing 18: Showing errors in a dialog box
<asp:ValidationSummary id="ValidationSummary1" runat="server"
  ShowMessageBox="True" ShowSummary="False"></asp:ValidationSummary>

This code produces results similar to those in Figure 10.
Figure 10: A dialog box showing the page's validation errors

Understanding the Difference Between the ErrorMessage and Text Properties

In the examples shown so far using the ValidationSummary server control, the error messages were next to the items that were being validated (the RequiredFieldValidator server controls) and were displayed within the ValidationSummary server control. One ideal way of presenting this validation-error information is to have an asterisk (*) appear next to the HTML form fields in question, while the error messages stating what is wrong with the input appear in the list of errors shown within the ValidationSummary control.
To accomplish this, you use the specific validation controls—not the ValidationSummary server control itself. For instance, if there is a RequiredFieldValidator server control validating a text box, you construct this validation control as shown in Listing 19.

Listing 19: Showing text differently than it is displayed in the ValidationSummary server control

<asp:RequiredFieldValidator id="RequiredFieldValidator1"
  runat="server" ErrorMessage="You must enter your first name"
  ControlToValidate="TextBox1">*</asp:RequiredFieldValidator>

Or:
<asp:RequiredFieldValidator id="RequiredFieldValidator1"
  runat="server" ErrorMessage="You must enter your first name"
  ControlToValidate="TextBox1" Text="*">
</asp:RequiredFieldValidator>

By constructing the page's validation server controls, as shown here, using different values for the ErrorMessage and Text properties, you get a result similar to that shown in Figure 11.
Figure 11: Using different text for the validation error messages

When both the ErrorMessage and Text properties are used for the validation controls, the value of the ErrorMessage property is displayed in the ValidationSummary server control's listing of validation errors, and the value assigned to the Text property is displayed in the validation control itself.
Conclusion
You can do a lot with validation, far more than this article explains. Validation controls make a developer's life a lot easier. (To develop the same type of functionality in the past, a developer had to sometimes go to extreme JavaScript-coding measures.)
The powerful thing about using these validation controls is that they are easy to implement. Modifying them is a piece of cake, so you can easily check for all sorts of parameters on the input generated from your forms.
Validation and Web controls make an outstanding combination for building smart forms.
About the Author
Bill Evjen is an active proponent of .NET technologies and community-based learning initiatives for .NET. He is a technical director for Reuters, the international news and financial services company based in St. Louis, Missouri. Bill is the founder and executive director of thewhich represents more than 100,000 members worldwide. Bill is also an author and speaker and has written such books as ASP.NET Professional Secrets, XML Web Services for ASP.NET, Web Services Enhancements, and the Visual Basic .NET Bible (all from Wiley).
© 2011 Microsoft. All rights reserved.

Powered by IndiaGel.com