黑白棋课程设计报告Word文档格式.docx
《黑白棋课程设计报告Word文档格式.docx》由会员分享,可在线阅读,更多相关《黑白棋课程设计报告Word文档格式.docx(32页珍藏版)》请在冰豆网上搜索。
经过对此项目进行详细调查研究,初拟系统实现报告,对游戏开发中将要面临的问题及其解决方案进行初步设计及合理安排。
明确开发风险及其所带来的经济效益。
2.2实现的功能
游戏有8×
8的棋盘,分别由两人执黑子和白子轮流下棋,最后子多方为胜方。
游戏中只要用自己的两个棋子夹住对方的棋子,便能使对方的棋子全部变色,变成自己的棋子颜色。
到一方或双方都无子可下的时候,统计各方得分,保留棋子最多者就是胜者。
2.3层次划分
我们将本游戏设计主要划分三个层次:
第一、设计游戏的基本框架、拟实现功能、各主要模块的划分、已经每期程序设计的进度划分。
第二、游戏的编写、测试以及修改,这是在整个项目中最难的一部分,我们详细的讨论了组员中个人的所长,详细的划分的各组员的任务,由全组成员共同完成。
第三、报告的撰写以及对程序进行最后的修改和完善,这也是整个项目中最后一个也是最重要的一部分。
2.4功能实现的可行性
黑白棋游戏是在一个8*8的网格中进行,而数组属于构造体类型,数组时具有相同数据类型的变量序列。
可以用一个二维数从而实现游戏的走棋,落棋,判断棋盘的变化等。
游戏的开发部同于基于C语言的其他程序的开发,由于游戏本身的目的在于缓解压力,所以基于C语言设计的游戏需要一个良好的游戏界面,给游戏者轻松和愉快的感觉。
而C语言提供了多种的图形函数,所以设计一个良好的界面是可行的。
因为我们的游戏是采用“人人对战”的模式,所以在游戏中是由两个游戏者进行轮流下棋,整个游戏过程中需要在两位游戏者之间不停的转换,在C语言if…else,switch…case、等分支语句可以完成该转换。
在每次落棋后,都需要根据相同的规则判断棋盘的变化,显然这些可以用C语言提供的while\for等循环语句来实现这个功能。
而游戏结果的输出,虽然C语言本身不提供输出语句,但是C语言的标准库函数中提供了一些输出、输入函数,综合应用这些输入、输出函数就可以实现上述内容。
2.5经济上的可行性
本系统在技术上采用MicrosoftVisualC++6.0,技术上开发难度大,但其可操作实用性强,方便用户使用,界面友好。
社会上同时也方便了其它软件编程人员,对其它软件的编程有借鉴的作用。
在经济上服务于游戏爱好者的人,使用成本低,使用效率高,节省了开支。
第三章总体设计
3.1主要功能
黑白棋游戏是一个深爱人们喜爱的游戏,通常是人机对弈,本程序设计为人与人对弈,一方执黑棋,一方执白棋,轮流走棋,每方都试图在游戏结束前让自己的棋子的数目多于对方。
按键盘上的方向键可以上下左右移动棋子,按回车键可以摆放棋子。
3.2各个模块
✧棋盘设计
✧人人对战
✧棋盘变化
✧分数处理
✧成绩输出
✧结果输出
3.3模块之间连接
黑白棋游戏由棋盘设计、人人对战、棋盘变化、分数处理、成绩输出和程序的结果输出六个模块组成。
模块之间的连接关系是:
首先初始化棋盘界面,游戏开始由棋手选择下子的位置,程序判断下子后的棋盘变化,并计算双方棋子数量,再把分数输出显示,游戏结束后输出最终得分及胜利方。
3.4文字思路分析
从程序界面看,这是一个二维平面图,所以应想到数据的表示用二维数组,数组两个下标可以表示棋盘上的位置,数组元素的值代表棋格中的状态,共有三种情况,分别是空格、黑棋和白棋。
这样给数组元素的取值设定为0、1、2,其中0代表空格,1代表白色棋子,2黑色棋子。
这样程序的主要工作是接收棋手按键操作,一旦接收到回车键,说明棋手摆子。
先判断是不是有效为止,也就是能不能包围住对方的棋子,若能,将这些被包围住的对方棋子都变成自己的棋子。
然后对当前棋盘中黑白棋个数进行统计并输出结果。
如果没有这样的位置可以落子,则要停步,让对方走棋,重复上述步骤,直到游戏结束。
若要终止,可以按Esc键退出。
3.5模糊思路流程图
第四章详细设计
4.1棋盘界面设计
4.1.1画棋盘
将背景颜色设置为蓝色,从坐标(100,100)开始每隔40单位用白色线条画一条水平线,一条垂直线,构成棋盘。
使用fillelipse(intx,inty,intxradius,intyradius)函数,以x和y为圆心,画圆代表棋子。
再使用setfillstyle函数设置填充模式和填充颜色。
再在棋盘上分别画2个白棋和两个黑棋,做为初始棋子,计算棋子改变后的分数,最后输出开始分数。
(如右图1-1)
4.1.2设置棋子颜色
因为整个下棋过程是由两个棋手交替下棋完成,因此整个过程中棋盘在不停的变化,所以为了判断棋手和棋盘的变化设置了整形变量t,根据t的价来判断填充的棋子的颜色,t的值为1的时候填充白棋,t的值为2的时候填充黑棋。
(如下图1-2)
4.2恢复原来格子的状态
由于棋手的走棋的时候,棋子总是先出现在棋盘的左上角,棋手通过移动光标后棋子的初始位置要恢复原本的蓝色棋盘,在经过的路程上显示当前棋子会覆盖原本的棋盘状态,所以棋子一旦走过,就应该得恢复原先的状态,是空格的依然为空,是棋子的依然为原先棋子,因此每次移动棋子都必须判断原来的状态,每次移动后都必须恢复成原来的状态。
如下图(1-3)
4.3人人对战
人人对战过程主要是接受棋手的按键消息,其处理过程如下:
1、按Esc键程序可以随时结束。
2、按上下左右光标键,则改变棋子移动的坐标值。
3、按回车键后判断:
(1)如落子的位子已经有棋作则无效,继续压键。
(2)如落子的位置是空格,可以将棋子落入格内,调用函数QpChange()判断是否引起棋盘的变化,函数值为1有变化,为0没变化。
如果棋盘有变化,说明将包围的对方棋子吃掉,统计当前分数,如果棋盘没有变化,则说明落子的位置无法对方的棋子也视为无效棋,可以继续寻找合适的位置,但开始统计其落子次数cc,一旦尝试次数超过当前的棋盘的空格数,则说明他无棋可走,则放弃此步,让对方下棋。
(3)如果棋子变化后,格子以占满64格或一方棋子为0,则游戏结束,显示胜利方信息。
按任意键程序结束。
重复上述步骤,直到游戏结束。
如上图(1-4)
4.4判断棋盘变化
当棋手按回车键落子后,就要分别往8个方向判断是否包围住对方的棋子,如果是,则改变棋盘,也就是棋盘上黑白棋子的个数要发生变化。
从当前位置开始,用循环语句判断右边是否有一个或连续多个对方的棋子,遇到自己的棋子或空格则结束循环,如果循环结束不是遇到空白,且列坐标小于8,则说明这些位置是被自己包围的对方棋子,将它们吃掉,也就是改变为自己的棋子,如果有棋子发生变化,给棋盘变化标志yes赋值为1,同样的方法向左、上、下等8个方向进行判断,并做相应的变化。
如果所有的方向都判断过,并且没有引起棋盘的变化,则棋盘变化标志值yes赋值为0,返回yes,结束本函数。
如下图(1-5)
4.5处理分数
根据当前数组元素的值判断分数,如果是白棋,则白棋子数加,否则,黑棋子数累加。
(如右图1-6)
4.6输出成绩
利用设置实体填充模式填充矩形清除前次成绩,设计分数输出样式,分别判断分数为黑棋还是白旗分数,分别在输出各自分数的位置输出。
(如下图1-7)
4.7输出结果
根据白棋分数和黑棋分数的大小得出下棋的结果,输出赢着的信息。
(如下图1-8)
第五章编码
/*源程序*/
#include"
graphics.h"
/*图形系统头文件*/
#defineLEFT0x4b00/*光标左键值*/
#defineRIGHT0x4d00/*光标右键值*/
#defineDOWN0x5000/*光标下键值*/
#defineUP0x4800/*光标上键值*/
#defineESC0x011b/*ESC键值*/
#defineENTER0x1c0d/*回车键值*/
inta[8][8]={0},key,score1,score2;
/*具体分数以及按键与存放棋子的变量*/
charplayone[3],playtwo[3];
/*两个人的得分转换成字符串输出*/
voidplaytoplay(void);
/*人人对战函数*/
voidDrawQp(void);
/*画棋盘函数*/
voidSetPlayColor(intx);
/*设置棋子第一次的颜色*/
voidMoveColor(intx,inty);
/*恢复原来棋盘状态*/
intQpChange(intx,inty,intz);
/*判断棋盘的变化*/
voidDoScore(void);
/*处理分数*/
voidPrintScore(intn);
/*输出成绩*/
voidplayWin(void);
/*输出胜利者信息*/
/******主函数*********/
voidmain(void)
{
intgd=DETECT,gr;
initgraph(&
gd,&
gr,"
c:
\\tc"
);
/*初始化图形系统*/
DrawQp();
/*画棋盘*/
playtoplay();
/*人人对战*/
getch();
closegraph();
/*关闭图形系统*/
}
voidDrawQp()/*画棋盘*/
inti,j;
score1=score2=0;
/*棋手一开始得分都为0*/
setbkcolor(BLUE);
for(i=100;
i<
=420;
i+=40)
{
line(100,i,420,i);
/*画水平线*/
line(i,100,i,420);
/*画垂直线*/
}
setcolor(0);
/*取消圆周围的一圈东西*/
setfillstyle(SOLID_FILL,15);
/*白色实体填充模式*/
fillellipse(500,200,15,15);
/*在显示得分的位置画棋*/
setfillstyle(SOLID_FILL,8);
/*黑色实体填充模式*/
fillellipse(500,300,15,15);
a[3][3]=a[4][4]=1;
/*初始两个黑棋*/
a[3][4]=a[4][3]=2;
/*初始两个白棋*/
setfillstyle(SOLID_FILL,WHITE);
fillellipse(120+3*40,120+3*40,15,15);
fillellipse(120+4*40,120+4*40,15,15);
fillellipse(120+3*40,120+4*40,15,15);
fillellipse(120+4*40,120+3*40,15,15);
score1=score2=2;
/*有棋后改变分数*/
DoScore();
/*输出开始分数*/
voidplaytoplay()/*人人对战*/
intx,y,t=1,i,j,cc=0;
while
(1)/*换棋手走棋*/
x=120,y=80;
/*每次棋子一开始出来的坐标,x为行坐标,y为列坐标*/
while
(1)/*具体一个棋手走棋的过程*/
PrintScore
(1);
/*输出棋手1的成绩*/
PrintScore
(2);
/*输出棋手2的成绩*/
SetPlayColor(t);
/*t变量是用来判断棋手所执棋子的颜色*/
fillellipse(x,y,15,15);
key=bioskey(0);
/*接收按键*/
if(key==ESC)/*跳出游戏*/
break;
else
if(key==ENTER)/*如果按键确定就可以跳出循环*/
{
if(y!
=80&
&
a[(x-120)/40][(y-120)/40]!
=1
=2)/*如果落子位置没有棋子*/
if(t%2==1)/*如果是棋手1移动*/
a[(x-120)/40][(y-120)/40]=1;
else/*否则棋手2移动*/
a[(x-120)/40][(y-120)/40]=2;
if(!
QpChange(x,y,t))/*落子后判断棋盘的变化*/
a[(x-120)/40][(y-120)/40]=0;
/*恢复空格状态*/
cc++;
/*开始统计尝试次数*/
if(cc>
=64-score1-score2)/*如果尝试超过空格数则停步*/
MoveColor(x,y);
continue;
/*如果按键无效*/
}
DoScore();
/*分数的改变*/
break;
/*棋盘变化了,则轮对方走棋*/
else/*已经有棋子就继续按键*/
continue;
else/*四个方向按键的判断*/
if(key==LEFT&
x>
120)/*左方向键*/
MoveColor(x,y);
fillellipse(x,y,15,15);
x-=40;
if(key==RIGHT&
x<
400&
y>
80)/*右方向键*/
x+=40;
if(key==UP&
120)/*上方向键*/
y-=40;
if(key==DOWN&
y<
400)/*下方向键*/
y+=40;
if(key==ESC)/*结束游戏*/
if((score1+score2)==64||score1==0||score2==0)/*格子已经占满或一方棋子为0判断胜负*/
playWin();
/*输出最后结果*/
t=t%2+1;
/*一方走后,改变棋子颜色即轮对方走*/
cc=0;
/*计数值恢复为0*/
}/*endwhile*/
voidSetPlayColor(intt)/*设置棋子颜色*/
if(t%2==1)
/*白色*/
/*灰色*/
voidMoveColor(intx,inty)/*走了一步后恢复原来格子的状态*/
if(y<
100)/*如果是从起点出发就恢复蓝色*/
setfillstyle(SOLID_FILL,BLUE);
else/*其他情况如果是1就恢复白色棋子,2恢复黑色棋子,或恢复蓝色棋盘*/
switch(a[(x-120)/40][(y-120)/40])
case1:
setfillstyle(SOLID_FILL,15);
break;
/*白色*/
case2:
setfillstyle(SOLID_FILL,8);
/*黑色*/
default:
setfillstyle(SOLID_FILL,BLUE);
/*蓝色*/
intQpChange(intx,inty,intt)/*判断棋盘的变化*/
inti,j,k,kk,ii,jj,yes;
yes=0;
i=(x-120)/40;
/*计算数组元素的行下标*/
j=(y-120)/40;
/*计算数组元素的列下标*/
/*设置棋子变化的颜色*/
/*开始往8个方向判断变化*/
if(j<
6)/*往右边*/
for(k=j+1;
k<
8;
k++)
if(a[i][k]==a[i][j]||a[i][k]==0)/*遇到自己的棋子或空格结束*/
if(a[i][k]!
=0&
8)
for(kk=j+1;
kk<
k&
kk++)/*判断右边*/
a[i][kk]=a[i][j];
/*改变棋子颜色*/
fillellipse(120+i*40,120+kk*40,15,15);
if(kk!
=j+1)/*条件成立则有棋子改变过颜色*/
yes=1;
if(j>
1)/*判断左边*/
for(k=j-1;
k>
=0;
k--)
if(a[i][k]==a[i][j]||!
a[i][k])
=0)
for(kk=j-1;
kk>
kk--)
a[i][kk]=a[i][j];
fillellipse(120+i*40,120+kk*40,15,15);
=j-1)
yes=1;
if(i<
6)/*判断下边*/
for(k=i+1;
if(a[k][j]==a[i][j]||!
a[k][j])
if(a[k][j]!
for(kk=i+1;
kk++)
a[kk][j]=a[i][j];
fillellipse(120+kk*40,120+j*40,15,15);
=i+1)
if(i>
1)/*判断上边*/
for(k=i-1;
for(kk=i-1;
=i-1)
1&
j<
6)/*右上*/
for(k=i-1,kk=j+1;
k--,kk++)
if(a[k][kk]==a[i][j]||!
a[k][kk])
if(a[k][kk]&
for(ii=i-1,jj=j+1;
ii>
ii--,jj++)
a[ii][jj]=a[i][j];
fillellipse(120+ii*40,120+jj*40,15,15);
if(ii!
6&
j>
1)/*左下*/
for(k=i+1,kk=j-1;
8&
k++,kk--)
if(a[k][kk]!
for(ii=i+1,jj=j-1;
ii<
ii++,jj--)
=i