.NET手持设备开发工具包实战…
示例一:简单的窗体程序,目标平台为Pocket PC
我们在第一篇已经介绍过了Smart Device Extensions for Visual Studio .NET的安装和建立新项目,所以在这里就不再进行说明了。在这一个例子中,我们先按照本文第一篇中介绍的方法新建一个Smart Device Application项目。由于这个程序是为Pocket PC设备开发的Windows窗口,所以在新建项目向导中目标平台选择Pocket PC,项目类型选择Windows Application。新建项目成功后,项目中即存在一个名为Form1的初始窗体。
图5-1 新建的空白项目 |
下面我们从工具箱中将两个Label、一个TextBox和一个Button分别拖到Form1上来,根据页面布局自己调整一下这四个控件的位置。接下来,我们分别修改一下这几个控件的名称和显示的文字(Value值)。这些都是可以通过鼠标单击相应控件,然后在属性中修改的。我们在这一部分操作中,使用了命名空间System.Windows.Forms下的几个类,这一命名空间的使用方法同常规的WinForm开发中命名空间及控件的使用方法是一样的。我们在介绍.NET手持设备开发时已经说过的,手持设备和常规WinForm的开发中的绝大部分内容都是一样的。这就是在.NET的框架下开发各种应用的好处-技术上可以无缝过渡。所以,在这里我们就不再详细的介绍相关命名空间和类的具体使用了。
为了增加交互性,我们给Button控件的单击事件加一些处理代码:
| private void Btn_submit_Click(object sender, System.EventArgs e) { MessageBox.Show("Hi "+this.name.Text.Trim()); } |
这句代码的功能是当使用者输入自己的名字后单击Click It!的Butotn时,系统弹出一个消息窗口,显示一句问候,被问候人的名字是使用者输入到名为Name的TextBox中取出的。
图5-2 编制完成的项目 |
至此,程序的代码工作已经完成。下面我们需要测试一下。这时我们选择菜单上的[调试]>>启动 或者直接点击"启动"按钮,就可以启动Pocket PC 2002的模拟器来测试我们的程序了。
在运行程序之前,需要将.NET Compact Framework 拷贝到模拟器上,如图5-3。
图5-3 拷贝并安装.NET Compact Framework |
在.NET Compact Framework安装完成之后,就会将我们刚刚完成的程序拷贝到模拟器上并且运行,这时我们会看到如图5-4的界面。填入我的名字:Hope Qin,然后点击Click It!按钮,将弹出一个对话框,对话框的文字为Hi Hope Qin。如图5-5所示。
图5-4 程序运行界面 |
图5-5 程序执行界面 |
我们的第一个简单的程序已经开发完成了,下一步需要将程序打包发布。我们只要使用VS.NET的生成菜单下的"生成解决方案"选项就可以将此项目编译生成最终可用的应用程序。
由于Pocket PC可以用于多种不同的CPU的手持设备,所以在发布时我们最好针对各个不同种类的设备都生成不同的安装包。我们使用生成菜单下的build Cab File 选项就可以在项目文件夹中生成四种Cab文件,每一种对应于一种不同CPU的手持设备。如我们这个简单的项目就会生成 HiPocketPC_PPC.ARM.CAB,HiPocketPC_PPC.MIPS.CAB,HiPocketPC_PPC.SH3.CAB,HiPocketPC_PPC.X86.CAB 四个Cab压缩包文件。由于手持设备可以通过连接电缆、红外线、无线网络等方式下载应用程序,所以将整个程序压缩打包发布也会节约很多资源。
示例二:简易黑白棋程序,目标平台为Windows CE .NET
下面,我们一起来再做一个更复杂一些的例子。这个例子是在Windows CE .NET平台上开发的一个简易游戏。Windows CE.NET的设备窗口大小是Pocket PC 2002设备的四倍,能表现更多的内容。之所以我们选择黑白棋作为开发对象,是因为黑白棋规则很简单,只要肯花点脑筋,新手也能玩得很好。因为棋盘小,下一局棋所花的时间也不多。它的规则虽然简单,但是变化复杂。也许你认为黑白棋很简单,但是有一种说法是:只需要几分钟学会它,却需要一生的时间去精通它。
黑白棋的规则:
把自己颜色的棋子放在棋盘的空格上,而当自己放下的棋子在横、竖、斜八个方向內有一个自己的棋子,则被夹在中间的全部会成为自己的棋子。并且,只有在可以翻转棋子的地方才可以下子。如果棋盘上没有地方可以下子,则该对手连下。双方都没有棋子可以下时棋局结束,棋子多的一方获胜。如果您对黑白棋的详细情况有兴趣的话,可以到中国黑白棋联盟:http://www.othello-china.com/ 或相关网站去查阅相关资料。
在这个程序中,我们采用了较为简单的权值算法,这种算法仅仅根据边、角的权值不同来寻找最优方案。由于黑白棋规则简单,所以比较容易编写出棋力很强的算法,早在1997年,Logistello程序就以6-0完胜人类世界冠军,而到了今天,已经没有任何人类棋手能够战胜任何一个顶尖程序了。所以你不要轻视这个简单的程序,要战胜它也不是那么容易的事情。对于黑白棋算法我们就不再介绍那么多,有兴趣的话可以到关于黑白棋算法的网站上了解。我们主要介绍在Windows CE .NET上开发窗体程序的方法。
在Windows CE .NET上开发WinForm 和在Windows 9X、2000和XP上没有太大区别,都遵循.NET 的整体要求。只不过受平台限制,两者可以利用的资源有所区别。下面我们就开始编制我们的黑白棋程序。首先我们同样是新建一个Smart Device Application项目,项目名称为Othello,项目目标平台为Windows CE .NET,项目类型为Windows Application。新建项目成功后,有一默认窗体Form1。先将Form1名称改为Othello,再从工具箱中拖四个Label到Form的右上角。两个一行排列整齐,分别命名为 blackname、black、whitename、white。其中blackname和whitename两个Label的值分别为:Black: 和White:。这四个Label是为了显示黑白双方的现有子数。至此我们在WinForm设计界面的工作已经完成,剩下的工作都是在代码界面下做的了。
Othello.cs
属性定义:
| private System.Drawing.SolidBrush solidBrush; file://画笔 private System.Windows.Forms.Label blackname; file://Label private System.Windows.Forms.Label black; file://Label,显示黑房子数 private System.Windows.Forms.Label whitename; file://Label private System.Windows.Forms.Label white; file://Label,显示白方子数 private int [,] State=new int[8,8]; file://状态矩阵 private int [,] StateW=new int[8,8]; file://权值矩阵 |
由于我们需要使用 System.Drawing 命名空间下的SolidBrush类。SolidBrush:单色画刷,画刷用于填充图形形状,如矩形、椭圆、扇形、多边形和封闭路径。无法继承此类。还有两个比较重要的属性:State和StateW,这两个是8*8的二维数组,它的作用是程序在走棋时计算每一步的权值大小是存储比较具体值用的。
构造器 Othello():
| public Othello() { InitializeComponent(); int i,j;//初始化状态矩阵 for(i=0;i<8;i++) for(j=0;j<8;j++) State[i,j]=0; State[4,3]=1; State[3,4]=-1; State[4,4]=-1; State[3,3]=1; for(i=0;i<8;i++) for(j=0;j<8;j++) StateW[i,j]=2; for(i=0;i<4;i++) { StateW[i+2,0]=3; StateW[i+2,1]=1; StateW[i+2,7]=3; StateW[i+2,6]=1; StateW[0,i+2]=3; StateW[1,i+2]=1; StateW[7,i+2]=3; StateW[6,i+2]=1; } for(i=0;i<2;i++) for(j=0;j<2;j++) { StateW[i,j]=0; StateW[7-i,j]=0; StateW[i,7-j]=0; StateW[7-i,7-j]=0; } StateW[0,0]=4; StateW[0,7]=4; StateW[7,0]=4; StateW[7,7]=4; } |
在构造器代码部分,我们需要初始化状态矩阵,并且由于在黑白棋中需要先在棋盘上放置黑白各两个棋子,所以从一开始就要初始化权值矩阵。在两个矩阵中各个单元的值是不相同的,这是因为各点的权值不同。
窗体绘制方法 Form1_Paint():
| private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { file://画棋盘 Pen p=new Pen(Color.SeaGreen); file://实例化画笔和定义画笔颜色 solidBrush = new SolidBrush(Color.White); file://实例化笔刷和定义笔刷颜色 int i; for(i=0;i<9;i++) e.Graphics.DrawLine(p,10,10+20*i,170,10+20*i); for(i=0;i<9;i++) e.Graphics.DrawLine(p,10+20*i,10,10+20*i,170); int j; for(i=0;i<8;i++) for(j=0;j<8;j++) { if(State[i,j]==1) { p.Color=Color.White; solidBrush.Color=Color.White; } if(State[i,j]==-1) { p.Color=Color.Black; solidBrush.Color=Color.Black; } if(State[i,j]!=0) { e.Graphics.DrawEllipse(p,i*20+10,j*20+10,20,20); e.Graphics.FillEllipse(solidBrush,i*20+10,j*20+10,20,20); } } } |
当Form的Paint(重绘)事件发生时,将调用此方法在Form上画出棋盘和初始的黑白各两个棋子。在这个方法里用到了System.Drawing 命名空间下的Pen、SolidBrush和Graphics三个类。其中Pen类用于绘制直线和曲线,在这里的作用是绘制棋盘和棋子的外形。SolidBrush类为笔刷类,用于填充棋子内部。Graphics类封装 GDI+ 绘图面,所有的窗体上的绘图工作都是在Graphics对象上完成。
在绘图时,我们根据需要先绘制出一个9*9的棋盘,这里就是使用Pen对象画出一条条直线。然后我们使用Pen对象先划出黑白各两个棋子的圆形,然后使用SolidBrush对象填充该圆形。这样就完成了画棋盘和初始棋子的工作。
走棋方法 Form1_MouseDown():
| private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { Point P; file://定义座标 P=MtoB(e.X,e.Y); file://实例座标,并转为棋盘表示 Point [] PP=new Point[8]; solidBrush = new SolidBrush(Color.White); if(State[P.X/20,P.Y/20]==0) { if(Valid(P.X,P.Y,-1,ref PP)) { int i; for(i=0;i<8;i++) { if(PP[i].IsEmpty) continue; int a=0,b=0; switch(i) { case 0: a=0; b=1; break; case 1: a=0; b=-1; break; case 2: a=-1; b=-1; break; case 3: a=-1; b=0; break; case 4: a=-1; b=1; break; case 5: a=1; b=-1; break; case 6: a=1; b=0; break; case 7: a=1; b=1; break; } while(PP[i].X!=P.X/20||PP[i].Y!=P.Y/20) { State[PP[i].X,PP[i].Y]=1; PP[i].X=PP[i].X-a; PP[i].Y=PP[i].Y-b; } } State[P.X/20,P.Y/20]=1; Thinking();//计算机走棋 } } RePaint(); } |
当我们在棋盘上的某个棋格点击鼠标时,即调用此方法来走棋。在这个方法里需要先取得鼠标点击的座标,然后转变为棋盘上的座标(哪一个棋格)。根据黑白棋的规则决定是否此格中是否可以落子。落子后进行棋子的翻转。然后调用计算机走棋的方法,最终进行重绘工作。
鼠标坐标转换为棋盘坐标的方法 MtoB():
| private Point MtoB(int x, int y)//鼠标坐标转换为棋盘坐标 { if(x<10||x>170||y<10||y>170) { x=-1; y=-1; } else { x=(x-10)/20*20; y=(y-10)/20*20; } return new Point(x,y); } |
在此方法中我们利用定义的棋格大小将鼠标坐标转换为棋盘坐标。
搜索最佳落棋点 LookFor():
| private bool LookFor(int x, int y, int v, int flag, ref Point [] P) file://向某个方向搜索当前位置是否合理 { int i,j; i=x/20; j=y/20; int a,b; switch(flag) { case 0: a=0; b=1; break; case 1: a=0; b=-1; break; case 2: a=-1; b=-1; break; case 3: a=-1; b=0; break; case 4: a=-1; b=1; break; case 5: a=1; b=-1; break; case 6: a=1; b=0; break; case 7: a=1; b=1; break; default: return false; } if((i+a)<8&&(i+a)>=0&&(j+b)<8&&(j+b)>=0) { while(State[i+a,j+b]==v) { i=i+a; j=j+b; if((i+a)>7||(i+a)<0||(j+b)>7||(j+b)<0) return false; } } else return false; if(i==x/20&&j==y/20) return false; if((i+a)<11&&(i+a)>=0&&(j+b)<11&&(j+b)>=0) if(State[i+a,j+b]==0) return false; if(i==8||j==8||i==-1||j==-1) return false; P[flag].X=i; P[flag].Y=j; return true; } |
在此方法中,利用权值比较搜索最佳落棋点,计算机方落子用的方法。
重绘棋子 RePaint():
| private void RePaint()//重画棋子 { int i,j,bs=0,ws=0; for(i=0;i<8;i++) for(j=0;j<8;j++) { System.Drawing.Graphics g=this.CreateGraphics(); Pen p=new Pen(Color.Black); solidBrush = new SolidBrush(Color.White); if(State[i,j]==1) { p.Color=Color.Black; solidBrush.Color=Color.Black; bs++; } if(State[i,j]==-1) { p.Color=Color.Black; solidBrush.Color=Color.White; ws++; } if(State[i,j]!=0) { g.DrawEllipse(p,i*20+10,j*20+10,20,20); g.FillEllipse(solidBrush,i*20+10,j*20+10,20,20); } black.Text=bs.ToString(); white.Text=ws.ToString(); } |
在各方落子后使用此方法进行棋子的翻转(颜色的变化)。主要使用的类和方法与Form_Paint方法中一致。在此方法中还对黑白双方的棋子进行统计,在重绘棋子完成后,将黑白双方的棋子的数量显示在右上角的Label上。
判断当前位置是否合理 Valid():
| private bool Valid(int x, int y, int v,ref Point [] P)//判断当前位置是否合理 { int i; bool flag=false; Point [] PP=new Point[8]; for(i=0;i<8;i++) { if(LookFor(x,y,v,i,ref PP)) { flag=true; } } if(flag) for(i=0;i<8;i++) { P[i].X=PP[i].X; P[i].Y=PP[i].Y; } return flag; } |
此方法中调用LookFor方法来验证当前位置是否为最佳位置。
计算机走棋 Thinking():
| private void Thinking()//计算机走棋 { int i=0,j=0,x=-1,y=-1,W=-1; Point [] P=new Point[8]; for(i=0;i<8;i++) for(j=0;j<8;j++) { if(State[i,j]==0&&StateW[i,j]>W) if(Valid(20*i,20*j,1,ref P)) { x=20*i; y=20*j; W=StateW[i,j]; } } if(x/20!=8&&y/20!=8&&x!=-1&&y!=-1) { for(i=0;i<8;i++) { if(P[i].IsEmpty)continue; int a=0,b=0; switch(i) { case 0: a=0; b=1; break; case 1: a=0; b=-1; break; case 2: a=-1; b=-1; break; case 3: a=-1; b=0; break; case 4: a=-1; b=1; break; case 5: a=1; b=-1; break; case 6: a=1; b=0; break; case 7: a=1; b=1; break; file://default:return false; } while(P[i].X!=x/20||P[i].Y!=y/20) { State[P[i].X,P[i].Y]=-1; P[i].X=P[i].X-a; P[i].Y=P[i].Y-b; } } State[x/20,y/20]=-1; } } |
计算机走棋的方法。调用Valid方法去验证每一个点的权值。
上面就是我们这个程序主要要使用的方法,其中LookFor、Valid和Thinking方法全部为黑白棋算法的代码,没有牵扯到WinFrom编程。其中的原理我们就不在这里给大家讲解了。做到这里,方法都实现了,下一步需要将方法与事件关联起来。我们只要在设计界面下,将Form1_MouseDown方法与MouseDown事件、Form1_Paint方法与Paint事件分别关联起来就可以了。至此,我们的程序就已经完成了。这个程序仅仅是为了演示一个手持设备的小游戏的编程过程。其中游戏方面的功能也很少,仅仅实现了人与计算机的对奕。如果大家有兴趣,可以对这个程序进行扩充:优化界面、加入各种提示和帮助、开发联机版网络对战游戏……。
下面我们就需要将这一程序发布在Windows CE .NET的模拟器上上进行测试了。操作步骤和启动过程与Pocket PC模拟器类似。
Windows CE .NET启动成功后显示如图5-6界面。接着运行程序,如图5-7所示。我们可以与计算机下几步棋,如图5-8所示。
图5-6 Window CE .NET模拟器启动后界面 |
图5-7 程序启动界面 |
图5-8 程序运行界面 |
我们关于.NET手持设备开发的文章内容已经全部介绍完成了。
下载本文源代码:
Smart Device Application Windows CE 上的黑白棋程序
Smart Device Application Pocket PC上的窗体事例程序
- · DIRECTX 5游戏强力制作
- · 用DirectDraw编写动画程序
- · 几种MAIL SERVER的功能应用…
- · 改变思路,从另一个角度使用…
- · 数据库的发展和现状
- · 移动Agent体系结构及迁移实…
- · Internet上的图像检索技术
- · 接口设计对软件性能的影响
- · 优化软件性能的方法
- · Linux 下 C++程序的异常处理技巧
- · Linux上的C/C++编译器gcc/egcs详解
- · Linux中BSD套接口开发的基础介绍
- · Kylix之经典十大难题
- · 050913:awk中几个内置变量的man说明,感觉英文记得牢点。
- · bash Shell中函數的應用小結
- · 正则表达式模式匹配
- · 计算网络广播地址的shell
- · Shell基本工作原理
- · 了解系统应用情况 彻底监控Windows运行
- · Windows的文件查找功能应用小技巧
- · USB设备还可以这样来安装进Windows
- · 巧用WinRAR为Win9x登陆系统加密
- · 重装系统如何恢复Win98备份文件
- · 在Win98中关闭光盘自动播放功能
- · 了解windows中Alt键的十大用法
- · 极度瘦身:40M的Windows 98
- · 让98也可拥有XP的开机声音
- · Windows 98全自动克隆安装盘
- · 松打造个性Win98启动画面
- · 用快捷键全面掌控你的Windo…
- · 利用Win98自带的Winipcfg命…
- · 让“状态栏”永驻“资源管理…
- · 在Win98中关闭光盘自动播放…
- · 巧用WinRAR为Win9x登陆系统…
- · 优化Windows启动提升性能
- · Win XP教程-XP高级技巧-添加无线Internet摄像机
- · Win XP教程-XP高级技巧-自动重启问题
- · Win XP教程-XP高级技巧-几个著名的Windows伪优化技巧
