Mark Six on the Fly


Abstract

This sample generates 6 random numbers and display them on an image in a WebForm.

Background

Mark Six is the official lottery game in Hong Kong. You can choose any six numbers from 1 to 47. The core of this code sample is the Dice Class, which is from Mr. John O'Donnell's Lottery article, many thanks to Mr. O'Donnell.

The Code

This sample contains 4 files.

Dice.cs is the Class file for the Dice class. It has only one method called RollDice(), which analogues to throwing a dice with 47 faces. Please refer to Mr. O'Donnell's article for more description about the Random and Stack Class.

MarkSixBall.cs exposes a method called Draw(), which puts the number on a circle that in turn lies on a 30*30 bitmap and return the bitmap.

// MarkSixBall.cs
using System;
using System.Drawing;
namespace MarkSix
{
/// <summary>
/// Summary description for MarkSixBall.
/// </summary>
public class MarkSixBall
{
public int imgX = 30; // width of image
public int imgY = 30; // height of image
public int ballX = 26; // width of ball
public int ballY = 26; // height of ball
public static Font myFont = new Font("Verdana", 10, FontStyle.Bold);
public MarkSixBall()
{
//
// TODO: Add constructor logic here
//
}
// to draw the marksixball inside a square
public Bitmap Draw(string s, Color Fcolor, Color Bcolor) // string s is in fact the number
{
Bitmap bmp = new Bitmap(imgX,imgY);
Graphics g = Graphics.FromImage(bmp);
Pen p = new Pen(Fcolor);
SolidBrush Fbrush = new SolidBrush(Fcolor); // for foreground color
SolidBrush Bbrush = new SolidBrush(Bcolor); // for background color
float strX = g.MeasureString(s,myFont).Width; // to get the width of the string
float strY = g.MeasureString(s,myFont).Height; // to get the height of the string 
g.Clear(Color.White); // set background to white
g.FillEllipse(Bbrush, (imgX-ballX)/2, (imgY-ballY)/2, ballX, ballY); // first fill the circle
g.DrawEllipse(p,(imgX-ballX)/2 ,(imgY-ballY)/2,ballX,ballY);
// then draw the border of circle so that border won't be covered.
g.DrawString(s, myFont, Fbrush, imgX/2 - strX/2, imgY/2 - strY/2);
// draw the number at the centre of the 30*30 square.
return bmp;
}
}
}

ImgMarkSix.aspx pushes the six random numbers on a stack, draw six MarkSixBalls and put them in a row. It then uses Response.OutputStream to return the image as a gif.

// ImgMarkSix.aspx.cs
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.IO;
namespace MarkSix
{
/// <summary>
/// Summary description for ImgMarkSix.
/// </summary>
public class ImgMarkSix : System.Web.UI.Page
{
public static int EndRange = 47; // total number of numbers to choose from.
public ImgMarkSix()
{
Page.Init += new System.EventHandler(Page_Init);
}
private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
Stack s = new Stack();
Dice d = new Dice();
GenerateNumbers(s,d); // generate six numbers using the Dice and put them in the Stack.
Bitmap myImg = GenImgMarkSix(s);
Response.ContentType = "image/gif";
myImg.Save(Response.OutputStream, ImageFormat.Gif);
}
private void Page_Init(object sender, EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
}
#region Web Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
/**************************************************************************
* Please refer to Mr. John O'Donnell's Lottery article
* for more information about the Random and Stack Class.
* http://www.c-sharpcorner.com/1/LotteryProgramJ.asp
***************************************************************************/
//Generate our unique numbers and push them onto stack
public static void GenerateNumbers(Stack s, Dice d)
{
bool exists=true;
int i;
int val;
for (i=1;i<=6;i++) // to generate 6 numbers
{
val=d.RollDice(EndRange); //Roll EM!
exists=s.Contains(val);
while (exists==true) //Reroll if we already
{ //have that number
val=d.RollDice(EndRange);
exists=s.Contains(val);
}
s.Push(val); // so we get 6 distinct numbers in the stack.
}
}
// Generate a gif with the six numbers in the stack, each in a circle.
public static Bitmap GenImgMarkSix(Stack s)
{
MarkSixBall ball = new MarkSixBall();
Bitmap bmp = new Bitmap(ball.imgX * 6, ball.imgY);
Pen p = new Pen(Color.Blue);
Graphics g = Graphics.FromImage(bmp);
g.Clear(Color.White); // anyway, this background color will be covered by the MarkSixBalls.
// to store the foreground and background color of a MarkSixBall
Color[,] ColorPair = new Color[6,2];
ColorPair[0,0] = Color.FromArgb(255,255,255);
ColorPair[0,1] = Color.FromArgb(128,0,128);
ColorPair[1,0] = Color.FromArgb(0,0,0);
ColorPair[1,1] = Color.FromArgb(250,200,50);
ColorPair[2,0] = Color.FromArgb(255,255,255);
ColorPair[2,1] = Color.FromArgb(211,16,89);
ColorPair[3,0] = Color.FromArgb(166,55,86);
ColorPair[3,1] = Color.FromArgb(253,219,220);
ColorPair[4,0] = Color.FromArgb(91,54,99);
ColorPair[4,1] = Color.FromArgb(231,150,239);
ColorPair[5,0] = Color.FromArgb(255,0,0);
ColorPair[5,1] = Color.FromArgb(231,231,231); 
// randomize the numbers 0 to 5 and push them into a stack.
int val;
Stack ColorStack = new Stack();
Random r = new Random();
for(int j=0;j<6;j++)
{
val=r.Next(6);
while (ColorStack.Contains(val)) // if the number already exists in the stack
val=r.Next(6);
ColorStack.Push(val);
}
// draw the six 30*30 images in a row.
for(int i=0;i<6;i++)
{
int n = (int)ColorStack.Pop(); // get the random number for colors
g.DrawImage(ball.Draw(s.Pop().ToString(), ColorPair[n,0], ColorPair[n,1]),i*30,0);
// draw the MarkSixBall image.
}
return bmp;
}
}
}

WebForm1.aspx is a test page that calls ImgMarkSix.aspx in an ImageBox. The user can refresh the ImageBox by pressing the MarkSix button.

Conclusion

In this sample, I demonstrated some simple usage of GDI+ functionalities on a WebForm, and how a WebForm can be called directly as an Image. If you have any comments or questions please feel free to drop an email at andy@hmcheung.com .