五子棋对弈系统设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
南京理工大学
毕业设计说明书(论文)
作者: 李国防准考证号:014910253063
教学点: 南京信息职业技术学院
专业: 电子工程专业
题目: 五子棋对弈系统设计
徐小平副教授
指导者:
(姓名) (专业技术职务)
评阅者:
(姓名) (专业技术职务)
2012年 05 月
毕业设计说明书(论文)中文摘要
毕业设计说明书(论文)外文摘要
本科毕业设计说明书(论文)第I共I页
目次
1引言 (1)
2五子棋概述 (2)
2.1五子棋背景及规则 (2)
2.2开发工具下图形界面函数的介绍 (2)
3设计思想 (4)
3.1总体模版的设计 (4)
3.2五子棋程序框架总图 (4)
4模块介绍 (5)
4.1初始化模块 (5)
4.2接收处理信息模块 (8)
4.3走棋控制模块 (9)
5数据测试 (15)
6 对人工智能对弈模式的设想 (17)
6.1棋型的定义 (17)
6.2棋型价值的定义及计算 (19)
结论 (21)
致谢 (22)
参考文献 (23)
附录(源程序) (24)
1 引言
随着人工智能的发展,越来越多的软件游戏应运而生,伴随着其庞大功能的同时,给出了各种越来越多的规则限制,更多的局限于游戏的竞技能力,逐步忽略了其原始为大众所追捧的趣味性,简单性。
因此,富有各种规则的棋类游戏渐渐淡出,而让我们迷恋追捧的却是那些简简单单,无太多章法,却趣味十足的软件游戏,如:“愤怒地小鸟”、“汤姆猫”等。
而本文则摆脱了棋类游戏的各种附带限制,将传统的五子棋游戏,通过DOXBOX系统给大家展示,将规则交给玩家,可塑性强。
与此同时,本文尽管基于TC工具来实现,但却别开生面,遗弃了复杂模糊的字符界面,完全体现了图形库函数的应用,呈现了简洁、大方的图形界面。
在论文的进展过程中,首先遇到的最大的难题就是对于图形库函数的认知不够全面,一些细致的东西,没抓到点的要求,从而导致程序一次次的编译失败。
在经过多次研究,比对和尝试后,最终才得以成功。
其次,因在win7下无法实现win-tc的全屏显示,多次失败后选择更换XP系统来完成,最后论文的书写过程中,因为全屏后无法剪切图片,而导致无法顺利完成论文,后经查询,确定用DOXBOX来实现,才得以成功完成。
本设计将程序分为3个主要模块,针对每一模块为实现其预期功能,而分开去构思研究,确定其在整个程序中的位置,最后完善。
另外,在实现本文设计内容之余,还展示了个人对人工智能实现人机对战的构想。
2 五子棋的概述
五子棋是一种两人对弈的纯决策谋略型棋类游戏,是起源于中国古代的传统黑白棋种类之一。
发展于日本,流行于欧美。
容易上手,老少皆宜,而且趣味横生,引人入胜;不仅能增强思维能力,提高智力,而且富有哲理,有助于修身养性。
2.1五子棋的背景及规则
五子棋是起源于中国古代的传统黑白棋种之一。
现代五子棋日文称之为“连珠”,英译为“Renju”,英文称之为“Gobang”或“FIR”(Five in a Row的缩写),亦有“连五子”、“五子连”、“串珠”、“五目”、“五目碰”、“五格”等多种称谓。
五子棋不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。
五子棋既有现代休闲的明显特征“短、平、快”,又有古典哲学的高深学问“阴阳易理”;它既有简单易学的特性,为人民群众所喜闻乐见,又有深奥的技巧和高水平的国际性比赛;它的棋文化源渊流长,具有东方的神秘和西方的直观;既有“场”的概念,亦有“点”的连接。
它是中西文化的交流点,是古今哲理的结晶。
五子棋的规则如下:棋盘:采用同围棋盘一样的15 路或19 路线的棋盘,为了实现传统的五子棋棋盘,本系统将采用19路线的棋盘。
下法:两人分别执黑白两色棋子,轮流在棋盘上选择一个无子的交叉点落子。
无子的交叉点又被称为空点。
输赢判断:黑、白双方有一方的5个棋子在横、竖或斜方向上连接成一线即为该方赢。
2.2开发工具下图形界面函数的介绍
应用Turbo C工具中的库函数graphics.h图形界面的画法,可以实现各种基本图形的绘制,比如说:圆、椭圆、方框、线、点、文本框等,本文主要介绍设计中会用到的一些图形界面函数的应用方法。
2.2.1画线函数
这类函数提供了从一个点到另一个点用设定的颜色画一条直线的功能,起始点的设定方法不同,因而有下面不同的画线函数。
1)两点之间画线函数。
void far line(int x0,int y0,int x1,int y1);
从(x0,y0)点到(x1,y1)点画一直线。
2)从现行画笔位置到某点画线函数。
void far lineto(int x,int y);
将从现行画笔位置到(x,y)点画一直线。
3)从现行画笔位置到一增量位置画线函数
void far linerel(int dx,int dy);
2.2.2画(椭)圆函数
在画图的函数中,有关于角的概念。
在Turbo C 中是这样规定的:屏的x 轴方向为0 度,当半径从此处逆时针方向旋转时,则依次是90 度、180 度、270 度,当360 度时,则和x轴正向重合,即旋转了一周。
1)画椭圆函数
void ellipse(int x,int y,int stangle,int endangel,int xradius,int yradius);
该函数将以(x,y)为中心,以xradius 和yradius 为x 轴和y 轴半径,从起始角stangle开始到endangle 角结束,画一椭圆线。
当stangle=0,endangle=360 时,则画出的是一个完整的椭圆,否则画出的将是椭圆弧。
当然,满足一定条件的椭圆也就是圆,应用椭圆的画法可以实现棋子的画法。
2)画圆函数
void far circle(int x,int y,int radius);
该函数将以(x,y)为圆心,radius 为半径画个圆。
2.2.3颜色设置函数
象素的显示颜色,或者说画线、填充面的颜色既可采用缺省值,也可用一些函数来设置。
与文本方式一样,图形方式下,象素也有前景色和背景色。
按照CGA、EGA、VGA 图形适配器的硬件结构,颜色可以通过对其内部相应的寄存器进行编程来改变。
1)前景色设置函数
void far setcolor(int color);
该函数将使得前景以所选color 颜色进行显示,对CGA,当为中分辨模式
只能选0,1,2,3。
2)选择背景颜色的函数
void far setbkcolor(int color)
该函数将使得背景色按所选16 种中的一种color 颜色进行显示
本文则根据传统五子棋的基本下法,运用所学的库函数图形界面的画法,设计了一篇简单的五子棋对弈系统,界面简洁美观,可塑性强且趣味性十足。
3 设计思想
传统的五子棋的棋具与围棋相同,棋子分为黑白两色,棋盘为19x19,棋子一般放置棋盘线交叉点上。
两人对局,各执一色,轮流下子,先将横、竖或斜线上5个同色棋子连成不间断的一排着为胜。
而本文设计通过程控,实现2人对弈的五子棋界面。
主要通过库函数的应用画制棋盘棋子,函数定义及判定循环方式来决定棋子是否可下,移动更新游标位置,同时根据下子后棋型扫描,判断是否赢棋,具体实现构思如下:
3.1总体的模板设计
按照设计思路,将整个程序根分为3个模块,即初始化模块、接受处理信息模块以及走棋控制模块,具体如图3-1所示。
图3-1总体模块设计图
3.2五子棋程序框架总图
本设计重在五子棋双人对战程序的编译实现,根据3.1总体模板的构思,初步涉论,提出各模块组合顺序、涉及具体内容,绘出本程序所需的总体流程方向及全局构架,见图3.2;
玩游戏
判断落子键的有效性
更新数组与棋盘显示
判断是否走成五子相连
图3-2五子棋程序框架总图
根据此框架流程图,逐次研究各模块为实现其对应的功能,所要采用的方法,每个模块涉及的思路以及编写技巧,将于下章详细介绍。
4 模块介绍
4.1初始化模块
游戏开始,首先显示的是棋盘界面,及一些操作键等提示信息的定义说明,简单的来讲就是一幅未下子的空界面,另外,一次游戏结束后的开局界面,也是在考虑初始化的过程中必然要研究的,总结分为以下3个方向:
4.1.1画棋盘
棋盘采用19*19的矩形棋盘,即应用19*19的二位数组fivemap[19][19],用来保存当前棋盘的落子资料组,其中对每个成员来说,0表示无子,1表示落1号玩家棋子,2表示落2号玩家棋子。
程序引用库函数中的线条画法,定义函数void drawmap(),定义颜色为4号红色,定义四角点坐标为(92,12)、(92,444)、(92,12)、(524,12)。
定义线与线区间间隔为24。
根据TC库函数线的画法,取棋盘的四角点坐标如上,根据两点之间直线的画法,void far line(int x0,int y0,int x1,int y1);定义线与线之间的距离为24,采用示例中的循环方式,画出棋盘。
int x0,int y0表示初始点的坐标,int x1,int y1为末点的坐标。
程序示例如下:
void drawmap()
{
int i;
setcolor(4);
for(i=0;i<19;i++)
{
line(92+24*i,12,92+24*i,444);
line(92,12+24*i,524,12+24*i);
}
}
4.1.2显示提示说明信息
主要用来显示按键提示说明以及提示,显示字体,以及背景颜色,通过应用TC库函数settextstyle定义文字类型/大小,库函数settextstyle的功能是为图形输出设置当前的文本属性,主要用法为: void far settextstyle (int font, int direction, char size);其中font 为字体:DEFAULT_FONT,TRIPLEX_FONT, SMALL_FONT, SANSSERIF_FONT, GOTHIC_FONT,也可以用0 ~ 4代替。
direction 为字符的排列方向:横向和竖向,0为横向排列,1为竖向排列。
size 为字体大小:可用interger做参数。
文中分别为:
settextstyle(0,HORIZ_DIR,1);settextstyle(0,HORIZ_DIR,5);
文本输出位置在下列语句中指出,其中(0,100)、(0,150)。
定义了说明语句的输出坐标,“”内容为显示内容。
示例如下:
outtextxy(0,100,"a : LEFT");
outtextxy(0,150,"d : RIGHT");
outtextxy(0,200,"w : UP");
outtextxy(0,250,"s : DOWN");
outtextxy(0,300,"Enter : DO");
outtextxy(0,350,"Esc : Exit");
outtextxy(250,200,"END!");
outtextxy(70,250,"WINNER : PLAYER1");
outtextxy(70,250,"WINNER : PLAYER2");
4.1.3棋盘置空
棋盘置空,也就是界面刷新,用于开始界面或重新开局,主要是通过主函数调用与界面有关的其它函数,例如背景颜色函数、棋盘绘制函数、文本说明函数等。
cleardevice()为界面初始函数,刷新整体界面;setbkcolor(11);定义背景颜色为11号淡青,settextstyle以及outtextxy的应用方式同4.12.
具体如下。
void drawall()
{
cleardevice();
setbkcolor(11);
setcolor(2);
settextstyle(0,HORIZ_DIR,1);
outtextxy(0,100,"a : LEFT");
outtextxy(0,150,"d : RIGHT");
outtextxy(0,200,"w : UP");
outtextxy(0,250,"s : DOWN");
outtextxy(0,300,"Enter : DO");
outtextxy(0,350,"Esc : Exit");
drawmap();
drawdata();
drawcursor();
}
4.2接收处理信息模块
主要分析处理输入信息命令,只要包括一般下子按键以及退出等类似的功能
键的定义,并且对按键输入命令进行处理,分析,直至整个游戏界面结束。
4.2.1一般下子按键的定义
一般下子键主要包括游标移动键,用‘w’‘a’‘s’‘d’表示,分别表示上循环、左循环、下循环、右循环。
按键用case定义,按键‘a’表示左移,其循环方式为从大到小依次递减,直至0以满足光标在棋盘范围内。
drawall()跳转到下子函数中。
其它按键工作原理类似。
具体程序如下所示:
case 'a':
if(nx>0)
{
nx--;
drawall();
}
break;
case 'd':
if(nx<18)
{
nx++;
drawall();
}
break;
case 'w':
if(ny>0)
{
ny--;
drawall();
}
break;
case 's':
if(ny<18)
{
ny++;
drawall();
}
break;
4.2.2功能键的定义说明
功能键主要是指功能说明键,也就是程序实现界面中的说明部分内容,即规定了,ESC按键退出、Enter键输入、W\S\A\D移动游标。
具体定义如下:
outtextxy(0,300,"Enter : DO");
outtextxy(0,350,"Esc : Exit");
(0,300)以及(0,350)定义了输入文本在界面中的显示位置。
“”内容为界面文本显示内容。
4.3走棋控制模块
本设计是五子棋中2人对弈模式的一种设计,因参加游戏的二人分别持两种非同色棋子,必须满足落子点可下,即满足该点为交叉点以及该点尚未有子,在本设计中需经程序判断是否有子后方可下棋,若一方取胜,则进入从新开局或游戏结束的选择菜单,主要涉及下子与判断以及游标的移动。
4.3.1下子与判断
1)判断落子键的有效性
落子键按下后,要么赢棋,要么交换行棋方,对于交换行棋方,程序是通过函数“who=3-who”,定义空为0,玩家1为1,玩家2为2,若确定落子键后,下子成功交换行棋方,棋子颜色更换为当前行棋方棋子颜色。
或者,落子后显示,当前行棋方获胜。
drawall()实现玩家落子,winner=checkwin();玩家赢棋函数说明,若无赢棋则,当前玩家落子,交换行棋方。
具体实现程序如下:
if(fivemap[nx][ny]==NONE)
{
fivemap[nx][ny]=who;
who=3-who;
winner=checkwin();
drawall();
if(winner!=NONE)
{
init();
who=PLAYER1;
getch();
drawall();
}
流程图如图4-1所示。
无
否
无
否
图4-1下子流程图
2)更新数组与棋面显示
确定落子后,若无赢家则需交换行棋方,本文通过定义,由4.31.1可知,分别定义无子为0,一号玩家为1,二号玩家为2,通过函数“who=3-who;”来交换行棋方。
直至一方胜出,输入显示说明信息。
具体程序说明为:
if(fivemap[nx][ny]==NONE)
{
fivemap[nx][ny]=who;
who=3-who;
winner=checkwin();
drawall();
if(winner!=NONE)
{
init();
who=PLAYER1;
getch();
drawall();
}
}
break;
玩家赢棋棋面显示:
if(winner==PLAYER1)
outtextxy(70,250,"WINNER : PLAYER1");
else
outtextxy(70,250,"WINNER : PLAYER2");
3)判断是否走成五子相连
判断是否走成五子相连,是从四个方向上判断,本文分别从4个方向上定
义,即水平方向,竖直方向,斜45°角方向以及斜135°角方向。
对于水平方向则是通过j不变,i不断加1的形式,实现同色棋五子相连。
竖直方向是通过i 不变,j不断加1;45°是通过i和j同时加1的形式,同理135°角线是通过i 减j加的形式实现的,具体如图4-2所示。
图4-2落子后棋型判断算法流程图
在水平方向连续有5个同色棋子的情况为:for(i=0;i<15;i++)
{
for(j=0;j<19;j++)
{
if(fivemap[i][j]!=NONE &&
fivemap[i][j]==fivemap[i+1][j] &&
fivemap[i][j]==fivemap[i+2][j] &&
fivemap[i][j]==fivemap[i+3][j] &&
fivemap[i][j]==fivemap[i+4][j])
return fivemap[i][j];
●在垂直方向上,形成5个相连同色棋子的情况为:
for(i=0;i<19;i++)
{
for(j=0;j<15;j++)
{
if(fivemap[i][j]!=NONE &&
fivemap[i][j]==fivemap[i][j+1] &&
fivemap[i][j]==fivemap[i][j+2] &&
fivemap[i][j]==fivemap[i][j+3] &&
fivemap[i][j]==fivemap[i][j+4])
return fivemap[i][j];
●在45°角在线形成五个相连同色棋子的情况为:
for(j=0;j<15;j++)
{
if(fivemap[i][j]!=NONE &&
fivemap[i][j]==fivemap[i+1][j+1] &&
fivemap[i][j]==fivemap[i+2][j+2] &&
fivemap[i][j]==fivemap[i+3][j+3] &&
fivemap[i][j]==fivemap[i+4][j+4])
return fivemap[i][j];
●在135°角在线形成五个相连同色棋子的情况为:
if(fivemap[18-i][j]!=NONE &&
fivemap[18-i][j]==fivemap[17-i][j+1] && fivemap[18-i][j]==fivemap[16-i][j+2] &&
fivemap[18-i][j]==fivemap[15-i][j+3] &&
fivemap[18-i][j]==fivemap[14-i][j+4])
return fivemap[18-i][j];
4.3.2移动游标
1)更新全局变量
游标的移动是依靠固定图形的坐标的改变,设计图形游标初始位置,定义初始坐标,控制坐标的改变,移动游标,从而游标的[i][j]变量值不断的改变。
具体如:
line(80+24*nx,24*ny,24*nx+86,24*ny);
line(24*nx+98,24*ny,24*nx+104,24*ny);
line(24*nx+80,24*ny+24,24*nx+86,24*ny+24);
line(24*nx+98,24*ny+24,24*nx+104,24*ny+24);
2)游标移动到新位置
游标的移动是通过坐标的移动,即定义初始坐标,然后随移动键的信息输入,改变游标的坐标,即可实现游标的移动,运用setcolor(1)定义游标颜色为1号蓝色。
运用画线的方式,上半部分画横线,下半部分画竖线,绘出光标。
通过变量nx和ny 的改变更换光标的位置,line(80+24*nx,24*ny,24*nx+86,24*ny);表示从坐标(80+24*nx,24*ny)到坐标(24*nx+86,24*ny)画水平线段,不同的变量值对应不同的水平线段,竖直方向亦是如此,通过水平与竖直线段拼凑成光标形状。
其具体实现形式如下:
void drawcursor()
{
setcolor(1);
line(80+24*nx,24*ny,24*nx+86,24*ny);
line(24*nx+98,24*ny,24*nx+104,24*ny);
line(24*nx+80,24*ny+24,24*nx+86,24*ny+24);
line(24*nx+98,24*ny+24,24*nx+104,24*ny+24);
line(24*nx+80,24*ny,24*nx+80,24*ny+6);
line(24*nx+80,24*ny+18,24*nx+80,24*ny+24);
line(24*nx+104,24*ny,24*nx+104,24*ny+6);
line(24*nx+104,24*ny+18,24*nx+104,24*ny+24);
}
5 数据测试
将书写完成的源程序拷贝到WIN-TC代码编译器中,并保存为“liguofang.C”然后通过编译连接显示编译成功,如图5-1所示。
图5-1程序编译结果
尝试将程序运行,成功!但WIN-TC全屏下未找到适当方式截图,经查询资料最终确定于DOXBOX中运行,运行状况如图5-2所示。
图5-2空界面显示
由图5-2所示,文本说明信息部分,字体过小且距离边界位置太近,于是对其进行修改,调整字体大小以及,文本坐标。
将字体由1号更换为2号,且整个棋盘界面往右移动24个点,同时文本距系统界面边界10个点,完成后如下图所示。
图5-3修改后的空界面显示
检查光标以及棋子是否超出棋盘,主要是四角点以及边界点,示例如图5-4所示。
图5-4边界点下棋子的界面显示
检查棋盘上是否所有点都可下子,随机在尽量不赢棋的情况下,下尽量多的
棋子,重复操作5次,检查是否存在不可下子的点,示例如图5-5所示。
图5-5检查是否存在不可下子的点
检查1号玩家赢棋界面,让一号玩家赢棋,检查输出信息是否对应,如图
5-6所示。
图5-6检查2号玩家赢棋界面
检查2号玩家赢棋界面,让一号玩家赢棋,检查输出信息是否对应,如图5-7所示。
图5-7检查2号玩家赢棋界面
通过对测试数据的全面检查、整改,最终得以成功完成,实现了预期要求的目的。
6 对人工智能对弈模式的设想
设计主要实现人人之间的对弈模式,其局限在必须2人同时在线操作游戏,
无法实现单人游戏。
因而针对人机对战,提出以下思想:
首先要实现人机对战,必须采用一些手段让机器有着自己的思维方式,也就是所谓的人工智能。
其与人人对战的最大区别就在于,机器能够用自己的“智慧”去分析最适当的落子点,经判断然后下子。
其分析的主要原理就是对棋盘从横向、纵向、45°角线方向以及135°角线方向进行扫描并且记录,然后对每一个可下子点进行计算得分,选择分数最高的点进行下子,当然为了能够做到攻防兼顾,必须对整个棋盘界面进行全方位扫描,记录并计算每个可下点的价值。
6.1棋型的定义
首先8个方向的棋型(如图示),可以用二维数组的形式去表现,如:gStytle[][](2,19,19,8,2)其中第一个下标为1时表示人或者用黑棋来代替,为2时表示机器或者用白棋来代替,第二和第三个下标表示(x,y),第四个下标表示8个方向,最后一个下标表示棋子数或空格数,用“1”和“2”来表示。
示例如下:
定义gStytle[][](1,2,2,1,1)=3,表示在第一个方向上,与坐标点(2,2)相邻的人所下的棋子数为3,示意图如下。
图6-1
定义 gStytle[][](1,2,2,1,2)=4表示在第一个方向上,与坐标点(2,2)相邻的人所下的棋子最近的空格数为4,示意图如下。
图6-2
对于方向的定义在语言中可表示如下:
Const DIR_UP = 1
Const DIR_UPRIGHT = 2
Const DIR_RIGHT = 3
Const DIR_RIGHTDOWN = 4
Const DIR_DOWN = 5
Const DIR_DOWNLEFT = 6
Const DIR_LEFT = 7
Const DIR_LEFTUP = 8
示意图如下。
图6-3
不难看出,后4个方向可用前4个方向加4表示,有效的利用的话,能够使语言更加简洁,从而利于编译成功。
通过上述表示方法,将棋盘上所有可下点均表示出来,对每一个棋型值进行定义记录。
以此来讨论他们的价值,对于价值的讨论,首先定义两个概念:1冲棋型,即棋有界限制;2活棋型,即无界的棋型。
示例如下:
Fn 表示先手n个棋子的活棋型,如:F4表示先手活四;
图6-4
Fn'表示先手n个棋子的冲棋型,如:F4'表示先手冲四;
图6-5
Ln 表示后手n个棋子的活棋型,如:L3表示后手活三;
图6-6
Ln'表示后手n个棋子的冲棋型,如:L3'表示后手冲三;
图6-7
6.2棋型价值的定义及计算
由五子棋常识可以看出,冲棋型跟活棋型价值不同,因此在计算下子点总价值的时候要综合考虑,此外还要考虑人和机器所处的顺序的先后问题,先手棋型与后手棋型价值也有区别,根据7.1的棋型分析,可得到如下关系: L1'<=F1'<L2'<=F2'<=L1<F1<L2<F2<L3'<=F3'<L4'<F4'=F4
这个关系是机器进攻和防守的依据,为了使机器具有更高的AI,可以深入的分析下这个关系,不如说4*F3<L4’表示在一点的4个方向上都有活三也比不上一个冲4,这类关系可在分值上进行区分定义,最后定义价值最小的L1’的值为1,那么其它棋型分值的定义如下示意:
F[2][5]={{0,2,5,50,16000},{0,10,30,750,16000}};
L[2][5]={{0,1,5,50,3750},{0,10,30,150,4000}};
F数组表示先手,第一个下标为0时表示冲型,第二个下标表示棋子数,则F2'对应F[0][2] L数组表示后手,第一个下标为0时表示冲型,第二个下标表示棋子数,棋型的分值关系确定好了以后,我们把每一个可下点的四个方向的棋型值相加(包括先手和后手的分值),最后选择一个最大值,并把这一点作为计算机要下的点。
结论
这篇论文到现在基本已经完成,在这段时间,从找数据到开始书写,再到整理完善,每一步在老师的监督、鼓励、指导下,终于算的上即将落幕。
首先,漫长的寻数据定题目的过程中,我认真的阅读了好多曾经不曾静下来,仔细研究的文章,真真切切的学到了好多未曾了解的知识。
其次,这次论文的研究书写,给了我一次深刻复习的机会,让我对以往的知识,加深理解,彻底的锻炼了自己。
然后,这次论文研究的题目,证实了自己在C上面的能力,更加深了自己在这方面的兴趣,可谓收获颇丰。
在这次的论文完成过程中,我遇到了几道难题,首先就是棋盘的绘制,开始想到的是通过字符型去表现,结果出来界面难看入目,最后在老师的建议下,改用图形界面去展现;其次在编译的过程中,开始用的是win7系统,在win7下win-TC编译无法全屏显示,然后我更换了XP系统,从而可以全屏显示;最后在书写论文的过程中,win-TC全屏下无法截图,尝试过多种截图软件,亦无法实现,最后经过查询,下载了DOXBOX,经过学习DOXBOX的使用,最终达到目的。
本文摆脱了现代棋类游戏的各种附带规则限制,将传统的五子棋游戏,通过DOXBOX系统给大家展示,将规则交给玩家,可塑性强。
与此同时,本文尽管基于TC工具来实现,但却别开生面,遗弃了复杂模糊的字符界面,完全体现了图形库函数的应用,呈现了简洁、大方的图形界面。
这篇论文,从算法的研究,到每一个函数的定义书写,花费了自己好大一份经历和时间,尽管如此,但最后感觉每一份的努力,每一点心血都值得。
致谢
这次论文的成功展现,首先我要感谢学校给了我这个舞台,能够让我有这么一次展现自我的机会,然后要感谢在这次论文完成的过程中全力辅导我的徐老师,徐老师百忙之中,抽出时间监督辅导,让我能够顺利完成。
还要感谢在学校几年辛苦培养我的老师们,你们辛苦了!最后感谢那些为本设计提供相关数据的朋友、及编写的老师们,是你们之前的成就,完善了我的这篇论文。
参考文献
[1]潘金贵,陆庆文,陈兆干,樊莉萍.学习和使用TURBO C语言[M].南京.南京
大学出版社.1993
[2]潘金贵,陆庆文,陈兆干,樊莉萍.学习和使用TURBO C语言(续编)--TURBO
C实用工具与库函数大全[M].南京.南京大学出版社.1993
[3]王军政.Turbo C实用高级编程编程技巧[M].上海.上海科学普及出版社.1993
[4]王声决,罗坚. C语言程序设计(第二版)[M].北京. 中国铁道出版社.2003
[5]浦滨.C游戏编程从入门到精通[M].北京.北京希望电子出版社.2002
[6]Andre Lamothe. WINDOWS游戏编程大师技巧[M].北京.中国电力出版社.2001
[7]Brian W. kernighan,Dennis M.Ritchie.C程序设计语言[M].北京.机械工
业出版社.2008
[8]Andrew Koenig.C陷井与缺陷[M].北京.人民邮电出版社.2008
[9]Stephen prata. C Primer Plus(第五版)[M].北京.人民邮电出版社.2005
[10]S ilicon Graphics, Inc. C Language Reference Manual [EB/OL],:
Technical Publications Silicon Graphics, Inc..1999-4-1
[11]E ric Huss.The C Library Reference Guide [EB/OL],:The Association for
Computing Machinery 2012-1-24
(源程序)/*************************************/
/* 李国防*/
/* 五子棋双人对战程序*/
/* 辅导老师徐小平*/
/*************************************/
#include<stdio.h>
#include<graphics.h>
#define NONE 0
#define PLAYER1 1
#define PLAYER2 2
int fivemap[19][19];
int nx,ny;
int winner=NONE;
void drawall();
void init();
void drawcursor();
void drawmap();
void drawdata();
int checkwin();
void main(void)
{
int gdriver=DETECT,gmode;
char c;
int who=PLAYER1;
registerbgidriver(EGA VGA_driver);
initgraph(&gdriver,&gmode,"D:\TC201E");
init();
drawall();
while((c=getch())!=27)
{
switch(c)
{
case 'a':
if(nx>0)
{
nx--;
drawall();
}
break;
case 'd':
if(nx<18)
{
nx++;
drawall();
}
break;
case 'w':
if(ny>0)
{
ny--;
drawall();
}
break;
case 's':
if(ny<18)
{
ny++;
drawall();
}
break;
case 13:
if(fivemap[nx][ny]==NONE)
{
fivemap[nx][ny]=who;
who=3-who;
winner=checkwin();
drawall();
if(winner!=NONE)
{
init();
who=PLAYER1;
getch();
drawall();
}
}
break;
}
}
closegraph();
}
void init()
{
int i,j;
for(i=0;i<19;i++)
for(j=0;j<19;j++)
fivemap[i][j]=NONE;
nx=8;
ny=10;
winner=NONE;
}
void drawmap()
{
int i;
setcolor(4);
for(i=0;i<19;i++)
{
line(92+24*i,12,92+24*i,444);
line(92,12+24*i,524,12+24*i);
}
}
void drawcursor()
{
setcolor(1);
line(80+24*nx,24*ny,24*nx+86,24*ny);
line(24*nx+98,24*ny,24*nx+104,24*ny);
line(24*nx+80,24*ny+24,24*nx+86,24*ny+24);
line(24*nx+98,24*ny+24,24*nx+104,24*ny+24);
line(24*nx+80,24*ny,24*nx+80,24*ny+6);
line(24*nx+80,24*ny+18,24*nx+80,24*ny+24);
line(24*nx+104,24*ny,24*nx+104,24*ny+6);
line(24*nx+104,24*ny+18,24*nx+104,24*ny+24); }
void drawdata()
{
int i,j;
setfillstyle(1,1);
setcolor(1);
for(i=0;i<19;i++)
{
for(j=0;j<19;j++)
{
if(fivemap[i][j]==PLAYER1)
fillellipse(i*24+92,j*24+12,10,10);
}
}
setfillstyle(1,15);
setcolor(15);
for(i=0;i<19;i++)
{
for(j=0;j<19;j++)
{
if(fivemap[i][j]==PLAYER2)
fillellipse(i*24+92,j*24+12,10,10);
}
}
}
int checkwin()
{
int i,j;
for(i=0;i<15;i++)
{
for(j=0;j<19;j++)
{
if(fivemap[i][j]!=NONE &&
fivemap[i][j]==fivemap[i+1][j] &&
fivemap[i][j]==fivemap[i+2][j] &&
fivemap[i][j]==fivemap[i+3][j] &&
fivemap[i][j]==fivemap[i+4][j])
return fivemap[i][j];
}
}
for(i=0;i<19;i++)
{
for(j=0;j<15;j++)
{
if(fivemap[i][j]!=NONE &&
fivemap[i][j]==fivemap[i][j+1] &&
fivemap[i][j]==fivemap[i][j+2] &&
fivemap[i][j]==fivemap[i][j+3] &&
fivemap[i][j]==fivemap[i][j+4])
return fivemap[i][j];
}
}
for(i=0;i<15;i++)
{
for(j=0;j<15;j++)
{
if(fivemap[i][j]!=NONE &&
fivemap[i][j]==fivemap[i+1][j+1] &&
fivemap[i][j]==fivemap[i+2][j+2] &&
fivemap[i][j]==fivemap[i+3][j+3] &&
fivemap[i][j]==fivemap[i+4][j+4])
return fivemap[i][j];
if(fivemap[18-i][j]!=NONE &&
fivemap[18-i][j]==fivemap[17-i][j+1] &&
fivemap[18-i][j]==fivemap[16-i][j+2] &&
fivemap[18-i][j]==fivemap[15-i][j+3] &&
fivemap[18-i][j]==fivemap[14-i][j+4])
return fivemap[18-i][j];
}
}
return NONE;
}
void drawall()
{
cleardevice();
setbkcolor(11);
setcolor(2);
settextstyle(0,HORIZ_DIR,1);
outtextxy(0,100,"a : LEFT");
outtextxy(0,150,"d : RIGHT");
outtextxy(0,200,"w : UP");
outte·xtxy(0,250,"s : DOWN");
outtextxy(0,300,"Enter : DO");
outtextxy(0,350,"Esc : Exit");
drawmap();
drawdata();
drawcursor();
if(winner!=NONE)
{
settextstyle(0,HORIZ_DIR,5);
setcolor(4);
outtextxy(250,200,"END!");
if(winner==PLAYER1)
outtextxy(70,250,"WINNER:PLAYER1");
else
outtextxy(70,250,"WINNER:PLAYER2");
}
}。