在应用Windows系统时,都接触过它自带的Solitaire(纸牌游戏),其实这个游戏中的纸牌图片和调用代码都是封装在一个Cards.dll中,Cards.dll位于系统目录System32中。读者只要知道如何使用Cards.dll中的API函数,就能调用绘制扑克牌而不用单独设计图片和代码了。
程序设计如图1。
图1 程序设计
Cards.dll包含很多的API函数,本例中要使用的是最基本的3个函数:cdtInit、cdtTerm和cdtDraw。
cdtInit函数的声明过程如下:
[DllImport("cards.dll")]
public static extern bool cdtInit(ref int width,ref int height);
cdtInit函数主要用于在调用Cards.dll时进行初始化工作,这样才能使用cards.dll中的其他函数如cdtDraw等。它使用时必须首先声明2个变量width和height、width,height用于返回纸牌默认的宽和高,单位为pixels。调用方法如下:
int width,height;
width=0;height=0;
cdtInit(ref width,ref height);
cdtTerm函数的声明过程如下:
[DllImport("cards.dll")]
public static extern void cdtTerm();
cdtTerm函数主要用于在所有调用工作结束时,通过调用它来结束对cards.dll的使用。调用方法如下:
cdtTerm();
cdtDraw函数的声明过程如下:
[DllImport("cards.dll")]
public static extern bool cdtDraw(IntPtr hdc,
int x,
int y,
int card,
int mode,
long color);
cdtDraw函数主要用于在指定位置、指定设备上根据用户设置进行画牌,程序每绘制一张牌就调用一次cdtDraw函数。 hdc用于指定绘图设备的句柄;x,y用于指定绘制纸牌位置的左上角坐标;card参数用于设置所绘纸牌的编号,其中0-51代表纸牌数值,纸牌是按照顺序排列。具体如下:
A(草花-0、方块-1、红桃-2、黑桃-3),2(草花-4、方块-5、红桃-6、黑桃-7),…,K(草花-48、方块-49、红桃-50、黑桃-51);53-65是12种纸牌的背面图形。
参数mode 用于指定纸牌的绘制方式,牌面向上为0,牌面向下为1; color用于指定绘制纸牌时的背景色。
画黑桃A纸牌代码如下:
int left_x,top_y, CardId;
left_x=20;
top_y=20;
CardId=3;
cdtDraw(this.CreateGraphics().GetHdc(),left_x,top_y,CardId,0,9);
画纸牌背面代码如下:
int i,left_x,top_y,BackId;
for(i=0;i<=11;i++){
BackId=i;
top_y=20+(i & 3)*100;
left_x=20+(i >> 2) *80+180+80;
cdtDraw(this.CreateGraphics().GetHdc(),left_x,top_y,54+BackId,1,9);
由于我们应用的计算机中并没有真正的随机数发生器,随机数的产生只能靠使用重复率很低的伪随机数来实现,实现这一功能的程序叫伪随机数发生器。C#语言中提供了一个基于ANSI标准的伪随机数发生器类Random来生成随机数。
使用方法如下:
int num = 0;
Random rnd = new Random();
num = rnd.Next(1, 1000);
上面代码用于产生1~1000中的随机数,这些数字是可重复的。
我们的随机发牌程序原理就是根据随机产生的牌的数值来决定此牌是否已经发过,如果发过就重新产生新牌,直到发完所有的纸牌。具体实现如下:
利用for循环实现的简单发牌程序1:
int[] theArray = new int[52];
Random r = new Random();
for(int i= 0; i<52;i++)
{
theArray[i] = i+1;
}
for(int i = 0; i< 52; i++)
{
int a = r.Next(52);
int b = r.Next(52);
int tmp = theArray[a];
theArray[a] = theArray[b];
theArray[b] = tmp;
}
产生的随机纸牌发牌序列就存储在theArray数组中。
利用while循环实现的简单发牌程序2:
int[] theArray = new int[52];
int i = 0;
while (i < theArray.Length)
{
theArray[i] = ++i;
}
Random r = new Random();
while (i > 1)
{
int j = r.Next(i);
int t = theArray[--i];
theArray[i] = theArray[j];
theArray[j] = t;
}
产生的随机纸牌发牌序列还是存储在theArray数组中。
完整源代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Windows.Forms.Design;
namespace GetCards
{
public partial class Form1 : Form
{
[DllImport("cards.dll")]
public static extern bool cdtInit(ref int width,ref int height);
[DllImport("cards.dll")]
public static extern void cdtTerm();
[DllImport("cards.dll")]
public static extern bool cdtDraw(IntPtr hdc,
int x,
int y,
int card,
int mode,
long color);
[DllImport("cards.dll")]
public static extern bool cdtDrawExt(IntPtr hdc,
int x,
int y,
int dx,
int dy,
int card,
int type,
long color);
[DllImport("cards.dll")]
public static extern bool cdtAnimate(IntPtr hdc,
int cardback,
int x,
int y,
int frame);
int[] bb = new int[100];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
int width,height;
width=0;height=0;
cdtInit(ref width,ref height);
}
private void button1_Click(object sender, EventArgs e)
{
int i,k, left_x,top_y, CardId;
for(k=0;k<=3;k++)
for(i=1;i<=13;i++)
{
left_x=20+(i-1)*15;
top_y=20+k*100;
CardId=(i-1)*4+k;
cdtDraw(this.CreateGraphics().GetHdc(),left_x,top_y,CardId,0,9);
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
cdtTerm();
}
private void button2_Click(object sender, EventArgs e)
{
int i,left_x,top_y,BackId;
for(i=0;i<=11;i++)
{
BackId=i;
top_y=20+(i & 3)*100;
left_x=20+(i >> 2) *80+180+80;
cdtDraw(this.CreateGraphics().GetHdc(),left_x,top_y,54+BackId,1,9);
}
}
private void button3_Click(object sender, EventArgs e)
{
int ii, k, left_x, top_y, CardId;
int[] theArray = new int[52];
Random r = new Random();
listBox1.Items.Clear();
for(int i= 0; i<52;i++)
{
theArray[i] = i+1;
}
for(int i = 0; i< 52; i++)
{
int a = r.Next(52);
int b = r.Next(52);
int tmp = theArray[a];
theArray[a] = theArray[b];
theArray[b] = tmp;
}
for(int i = 0; i< 52; i++)
{
listBox1.Items.Add(theArray[i]);
k = (int)(i / 13);
ii = i % 13 +1;
left_x = 20 + (ii - 1) * 15;
top_y = 20 + k * 100;
CardId = theArray[i]-1;
cdtDraw(this.CreateGraphics().GetHdc(), left_x, top_y, CardId, 0, 9);
}
}
private void button4_Click(object sender, EventArgs e)
{
int ii, k, left_x, top_y, CardId;
int[] theArray = new int[52];
int i = 0;
while (i < theArray.Length)
{
theArray[i] = ++i;
}
Random r = new Random();
listBox1.Items.Clear();
while (i > 1)
{
int j = r.Next(i);
int t = theArray[--i];
theArray[i] = theArray[j];
theArray[j] = t;
}
for (i = 0; i < theArray.Length; ++i)
{
listBox1.Items.Add(theArray[i].ToString());
k = (int)(i / 13);
ii = i % 13 + 1;
left_x = 20 + (ii - 1) * 15;
top_y = 20 + k * 100;
CardId = theArray[i] - 1;
cdtDraw(this.CreateGraphics().GetHdc(), left_x, top_y, CardId, 0, 9);
}
}
}
}
程序运行效果如图2。
图2 运行效果
|