数据结构中国象棋实验报告.docx

上传人:b****8 文档编号:9726930 上传时间:2023-02-06 格式:DOCX 页数:72 大小:396.53KB
下载 相关 举报
数据结构中国象棋实验报告.docx_第1页
第1页 / 共72页
数据结构中国象棋实验报告.docx_第2页
第2页 / 共72页
数据结构中国象棋实验报告.docx_第3页
第3页 / 共72页
数据结构中国象棋实验报告.docx_第4页
第4页 / 共72页
数据结构中国象棋实验报告.docx_第5页
第5页 / 共72页
点击查看更多>>
下载资源
资源描述

数据结构中国象棋实验报告.docx

《数据结构中国象棋实验报告.docx》由会员分享,可在线阅读,更多相关《数据结构中国象棋实验报告.docx(72页珍藏版)》请在冰豆网上搜索。

数据结构中国象棋实验报告.docx

数据结构中国象棋实验报告

数据结构课程设计报告——中国象棋

姓名:

林泽全学号:

*********班级:

09网络工程

一、问题描述

1.象棋概述

象棋,又称中国象棋(英文现译作chess)。

在中国有着悠久的历史,属于二人对抗性游戏的一种,由于用具简单,趣味性强,成为流行极为广泛的棋艺活动。

中国象棋是我国正式开展的78个体育运动项目之一,为促进该项目在世界范围内的普及和推广,现将“中国象棋”项目名称更改为“象棋”。

此外,高材质的象棋也具有收藏价值,如:

高档木材、玉石等为材料的象棋。

更有文人墨客为象棋谱写了诗篇,使象棋更具有一种文化色彩。

2.棋子的初始棋位

整个棋盘以“河界”分为相等的两部分。

为了比赛记录和学习棋谱方便起见,现行规则规定:

按九条竖线从右至左用中文数字一至九来表示红方的每条竖线,用阿拉伯数字1只至9来表示黑方的每条竖线。

己方的棋子始终使用己方的线路编号,无论棋子是否“过河”。

对弈开始之前,红黑双方应该把棋子摆放在规定的位置。

任何棋子每走一步,进就写“进”,退就写“退”,如果像车一样横着走,就写“平”。

3.象棋棋子

象棋是一种双方对阵的竞技项目。

棋子共有三十二个,分为红黑两组,各有十六个,由对弈的双方各执一组。

棋子种类说明如下表:

红方名称

黑方名称

每方棋子数

可以到达的范围

1

己方九宫内

2

全盘任何位置

2

全盘任何位置

2

全盘任何位置

2

己方区域内(实际上是7个特殊棋位)

2

己方九宫内(实际上是5个特殊棋位)

5

起始位置及向前一步的位置,敌方所有棋位

帅与将;仕与士;相与象;兵与卒的作用完全相同,仅仅是为了区别红棋和黑棋而已。

4.棋子的走法

Ø帅(将)

帅(将)是棋中的首脑,是双方竭力争夺的目标。

它只能在九宫之内活动,可上可下,可左可右,每次走动只能按竖线或横线走动一格。

帅与将不能在同一直线上直接对面,否则走方判负。

Ø仕(士)

仕(士)是将(帅)的贴身保镖,它也只能在九宫内走动。

它的行棋路径只有九宫内的斜线。

Ø相(象)

相(象)的主要作用是防守,保护自己的帅(将)。

它的走法是每次循对角线走两格,俗称“象飞田”。

相(象)的活动范围限于河界以内的本方阵地,不能过河,且如果它走的田字中央有一个棋子,就不能走,俗称“塞象眼”。

Ø车

车在象棋中威力最大,无论横线、竖线均可行走,只要无子阻拦,步数不受限制。

因此,一车可以控制十七个点,故有“一车十子寒”之称。

Ø炮(炮)

炮(炮)在不吃子的时候,移动与车完全相同。

当吃子时,己方和对方的棋子中间必须间隔1个棋子(无论对方或己方棋子),炮是象棋中唯一可以越子的棋种。

Ø马

马走动的方法是一直一斜,即先横着或直着走一格,然后再斜着走一个对角线,俗称“马走日”。

马一次可走的选择点可以达到四周的八个点,故有八面威风之说。

如果在要去的方向有别的棋子挡住,马就无法走过去,俗称“蹩马腿”。

Ø兵(卒)

兵(卒)在未过河前,只能向前一步步走,过河以后,除不能后退外,允许左右移动,但也只能一次一步,即使这样,兵(卒)的威力也大大增强,故有“过河的卒子顶半个车”之说。

5.胜负的判定

1)当棋局中出现一下情况判负,对方取胜:

a.帅(将)被“将死”——另一方走一步棋之后试图吃掉一方的帅(将),但该方的帅(将)却不能躲避;

b.困毙——轮到一方行棋,但按规定,己方无棋可走;

c.由于子力悬殊,继续抵抗毫无意义的主动认输;

d.长打(即长捉、长将、长杀、或一将一要杀)的一方通常判负;

e.行棋违规、违纪、超时等情况判负。

2)当棋局中出现一下情况作和:

a.双方理论上无法取胜的简单局面;

b.符合“六十回合规定”——从任意一步开始,六十回合内双方均无损失一子;

c.一方提和,另一方同意和棋;

d.长跟、长兑、长拦、长献、一捉一闲、或一将一闲,循环三回合后可判和。

6.棋子的子力价值

Ø车:

象棋中实力最强的棋子,由于可以在棋盘线上飞快的移动,不论吃子与移动都十分方便,因此在全盘的价值都很高,其实力相当于双马、双炮、马炮,为其评估10分。

其近、中、远程作战都适用。

Ø炮:

由于其“炮打隔子”因此中远程作战,其多用于牵制,和各子(主要是车)配合都很容易。

在残局要依靠仕相的力量攻守(俗称“残局炮还家”)。

开、中局由于子多,他的“炮架子”也多,实力略高于马,此时为他打5分。

残局“炮架子”少,实力也相应减弱,但其依靠仕相防守力强于马(如单车可胜马双仕却难胜炮双仕),因此“求和易留炮”,此时为其打4.5分。

其实力等于一马、双仕、双相、一仕一相。

Ø马:

中距离作战兵器。

与炮相反,由于“蹩腿”,子力少时,实力较炮强。

由于此性质,它易往开阔处跳,戍边反而不利。

其实力相当于一炮、双相、双仕、一仕一相。

Ø兵(卒):

开局时由于只能向前,几乎无攻击力,但有限疏通我方马路兼限制敌方马路的作用,为其打0.5分。

过河后可以转弯,当靠近敌方九宫时威力大增,故有“小兵过河顶大车”、“过河卒子半个车”等说法。

残局时,双方子力较少,兵的作用显现出来,过河的高兵,价值倍增为其打3分;低兵价值2分;因为底兵只对一楼的老将有威胁,所以底兵价值1分。

过河的兵相当于一仕、一相。

注意兵轻易不要沉底。

Ø仕(士)、相(象):

属于防守的棋子,一仕等于一相。

开局阶段,老将不易受攻击为其打2分,正因为如此,开局人们不爱用马(炮)兑仕相。

中、残局时矛头直指老将,此时急需仕相守卫,同时仕相还可配合炮攻防或走闲着以防困毙,因此不占便宜就不要轻易丢弃仕相,此时为其打3分。

切记:

缺仕宜兑车,缺相宜兑炮。

花士象可防车,中联仕相可防炮。

仕相宜中联,相不轻易散边。

Ø帅(将):

全盘棋子争夺的目标,需要我方棋子保护。

开局时不宜乱动免得自找麻烦。

中、残局安全时可出帅助攻,如“铁门栓”。

二、基本要求

程序的用户作为玩者的角色,计算机是对手。

计算机可以实现简单地人机对战。

三、工具/准备工作

需要一台计算机,其中安装有VisualC++6.0集成开发环境软件。

四、分析与实现

Ø首先是根据中国象棋的走法,规定各个棋子的走法。

其具体实现方法用函数CanGo实现,

BOOLCanGo(intmanmap[11][12],intman,constPOINT&from,constPOINT&to)

{

staticinti,j;

if(!

IsNormal(ManToType[man],to))//这个棋子不能放在目标位置

{

//如果不是将/帅(将/帅可以“照相”)

if(ManToType[man]!

=RED_K&&ManToType[man]!

=BLACK_K)

returnFALSE;

elseif(ManToType[man]==RED_K&&//走的是帅

ManToType[manmap[to.x][to.y]]==BLACK_K)//目标是将

{

BOOLflag=FALSE;

for(j=from.y-1;j>0;j--)

{

if(manmap[from.x][j]!

=32)

{

if(ManToType[manmap[from.x][j]]==BLACK_K)//照相

flag=TRUE;

break;

}

}

if(flag)

returnTRUE;

else

returnFALSE;

}

elseif(ManToType[manmap[to.x][to.y]]==RED_K)//走的是将,目标是帅

{

BOOLflag=FALSE;

for(j=from.y+1;j<11;j++)

{

if(manmap[from.x][j]!

=32)

{

if(ManToType[manmap[from.x][j]]==RED_K)//照相

flag=TRUE;

break;

}

}

if(flag)

returnTRUE;

else

returnFALSE;

}

else

returnFALSE;

}

//下面几行判断目标点是否己方的棋子

if(SideOfMan[man]==0)

{

if(manmap[to.x][to.y]!

=32&&SideOfMan[manmap[to.x][to.y]]==0)

returnFALSE;

}

elseif(SideOfMan[man]==1)

{

if(manmap[to.x][to.y]!

=32&&SideOfMan[manmap[to.x][to.y]]==1)

returnFALSE;

}

//以下是各棋子的规则

switch(ManToType[man])

{

caseRED_B:

//兵不回头

if(to.y>from.y)

returnFALSE;

//兵只走一步直线

if(from.y-to.y+abs(to.x-from.x)>1)

returnFALSE;

break;

caseBLACK_B:

//卒不回头

if(to.y

returnFALSE;

//卒只走一步直线

if(to.y-from.y+abs(to.x-from.x)>1)

returnFALSE;

break;

caseRED_S:

caseBLACK_S:

//士走斜线一步

if(abs(from.y-to.y)>1||abs(to.x-from.x)>1)

returnFALSE;

break;

caseRED_X:

caseBLACK_X:

//象走田

if(abs(from.x-to.x)!

=2||abs(from.y-to.y)!

=2)

returnFALSE;

//象心

if(manmap[(from.x+to.x)/2][(from.y+to.y)/2]!

=32)

returnFALSE;

break;

caseRED_K:

caseBLACK_K:

//将帅只走一步直线

if(abs(from.y-to.y)+abs(to.x-from.x)>1)

returnFALSE;

break;

caseRED_J:

caseBLACK_J:

//车只能走直线

if(from.y!

=to.y&&from.x!

=to.x)

returnFALSE;

//车经过的路线不能有棋子

if(from.y==to.y)

{

if(from.x

{

for(i=from.x+1;i

if(manmap[i][from.y]!

=32)

returnFALSE;

}

else

{

for(i=to.x+1;i

if(manmap[i][from.y]!

=32)

returnFALSE;

}

}

else

{

if(from.y

{

for(j=from.y+1;j

if(manmap[from.x][j]!

=32)

returnFALSE;

}

else

{

for(j=to.y+1;j

if(manmap[from.x][j]!

=32)

returnFALSE;

}

}

break;

caseRED_P:

caseBLACK_P:

//炮只能走直线

if(from.y!

=to.y&&from.x!

=to.x)

returnFALSE;

//炮不吃子时经过的路线不能有棋子

if(manmap[to.x][to.y]==32)

{

if(from.y==to.y)

{

if(from.x

{

for(i=from.x+1;i

if(manmap[i][from.y]!

=32)

returnFALSE;

}

else

{

for(i=to.x+1;i

if(manmap[i][from.y]!

=32)

returnFALSE;

}

}

else

{

if(from.y

{

for(j=from.y+1;j

if(manmap[from.x][j]!

=32)

returnFALSE;

}

else

{

for(j=to.y+1;j

if(manmap[from.x][j]!

=32)

returnFALSE;

}

}

}

else//吃子时

{

intcount=0;

if(from.y==to.y)

{

if(from.x

{

for(i=from.x+1;i

{

if(manmap[i][from.y]!

=32)

count++;

}

if(count!

=1)

returnFALSE;

}

else

{

for(i=to.x+1;i

{

if(manmap[i][from.y]!

=32)

count++;

}

if(count!

=1)

returnFALSE;

}

}

else

{

if(from.y

{

for(j=from.y+1;j

{

if(manmap[from.x][j]!

=32)

count++;

}

if(count!

=1)

returnFALSE;

}

else

{

for(j=to.y+1;j

{

if(manmap[from.x][j]!

=32)

count++;

}

if(count!

=1)

returnFALSE;

}

}

}

break;

caseRED_M:

caseBLACK_M:

//马走日

if(!

((abs(to.x-from.x)==1&&abs(to.y-from.y)==2)

||(abs(to.x-from.x)==2&&abs(to.y-from.y)==1)))

returnFALSE;

//找马脚

if(to.x-from.x==2){i=from.x+1;j=from.y;}

elseif(from.x-to.x==2){i=from.x-1;j=from.y;}

elseif(to.y-from.y==2){i=from.x;j=from.y+1;}

elseif(from.y-to.y==2){i=from.x;j=from.y-1;}

//绊马脚

if(manmap[i][j]!

=32)

returnFALSE;

break;

default:

break;

}

returnTRUE;

}

Ø判断棋子的位置是不是合法,用函数IsNormal实现。

具体是实现如下:

BOOLIsNormal(constint&mantype,constPOINT&point)

{

if(point.x<1||point.x>9||point.y<1||point.y>10)

returnFALSE;

switch(mantype)

{

caseRED_K:

//帅不能在红方宫外

if(point.x>6||point.x<4||point.y<8)

returnFALSE;

break;

caseRED_S:

//士只能在宫内特定点

if(!

(point.x==4&&point.y==10)||

(point.x==4&&point.y==8)||

(point.x==5&&point.y==9)||

(point.x==6&&point.y==10)||

(point.x==6&&point.y==8)

))

returnFALSE;

break;

caseRED_X:

//七个相位

if(!

(point.x==1&&point.y==8)||

(point.x==3&&point.y==10)||

(point.x==3&&point.y==6)||

(point.x==5&&point.y==8)||

(point.x==7&&point.y==10)||

(point.x==7&&point.y==6)||

(point.x==9&&point.y==8)

))returnFALSE;

break;

caseRED_B:

//兵不能在兵位后

if(point.y>7)

returnFALSE;

//兵过河前不能左右移动

if(point.y>5&&point.x%2==0)

returnFALSE;

break;

caseBLACK_K:

//帅不能在红方宫外

if(point.x>6||point.x<4||point.y>3)

returnFALSE;

break;

caseBLACK_S:

//士只能在宫内特定点

if(!

(point.x==4&&point.y==1)||

(point.x==4&&point.y==3)||

(point.x==5&&point.y==2)||

(point.x==6&&point.y==1)||

(point.x==6&&point.y==3)

))

returnFALSE;

break;

caseBLACK_X:

//七个相位

if(!

(point.x==1&&point.y==3)||

(point.x==3&&point.y==1)||

(point.x==3&&point.y==5)||

(point.x==5&&point.y==3)||

(point.x==7&&point.y==1)||

(point.x==7&&point.y==5)||

(point.x==9&&point.y==3)

))returnFALSE;

break;

caseBLACK_B:

//兵不能在兵位后

if(point.y<4)

returnFALSE;

//兵过河前不能左右移动

if(point.y<6&&point.x%2==0)

returnFALSE;

break;

default:

break;

}

returnTRUE;

}

Ø保存棋盘状态。

其具体实现如下:

voidFixManMap(intmap[11][12],POINTmanpoint[32],intside)

{

memcpy(map,_defaultmap,132*sizeof(int));

staticPOINT*pman;

staticinti;

for(i=0;i<32;i++)

{

pman=&manpoint[i];

if(pman->x)

map[pman->x][pman->y]=i;

}

}

Ø规定各个位置不同的价值值:

//兵卒在不同位置的价值,数字越大价值越高

constintManBPlus[2][12][11]=

{

{

{0,0,0,0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0,0,0},

{0,1,2,3,4,4,4,3,2,1,0},

{0,1,2,3,4,4,4,3,2,1,0},

{0,1,2,3,3,3,3,3,2,1,0},

{0,1,1,1,1,1,1,1,1,1,0},

{0,0,0,1,0,0,0,1,0,0,0},

{0,0,0,0,0,2,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0,0,0}

},

{

{0,0,0,0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 畜牧兽医

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1