1、C语言课程设计报告题目: 简单的c五子棋 设计者: 方阳 专业班级: 软件工程1303班 学号: 311309060324 指导老师: 刘洁 所属系部: 计算机学院 2014年6月25日河南理工大学1、设计任务书1.1、 题目与要求:本人计划编写一个简单的c五子棋,应用C语言编写程序可以在计算机上实现二人对弈五子棋功能。二人对弈五子棋程序由图像生成、光标移动与落子、判断胜负和系统帮助等子程序构成;程序中应用了结构体、数组、全局变量、按键处理和图形编程等元素和语句。程序通过棋盘和棋子图像生成、二人移子与落子和判断胜负等功能的实现,在计算机上实现了二人五子棋对弈。1.2、 本系统涉及的知识点:结构
2、、数组、循环、函数、分支、2、功能设计根据功能需求,将程序分为图形显示、玩家控制、胜负判断和玩家计分四个模块,以下分析各模块的需求。图形显示模块:程序开始运行时,给出欢迎及帮助界面;游戏开始后要求生成1919的棋盘图像,并在棋盘上方提示当前落子方棋子颜色,游戏进行过程中,要求实时显示棋盘上已落下的棋子;分出胜负后,要求给出游戏结束画面。玩家控制模块:程序开始时,需玩家确定而后开始游戏;游戏过程中,两个玩家通过不同的按键移动光标,选择落子;游戏结束时,有玩家选择是否开始新棋局。胜负判断模块:实时监测棋盘上棋子,一旦某一色棋子出现五子连线,终止游戏程序,并着色连成一线的五子,弹出该色玩家胜出界面。
3、玩家计分模块:一方玩家再胜利后通过对文件的操作进行计分,并输出于计分板上。2.1、算法设计根据程序需求分析结果,可以得出程序的总体结构图如图。2.2部分模块流程图程序流程图3、程序代码设计3.1 图形模块initgr() /* BGI初始化 */ int gd = DETECT, gm = 0; /* 和gd = VGA,gm = VGAHI是同样效果 */ registerbgidriver(EGAVGA_driver);/* 注册BGI驱动后可以不需要.BGI文件的支持运行 */ initgraph(&gd, &gm, ); welcome() /*欢迎界面*/ initgr() ;/*初
4、始化*/clearviewport();/*清屏*/ setcolor(2); /*设置颜色*/ 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();
5、setcolor(2); settextstyle(0,0,2); outtextxy(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,); outtextx
6、y(60,300,press Esc.); outtextxy(220,440,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); /*线
7、色*/ setfillstyle(1,6); /*样式*/ bar(120,50,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,
8、210,2p); delay(50000); show(); /*显示动态变色效果的标题*/ 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(get
9、x(),gety(),0);green() /*用粉色着色连珠时的棋子*/setcolor(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);set
10、fillstyle(1,0);circle(580,250,9);floodfill(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,
11、9) ;setcolor(9);settextstyle(3,0,4);outtextxy(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,
12、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);delborder() /*除去定位框*/ setcolor(6); /*本质在于颜色覆盖*/ line(getx()-8,gety()-9,getx()-3,gety()-9); line(getx()+8,gety()-9,getx()+3,gety()-9); line(getx
13、()-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()+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)
14、/*点阵图所用标准输出方式*/ int i,j,k,m; m=(matsize-1)/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); d
15、elay(10000); drawmat(wu32K,32,240,0,2); delay(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语句作用在于如果落子即将溢出边框,让其改变位置到另一端,例如移动棋盘最上端,若继续向上移动,则移动至棋盘最下端对应位置 if(gety()90) delborder();moveto(get
16、x(),430); delborder();moverel(0,-20);border();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()!=
17、6)/*判定如果棋盘此处无子才能下,否则重新调用p1move函数*/ p1move();delborder(); /*去除定位框*/white();/*画棋子*/agetx()gety()=1;/*将所在位置对应的数组点赋值为1*/win(); /*判断胜负*/border(); /*在新的位置画出定位框*/对左右两边提示框操作,提示轮到2p进行操作,并调用p2move()函数p1del();p2turn();p2move(); case ESC: / *结束游戏*/ bye();closegraph(); exit(0); case BACK : /*悔棋操作*/ back();p1del(
18、);p2turn();p2move(); default: p1move(); p2move() /*玩家2操作*/P2move(); 函数与p1move();函数基本作用相同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();p2mo
19、ve(); case RIGHT: if(getx()480) delborder();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 : bac
20、k();p2del();p1turn();p1move(); back()/*悔棋功能*/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()/
21、*胜负判断主程序*/ for(i=120;i540;i=i+20) for(j=50;j470;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+
22、60j+ai+80j=5) 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
23、(10000);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+6
24、0);green();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();del
25、ay(10000); delscore1();p1_point_input2();p1_point_output() ; p1win(); 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=0) moveto(i,j); green();
26、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);moveto(i,j+40);green();dela
27、y(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();delay(10000);moveto(i+80
28、,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_in
29、put2();p2_point_output() ;p2win(); p1win()setcolor(15) ;settextstyle(0,0,2);此处2个函数用于1p或2p获胜后的告知以及询问是否开始新的一局,调用restart();函数以继续或退出。outtextxy(10,110,1p win);outtextxy(240,460,Restart?(Y/N);restart();p2win()setcolor(15) ;settextstyle(0,0,2); outtextxy(535,110,2p win); outtextxy(240,460,Restart?(Y/N); re
30、start();restart()通过对键盘的操作,提取Y或N以确定是否开始新的一局。switch(bioskey(0)case Y: main();case N: bye();closegraph(); exit(0); default:restart(); initialization() for(i=120;i540;i+) for(j=50;j470;j+) /*循环初始化棋盘对应的数组所在位置值为6*/ aij=6; 3.4 文件操作模块point() /*用于整合所有计分的函数,方便操作*/之所以做这么多函数来实现文件操作的计分,是因为我发现C语言中对文件操作似乎存在bug,如果放
31、在一个函数中经常出现文件无法正常读取,无法正常写入等现象,即使拆分成如此多函数,也依旧偶尔会出现以上提到的一些小bug。p1_point_input();p1_point_output() ;p2_point_input();p2_point_output() ;p1_point_input() /*1p计分文件读取*/首先打开文件,然后取出里面的数字赋值于ch变量,再用另一个函数打开文件并对ch进行自增操作,最后将ch写入文件。 FILE *fp; fp=fopen(score1.txt,r); ch=getw(fp); fclose(fp);p1_point_input2() /*1p计分
32、文件输入*/ FILE *fp; fp=fopen(score1.txt,r+); ch=ch+1; putw(ch,fp); fclose(fp); p1_point_output() /*1p计分输出*/ int i=0; char sh,score10; FILE *fp;通过再次打开文件,循环扫描,输出文件中的数值并设置其样式。 fp=fopen(score1.txt, r); for(; (sh=fgetc(fp)!=EOF; ) scorei+=sh; scorei=0; setcolor(12); settextstyle(3,0,4); outtextxy(40,320,sco
33、re); outtextxy(55,340,score); fclose(fp); p2_point_input()玩家2的计分模块,和玩家1的相同,就不再重复介绍了。 FILE *fp; fp=fopen(score2.txt,r); dh=getw(fp); fclose(fp);p2_point_input2() FILE *fp; fp=fopen(score2.txt,r+); dh=dh+1; putw(dh,fp); fclose(fp); p2_point_output() int i=0; char fh,score10; FILE *fp; fp=fopen(score2.
34、txt, r); for(; (fh=fgetc(fp)!=EOF; ) scorei+=fh; scorei=0; setcolor(12); settextstyle(3,0,4); outtextxy(560,320,score); outtextxy(575,340,score); fclose(fp);依旧通过循环读取文件内比分,然后通过颜色覆盖从而达到分数改变功能,这么操作十分复杂,体现了C语言图形编程下的不完善性。delscore1() /*删除当前1p分数*/ int i=0; char sh,score10; FILE *fp; fp=fopen(score1.txt, r)
35、; for(; (sh=fgetc(fp)!=EOF; ) scorei+=sh; scorei=0; setcolor(0); settextstyle(3,0,4); outtextxy(40,320,score); outtextxy(55,340,score); fclose(fp);delscore2() /*删除当前2p分数*/ int i=0; char fh,score10; FILE *fp; fp=fopen(score2.txt, r); for(; (fh=fgetc(fp)!=EOF; ) scorei+=fh; scorei=0; setcolor(0); sett
36、extstyle(3,0,4); outtextxy(560,320,score); outtextxy(575,340,score);4、程序设计总结 经过这次课程设计,我发现在很多地方的知识都不足,很多函数和技巧都要从网络上或其他书籍上找,可能学计算机要看看很多很多书,尤其在大学,很多情况下都需要自学,我想在以后的学习和实践工作中,会多读多看多练的,努力让自己的实力得到提高,在这个小游戏中,不能调用鼠标,只能通过输入坐标点位置,这是一个很大的不足,以后学习了一定要修改的更好!5、参考文献1 湛为芳C语言程序设计技术清华大学出版社,20062 谭浩强C程序设计(第三版)清华大学出版社,20053 Kennth A.reek. C和指针 (徐波译)4 另外还使用了百度中文搜索引擎