第一篇:数据结构24点游戏源代码
#include
eOperator = 1 //算子 };
int oper[7]={43,45,42,47,40,41,35};
char OPSET[OPSETSIZE]={'+' , '-' , '*' , '/' ,'(' , ')' , '#'};
typedef struct sqlist{ int bol;//bol 是 0 时,num-ch是一个数字;bol 是 1 时 num_ch 运算符
int num_ch;struct sqlist *next;}sqlist;//线性表
typedef struct sqstack{ int *base;int *top;int stacksize;}sqstack;//栈的定义
unsigned char Prior[7][7] = {// 课本 表3.1 算符间的优先关系
'>','>','<','<','<','>','>','>','>','<','<','<','>','>','>','>','>','>','<','>','>','>','>','>','>','<','>','>','<','<','<','<','<','=',' ','>','>','>','>',' ','>','>','<','<','<','<','<',' ','=' };
int init_sq(sqlist *l){//初始化链表
l=(sqlist*)malloc(sizeof(sqlist));if(l==NULL){
exit(-2);} l->next=NULL;return 1;}
int insert_sq(sqlist **p,int e,int bl){//链表插入操作
sqlist *q;q=(sqlist*)malloc(sizeof(sqlist));q->num_ch=e;q->bol=bl;q->next=NULL;(*p)->next=q;(*p)=(*p)->next;return 1;}
int check(sqlist l)//保证输入的数字是给出的四个数字 { int right=1,find=0,i;sqlist *q=&l;q=q->next;for(;q->next!=NULL;q=q->next){
if(q->bol==1){
if(q->num_ch <=39||q->num_ch>57||q->num_ch==44||q->num_ch==46){
right=0;
printf(“%c不是有效的运算符!n”);
}
}
else {
find=0;
for(i=0;i<4;i++){
if(number[1][i]==0&&number[0][i]==q->num_ch){
number[1][i]=1;
find=1;
break;
}
}
if(find==0){
printf(“%d 不在给出的四个数字中!n”,q->num_ch);
right=0;
}
} }//end for for(i=0;i<4;i++){
if(number[1][i]==0){
printf(“%d没有用上!n”,number[0][i]);
right=0;
} } return right;}
int chang(char *s,sqlist *l){//将用户的输入转化为单链表
int t=0;unsigned int i=0;int bl,ch;int a1,a2,a;sqlist *p=l;for(;i if(s[i]>47&&s[i]<58&&t==0){ a1=(int)s[i]-48; t++; } else if(s[i]>47&&s[i]<58&&t==1){ a2=(int)s[i]-48; a=a1*10+a2; t++; } else if(s[i]<48&&s[i]>39&&s[i]!=44&&s[i]!=46){ if(t==1){ bl=0; insert_sq(&p,a1,bl); t=0; } else if(t==2){ bl=0; insert_sq(&p,a,bl); t=0; } bl=1; ch=(int)s[i]; insert_sq(&p,ch,bl); t=0; } else { printf(“%c不是有效的运算符!n”,s[i]); } } //end for i=strlen(s)-1;if(s[i]>47&&s[i]<58){ if(s[i-1]>47&&s[i-1]<58){ bl=0; insert_sq(&p,a,bl); } else { bl=0; insert_sq(&p,a1,bl); } } bl=1;a=35;insert_sq(&p,a,bl);return(check(*l));} int Operate(int a,int theta, int b){//计算 switch(theta){ case 43: return a+b;case 45: return a-b;case 42: return a*b;case 47: { if(b==0){ return-2000; } if(a%b==0){ return a/b; } else {//printf(“不能为小数n”); return-10000; } } default : return 0;} } int ReturnOpOrd(char op,char* TestOp)// precede()函数调用求优先级 { int i;for(i=0;i< OPSETSIZE;i++){ if(op == TestOp[i])return i;} return 0;} char precede(char Aop, char Bop){ return Prior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];} int initstack(sqstack *s){(s)->base =(int*)malloc(STACK_INIF_SIZE*sizeof(int));if((s)->base==NULL)exit(-2);(s)->top=(s)->base;(s)->stacksize = STACK_INIF_SIZE;return 1;} int gettop(sqstack *s){ //取得栈顶元素 int e;if(s->top==s->base){ printf(“栈空,无法取得栈顶元素!n”); return 0;} e=*(s->top-1);return e;} int push(sqstack *s,int e){ //压栈 if(s->top-s->base>=s->stacksize){ s->base=(int*)realloc(s->base,(s->stacksize+STACKINCREMENT)*sizeof(int)); if(!s->base)exit(-2); s->stacksize+= STACKINCREMENT;} *(s->top++)=e;return 1;} int pop(sqstack *s,int *e){ //出栈 if(s->top==s->base){ printf(“栈空,出栈错误!n”); return 0;} *e=*(--s->top);return 1;} int EvaluateExpression(char* MyExpression){ // 算法3.4----计算表达式的值 // 算术表达式求值的算符优先算法。 // 设OPTR和&&OPND分别为运算符栈和运算数栈 int result;sqstack OPTR; // 运算符栈,字符元素 sqstack OPND; // 运算数栈,实数元素 int c,bl,a,b,theta,top;sqlist *q,l;char *s=MyExpression;init_sq(&l);if(chang(s,&l)!=0){ q=&l; initstack(&OPTR); push(&OPTR, 35); initstack(&OPND); q=q->next; c=q->num_ch; bl=q->bol; while((c!= 35 || gettop(&OPTR)!=35)){ if(bl!=1){ push(&OPND, c); q=q->next; c=q->num_ch; bl=q->bol; } // 不是运算符则进栈 else{ top=gettop(&OPTR); switch(precede((char)top,(char)c)){ case '<': // 栈顶元素优先权低 push(&OPTR, c); q=q->next; c=q->num_ch; bl=q->bol; break; case '=': // 脱括号并接收下一字符 pop(&OPTR, &c); q=q->next; c=q->num_ch; bl=q->bol; break; case '>': // 退栈并将运算结果入栈 pop(&OPTR, &theta); pop(&OPND, &b); pop(&OPND, &a); push(&OPND, Operate(a, theta, b)); break; default : printf(“没有这个运算符!n”); return 0; } // switch }//else } // while result=gettop(&OPND); return result;} else { printf(“你的输入有错误!n”); return 0;} } int randomm()//产生四个随机数 { int i=0;srand((unsigned)time(NULL));for(;i<4;i++){ number[0][i]=0; number[0][i]=rand(); number[0][i]%=13; number[0][i]++; number[1][i]=0;} return number[2][4];} int CalcOneExpress(int expression[][2])// 计算表达式 { // 算术表达式求值的算符优先算法。 // 设OPTR和&&OPND分别为运算符栈和运算数栈,OP为运算符集合。int index=0,result,c,theta,a,b;sqstack OPTR; // 运算符栈,字符元素 sqstack OPND; // 运算数栈,实数元素 initstack(&OPTR);push(&OPTR, 35);initstack(&OPND);c=expression[index][0];while(c!= 35 || gettop(&OPTR)!=35){ if(expression[index][1]!=1){ push(&OPND, c); index++; c=expression[index][0];} // 不是运算符则进栈 else { switch(precede((char)gettop(&OPTR),(char)c)) { case '<': // 栈顶元素优先权低 push(&OPTR, c); index++; c=expression[index][0]; break; case '=': // 脱括号并接收下一字符 pop(&OPTR, &c); index++; c=expression[index][0]; break; case '>': // 退栈并将运算结果入栈 pop(&OPTR, &theta); pop(&OPND, &b); pop(&OPND, &a); push(&OPND, Operate(a, theta, b)); break; default : printf(“没有这个运算符n”); return 0; } // switch }//else } // while result=gettop(&OPND);return result;} int Equal24(int n){ if(n==24){ return 1;} else return 0;} //括号的几种情况 //1 无括号 //2(a b)c d 同a b(c d), 下省略 //3(a b c)d //4(a b)(c d)//5((a b)c)d int CalcArray1(int iNumInput[2][4]){ // a * b * c * d 7 个字符 int expression[8][2],ii,jj,kk;int i,j,k,l,dRes;for(i=0;i<4;i++){ for(j=0;j<4;j++) { if(j==i) { continue; } for(k=0;k<4;k++) { if(k==i||k==j) { continue; } for(l=0;l<4;l++) { if(l==i||l==j||l==k) { continue; } expression[0][0]=iNumInput[0][i]; expression[2][0]=iNumInput[0][j]; expression[4][0]=iNumInput[0][k]; expression[6][0]=iNumInput[0][l]; expression[0][1]=eNumber; expression[2][1]=eNumber; expression[4][1]=eNumber; expression[6][1]=eNumber; for(ii=0;ii<4;ii++) { for(jj=0;jj<4;jj++) { for(kk=0;kk<4;kk++) { expression[1][0] = oper[ii]; expression[1][1] = eOperator; expression[3][0] = oper[jj]; expression[3][1] = eOperator; expression[5][0] = oper[kk]; expression[5][1] = eOperator; expression[7][0] = oper[6]; expression[7][1] = eOperator; dRes = CalcOneExpress(expression); if(Equal24(dRes)) { printf(“可以这样运算:%d%c%d%c%d%c%dn”,expression[0][0],oper[ii],expression[2][0],oper[jj],expression[4][0],oper[kk],expression[6][0]); return 1; } } } }//end of for oper } } } } return 0;} int CalcArray2(int iNumInput[2][4]){ //(a * b)* c * d //9 number int expression[10][2];int ii,jj,i,j,k,l,kk;int dRes;for(i=0;i<4;i++){ for(j=0;j<4;j++) { if(j==i) { continue; } for(k=0;k<4;k++) { if(k==i||k==j) { continue; } for(l=0;l<4;l++) { if(l==i||l==j||l==k) { continue; } expression[1][0]=iNumInput[0][i]; expression[3][0]=iNumInput[0][j]; expression[6][0]=iNumInput[0][k]; expression[8][0]=iNumInput[0][l]; expression[1][1]=eNumber; expression[3][1]=eNumber; expression[6][1]=eNumber; expression[8][1]=eNumber; for(ii=0;ii<4;ii++) { for(jj=0;jj<4;jj++) { for(kk=0;kk<4;kk++) { expression[0][0] = oper[4]; expression[0][1] = eOperator; expression[2][0] = oper[ii]; expression[2][1] = eOperator; expression[4][0] = oper[5]; expression[4][1] = eOperator; expression[5][0] = oper[jj]; expression[5][1] = eOperator; expression[7][0] = oper[kk]; expression[7][1] = eOperator; expression[9][0] = oper[6]; expression[9][1] = eOperator; dRes = CalcOneExpress(expression); if(Equal24(dRes)) { printf(“可以这样运算:%c%d%c%d%c%c%d%c%dn”,oper[4],expression[1][0],oper[ii],expression[3][0],oper[5],oper[jj],expression[6][0],oper[kk],expression[8][0]); return 1; } } } }//end of for oper } } } } return 0;} int CalcArray3(int iNumInput[2][4]){ //(a * b * c)* d //9 number int expression[10][2];int ii,jj,i,j,k,l,kk;int dRes;for(i=0;i<4;i++){ for(j=0;j<4;j++) { if(j==i) { continue; } for(k=0;k<4;k++) { if(k==i||k==j) { continue; } for(l=0;l<4;l++) { if(l==i||l==j||l==k) { continue; } expression[1][0]=iNumInput[0][i]; expression[3][0]=iNumInput[0][j]; expression[5][0]=iNumInput[0][k]; expression[8][0]=iNumInput[0][l]; expression[1][1]=eNumber; expression[3][1]=eNumber; expression[5][1]=eNumber; expression[8][1]=eNumber; for(ii=0;ii<4;ii++) { for(jj=0;jj<4;jj++) { for(kk=0;kk<4;kk++) { expression[0][0] = oper[4]; expression[0][1] = eOperator; expression[2][0] = oper[ii]; expression[2][1] = eOperator; expression[4][0] = oper[jj]; expression[4][1] = eOperator; expression[6][0] = oper[5]; expression[6][1] = eOperator; expression[7][0] = oper[kk]; expression[7][1] = eOperator; expression[9][0] = oper[6]; expression[9][1] = eOperator; dRes = CalcOneExpress(expression); if(Equal24(dRes)) { printf(“可以这样运算:%c%d%c%d%c%d%c%c%dn”,oper[4],expression[1][0],oper[ii],expression[3][0],oper[jj],expression[5][0],oper[5],oper[kk],expression[8][0]); return 1; } } } }//end of for oper } } } } return 0;} int CalcArray4(int iNumInput[2][4]){ //(a * b)*(c * d)//11 numbers int expression[12][2];int ii,jj,i,j,k,l,kk;int dRes;for(i=0;i<4;i++){ for(j=0;j<4;j++) { if(j==i) { continue; } for(k=0;k<4;k++) { if(k==i||k==j) { continue; } for(l=0;l<4;l++) { if(l==i||l==j||l==k) { continue; } expression[1][0]=iNumInput[0][i]; expression[3][0]=iNumInput[0][j]; expression[7][0]=iNumInput[0][k]; expression[9][0]=iNumInput[0][l]; expression[1][1]=eNumber; expression[3][1]=eNumber; expression[7][1]=eNumber; expression[9][1]=eNumber; for(ii=0;ii<4;ii++) { for(jj=0;jj<4;jj++) { for(kk=0;kk<4;kk++) { expression[0][0] = oper[4]; expression[0][1] = eOperator; expression[2][0] = oper[ii]; expression[2][1] = eOperator; expression[4][0] = oper[5]; expression[4][1] = eOperator; expression[5][0] = oper[jj]; expression[5][1] = eOperator; expression[6][0] = oper[4]; expression[6][1] = eOperator; expression[8][0] = oper[kk]; expression[8][1] = eOperator; expression[10][0] = oper[5]; expression[10][1] = eOperator; expression[11][0] = oper[6]; expression[11][1] = eOperator; dRes = CalcOneExpress(expression); if(Equal24(dRes)) { printf(“可以这样运算:%c%d%c%d%c%c%c%d%c%d%cn”,oper[4],expression[1][0],oper[ii],expression[3][0],oper[5],oper[jj],oper[4],expression[7][0],oper[kk],expression[9][0],oper[5]); return 1; } } } }//end of for oper } } } } return 0;} int CalcArray5(int iNumInput[2][4]){ //((a * b)* c)* d //11 numbers int expression[12][2];int ii,jj,i,j,k,l,kk;int dRes;for(i=0;i<4;i++){ for(j=0;j<4;j++) { if(j==i) { continue; } for(k=0;k<4;k++) { if(k==i||k==j) { continue; } for(l=0;l<4;l++) { if(l==i||l==j||l==k) { continue; } expression[2][0]=iNumInput[0][i]; expression[4][0]=iNumInput[0][j]; expression[7][0]=iNumInput[0][k]; expression[10][0]=iNumInput[0][l]; expression[2][1]=eNumber; expression[4][1]=eNumber; expression[7][1]=eNumber; expression[10][1]=eNumber; for(ii=0;ii<4;ii++) { for(jj=0;jj<4;jj++) { for(kk=0;kk<4;kk++) { expression[0][0] = oper[4]; expression[0][1] = eOperator; expression[1][0] = oper[4]; expression[1][1] = eOperator; expression[3][0] = oper[ii]; expression[3][1] = eOperator; expression[5][0] = oper[5]; expression[5][1] = eOperator; expression[6][0] = oper[jj]; expression[6][1] = eOperator; expression[8][0] = oper[5]; expression[8][1] = eOperator; expression[9][0] = oper[kk]; expression[9][1] = eOperator; expression[11][0] = oper[6]; expression[11][1] = eOperator; dRes = CalcOneExpress(expression); if(Equal24(dRes)) { printf(“可以这样运算:%c%c%d%c%d%c%c%d%c%c%dn”,oper[4],oper[4],expression[2][0],oper[ii],expression[4][0],oper[5],oper[jj],expression[7][0],oper[5],oper[kk],expression[10][0]); return 1; } } } }//end of for oper } } } } return 0;} int Calc24(int number[2][4]){ int find=0;//括号的 5 种情况 //1 a b c d //2(a b)c d 同 a b(c d)和 a(b c)d //3(a b c)d //4(a b)(c d)//5((a b)c)d 同(a(b c))d if(CalcArray1(number)){ find=1; return 1;} if(CalcArray2(number)){ find=1; return 1;} if(CalcArray3(number)){ find=1; return 1;} if(CalcArray4(number)){ find=1; return 1;} if(CalcArray5(number)){ find=1; return 1;} if(find==0){ printf(“这四个数字算不出24点.n”); return 0;} return 0;} void gameinformation(){ printf(“┌────────────────────────┐n”);printf(“│ 点 游 戏 │n”);printf(“│ 学号: │n”);printf(“│ 设计人:XXX │n”);printf(“│ 完成时间:2015年7月20日 │n”);printf(“└────────────────────────┘nn”);} void menu(){ char s[40],ch,mood;int result,t=1,t0=1,nall=0,nright=0,t1=1;double right;while(t==1){ printf(“本游戏有以下三种模式可选择↓n”); printf(“┌────────────────────────┐n”); printf(“│→ 0.开始游戏 │n”); printf(“│◇ 1.游戏规则 │n”); printf(“│→ 2.退出游戏 │n”); printf(“└────────────────────────┘nn”); printf(“请输入选项所对应的数字↑:”); scanf(“ %c”,&mood); if(mood=='0'){ //计算机成四个数字,游戏者求表达式 nall=0; nright=0; t0=1; while(t0==1) { number[2][4]=randomm(); printf(“这四个数是: %d %d %d %dn”,number[0][0],number[0][1],number[0][2],number[0][3]); printf(“请输入算式n”); printf(“如果你认为这四个数算不出24点,请输入'?'n”); printf(“计算机将会给出答案,算不出也是一种答案!n”); printf(“你的算式是:”); scanf(“%s”,s); if(s[0]=='?'){ if(Calc24(number)==0){ nright++; } nall++; } else { result=EvaluateExpression(s); printf(“你输入的算式的结果是: %d n”,result); if(result==24) { printf(“你赢了!n”); nright++; nall++; } else { 字 printf(“你输了!n”); nall++; } }//else right=(double)nright/nall; printf(“你共做了 %d 道,做对了 %d 道,正确率为:%.2f%%n”,nall,nright,right*100); printf(“继续这个模式吗?请选择: 'y':继续 'n':退出?n”); scanf(“ %c”,&ch); if(ch=='n'||ch=='N'){ t0=0; } else if(ch=='Y'||ch=='y')t0=1; else{ printf(“你的选择(输入)有误!n”); t0=0; } } }//end mood 0 else if(mood=='1'){ //游戏规则说明 printf(“ 规则其实很简单: n”); printf(“ 只能使用+,-,*,/,(,)这6种符号完成表达式 printf(” 当然也允许改变数字顺序n“); printf(” 下面请看示例:n“); printf(” 系统给出的数字为:1 5 5 5n“); printf(” 你只要输入(5-1/5)*5 即可n“); printf(”n“); printf(”n“); printf(”n“); }//end mood 1 else if(mood=='2'){//退出游戏 printf(”游戏结束!n“); t=0; } else { printf(”mood =%cn“,mood); printf(”您的输入有误,游戏结束!n“); t=0; } }//end big while n”);} void main(){ gameinformation();//输出作者信息 menu();//输出功能菜单,游戏开始 } #include gets(str); if(strlen(str)>100) { printf(“每行最多输入100字符”); break; } if(str[0]==64) { str[0]=' '; p->ch[0]=str[0]; break; } p->next=(Lstring *)malloc(sizeof(Lstring)); strcpy(p->ch,str); if(str[strlen(str)-1]==64) { p->ch[strlen(str)-1]=' '; break; } p=p->next;} p->next=NULL;return head;} /****输出文章*****/ Lstring *OutPut(Lstring *head){ Lstring *p=head;do { printf(“%sn”,p->ch);} while((p=p->next)!=NULL);return head;} /****统计字母的个数*****/ int Alphabet(Lstring *head){ Lstring *p=head;int count=0;do { int Len; Len=strlen(p->ch); for(int i=0;i if((p->ch[i]>='a'&&p->ch[i]<='z')||(p->ch[i]>='A'&&p->ch[i]<='Z')) count++;}while((p=p->next)!=NULL);return count;} /****统计数字的字数*****/ int Num(Lstring *head){ Lstring *p=head;int count=0;do { int Len; Len=strlen(p->ch);for(int i=0;i if(p->ch[i]>='0' && p->ch[i]<='9') count++;}while((p=p->next)!=NULL);return count;} /****统计空格的字数*****/ int Space(Lstring *head){ Lstring *p=head;int count=0;do { int Len; Len=strlen(p->ch); for(int i=0;i if(p->ch[i]==32)count++;} while((p=p->next)!=NULL);return count;} /*统计文章的总字数*/ int All(Lstring *head){ Lstring *p=head;int count=0;do { count+=strlen(p->ch);} while((p=p->next)!=NULL);return count;} /****串的简单模式匹配*****/ int FindString(Lstring *head,char *str){ Lstring *p=head;int count=0;int h=0;int len1=0;int len2=strlen(str);int i,j,k;do { len1=strlen(p->ch); for(i=0;i { if(p->ch[i]==str[0]) { k=0; for(j=0;j if(p->ch[i+j]==str[j])k++; if(k==len2) { count++; i=i+k-1; } } } }while((p=p->next)!=NULL);return count;} void delstringword(char *s,char *str){ char *p;int count,len,i,j;char s1[80];p=strstr(s,str);len=strlen(s);i=len-strlen(p);j=i+strlen(str);count=0;for(int m=0;m s1[count++]=s[m]; for(int n=j;n s1[count++]=s[n]; s1[count]=' ';strcpy(s,s1);} Lstring *DelString(Lstring *head,char *str){ Lstring *p=head;do { while(strstr(p->ch,str)!=NULL) delstringword(p->ch,str);} while((p=p->next)!=NULL);return head;} void main(){ int i=0;int m;Lstring *head;char s1[20],s2[20];head=input();printf(“输入的文章为:n”);head=OutPut(head);printf(“n”);printf(“全部字母数:%d n”,Alphabet(head));printf(“数字个数:%d n”,Num(head));printf(“空格个数: %d n”,Space(head));printf(“文章总字数: %d n”,All(head));printf(“n”);printf(“**********************n”);printf(“* 菜 单 *n”);printf(“**********************n”);printf(“* 1---统计字符串 *n”);printf(“* 2---删除字符串 *n”);printf(“* 0---退出 *n”);printf(“**********************n”);do { printf(“请输入你要选择的操作(0~2):”); scanf(“%d”,&m); switch(m) { case 0: exit(0); break; case 1: printf(“请输入要统计的字符串:”); scanf(“%s”,&s1); printf(“%s在文章中出现的次数为:%d n”,s1,FindString(head,s1)); } printf(“n”); break; case 2: printf(“请输入要删除的某一字符串:”); scanf(“%s”,&s2); head=DelString(head,s2); printf(“删除%s后的文章为:n”,s2); OutPut(head); break; } }while(m!=0); 目录 前言..................................................................................................................2 概要设计..................................................................................................................3 1.1 数据结构设计...........................................................................................3 2.1 算法设计...................................................................................................3 2.1.1 建立链表的算法..............................................................................3 2.1.2 链表插入一个元素的算法..............................................................3 2.1.3 链表删除一个元素的算法..............................................................3 3.1 ADT描述..................................................................................................4 4.1 详细设计…………………………………………… ……………………………… 4 4.1.1 数据存储结构……………………………… ……………………………… 4.4.1.2 主要伪代码…… …………………… ……………………………………… 4 软件测试..................................................................................................................7 心得体会................................................................................................................11 源代码...................................................................................................................12 参考文献………………………………………………………………………...21 前言 数据结构是计算机程序设计的重要理论技术基础,它不仅是计算机学科的核心课程,而且已经成为其他理工专业的热门选修课。 随着计算机科学的技术和发展,计算机的功能和运算速度不断地提高,其应用于信息处理的范围日益扩大。与之相应的,计算机的加工处理对象也从简单的数据发展到一般的符号,进而发展到更复杂的数据结构。数据结构是计算机程序设计的重要理论技术基础,数据结构的表示和操作都涉及到算法,如何描述数据的结构和讨论有关的算法,又涉及到程序设计语言。因此,它不仅是计算机学科的核心课程,而且已经成为其他理工专业的热门选修课。我们通过对这门基础课程的学习,要学会分析研究计算机加工的数据结构的特性,以便为应用涉及的数据选择适合的逻辑结构,储存结构及其相应的算法,并初步掌握算法时间分析和空间分析的技术。通过实际操作去了解数据结构原理,练习编写代码的能力,以及抽象能力。 从课程性质上讲,“数据结构”是一门专业技术基础课。它的要求是学会分析研究计算机加工的数据结构的特性,以便为应用涉及的数据选择适当的逻辑结构,存储结构及相应的算法,并初步掌握算法的时间分析和空间分析的技术。另一方面,数据结构的学习过程也是复杂程序设计的训练过程,要求编写的程序结构清楚和正确易读,符合软件工程的规范。 概要设计 1.1 数据结构设计 采用链式储存结构。typedef struct LNode{ ElemType data;struct LNode *next;}LNode,*LinkList;2.1 算法设计 2.1.1 建立链表的算法 (1)算法思想分析 首先从表尾到表头逆向建立单链表,然后再建立的单链表基础上进行对链表上的元素进行查询,删除,插入的操作。(2)要点描述 首先建立一个带头结点的单链表,通过申请内存,先建立一个空链表。然后结点的插入,建立一个有多个结点的链表。在进行查询等操作。(3)时间和空间复杂度分析 程序的时间复杂度为O(n)。 2.1.2 链表插入一个元素的算法 (1)算法思想分析 要生成一个新数据域为X的结点,然后插入在单链表中。(2)要点描述 在链表中插入结点只需要修改指针。若要在第 i 个结点之前插入元素,修改的是第 i-1 个结点的指针。 (3)时间和空间复杂度分析 时间复杂度O(n)2.1.3 链表删除一个元素的算法 (1)算法思想分析 要删除一个结点,必须修改指针并且释放空间。(2)要点描述 找到线性表中第i-1个结点,修改其指向后继的指针。 (3)时间和空间复杂度分析 时间复杂度O(n) 3.1 ADT描述 ADT LinkList{ 数据对象:D={ e | e∈LNode } 数据关系:R1={ 基本操作: GreateList_L(&L, n) 操作结果:构造了一个长为n的数据链表 ListDelete_L(&L, i, &e) 初始条件:链表L已存在而且非空 操作结果:删除L的第i个数据,并且用e返回其值 ListInsert_L(&L, i, e) 初始条件:链表L已存在 操作结果: 在L的第i个位置插入数据e GetElem(L, i, e) 初始条件:链表L已存在 操作结果:用e返回L中的第i个数据 }ADT LinkList 4.1 详细设计 4.1.1数据存储结构设计 采用单链式线性表实现 4.1.2 主要伪代码 Status GetElem(LinkList L, int i, ElemType *e){ int j=0;int d;LinkList p = L;while(p&&jnext;j++; } if(!p || j > i)return ERROR;printf(“您要查询的元素是:n”);d=p->data;printf(“%d”,d);printf(“n”);} void InitList(LinkList *L){ *L =(LinkList)malloc(sizeof(struct LNode));if(!*L)exit(OVERFLOW);(*L)->next = NULL;} Status ListInsert(LinkList L, int i, ElemType e){ int j = 0;LinkList p = L, s;while(p && j < i-1){ p = p->next;j++;} if(!p|| j > i-1)return ERROR;s =(LinkList)malloc(sizeof(struct LNode));s->data = e;s->next = p->next;p->next = s;return OK;} Status ListDelete(LinkList L, int i, ElemType *e){ int j = 0;LinkList p = L, q;while(p->next && j < i-1){ p = p->next; j++;} if(!p->next || j > i-1)return ERROR;q = p->next;p->next = q->next;*e = q->data;free(q);return OK;} void ListTraverse(LinkList L, void(*vi)(ElemType)){ LinkList p = L->next;while(p){ vi(p->data);p = p->next;} printf(“n”);} void ListPrint(LinkList L){ LinkList p = L->next;while(p){ printf(“%d ”, p->data);p = p->next;} printf(“n”);} void printInt(int data){ printf(“%d ”, data);}.软件测试 图一(主界面) 图二(插入学生信息) 图三(显示所有学生信息) 图四(查询个人信息) 图五(统计信息) 图六(修改信息) 图七(保存数据) 图八(删除信息) 心得体会 通过本程序的设计,我对数据结构作了以下总结:要解决一道程序题必须先要认真捕捉改程序中的有用信息,找出解决方法。先规划好,程序需要什么样的数据结构,什么函数,对程序有什么要求。然后从整体把握对程序设计进行分工,相应地把程序分成若干模块,具体实现各部分实行相应的功能。一个程序要顺利地进行设计,一是要对程序的功能有全面的了解,如果漏了某些部分,都会使得这个程序调试不出来或者是令该程序没有达到预想的效果。其次,在程序的编译中,必须注重程序设计过程中的细节,像单链表的程序,就要理解链表的概念,理解链表的数据特点,要清楚知道数据域和指针域的作用,否则,很容易会浪费大量时间在检测错误上面。要说到解题的思考方向,如果要总结成规律,我认为要灵活的进行方法的设计,通过不同的方法来实现不同的功能,如通过结点的插入来实现链表的创建。同时应该注意各种语句的选择,要先预想好需要什么样的语句来实现函数定义,尽量简单快捷地完成,避免出错。 要规范面向对象程序设计师的书写协管,在这次课程设计中,我们再次感受到,规范的程序书写,可以更好的进行后期的差错补漏。还应该注意各种面向对象语言语法的运用,例如继承的方法,都要严格按照语法来进行,否则很容易就会出现错误,甚至严重影响课程设计的进度。 源代码 #include “stdio.h” #include “stdlib.h” #include “string.h” int shoudsave=0;// struct student { char num[10];//学号 char name[20]; char sex[4]; int cgrade; int mgrade; int egrade; int totle; int ave; char neartime[10];//最近更新时间 }; typedef struct node { struct student data; struct node *next;}Node,*Link; int menu(){ char m[3]; int n; printf(“ ************************欢迎进入学生成绩管理系统******************************nn”); printf(“t欢迎使用本学生管理系统,本系统将为您提供历史学生信息查询,学生成绩信息管理功能。n”); printf(“********************************************************************************”); printf(“t1输入学生资料ttttt2删除学生资料n”); printf(“t3查询学生资料ttttt4修改学生资料n”); printf(“t5显示学生资料ttttt6统计学生成绩n”); printf(“t7保存学生资料n”); printf(“ttplease choose a operation(1-7):n”); printf(“*********************************************************************** *********n”); scanf(“%s”,m); n=atoi(m); return(n);} void printstart(){ printf(“---------n”);} void Wrong(){ printf(“n=====>提示:输入错误!n”);} void Nofind(){ printf(“n=====>提示:没有找到该学生!n”);} void printc()// 本函数用于输出中文 { printf(“学号t 姓名 性别 英语成绩 数据库成绩 数据结构成绩 总分平均分n”);} void printe(Node *p)//本函数用于输出英文 { printf(“%-12s%stt%st%dtt%dt%dt%dt %dn”,p->data.num,p->data.name,p->data.sex,p->data.egrade,p->data.mgrade,p->data.cgrade,p->data.totle,p->data.ave);} Node* Locate(Link l,char findmess[],char nameornum[])//该函数用于定位连表中符合要求的接点,并返回该指针 { Node *r; if(strcmp(nameornum,“num”)==0)//按学号查询 { r=l->next; while(r!=NULL) { if(strcmp(r->data.num,findmess)==0) return r; r=r->next; } } else if(strcmp(nameornum,“name”)==0)//按姓名查询 { r=l->next; while(r!=NULL) { if(strcmp(r->data.name,findmess)==0) return r; r=r->next; } } return 0;} void Add(Link l)//增加学生 { Node *p,*r,*s; char num[10]; r=l; s=l->next; while(r->next!=NULL) r=r->next;//将指针置于最末尾 while(1) { printf(“请你输入学号(以'0'返回上一级菜单:)”); scanf(“%s”,num); if(strcmp(num,“0”)==0) break; while(s) { if(strcmp(s->data.num,num)==0) { printf(“=====>提示:学号为'%s'的学生已经存在,若要修改请你选择'4 修改'!n”,num); printstart(); printc(); printe(s); printstart(); printf(“n”); return; } s=s->next; } p=(Node *)malloc(sizeof(Node)); strcpy(p->data.num,num); printf(“请你输入姓名:”); scanf(“%s”,p->data.name); getchar(); printf(“请你输入性别:”); scanf(“%s”,p->data.sex); getchar(); printf(“请你输入数据结构成绩:”); scanf(“%d”,&p->data.cgrade); getchar(); printf(“请你输入数据库成绩:”); scanf(“%d”,&p->data.mgrade); getchar(); printf(“请你输入英语成绩:”); scanf(“%d”,&p->data.egrade); getchar(); p->data.totle=p->data.egrade+p->data.cgrade+p->data.mgrade; p->data.ave=p->data.totle / 3; //信息输入已经完成p->next=NULL; r->next=p; r=p; shoudsave=1; } } void Qur(Link l)//查询学生 { char findmess[20]; Node *p; if(!l->next) { printf(“n=====>提示:没有资料可以查询!n”); return; } printf(“请你输入要查找的学号:”); scanf(“%s”,findmess); p=Locate(l,findmess,“num”); if(p) { printf(“tttt查找结果n”); printstart(); printc(); printe(p); printstart(); } else Nofind();} void Del(Link l)//删除 { Node *p,*r; char findmess[20]; if(!l->next) { printf(“n=====>提示:没有资料可以删除!n”); return; } printf(“n=====>确定进行删除操作请按 1,按其他按键退出该操作nnnn”); if(menu()==1) { printf(“请你输入要删除的学号:”); scanf(“%s”,findmess); p=Locate(l,findmess,“num”); if(p) { r=l; while(r->next!=p) r=r->next; r->next=p->next; free(p); printf(“n=====>提示:该学生已经成功删除!n”); shoudsave=1; } else Nofind(); } else exit;} void Modify(Link l)//修改函数 { Node *p; char findmess[20]; if(!l->next) { printf(“n=====>提示:没有资料可以修改!n”); return; } printf(“请你输入要修改的学生学号:”); scanf(“%s”,findmess); p=Locate(l,findmess,“num”); if(p) { printf(“请你输入新学号(原来是%s):”,p->data.num); scanf(“%s”,p->data.num); printf(“请你输入新姓名(原来是%s):”,p->data.name); scanf(“%s”,p->data.name); getchar(); printf(“请你输入新性别(原来是%s):”,p->data.sex); scanf(“%s”,p->data.sex); printf(“请你输入新的数据结构成绩(原来是%d分):”,p->data.cgrade); scanf(“%d”,&p->data.cgrade); getchar(); printf(“请你输入新的数据库成绩(原来是%d分):”,p->data.mgrade); scanf(“%d”,&p->data.mgrade); getchar(); printf(“请你输入新的英语成绩(原来是%d分):”,p->data.egrade); scanf(“%d”,&p->data.egrade); p->data.totle=p->data.egrade+p->data.cgrade+p->data.mgrade; p->data.ave=p->data.totle/3; printf(“n=====>提示:资料修改成功!n”); shoudsave=1; } else Nofind(); } void Disp(Link l)//显示函数 { int count=0; Node *p; p=l->next; if(!p) { printf(“n=====>提示:没有资料可以显示!n”); return; } printf(“tttt显示结果n”); printstart(); printc(); printf(“n”); while(p) { printe(p); p=p->next; } printstart(); printf(“n”);} void Tongji(Link l)//统计函数 { Node *pm,*pe,*pc,*pt,*pa;//用于指向分数最高的接点 Node *r=l->next; if(!r) { printf(“n=====>提示:没有资料可以统计!n”); return; } pm=pe=pc=pt=pa=r; while(r!=NULL) { if(r->data.cgrade>=pc->data.cgrade) pc=r; if(r->data.mgrade>=pm->data.mgrade) pm=r; if(r->data.egrade>=pe->data.egrade) pe=r; if(r->data.totle>=pt->data.totle) pt=r; if(r->data.ave>=pa->data.ave) pa=r; r=r->next; } printf(“------------------------------统计结果-n”); printf(“总分最高者:t%s %d分n”,pt->data.name,pt->data.totle); printf(“平均分最高者:t%s %d分n”,pa->data.name,pa->data.ave); printf(“英语最高者:t%s %d分n”,pe->data.name,pe->data.egrade); printf(“数据库最高者:t%s %d分n”,pm->data.name,pm->data.mgrade); printf(“数据结构最高者:t%s %d分n”,pc->data.name,pc->data.cgrade); printstart();} void Save(Link l)//保存函数 { FILE* fp; Node *p; int flag=1,count=0; fp=fopen(“c:student”,“wb”); if(fp==NULL) { printf(“n=====>提示:重新打开文件时发生错误!n”); exit(1); } p=l->next; while(p) { if(fwrite(p,sizeof(Node),1,fp)==1) { p=p->next; count++; } else { flag=0; break; } } if(flag) { printf(“n=====>提示:文件保存成功.(有%d条记录已经保存.)n”,count); shoudsave=0; } fclose(fp);} void main(){ Link l;//连表 FILE *fp;//文件指针 char ch; char jian; int count=0; Node *p,*r; l=(Node*)malloc(sizeof(Node)); l->next=NULL; r=l; fp=fopen(“C:student”,“rb”); if(fp==NULL) { fp=fopen(“C:student”,“wb”); exit(0); } printf(“n=====>提示:文件已经打开,正在导入记录......n”); while(!feof(fp)) { p=(Node*)malloc(sizeof(Node)); if(fread(p,sizeof(Node),1,fp))//将文件的内容放入接点中 { p->next=NULL; r->next=p; r=p;//将该接点挂入连中 count++; } } fclose(fp);//关闭文件 printf(“n=====>提示:记录导入完毕,共导入%d条记录.n”,count); for(;;) { switch(menu()) { case 1:Add(l);break;//增加学生 case 2:Del(l);break;//删除学生 case 3:Qur(l);break;//查询学生 case 4:Modify(l);break;//修改学生 case 5:Disp(l);break;//显示学生 case 6:Tongji(l);break;//统计学生 case 7:Save(l);break;//保存学生 default: Wrong(); getchar(); break; } } } 参考文献 《数据结构(C语言版)》----------------清华大学出版社 严蔚敏 吴伟民 编著 《C语言程序设计》------------------------中国铁道出版社 丁峻岭 余坚 编著 泄露游戏源代码的严重性 (相关法律知识及案例)为了防止因员工将公司开发的网络游戏的源代码泄露或擅自复制设立私服,进而导致公司遭受不可逆转的经济损失;公司欲向员工普及相关法律知识,从而使员工能够了解私自泄露源代码的严重性,提高其自身职业素养。 I.网络游戏源代码概述 网络游戏,英文名称为Online Game,又称 “在线游戏”,简称“网游”。指以互联网为传输媒介,以游戏运营商服务器和用户计算机为处理终端,以游戏客户端软件为信息交互窗口的旨在实现娱乐、休闲、交流和取得虚拟成就的具有可持续性的个体性多人在线游戏。网络游戏形式分为浏览器形式和客户端形式两种。 网络游戏存在的形式为计算机软件,计算机软件(以下简称软件),是指计算机程序及其有关文档。计算机程序,是指为了得到某种结果而可以由计算机等具有信息处理能力的装置执行的代码化指令序列,或者可以被自动转换成代码化指令序列的符号化指令序列或者符号化语句序列。同一计算机程序的源程序(又称源代码)和目标程序为同一作品。文档是指用来描述程序的内容、组成、设计、功能规格、开发情况、测试结果及使用方法的文字资料和图表等,如程序设计说明书、流程图、用户手册等。 源代码是用源语言编制的计算机程序。因此,源代码是计算机软件的核心内容,是软件设计方案的具体表现,一旦被公开,软件的核心技术即泄露,从而会失去应有的商业价值。由此可以看出源代码是网络游戏软件构成的最为重要的基本元素。 II.网络游戏源代码泄露形式介绍 网络游戏是有其生命周期的,在绝大部分情况下,网络游戏源代码的泄露和公开将直接导致网络游戏的死亡或者导致网络游戏平衡性的丧失而失去玩家。最终导致网络游戏开发公司和运营公司的巨额亏损直至破产清算。 网络游戏源代码的泄露,通常分成三种情况: 私服; 法为依据要求对方承担相应的法律责任。当然,根据其技术原理,这种擅自开设“私服”行为,同时也侵犯了游戏软件版权人的使用权,因此,属于版权侵权行为,应该承担版权法上的侵权责任。对于 输入游戏的账号和密码后,很有可能发生丢号事件、丢失虚拟物品事件。还有部分外挂程序制作分子利用玩家贪图一时便利而注册外挂的途径,大肆实施窃取他人账号行径。更有甚者打出了免费的旗帜,当玩家在使用一定时期后,逐渐依赖外挂而游戏时,再收取费用。 四个账户,建立了私服《天子传奇》。 2005年5月25日晚,经过周密准备,上海市公安局普陀分局将该私服的服务器、远程维护电脑等设备同时起获,并抓获了犯罪嫌疑人游某。至案发时,该私服所设立的账户共收到会员缴费53万余元(均为非法获利)。 2005年6月30日,犯罪嫌疑人游某被检察机关以侵犯著作权罪批准逮捕。2005年11月,游某被判处有期徒刑三年缓刑三年。2006年7月,主犯罗治国向公安机关投案自首。 这是以刑事手段打击“私服”活动的全国 罚金70万元;以侵犯著作权罪判处梁文宇有期徒刑三年六个月,并处罚金60万元;以销售侵权复制品罪判处阮晓霞拘役六个月,并处罚金30万元;以销售侵权复制品罪判处刘阳拘役六个月,并处罚金20万元;各被告人的违法所得及被扣押的电子设备予以没收。 本案是全国“扫黄打非”办、新闻出版总署(国家版权局)、公安部、高法院、高检院五部门挂牌督办的专项行动重点案件,本案中提出的“未经权利人许可,以营利为目的,制作游戏软件的外挂程序,是复制游戏软件客户端程序的行为,应以侵犯著作权罪查处”等法律适用意见,以及本案从淘宝网店铺销售侵权复制品入手对案件的全面深入查处,对于办理网络游戏“外挂”案件、严厉打击通过网络渠道销售侵权复制品等违法案件具有指导意义。 3.员工故意泄露源代码侵犯网络游戏《征途》著作权的刑事案件 游戏公司内部员工故意泄露源代码给从事私服和外挂业务的犯罪嫌疑人,将构成侵犯著作权罪共犯。不但要承担侵权赔偿民事责任,还有可能承担刑事犯罪责任。其典型案例为征途“内贼”案件。 2006年3月,拥有大学文凭的王予川进入上海征途网络公司,担任研发中心开发部程序员一职,负责征途网络游戏部分源代码的研发工作。3个月后,王予川离开征途公司,临走时,他私自复制并带走了服务端源代码、客户端源代码及辅助文档,这是征途公司具有独立著作权的征途游戏的程序。 失业后的王予川经济拮据,于是他想到了手中的“宝贝”、也就是征途游戏的源代码。今年3月,他通过互联网发布相关信息,并很快找到了江苏和东北的两名买家。同月15日、30日,王予川在上海浦东某酒店内,将上述服务端源代码等分别以7万元和6万元的价格卖给了王岩等人。不日,王岩和汤帅前往南京,又以20万元的价格将这些源代码转手卖给了另一名下家。与此同时,征途公司发现了征途游戏源代码被秘密复制外泄的情况,并立即报警。4月4日,王岩和汤帅在江苏和下家交易时被公安人员人赃俱获。同月8日,王予川被公安人员抓获。 法院经审理后查明,被告人王予川利用职务便利,未经著作权人许可,复制计算机软件并予以发行,违法所得数额较大,其行为已构成侵犯著作权罪,应予处罚。被告人王岩明知是侵权复制品仍予以购买,并伙同被告人汤帅进行非法销售,其行为已构成销售侵权复制品罪,且系共同犯罪,也应予处罚。被告人王予川到案后主动交代了以6万元将源代码等销售给他人的事实,属于坦白,并退出了全部违法所得。 据此,为严肃国家法制,维护社会主义市场经济秩序,保障著作权人的合法权益不受侵害,2007年12月7日,上海市徐汇区人民法院对此案作出一审判决,被告人王予川犯侵犯著作权罪,被判处有期徒刑1年零6个月,并处罚金5万元;被告人王岩、汤帅犯销售侵权复制品罪,分别被判处有期徒刑1年、10个月,并处罚金4万元、3万元。 4.员工故意泄露源代码侵犯网络游戏《JGnet》著作权的刑事案件 内部员工泄露网络游戏源代码的另一个著名案例是,2009年8月,刘波从成都汉森信息技术有限公司离职后,将其私自复制的该公司拥有著作权的“JGnet”游戏引擎程序、“倾城”网络游戏软件等在互联网上公开出售。据成都市高新区法院公布的案情调查显示,2009年9月17日下午16时,刘波将“JGnet”游戏引擎程序以10万元的价格出售给了高飞,在刘波与高飞交易时,被警方当场抓获。2009年10月20日,刘波被成都市高新检察院批捕;2010年2月底,成都市高新区法院宣布,驳回被告刘波的上诉,并维持原判,以“侵犯著作权”的罪名判处刘波有期徒刑两年,并处罚款一万元人民币。 小结: 基于上述分析可以看出,网络游戏非法外挂给网络游戏公司造成重大损失的案件。网络游戏源代码的泄露,将带来无休止的游戏私服和外挂问题,加速了游戏的死亡时间,给游戏开发和运营公司将造成巨大的损失。同时擅自泄露网络游戏源代码的内部员工将构成版权侵权,甚至版权犯罪,不但要承担侵权赔偿责任,有可能也会承担刑事责任。 基于目前中国大陆地区由于网络游戏源代码泄露而引发的刑事案件已有30余起、因此而获刑的人员也有50余人。还有更多的网络游戏源代码泄露导致网络游戏的死亡和游戏公司的巨额亏损案件不停的披露出来。 附件 一、网络游戏源代码保护的相关法律法规 根据《刑法》 款;违法经营额不足1万元的,并处1万元以上5万元以下罚款;情节严重的,责令限期停业整顿或者撤销批准。“私服”经营者经营的内容侵犯合法厂商的权益,应当依据该条承担行政责任。 2005年文化部等五部委联合发出通知,指出“私服”等侵犯知识产权、扰乱市场秩序的问题突出,需要严厉打击。 《互联网文化管理暂行规定》 闭网站。“私服”经营者应当承担该项行政责任。 根据《著作权法》 青岛大学软件技术学院 游戏算法实践报告 姓 名 专 业 班 级 指导教师 2013年 1 月 16日 目录 问题定义与描述...................................................................................................3 1.1 问题定义.....................................................................................................3 1.2 问题描述.....................................................................................................3 2 关键技术...............................................................................................................3 3 数据的组织...........................................................................................................3 3.1数据类型定义..............................................................................................3 3.2数据存储结构..............................................................................................3 4 总体设计...............................................................................................................4 4.1 系统模块图..................................................................................................4 4.2 二维数组的基本操作..................................................................................4 5.详细设计................................................................................................................5 5.1主函数流程图...............................................................................................5 5.2双方走棋函数流程图...................................................................................6 5.3计算分数函数流程图...................................................................................8 6 测试结果及分析...................................................................................................9 7 心得体会...............................................................................................................9 附录:程序代码.......................................................................................................9 1 问题定义与描述 1.1 问题定义 黑白棋游戏 1.2 问题描述 将黑白棋8X8的棋盘转化为一个二维数组,将棋的各种操作转化为二维数组的操作 关键技术 二维数组,判断情况的选择 数据的组织 棋盘各个格子的地址x、y,双方棋子放置的地址i、j,双方新棋子放置的地址ii、jj,棋子活动的地址kk,将要被连成一行的棋子k,图形、颜色文件的调用等 3.1数据类型定义 #define LEFT 0x4b00 /*光标左键值*/ #define RIGHT 0x4d00 /*光标右键值*/ #define DOWN 0x5000 /*光标下键值*/ #define UP 0x4800 /*光标上键值*/ #define ESC 0x011b /* ESC键值*/ #define ENTER 0x1c0d /* 回车键值*/ int a[8][8]={0},key,score1,score2;/*具体分数以及按键与存放棋子的变量*/ char playone[3],playtwo[3];/*两个人的得分转换成字符串输出*/ 3.2数据存储结构 二维数组以顺序存储的形式实现 4 总体设计 4.1 系统模块图 图4.1 系统模块图 4.2 二维数组的基本操作 向上:纵坐标-1 向下:纵坐标+1 向左:横坐标-1 向右:横坐标+1 左上:横-1,纵-1 左下:横-1,纵+1 右上:横+1,纵-1 右下:横+1,纵+1 确定落子:返回1值,结束循环,跳入player2,反之亦然 统计分数:落子后score++,结束循环,跳入score2,反之亦然 5.详细设计 5.1主函数流程图 图5.1 主函数流程图 5.2双方走棋函数流程图 图5.2 双方走棋函数流程图 5.3计算分数函数流程图 图5.3 计算分数函数流程图 6 测试结果及分析 图6 运行程序,初始状态如图所示 心得体会 数据结构的课程设计学习让我初步体会到编程需要的耐心、细致,在调整程序时更深刻地体会到函数调用名必须一致,C语言对大写小写十分敏感,以前没用过这么复杂的程序,这次更有了深刻的体会。与此同时更加熟悉了二维数组在游戏编程中的应用和C语言的图形文件的使用方法,不止迷宫的边界,棋盘的操作也是靠二维数组完成的。 附录:程序代码 /*3.3.4 源程序*/ #include “graphics.h” /*图形系统头文件*/ #include “stdio.h” #define LEFT 0x4b00 /*光标左键值*/ #define RIGHT 0x4d00 /*光标右键值*/ #define DOWN 0x5000 /*光标下键值*/ #define UP 0x4800 /*光标上键值*/ #define ESC 0x011b /* ESC键值*/ #define ENTER 0x1c0d /* 回车键值*/ int a[8][8]={0},key,score1,score2;/*具体分数以及按键与存放棋子的变量*/ char playone[3],playtwo[3];/*两个人的得分转换成字符串输出*/ void playtoplay(void);/*人人对战函数*/ void DrawQp(void);/*画棋盘函数*/ void SetPlayColor(int x);/*设置棋子第一次的颜色*/ void MoveColor(int x,int y);/*恢复原来棋盘状态*/ int QpChange(int x,int y,int z);/*判断棋盘的变化*/ void DoScore(void);/*处理分数*/ void PrintScore(int n);/*输出成绩*/ void playWin(void);/*输出胜利者信息*/ /******主函数*********/ void main(void){ int gd=DETECT,gr; initgraph(&gd,&gr,“c: c”);/*初始化图形系统*/ DrawQp();/*画棋盘*/ playtoplay();/*人人对战*/ closegraph();/*关闭图形系统*/ getch();} void DrawQp()/*画棋盘*/ { int i,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); setfillstyle(SOLID_FILL,8); fillellipse(120+3*40,120+4*40,15,15); fillellipse(120+4*40,120+3*40,15,15); score1=score2=2;/*有棋后改变分数*/ DoScore();/*输出开始分数*/ } void playtoplay()/*人人对战*/ { int x,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&&a[(x-120)/40][(y-120)/40]!=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); fillellipse(x,y,15,15); break; } else continue;/*如果按键无效*/ } DoScore();/*分数的改变*/ break;/*棋盘变化了,则轮对方走棋*/ } else/*已经有棋子就继续按键*/ continue; } else /*四个方向按键的判断*/ if(key==LEFT&&x>120)/*左方向键*/ { MoveColor(x,y); fillellipse(x,y,15,15); SetPlayColor(t); x-=40; fillellipse(x,y,15,15); } else if(key==RIGHT&&x<400&&y>80)/*右方向键*/ { MoveColor(x,y); fillellipse(x,y,15,15); SetPlayColor(t); x+=40; fillellipse(x,y,15,15); } else if(key==UP&&y>120)/*上方向键*/ { MoveColor(x,y); fillellipse(x,y,15,15); SetPlayColor(t); y-=40; fillellipse(x,y,15,15); } else if(key==DOWN&&y<400)/*下方向键*/ { MoveColor(x,y); fillellipse(x,y,15,15); SetPlayColor(t); y+=40; fillellipse(x,y,15,15); } } if(key==ESC)/*结束游戏*/ break; if((score1+score2)==64||score1==0||score2==0)/*格子已经占满或一方棋子为0判断胜负*/ { playWin();/*输出最后结果*/ break; } t=t%2+1;/*一方走后,改变棋子颜色即轮对方走*/ cc=0;/*计数值恢复为0*/ } /*endwhile*/ } void SetPlayColor(int t)/*设置棋子颜色*/ { if(t%2==1) setfillstyle(SOLID_FILL,15);/*白色*/ else setfillstyle(SOLID_FILL,8);/*灰色*/ } void MoveColor(int x,int y)/*走了一步后恢复原来格子的状态*/ { if(y<100)/*如果是从起点出发就恢复蓝色*/ setfillstyle(SOLID_FILL,BLUE); else/*其他情况如果是1就恢复白色棋子,2恢复黑色棋子,或恢复蓝色棋盘*/ switch(a[(x-120)/40][(y-120)/40]) { case 1: setfillstyle(SOLID_FILL,15);break;/*白色*/ case 2: setfillstyle(SOLID_FILL,8);break;/*黑色*/ default: setfillstyle(SOLID_FILL,BLUE);/*蓝色*/ } } int QpChange(int x,int y,int t)/*判断棋盘的变化*/ { int i,j,k,kk,ii,jj,yes; yes=0; i=(x-120)/40;/*计算数组元素的行下标*/ j=(y-120)/40;/*计算数组元素的列下标*/ SetPlayColor(t);/*设置棋子变化的颜色*/ /*开始往8个方向判断变化*/ if(j<6)/*往右边*/ { for(k=j+1;k<8;k++) if(a[i][k]==a[i][j]||a[i][k]==0)/*遇到自己的棋子或空格结束*/ break; if(a[i][k]!=0&&k<8) { for(kk=j+1;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]) break; if(a[i][k]!=0&&k>=0) { for(kk=j-1;kk>k&&k>=0;kk--) { a[i][kk]=a[i][j]; fillellipse(120+i*40,120+kk*40,15,15); } if(kk!=j-1) yes=1; } } if(i<6)/*判断下边*/ { for(k=i+1;k<8;k++) if(a[k][j]==a[i][j]||!a[k][j]) break; if(a[k][j]!=0&&k<8) { for(kk=i+1;kk { a[kk][j]=a[i][j]; fillellipse(120+kk*40,120+j*40,15,15); } if(kk!=i+1) yes=1; } } if(i>1)/*判断上边*/ { for(k=i-1;k>=0;k--) if(a[k][j]==a[i][j]||!a[k][j]) break; if(a[k][j]!=0&&k>=0) { for(kk=i-1;kk>k&&k>=0;kk--) { a[kk][j]=a[i][j]; fillellipse(120+kk*40,120+j*40,15,15); } if(kk!=i-1) yes=1; } } if(i>1&&j<6)/*右上*/ { for(k=i-1,kk=j+1;k>=0&&kk<8;k--,kk++) if(a[k][kk]==a[i][j]||!a[k][kk]) break; if(a[k][kk]&&k>=0&&kk<8) { for(ii=i-1,jj=j+1;ii>k&&k>=0;ii--,jj++) { a[ii][jj]=a[i][j]; fillellipse(120+ii*40,120+jj*40,15,15); } if(ii!=i-1) yes=1; } } if(i<6&&j>1)/*左下*/ { for(k=i+1,kk=j-1;k<8&&kk>=0;k++,kk--) if(a[k][kk]==a[i][j]||!a[k][kk]) break; if(a[k][kk]!=0&&k<8&&kk>=0) { for(ii=i+1,jj=j-1;ii { a[ii][jj]=a[i][j]; fillellipse(120+ii*40,120+jj*40,15,15); } if(ii!=i+1) yes=1; } } if(i>1&&j>1)/*左上*/ { for(k=i-1,kk=j-1;k>=0&&kk>=0;k--,kk--) if(a[k][kk]==a[i][j]||!a[k][kk]) break; if(a[k][kk]!=0&&k>=0&&kk>=0) { for(ii=i-1,jj=j-1;ii>k&&k>=0;ii--,jj--) { a[ii][jj]=a[i][j]; fillellipse(120+ii*40,120+jj*40,15,15); } if(ii!=i-1) yes=1; } } if(i<6&&j<6)/* 右下*/ { for(k=i+1,kk=j+1;kk<8&&kk<8;k++,kk++) if(a[k][kk]==a[i][j]||!a[k][kk]) break; if(a[k][kk]!=0&&kk<8&&k<8) { for(ii=i+1,jj=j+1;ii { a[ii][jj]=a[i][j]; fillellipse(120+ii*40,120+jj*40,15,15); } if(ii!=i+1) yes=1; } } return yes;/*返回是否改变过棋子颜色的标记*/ } void DoScore()/*处理分数*/ { int i,j; score1=score2=0;/*重新开始计分数*/ for(i=0;i<8;i++) for(j=0;j<8;j++) if(a[i][j]==1)/*分别统计两个人的分数*/ score1++; else if(a[i][j]==2) score2++;} void PrintScore(int playnum)/*输出成绩*/ { if(playnum==1)/*清除以前的成绩*/ { setfillstyle(SOLID_FILL,BLUE); bar(550,100,640,400); } setcolor(RED); settextstyle(0,0,4);/*设置文本输出样式*/ if(playnum==1)/*判断输出哪个棋手的分,在不同的位置输出*/ { sprintf(playone,“%d”,score1); outtextxy(550,200,playone); } else { sprintf(playtwo,“%d”,score2); outtextxy(550,300,playtwo); } setcolor(0);} void playWin()/*输出最后的胜利者结果*/ { settextstyle(0,0,4); setcolor(12); if(score2>score1)/*开始判断最后的结果*/ outtextxy(100,50,“black win!”); else if(score2 outtextxy(100,50,“white win!”); else outtextxy(60,50,“you all win!”); getch();}第二篇:数据结构课程设计 文章编辑 源代码
第三篇:数据结构实验报告(报告+C语言源代码)
第四篇:泄露游戏源代码的严重性
第五篇:黑白棋游戏数据结构课程设计