两国军旗

一、界面设计

下棋需要有棋盘,程序中通过在窗体激活时在图片框控件qi_pan上显示军旗棋盘图片文件。有了盘还需要有棋子,使用了以下如图5-6,图5-7中的图片表示棋子。另外还有R.bmp和G.bmp两个图片表示红方和绿方暗子。使用控件数组Qizi_Pic[]的Add方法加载了我们所需要的棋子图片控件并使用相应图片。Qizi_Pic[]中下标i的含义是:如果i小于24,那么说明它属于红方的棋子,否则是绿方的棋子。同时Qizi_Pic[i]的tag属性保存了棋子在控件数组的索引号。

图5-6  红方军棋棋子图片
图5-7  绿方军棋棋子图片

在界面中要求用户输入对方IP、端口(本地及对方远端)。同时按图5-8添加“联机”、“重新开始”、“退出”、“保存布阵”、“读取布阵”、“开始对战”6个按钮以及一些题使用的标签。

图5-8  网络两人对战军棋设计界面

二、通讯协议设计

网络程序设计的难点在于与对方需要通讯。这里使用了UDP(User Data Protocol)。UDP是用户数据文报协议的简称,两台计算机之间的传输类似于传递邮件;两台之间没有明确的连接,使用UDP协议建立对等通信。这里虽然两者两台计算机不分主次,但我们设计时假设一台做主机(红方),等待其他人加入。其他人想加入的时候输入主机的IP。为了区分通信中传送的是“输赢信息”,“下的棋子位置信息”,“重新开始”等,在发送信息的首部加上代号。定义了如下协议:

命令|参数|参数……

(1)联机功能

join|

(2)对方棋子移动信息

move|x , y , idx, old_x, old_y,old_idx

其中:棋子移动的目标位置坐标(x,y),棋子移动的起始位置坐标(old_x,old_y);

old_idx是被移动棋子的控件数组索引号,

idx是目标位置留下的棋子的控件数组索引号。

(3)游戏结束

over|+赢方代号 (赢了此局)

(4)表示要重新开始

reset|

(5)布阵信息

layout|布阵棋子信息

布阵棋子信息形式为x,y,idx,x,y,idx,x,y,idx……

idx是(x,y)处的棋子的控件数组索引号。

注意本程序在传递布阵信息时,我们默认了是绿方在棋盘上方,红方在下。但实际下棋如果棋手使用绿方,这样看非累死不可。所以这里我们采取了个小技巧,在发送布阵数据的时候我们把坐标在颠倒(把自己的棋盘颠倒)。即(x,y)坐标以(18-x),(18-y) 坐标发给对方。

在下棋过程中,为了保存下过的棋子的位置使用了Map数组,Map数组初值为101,表示此处无棋子。Map数组可以有0到49值,其中0到24代表红方棋子;25到49代表绿方棋子。

关于0到24的棋子含义如下在qi_index()规定:

private void qi_index()

{

Q=new int[25];

Q[0]=29; //军旗29

Q[1]=30;Q[2]=30;Q[3]=30;//地雷30

Q[4]=31;Q[5]=31;//炸弹31

Q[6]=32;Q[7]=32;Q[8]=32;//工兵32

Q[9]=33;Q[10]=33;Q[11]=33;//排长33

Q[12]=34;Q[13]=34;Q[14]=34;//连长34

Q[15]=35;Q[16]=35;//营长35

Q[17]=36;Q[18]=36;//团长36

Q[19]=37;Q[20]=37;//旅长37

Q[21]=38;Q[22]=38;//师长38

Q[23]=39;//军长39

Q[24]=40;//司令40

}

也即是0军旗,1—3地雷,4—5炸弹,6—8工兵,9—11排长,12—14连长,15—16营长,17—18团长,19-20旅长,21—22师长,23军长,24司令。

在Q数组中Q[24]=40而不直接写为“司令”,原因是棋子图片的命名时采用40.bmp

所以为显示图片时的方便,这里Q[24]=40。

25到49代表绿方棋子。绿方只要减去25(每方25个棋子)即可利用Q数组得知绿方棋子的含义。例如27代表的绿方地雷。

三、走棋规则设计

对于军旗游戏来说,规则非常简单,就是按照先后顺序在棋盘上走棋吃子,直到最先一方将对方的“军旗”挖掉为胜。

但在走棋过程中,需要考虑以下情况:

(1)是否为非棋子区;

(2)目标处是否是自己的棋子;

(3)判断目标是否实行营,如果是则需判断是否有子,如果没有可以如“士”一样斜线走棋。

(4)判断起始位置是否是铁道线,如果是则考虑弯道、直道、棋盘正中间的3*3“田子”,否则只能移动一步。

(5)“军旗”棋子、地雷棋子不能走动;

(6)在“大本营”中的棋子不能走动;

可以看出走棋规则实行比较复杂。在设计时Go_Juge(int old_x,int old_y,int x,int y)判断走棋的位置是否适当。

private bool Go_Juge(int old_x,int old_y,int x,int y)

{

//是否是棋子区域

if( (x<=6 && y>=1 && y<=6) || (x>=12 && y>=1 && y<=6) ||

(x<=6 && y>=12 && y<=17) || (x>=12 && y>=12 && y<=17)|| y>17 )

return false;

//目标位置是自己方的棋子

if(IsmyChess(x,y)) return false;

//到行营,行营是否有子

if(Is_Home( x, y)&& Map[x,y]!=101)return false;

//如“士”斜线从行营中出来**********

if(Is_Home( old_x, old_y)&& Map[x,y]==101&& Math.Abs(x-old_x)*Math.Abs(y-old_y)==1 )return true;

//如“士”斜线走入行营************

if(Is_Home( x, y)&& Map[x,y]==101 && Math.Abs(x-old_x)*Math.Abs(y-old_y)==1 )return true;

//移动一步

if( Math.Abs(x-old_x)==1 && y==old_y ||Math.Abs(y-old_y)==1 && x==old_x) return  true;

//铁道线

if(T_Juge(old_x,old_y,x,y))   return true;

return false;

}

本程序中go_chess(int old_x,int old_y,int x,int y,int idx)完成走棋吃子功能,其中判断以下几种情况:

(1)双发均为工兵到司令的棋子,则按大小比较决定保留那方棋子;

(2)其中一方式炸弹(31),则同时去掉。

(3)其中一方是地雷(30),对方为工兵,则留兵,否则留雷。

(4)其中一方是军旗(29),则可以判断输赢。

注意:在发送走棋数据的时候我们仍然需要把坐标在颠倒(把自己的棋盘颠倒)。即(x,y)坐标以(18-x),(18-y) 坐标发给对方。

四、布阵规则设计

注意布阵是采用两次单击不同棋子来决定对调的,所以(old_x, old_y)是第一次单击的棋子坐标,(x1,y1)是第二次单击的棋子坐标。

判断布局棋子的位置是否适当是使用Layout_Juge(int old_x,int old_y,int x1,int y1)实现以下情况判断:

(1)第一排不允许放置炸弹;由于布阵均在南方,所以第一排即(y1=12);

(2)自己的军旗只能放置在大本营;由于布阵均在南方,所以大本营即x1==8&&y1==17||x1==10&&y1==17;

(3)后两排允许放置地雷。由于布阵均在南方,后两排即y1==16||y1==17。

具体实现如下:

//炸弹控件编号4,5,第一排(y1=12)不允许放置炸弹

if(Q[Map[old_x,old_y]%25]==31 && y1==12)   return false;

if(Q[Map[x1,y1]%25]==31 && old_y==12)      return false;                  if(Q[Map[old_x,old_y]%25]==29 && !(x1==8&&y1==17||x1==10&&y1==17))

return false;//自己的军旗控件,只能放置在大本营

if(Q[Map[x1,y1]%25]==29 && !(old_x==8&&old_y==17||old_x==10&&old_y==17))

return false;//自己的军旗控件,只能放置在大本营

if(Q[Map[x1,y1]%25]==30 && !(old_y==16||old_y==17))

return false;//第1,2,3,4排不允许放置地雷,

if(Q[Map[old_x,old_y]%25]==30 && !(y1==16||y1==17))

return false;//第1,2,3,4排不允许放置地雷,

return true;//其余情况均可以

五、通讯过程
游戏开始后,创建一个线程th:
th = new Thread ( new ThreadStart ( read ) ) ;
th_flag=true;
th.Start ( )启动线程后,通过read ( )实现不断侦听本机设定的端口,得到对方发送来的信息,根据自己定义的通信协议通信中传送的是“输赢信息”,“下的棋子位置信息”,“重新开始”等信息而分别处理。
private void read ( )
{
//侦听本地的端口号
udpclient = new UdpClient ( Convert.ToInt32(txt_port.Text) ) ;
remote = null ;
//设定编码类型
Encoding enc = Encoding.Unicode ;
int x,y,old_x,old_y,idx,old_idx;
while ( ReadFlag == true )
//一个While(ture)循环,不断判断是否有信息流入,有就接收
{
try{
Byte[] data = udpclient.Receive ( ref remote ) ;
//得到对方发送来的信息
String strData = enc.GetString ( data ) ;
string []a=new string[5];
a=strData.Split('|');
switch(a[0])
{
case "join":
case "begin_layout"://允许对方布阵
case "layout"://布阵信息
case "move"://对方棋子移动信息
case "over":
case "reset":
}
}
catch{
//退出循环,结束线程
break;
}
}
}
发送信息send(string info)较为简单,主要实现创建UDP网络服务,传送信息到指定计算机的txt_remoteport端口号后,关闭UDP网络服务。
private void send(string info)
{
//创建UDP网络服务
UdpClient SendUdp = new UdpClient ( ) ;
IPAddress remoteIP ;
//判断IP地址的正确性
try{
remoteIP = IPAddress.Parse ( txt_IP.Text );
}
catch{
MessageBox.Show ( "请输入正确的IP地址!" , "错误" ) ;
return ;
}
IPEndPoint remoteep = new
IPEndPoint ( remoteIP , Convert.ToInt32 (txt_remoteport.Text )) ;
Byte [] buffer = null ;
Encoding enc = Encoding.Unicode ;
string str = info ;
buffer = enc.GetBytes ( str.ToCharArray ( ) ) ;
//传送信息到指定计算机的txt_remoteport端口号
SendUdp.Send ( buffer , buffer.Length , remoteep ) ;
//关闭UDP网络服务
SendUdp.Close ( ) ;
}

10天开发的两国军旗相关推荐

  1. 张高兴的 Windows 10 IoT 开发笔记:BH1750FVI 光照度传感器

    张高兴的 Windows 10 IoT 开发笔记:BH1750FVI 光照度传感器 原文:张高兴的 Windows 10 IoT 开发笔记:BH1750FVI 光照度传感器 BH1750FVI 是一款 ...

  2. iOS 10应用开发基础教程

    iOS 10应用开发基础教程 介绍: 本教程是国内第一本iOS 10开发应用教程.本教程基于Xcode 8.0,使用Swift 3.0语言讲解如何开发iOS 10的应用App. 学习建议:本教程针对i ...

  3. 【Win 10 应用开发】Toast通知激活应用——前台后台

    原文:[Win 10 应用开发]Toast通知激活应用--前台&后台 老周最近热衷于讲故事,接下来还是讲故事时间. 有人问我:你上大学的时候,有加入过学生会吗?读大学有没有必要加入学生会? 哎 ...

  4. 【Win 10应用开发】SplitView控件

    [Win 10应用开发]SplitView控件 原文:[Win 10应用开发]SplitView控件 SplitView控件用于呈现分隔视图,简单地说,就是把一个视图分割为两部分,Content属性所 ...

  5. 水晶报表10高级开发版下载及序列号

    水晶报表10高级开发版下载及序列号 分类: 编程语言 2011-04-28 22:24 526人阅读 评论(0) 收藏 举报 Crystal Reports 10 Advanced Developer ...

  6. 【Win 10 应用开发】RTM版的UAP项目解剖

    原文:[Win 10 应用开发]RTM版的UAP项目解剖 Windows 10 发布后,其实SDK也偷偷地在VS的自定义安装列表中出现了,今天开发人员中心也更新了下载.正式版的SDK在API结构上和以 ...

  7. 张高兴的 Windows 10 IoT 开发笔记:RTC 时钟模块 DS3231

    原文:张高兴的 Windows 10 IoT 开发笔记:RTC 时钟模块 DS3231 GitHub:https://github.com/ZhangGaoxing/windows-iot-demo/ ...

  8. 【Win 10应用开发】Adaptive磁贴模板的XML文档结构

    原文:[Win 10应用开发]Adaptive磁贴模板的XML文档结构 在若干天之前,老周给大家讲了Adaptive Toast通知的XML模板,所以相应地,今天老周给大家介绍一下Adaptive磁贴 ...

  9. 【Windows 10 应用开发】细说文本资源文件(resw)

    原文:[Windows 10 应用开发]细说文本资源文件(resw) 最近,小戏骨版<红楼梦>很是火热,老周一口气看完了9集,一直看到 Surface 的风扇呼呼响.林黛玉和薛宝钗这两个角 ...

最新文章

  1. 摄像头标定入门资料整理
  2. 【Linux系统编程】Linux进程调度
  3. 360画报屏保,放大营销“感官力”
  4. go kegg_玩转GO和KEGG富集因子图的N种姿势: 3种数据处理(含在线筛选条目),3种排序方式,本地交互图片...
  5. 细谈最近上线的Vue2.0项目(一)
  6. 如何让自己的视频号作品上热门
  7. WEB API Filter的使用以及执行顺序
  8. 云原生的基石,一文读懂容器、Docker、Pod到底是什么!
  9. 【PostgreSQL-9.6.3】物化视图
  10. 西瓜书读书笔记3-对数几率回归(logistic回归)公式推导
  11. ActiveMQ 命令行启动 与 嵌入式启动、MessageListener 监听消息
  12. Java二叉树的完全性检验
  13. 云端软件平台 封装了诺基亚PC套件无法找到驱动怎么办
  14. Excel数据分析--客户对象分析
  15. 使用npm运行react程序报错The 'mode' option has not been set, webpack will fallback to 'production' for th
  16. ubuntu16.04下安装为知笔记
  17. 平均年薪40万!为什么却很少见程序员炫富?
  18. Qlikview---日期字段
  19. 地图位置开发解析(一)
  20. android 照片特效,Android使用Gallery实现照片拖动的特效

热门文章

  1. 《神经质人格》摘录(第十一章)
  2. 新瑞鹏冲刺上市:持续亏损,旗下宠物医院屡被罚,彭永鹤为董事长
  3. arcgis怎么转面的中心点并计算中心点坐标
  4. 打印机扫描显示服务器错误代码,打印机操作无法完成错误代码0x00000015的解决办法...
  5. Python基础知识之pandas加载本地txt格式或csv格式的数据
  6. 西门子1200 PLC中SWAP交换指令
  7. 新疆计算机系统集成资质年审,新疆系统集成保密资质
  8. 总结:前端开发从入门到高薪中文指南.pdf
  9. 检测多机连接常用工具
  10. Odoo 16 企业版手册 - 采购之采购报价