C#控件数组实现象棋游戏.docx
- 文档编号:23947542
- 上传时间:2023-05-22
- 格式:DOCX
- 页数:21
- 大小:185.16KB
C#控件数组实现象棋游戏.docx
《C#控件数组实现象棋游戏.docx》由会员分享,可在线阅读,更多相关《C#控件数组实现象棋游戏.docx(21页珍藏版)》请在冰豆网上搜索。
C#控件数组实现象棋游戏
VisualC#.NET控件数组实现象棋游戏
【Abstract】Inthispaper,thecontrolsarraytechnologycaneasilyachievechessgame.thispaperexplaintheKeyissuessuchasrulesofchessgoing,representationofthegameboardandpieces.
【Keywords】controlsarray;VisualC#;ChessGame;Chessboardcoordinates
1.引言
设计一个项目时,常常会遇到具有相同性质的事件方法,比如在计算器中的数字按钮,它们不仅类型一样,而且执行的过程也一样。
如果为每个按钮控件分别编写一段事件方法的话,则显得十分的不合理。
在VisualBasic中可以把多个相同的控件定义为一个控件数组,那么,控件数组内的每个控件都可以共享程序代码。
通过控件数组的应用,使得开发人员不仅减少了重复劳动而且还提高了程序的可读性。
2.VisualC#.NET控件数组的建立
VisualC#.NET本身并不支持控件数组的建立,但可以有两种实现方法:
(1)动态添加已设计好的控件
因为.NET里支持动态数组,所以可以把已设计好的控件,赋给数组,这样就可以使用控件数组了。
代码如下:
privatevoidbutton1_Click(objectsender,System.EventArgse)
{
TextBox[]myTextBox=newTextBox[5];
myTextBox[0]=textBox1;
myTextBox[1]=textBox2;
myTextBox[2]=textBox3;
myTextBox[3]=textBox4;
myTextBox[4]=textBox5;
for(inti=0;i<5;i++)
myTextBox[i].Text=i.ToString();
}
(2)动态添加新增控件
用本方法可以实现计算器中的数字按钮控件数组的功能。
用new来建立Button控件,同时通过赋值把控件加到动态的数组btNum中。
通过代码设置好控件大小、位置等属性,然后用Form.Comtrols.Add方法添加控件到窗体上自身的控件数组Controls中。
因为窗体里的控件,都要被包括在Controls里面。
Button[]btNum=newButton[10];//数字按钮控件数组
btNum[i]=newButton();
btNum[i].Left=10+50*(i%3);
btNum[i].Top=50*(int)(i/3)+70;
btNum[i].Width=40;
btNum[i].Height=40;
btNum[i].Name="BTNUM"+i.ToString();
btNum[i].Text=i.ToString();
this.Controls.Add(btNum[i]);
上面的代码仅仅将按钮加入窗体中,如果为按钮加入单击事件代码,可以利用.NET中提供的System.EventHandler动态关联按钮控件Click事件与处理程序:
button1.Click+=newSystem.EventHandler(bt_Click);
通过System.EventHandler将方法bt_Click作为button1.Click事件代码。
3.象棋游戏程序设计的思路
3.1棋盘和棋子的表示
象棋游戏的红黑方32个棋子可以使用32个图片控件表示,可以采用类似实现计算器中的数字按钮控件数组的方法而采用图片控件数组实现。
为设计程序方便,将32个图片控件赋给了图片控件数组picChess。
picChess[i]中下标i的含义是:
如果i小于16,那么说明它属于黑方的棋子,否则是红方的棋子。
同时picChess[i]的tag属性还保存了棋子的类型。
这样就可以得到我们所需要的全部象棋棋子了。
黑方对应的是0至15,红方则用16至31。
具体下标含义如下:
0将1士2士3象4象5马6马7车8车9炮10炮11—15卒
16帅17仕18仕19相20相21马22马23车24车25炮26炮27—31兵
棋盘表示就是使用一种数据结构来描述棋盘及棋盘上的棋子,我们使用一个二维数组Map。
一个典型的中国象棋棋盘是使用9×10的二维数组表示,每一个元素代表棋盘上的一个交点,一个没有棋子的交点所对应的元素是-1。
一个二维数组Map保存了当前棋盘的布局,当Map[x,y]=i时说明此处是索引号为i的棋子对象,否则-1此处为空。
3.2走棋规则
对于象棋来说,有马走日,象走田等一系列复杂的规则。
走法产生是博弈程序中一个相当复杂而且耗费运算时间的方面。
不过,通过良好的数据结构,可以显著地提高生成的速度。
如何分辨棋子?
程序中采用了控件自带属性tag,将棋子名字赋值给tag,移动棋子时,通过tag值判断走法。
程序中IsAbleToPut(idx,x,y)函数实现判断是否能走棋返回逻辑值,这代码最复杂。
其中参数含义如下:
idx代表走的棋子的下标号,参数x,y代表走棋的目标位置。
走动棋子原始位置可以通过GetChessX(idx)GetChessY(idx)两个函数取得。
GetChessX(idx)获取的原x坐标oldx,GetChessY(idx)获取的原y坐标oldy。
IsAbleToPut(idx,x,y)函数完成以下判断:
(1)检查终点位置棋子是否为当前方,是则不能走棋返回假
if(IsMyChess(Map[x,y]))returnfalse;
(2)实现走棋规则判断
例如“将”或“帅”走棋规则,只能走一格,所以GetChessX(idx)获取的原x坐标与新位置x坐标之差不能大于1,GetChessY(idx)获取的原y坐标与新位置y坐标之差不能大于1。
if(Math.Abs(x-oldx)>1||Math.Abs(y-oldy)>1)
returnfalse;
由于不能走出九宫,所以x坐标4,5,6且1<=y<=3或8<=y<=10(实际上仅需判断是否8<=y<=10即可,因为走棋时自己的“将”或“帅”只能在己方的九宫中),否则此步违规,将返回False。
if(x<4||x>6||(y>3&&y<8))returnfalse;
“士”走棋规则,只能走斜线一格,所以GetChessX(idx)获取的原x坐标与新位置x坐标之差为1且GetChessY(idx)获取的原y坐标与新位置y坐标之差也同时为1。
if((x-oldx)*(y-oldy)==0)returnfalse;
if(Math.Abs(x-oldx)>1||Math.Abs(y-oldy)>1)returnfalse;
由于不能走出九宫,所以x坐标4,5,6且1<=y<=3或8<=y<=10,否则此步违规,将返回False。
if(x<4||x>6||(y>3&&y<8))returnfalse;
“炮”走棋规则,只能走直线,所以x,y不能同时改变,即(x-oldx)*(y-oldy)=0保证走直线。
然后判断如果x坐标改变了,是否原位置oldx到目标位置其间是否有棋子,如果有子则累加其间棋个数c。
通过c是否为1且目标处非己方棋子,可以判断是否可以走棋。
“兵”或“卒”走棋规则,只能向前走一步,根据是否过河,检查是否横走。
所以x与原坐标oldx改变的值不能大于1,同时y与原坐标oldy改变的值也不能大于1。
如果“兵”过河即是y<6,而“卒”过河即是y>=6。
if((x-oldx)*(y-oldy)!
=0)//斜向移动则返回false
returnfalse;
if(Math.Abs(x-oldx)>1||Math.Abs(y-oldy)>1)//移动大于一格返回false
returnfalse;
if(y>=6&&(x-oldx)!
=0)//“兵”没过河且横走则返回false
returnfalse;
if(y-oldy>0)//“兵”向后移动返回false
returnfalse;
其余的棋子判断方法类似,这里不再一一介绍。
3.3棋子坐标转换
走棋过程中,需要将图片的像素坐标转换成棋盘坐标,用到以下两个函数:
privateintGetPointX(intx)
{
//屏幕像素坐标转换成在棋盘中X坐标值
return(x)/(2*r)+1;
}
privateintGetPointY(inty)
{
//屏幕像素坐标转换成在棋盘中Y坐标值
return(y)/(2*r)+1;
}
3.4根据图片的索引号获取棋子棋盘坐标
走棋过程中,需要将图片的索引号获取棋子棋盘坐标,用到以下两个函数:
GetChessX可以根据索引号获取相应图片控件Left属性(屏幕x坐标位置)换算成棋盘x坐标位置。
privateintGetChessX(intidx)
{
//根据索引号获取棋子在棋盘中X坐标值
return(picChess[idx].Left)/(2*r)+1;
}
GetChessY可以根据索引号获取相应图片控件Top属性(屏幕y坐标位置)换算成棋盘y坐标位置。
privateintGetChessY(intidx)
{
//根据索引号获取棋子在棋盘中Y坐标值
return(picChess[idx].Top)/(2*r)+1;
}
3.5移动棋子
MoveChess()函数实现将棋子移动到棋盘坐标(x,y)处,方法是改变图片框的Left和Top的值即可,同时修改保存当前棋盘的布局Map数组。
privatevoidMoveChess(intidx,intx,inty)
{
picChess[idx].Parent=picBoard;
picChess[idx].Left=r+(x-1)*2*r-r+1;
picChess[idx].Top=r+(y-1)*2*r-r+1;
picChess[idx].BackColor=System.Drawing.SystemColors.GrayText;
Map[x,y]=idx;
}
4.象棋游戏程序设计的步骤
(1)新建一个Windows应用程序,项目命名为“控件版象棋”。
如图1设计中国象棋界面。
在VisualStudio.NET集成开发环境中的【解决方案资源管理器】窗口中,双击Form1.cs文件,进入Form1.cs文件的编辑界面。
如图添加控件,主要控件属性如表1所示。
图1控件版象棋界面
表1控件属性设置
控件
对象
属性
属性值
Form窗体
Frmchess
Name
Frmchess
Frmchess
Text
控件版象棋
Button控件
button1
Text
重新开始
button2
Text
退出游戏
ListBox控件
listBox1
PictureBox控件
picBoard
Image
棋盘图像
ToolStripStatusLabel
toolStripStatusLabel1
Text
象棋1.0
(2)在Form1.cs文件中如下编写代码:
窗体类Frmchess成员变量定义:
publicconstshortREDPLAYER=1;
publicconstshortBLACKPLAYER=0;
int[,]Map=newint[10,11];//map是布局
intCurSelect=-1;//CurSelect表示当前选中的棋子索引号
intr=18;//r是棋子半径
publicintLocalPlayer;//LocalPlayer记录自己是红方还是黑方
boolIsMyTurn=true;//IsMyTurn判断是否该自己走了
boolstep_flag;
publicPictureBox[]picChess=newPictureBox[32];//象棋棋子图片控件
SetMyTurn()设置是否该自己走的提示信息。
privatevoidSetMyTurn(boolbolIsMyTurn)
{
if(LocalPlayer==BLACKPLAYER)//游戏者角色改变
{
LocalPlayer=REDPLAYER;
toolStripStatusLabel1.Text="红方走棋";
}
else
{
LocalPlayer=BLACKPLAYER;
toolStripStatusLabel1.Text="黑方走棋";
}
}
LoadChess()方法实现加载棋子图片,Draw_qizi()显示棋子的时候,默认红方棋子在下方(南边),黑方棋子在上方。
privatevoidLoadChess()
{
stringstr;
stringpath;
path=System.Windows.Forms.Application.StartupPath;//bin路径
inti;
for(i=0;i<32;i++){
//黑方对应的是0至15,红方对应的是16至31
picChess[i]=newPictureBox();
this.Controls.Add(picChess[i]);
picChess[i].SetBounds(0,0,(r-1)*2,(r-1)*2);
picChess[i].BackColor=System.Drawing.SystemColors.GrayText;
picChess[i].Name="MyPic"+i.ToString();
picChess[i].Width=35;
picChess[i].Height=35;
str=path+"\\..\\..\\image\\q"+i.ToString()+".jpg";
if(i>=0&&i<=10)
picChess[i].Image=Image.FromFile(str);
if(i>=16&&i<=26)
picChess[i].Image=Image.FromFile(str);
picChess[i].Text=i.ToString();
picChess[i].Visible=false;
picChess[i].BringToFront();
picChess[i].Click+=pic_click;
}
}
privatevoidDraw_qizi()//显示棋盘上的棋子
{
stringstr,path;
inti;
path=System.Windows.Forms.Application.StartupPath;//bin路径
//默认红方棋子在下方,黑方棋子在上方
picChess[0].Tag="将";picChess[16].Tag="帅";
MoveChess(0,5,1);MoveChess(16,5,10);
picChess[1].Tag="士";picChess[17].Tag="仕";
MoveChess(1,4,1);MoveChess(17,4,10);
picChess[2].Tag="士";picChess[18].Tag="仕";
MoveChess(2,6,1);MoveChess(18,6,10);
picChess[3].Tag="象";picChess[19].Tag="相";
MoveChess(3,3,1);MoveChess(19,3,10);
picChess[4].Tag="象";picChess[20].Tag="相";
MoveChess(4,7,1);MoveChess(20,7,10);
picChess[5].Tag="马";picChess[21].Tag="马";
MoveChess(5,2,1);MoveChess(21,2,10);
picChess[6].Tag="马";picChess[22].Tag="马";
MoveChess(6,8,1);MoveChess(22,8,10);
picChess[7].Tag="车";picChess[23].Tag="车";
MoveChess(7,1,1);MoveChess(23,1,10);
picChess[8].Tag="车";picChess[24].Tag="车";
MoveChess(8,9,1);MoveChess(24,9,10);
picChess[9].Tag="炮";picChess[25].Tag="炮";
MoveChess(9,2,3);MoveChess(25,2,8);
picChess[10].Tag="炮";picChess[26].Tag="炮";
MoveChess(10,8,3);MoveChess(26,8,8);
for(i=11;i<=15;i++){
picChess[i].Tag="卒";
MoveChess(i,(i-11)*2+1,4);
str=path+"\\..\\..\\image\\q11.jpg";
picChess[i].Image=Image.FromFile(str);
picChess[16+i].Tag="兵";
MoveChess(16+i,(i-11)*2+1,7);
str=path+"\\..\\..\\image\\q27.jpg";
picChess[16+i].Image=Image.FromFile(str);
}
for(i=0;i<=31;i++)
{
picChess[i].Visible=true;
}
}
GetChessX()和GetChessY()实现根据棋子idx获取该子在棋盘中坐标值。
privateintGetChessX(intidx)
{
//棋子在棋盘中X坐标值
return(picChess[idx].Left)/(2*r)+1;
}
privateintGetChessY(intidx)
{
//棋子在棋盘中Y坐标值
return(picChess[idx].Top)/(2*r)+1;
}
GetPointX()和GetPointY()实现屏幕像素坐标转换成在棋盘中坐标值。
privateintGetPointX(intx)
{
//屏幕像素坐标转换成在棋盘中X坐标值
return(x)/(2*r)+1;
}
privateintGetPointY(inty)
{
//屏幕像素坐标转换成在棋盘中Y坐标值
return(y)/(2*r)+1;
}
IsMyChess()实现根据棋子idx判断是否是己方棋子。
privateboolIsMyChess(intidx)//判断是否是己方棋子
{
boolfunctionReturnValue=false;
if(idx>=0&&idx<16&&LocalPlayer==BLACKPLAYER)
functionReturnValue=true;
if(idx>=16&&idx<32&&LocalPlayer==REDPLAYER)
functionReturnValue=true;
returnfunctionReturnValue;
}
棋子的单击事件方法pic_click()处理用户走棋过程。
用户走棋时,首先须选中自己的棋子(第1次选择棋子),所以有必要判断是否单击成对方棋子了。
如果是自己的棋子,则CurSelect记录用户选择的棋子,同时棋子的背景色变成蓝色。
当用户选过己方棋子后,单击对方棋子(第2次选择棋子),则是吃子,如果将或帅被吃掉,则游戏结束。
当然第2次选择棋子有可能是用户有可能改变主意,选择自己的另一棋子,则CurSelect重新记录用户选择的己方棋子。
privatevoidpic_click(objectsender,System.EventArgse)
{
//这里处理公共事件
if(IsMyTurn==false)return;
intx,y,idx;
x=GetChessX(Convert.ToInt16(((PictureBox)sender).Text));
y=GetChessY(Convert.ToInt16(((PictureBox)sender).Text));
if(CurSelect==-1)//第一次棋子
{
if(!
IsMyChess(Map[x,y])){
toolStripStatusLabel1.Text="错误!
,单击成对方棋子了!
";
}
else{
CurSelect=Convert.ToInt16(((PictureBox)sender).Text);
picChess[CurSelect].BackColor=System.Drawing.Color.Blue;
step_flag=true;
}
}
else//第2次选择棋子
{
//如果是自己的棋子,则换上次选择的棋子
i
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C# 控件 数组 实现 象棋 游戏
![提示](https://static.bdocx.com/images/bang_tan.gif)