1、C语言课程设计汇报五子棋院系:软件学院专业:软件工程班级:102032学号:10203230指导老师:王星摘 要五子棋是一个两人对弈纯策略型棋类游戏,应用C语言编写程序能够在计算机上实现二人对弈五子棋功效。二人对弈五子棋程序由图像生成、光标移动和落子、判定胜败和系统帮助等子程序组成;程序中应用了结构体、数组、全局变量、按键处理和图形编程等元素和语句。程序经过棋盘和棋子图像生成、二人移子和落子和判定胜败等功效实现,在计算机上实现了二人五子棋对弈。Abstract Gobang is a traditional checker-type game in which the lining up of
2、 five pieces in a straight line scores victory. And C language can accomplish a 2-player gobang on computers. This 2-player gobang program contains 4 main sections, they are, graphics, movement and selection, victory judgment and helping system. Several elements and sentences of C programming langua
3、ge such as structural element, array, global variables, press processing and Graphics Programming are also applied in the program. With the accomplishment of the three main subprograms, namely, checker board and pieces construction, players step-selection and victory judgment, a whole program of gob
4、ang is established and gobang is available on computers.目 录一、需求分析4二、概要设计6三、具体设计9四、调试分析23五、用户手册24六、测试数据25七、附录26第1章:需求分析1.1五子棋背景传统五子棋棋具和围棋相同,棋子分为黑白两色,棋盘为1515,棋子放置于棋盘线交叉点上。两人对局,各执一色,轮番下一子,先将横、竖或斜线5个或5个以上同色棋子连成不间断一排者为胜。 因为传统五子棋在落子后不能移动或拿掉,所以也能够用纸和笔来进行游戏。1.2 程序设计本程序设计为人和人对弈,一方执黑棋,一方执白棋,轮番走棋,每方全部试图在游戏结束前让
5、自己棋子五子相连,首先实现五子相连一方获胜。程序实施过程中,要求棋盘、棋子时时可见,而且人能够经过按键盘按键移动光标,摆放棋子。1.2.1 程序需求分析依据功效需求,将程序分为图形显示、玩家控制、胜败判定和玩家计分四个模块,以下分析各模块需求。图形显示模块:程序开始运行时,给出欢迎及帮助界面;游戏开始后要求生成1919棋盘图像,并在棋盘上方提醒目前落子方棋子颜色,游戏进行过程中,要求实时显示棋盘上已落下棋子;分出胜败后,要求给出游戏结束画面。玩家控制模块:程序开始时,需玩家确定以后开始游戏;游戏过程中,两个玩家经过不一样按键移动光标,选择落子;游戏结束时,有玩家选择是否开始新棋局。胜败判定模块
6、:实时监测棋盘上棋子,一旦某一色棋子出现五子连线,终止游戏程序,并着色连成一线五子,弹出该色玩家胜出界面。玩家计分模块:一方玩家再胜利后经过对文件操作进行计分,并输出于计分板上。1.2.2程序步骤设计依据程序需求分析结果,能够得出程序总体结构图图1,程序总体步骤图图2。图1第2章:概要设计2.1.1 各类头文件,变量及宏定义#includestdio.h#include Conio.h#include graphics.h#include #include#define closegr closegraph/*定义1号玩家操作键键码*/#define W 0x1177/*上移-W*/#defi
7、ne S 0x1f73/*下移-S*/#define A 0x1e61/*左移-A*/#define D 0x2064/*右移-D*/#define SP 0x3920/*落子-空格键*/*定义2号玩家操作键键码*/ #define UP 0x4800/*上移-方向键up*/#define DOWN 0x5000/*下移-方向键down*/#define LEFT 0x4b00/*左移-方向键left*/#define RIGHT 0x4d00/*右移-方向键right*/#define ENTER 0x1c0d/*落子-回车键Enter*/#define ESC 0x011b/*退出*/#d
8、efine Y 0x1579/*YES*/#define N 0x316e/*NO*/#define BACK 0xe08 /*悔棋*/#define DEL 0x5300 /*删除比分*/2.1.2 全局变量int ch,dh,del;/*文件操作计分变量*/int k,i,j,n,t;/*控制变量*/int a2020;/*棋盘数组*/2.2 图形模块棋盘显示由游戏开始和结束部分控制,棋子和棋子定位框显示和保留由玩家操控部分决定,本章只列写棋盘和棋子显示程序。图形模块关键由以下函数组成:initgr();/*图形界面初始化函数*/Welcome();/*欢迎界面*/Help();/*帮助界
9、面*/board();/*画棋盘*/white();/*画白棋子*/black();/*画黑棋子*/bye();/*结束界面*/green();/*连珠时着色对应棋子*/show();drawmat();/*显示汉字点阵图函数,和产生动态变色效果*/border();/*棋子定位框函数*/delborder();/*删除目前位置棋子定位框函数*/p1turn();/*轮到1p时在左边边框画出白棋和输出white turn以提醒1p进行操作*/p2turn();/*轮到2p时在右边边框画出黑棋和输出black turn以提醒2p进行操作*/p1del();/*轮到2p时去除p1turn();函数
10、效果*/p2del();/*轮到1p时去除p2turn();函数效果*/2.3 玩家操作模块棋子移动和落子有键盘上按键控制,本程序选择1P按键为W、S、A、D和空格键,2P按键为、和回车键,分别代表上移、下移、左移、右移光标和落子。在光标移动过程中,光标根据玩家按键移动;在玩家按下落子按键后,程序自动调用棋子显示子程序和判定胜败子程序。1P、2P落子后,程序会为落子处数组元素赋一个特定值,用于判定胜败。玩家操作模块关键由以下函数组成:P1move();/*玩家1移动函数*/P2move();/*玩家2移动函数*/Back();/*悔棋函数*/2.4 胜败判定模块胜败判定模块是程序关键,该模块设
11、计直接关系到程序运行速率和运行结果正确是否。本函数依据每次落子位置,分别向上、下、左、右、左上、左下、右上、右下八个方向判定是否有相同颜色棋子连成五子,假如成立,游戏就结束,并显示提醒信息,不然继续落子。以下简析本程序步骤:,由获胜条件能够知,经过判定上、下、左、右、斜上、斜下八个方向上是否有连续5个子即可得出是否获胜结果。在游戏开始时,将棋盘初始化,立即棋盘抽象为一个19*19数组,数组中每个元素数值设为6。1P落子时,将数组内对应坐标处元素赋值为0;2P落子时,将数组内对应坐标处元素赋值为1。经过循环扫描棋盘数组,假如 上、下、左、右、斜上、斜下八个方向某5个连续子所对应数组中元素之和等于
12、5时,1P获胜;当上、下、左、右、斜上、斜下八个方向某5个连续子所对应数组中元素之和等于0时,2P获胜。胜败判定模块关键由以下多个函数组成:Win();/*关键函数,判定胜败*/P1win();/*p1胜利时调用,用于通知p1玩家胜利及问询是否继续*/P1win();/*p2胜利时调用,用于通知p2玩家胜利及问询是否继续*/restart();/*问询是否重新开始新一局比赛函数*/initialization();/*初始化棋盘对应数组全部值为6*/2.5玩家计分模块为了能使1p和2p更直观更便捷地看到双方对战比分,所以做了此计分模块,因为分数不能因为重新调用main()函数就丢失了,所以采取
13、对文件操作,经过文件来统计双方比分,这里对score1.txt和score2.txt文件进行操作,用来计1p和2p分数。玩家计分模块关键由以下多个函数组成:Point();/*整合全部文件操作模块*/ p1_point_input();/*1p计分文件读取*/ p1_point_input2();/*1p计分文件写入*/ p1_point_output();/*1p计分文件输出*/ p2_point_input();/*2p计分文件读取*/ p2_point_input2();/*2p计分文件写入*/ p2_point_output();/*2p计分文件输出*/delscore1() ; /*
14、删除目前1p分数*/delscore2(); /*删除目前2p分数*/2.6 各模块之间调用关系以下第3章:具体设计3.1 图形模块initgr() /* BGI初始化 */ int gd = DETECT, gm = 0; /* 和gd = VGA,gm = VGAHI是一样效果 */ registerbgidriver(EGAVGA_driver);/* 注册BGI驱动后能够不需要.BGI文件支持运行 */ initgraph(&gd, &gm, ); welcome() /*欢迎界面*/ initgr() ;/*初始化*/clearviewport();/*清屏*/ setcolor(2
15、); /*设置颜色*/ settextstyle(0,0,6); /*样式*/ outtextxy(180,180,Welcome);/*位置和内容*/ settextstyle(0,0,2); /*文本样式*/ outtextxy(240,420,press any key to continue);/*位置和内容*/ getch();/*press any key to continue*/ help() /*帮助界面,基础操作同welcome();函数*/ initgr(); clearviewport(); setcolor(2); settextstyle(0,0,2); outte
16、xtxy(60,100,P1 move; W S A D ); outtextxy(60,120, set : space ); outtextxy(60,180,P2 move: up down left right ); outtextxy(60,200, set: Enter); outtextxy(60,240,You can press Backspace to pull back!) ; outtextxy(60,280,When you want to quit the game,); outtextxy(60,300,press Esc.); outtextxy(220,440
17、,press any key to continue); getch(); bye() /*say bye!,实现功效同上*/ initgr(); clearviewport(); setcolor(4) ; settextstyle(0,0,6); outtextxy(130,180,Thank you!); settextstyle(0,0,2); outtextxy(240,420,press any key to quit); getch(); board()/*画棋盘*/ setcolor(14); /*线色*/ setfillstyle(1,6); /*样式*/ bar(120,5
18、0,520,450); /*棋盘底*/ for(k=0;k21 ;k+) line(120+20*k,50,120+20*k,450) ; /*竖线*/ line(120,50+20*k,520,50+20*k) ; /*横线*/ setfillstyle(1,9) ; bar(540,200,620,300); /*1p2p两边框*/ bar(20,200,100,300); setcolor(2); settextstyle(3,0,4); outtextxy(50,210,1p); outtextxy(570,210,2p); delay(50000); show(); /*显示动态变色
19、效果标题*/ moveto(320,250); /*初始化中心位置*/ border();/*画定位框*/ p1turn();/*p1开始落子,游戏开始*/ white() /*画白棋*/setcolor(15);setfillstyle(1,15);circle(getx(),gety(),9);floodfill(getx(),gety(),15);black() /*画黑棋*/setcolor(0);setfillstyle(1,0);circle(getx(),gety(),9);floodfill(getx(),gety(),0);green() /*用粉色着色连珠时棋子*/setc
20、olor(13);setfillstyle(1,13);circle(getx(),gety(),9);floodfill(getx(),gety(),13);p1turn()/*画左边边框内白棋子*/setcolor(15);setfillstyle(1,15);circle(60,250,9);floodfill(60,250,15); settextstyle(3,0,4);outtextxy(20,280,white turn); p2turn() /*右边边框内黑色棋子*/setcolor(0);setfillstyle(1,0);circle(580,250,9);floodfil
21、l(580,250,0);settextstyle(3,0,4);outtextxy(540,280,black turn); p1del()/*不是1turn时候抹去左边边框内棋子*/ setfillstyle(1,9) ;floodfill(60,250,9);setcolor(9);settextstyle(3,0,4);outtextxy(20,280,white turn);p2del()/*不是2turn时候抹去右边边框内棋子*/setfillstyle(1,9);floodfill(580,250,9) ;setcolor(9);settextstyle(3,0,4);outte
22、xtxy(540,280,black turn);border() /*画定位框*/ setcolor(14); line(getx()-8,gety()-9,getx()-3,gety()-9); /*经过画线函数画出定位框*/ line(getx()+8,gety()-9,getx()+3,gety()-9); line(getx()-8,gety()-9,getx()-8,gety()-4); line(getx()+8,gety()-9,getx()+8,gety()-4); line(getx()-8,gety()+9,getx()-3,gety()+9); line(getx()+
23、8,gety()+9,getx()+3,gety()+9); line(getx()-8,gety()+9,getx()-8,gety()+4); line(getx()+8,gety()+9,getx()+8,gety()+4);delborder() /*除去定位框*/ setcolor(6); /*本质在于颜色覆盖*/ line(getx()-8,gety()-9,getx()-3,gety()-9); line(getx()+8,gety()-9,getx()+3,gety()-9); line(getx()-8,gety()-9,getx()-8,gety()-4); line(ge
24、tx()+8,gety()-9,getx()+8,gety()-4); line(getx()-8,gety()+9,getx()-3,gety()+9); line(getx()+8,gety()+9,getx()+3,gety()+9); line(getx()-8,gety()+9,getx()-8,gety()+4); line(getx()+8,gety()+9,getx()+8,gety()+4);drawmat(char *mat,int matsize,int x,int y,int color)/*点阵图所用标准输出方法*/ int i,j,k,m; m=(matsize-1
25、)/8+1; for(j=0;jmatsize;j+) for(i=0;im;i+) for(k=0;kk) putpixel(x+i*8+k,y+j,color);show() /*动态点阵图汉字闪烁效果*/ for(n=0;n3;n+) delay(10000); drawmat(wu32K,32,240,0,3);/*输出点阵图“五”字*/ delay(10000); drawmat(zi32K,32,290,0,3); delay(10000); drawmat(qi32K,32,340,0,3); delay(10000); drawmat(wu32K,32,240,0,2); de
26、lay(10000); drawmat(zi32K,32,290,0,2); delay(10000); drawmat(qi32K,32,340,0,2); 3.2 玩家操作模块p1move() /*玩家1操作*/switch(bioskey(0) /*bioskey函数对键盘操作*/ case W: /*上移*/ if(gety()90)全部if语句作用在于假如落子立即溢出边框,让其改变位置到另一端,比如移动棋盘最上端,若继续向上移动,则移动至棋盘最下端对应位置 delborder();moveto(getx(),430); delborder();moverel(0,-20);borde
27、r();p1move(); case A: /*左移*/ if(getx()410) delborder();moveto(getx(),70); delborder();moverel(0,20);border();p1move(); case D: /*右移*/ if(getx()480) delborder();moveto(140,gety(); delborder();moverel(20,0);border();p1move(); case SP: /*落子*/ if(agetx()gety()!=6)/*判定假如棋盘此处无子才能下,不然重新调用p1move函数*/ p1move(
28、);delborder(); /*去除定位框*/white();/*画棋子*/agetx()gety()=1;/*将所在位置对应数组点赋值为1*/win(); /*判定胜败*/border(); /*在新位置画出定位框*/对左右两边提醒框操作,提醒轮到2p进行操作,并调用p2move()函数p1del();p2turn();p2move(); case ESC: / *结束游戏*/ bye();closegraph(); exit(0); case BACK : /*悔棋操作*/ back();p1del();p2turn();p2move(); default: p1move(); P2mo
29、ve(); 函数和p1move();函数基础作用相同p2move() /*玩家2操作*/switch(bioskey(0) case UP: if(gety()90) delborder();moveto(getx(),430); delborder();moverel(0,-20);border();p2move(); case LEFT: if(getx()410) delborder();moveto(getx(),70);delborder();moverel(0,20);border();p2move(); case RIGHT: if(getx()480) delborder();
30、moveto(140,gety();delborder();moverel(20,0);border();p2move(); case ENTER: if(agetx()gety()!=6) p2move();delborder();black();agetx()gety()=0;win();border();p2del();p1turn();p1move(); default: p2move(); case ESC: bye();closegraph(); exit(0); case BACK : back();p2del();p1turn();p1move(); back()/*悔棋功效*
31、/setcolor(6);setfillstyle(1,6);circle(getx(),gety(),9);floodfill(getx(),gety(),6); /*经过将现有棋子覆盖和棋盘底色相同颜色来实现*/setcolor(14) ;line(getx()-9,gety(),getx()+9,gety() ;因为覆盖棋盘颜色后对应棋谱线条颜色被覆盖,所以经过画线函数补回被覆盖负分线色line(getx(),gety()-9,getx(),gety()+9) ; 3.3胜败判定模块win()/*胜败判定主程序*/ for(i=120;i540;i=i+20) for(j=50;j470
32、;j=j+20)/*经过循环扫描整个棋盘判定胜败*/ if(aij+ai+20j+ai+40j+ai+60j+ai+80j=5)|(aij+aij+20+aij+40+aij+60+aij+80=5)| (aij+ai+20j+20+ai+40j+40+ai+60j+60+ai+80j+80=5)|(aij+80+ai+20j+60+ai+40j+40+ai+60j+20+ai+80j=5)/*假如棋盘上任何位置数组对应值之和为5,则白方5子连珠*/ if(aij+ai+20j+ai+40j+ai+60j+ai+80j=5)假如五子连珠,扫描是哪一个方向有连珠,并将连珠5个字进行动态着色,方便
33、玩家双方识别。 moveto(i,j); green();delay(10000);moveto(i+20,j);green(); delay(10000);moveto(i+40,j);green();delay(10000);moveto(i+60,j);green();delay(10000);moveto(i+80,j);green();delay(10000); else if(aij+aij+20+aij+40+aij+60+aij+80=5) moveto(i,j); green();delay(10000);moveto(i,j+20);green(); delay(10000
34、);moveto(i,j+40);green();delay(10000);moveto(i,j+60);green();delay(10000);moveto(i,j+80);green();delay(10000); else if(aij+ai+20j+20+ai+40j+40+ai+60j+60+ai+80j+80=5) moveto(i,j); green();delay(10000);moveto(i+20,j+20);green(); delay(10000);moveto(i+40,j+40);green();delay(10000);moveto(i+60,j+60);gre
35、en();delay(10000);moveto(i+80,j+80);green();delay(10000); else if(aij+80+ai+20j+60+ai+40j+40+ai+60j+20+ai+80j=5) moveto(i,j+80); green();delay(10000);moveto(i+20,j+60);green(); delay(10000);moveto(i+40,j+40);green();delay(10000);moveto(i+60,j+20);green();delay(10000);moveto(i+80,j);green();delay(100
36、00); delscore1();p1_point_input2();p1_point_output() ; p1win(); 此处判定假如棋盘上任何位置数组对应值之和为0,则黑方5子连珠 if(aij+ai+20j+ai+40j+ai+60j+ai+80j=0)|(aij+aij+20+aij+40+aij+60+aij+80=0)| (aij+ai+20j+20+ai+40j+40+ai+60j+60+ai+80j+80=0)|(aij+80+ai+20j+60+ai+40j+40+ai+60j+20+ai+80j=0) if(aij+ai+20j+ai+40j+ai+60j+ai+80j
37、=0) moveto(i,j); green();delay(10000);moveto(i+20,j);green(); delay(10000);moveto(i+40,j);green();delay(10000);moveto(i+60,j);green();delay(10000);moveto(i+80,j);green();delay(10000); else if(aij+aij+20+aij+40+aij+60+aij+80=0) moveto(i,j); green();delay(10000);moveto(i,j+20);green(); delay(10000);mo
38、veto(i,j+40);green();delay(10000);moveto(i,j+60);green();delay(10000);moveto(i,j+80);green();delay(10000); else if(aij+ai+20j+20+ai+40j+40+ai+60j+60+ai+80j+80=0) moveto(i,j); green();delay(10000);moveto(i+20,j+20);green(); delay(10000);moveto(i+40,j+40);green();delay(10000);moveto(i+60,j+60);green()
39、;delay(10000);moveto(i+80,j+80);green();delay(10000); 此处依旧是五子连珠后着色模块。 else if(aij+80+ai+20j+60+ai+40j+40+ai+60j+20+ai+80j=0) moveto(i,j+80); green();delay(10000);moveto(i+20,j+60);green(); delay(10000);moveto(i+40,j+40);green();delay(10000);moveto(i+60,j+20);green();delay(10000);moveto(i+80,j);green();delay(10000); delscore2(); p2_point_input2();p2_point_output() ;p2win();