/*贪吃蛇游戏,由于是C++源码 且 用到Windows API ,是控制台界面不是图形界面,需要用VC++6.0 或 VC++2010 在windows环境编译运行。如果符合上述条件一定可以编译运行zjlj,2015.3.16*/#define DEBUG 0 //当程序在调试阶段时 DEBUG为 1#include#include#include#includeusing namespace std;void readini(FILE **fphead, int *score, char *argv[]) //创建或打开一个和运行文件对应的ini文件,读取最高纪录{ char filename[200],*pfilename; int flag=-1,i; strcpy(filename,argv[0]); for(i=0;filename[i]!='\0';i++) { if ('.'==filename[i])flag=1; } if(1==flag) { filename[i-1]='i'; filename[i-2]='n'; filename[i-3]='i'; } else { filename[i]='.'; filename[i+1]='i'; filename[i+2]='n'; filename[i+3]='i'; filename[i+4]='\0'; } for(;filename[i]!='\\'&&i>=0;i--)pfilename=&filename[i]; if ( (*fphead=fopen(pfilename, "rb+"))==NULL) { if ( (*fphead=fopen(pfilename, "wb+"))==NULL) { printf("无法创建或打开\"%s\"文件\n",pfilename); system("pause"); exit(0); } } else { fread(score,sizeof(int),1,*fphead); }}void writeini(FILE **fphead, int *score, char *argv[]) //打开一个和运行文件对应的ini文件,写入最高纪录{ char filename[200],*pfilename; int flag=-1,i; strcpy(filename,argv[0]); for(i=0;filename[i]!='\0';i++) { if ('.'==filename[i])flag=1; } if(1==flag) { filename[i-1]='i'; filename[i-2]='n'; filename[i-3]='i'; } else { filename[i]='.'; filename[i+1]='i'; filename[i+2]='n'; filename[i+3]='i'; filename[i+4]='\0'; } for(;filename[i]!='\\'&&i>=0;i--)pfilename=&filename[i]; if ( (*fphead=fopen(pfilename, "wb+"))==NULL) { printf("无法写入\"%s\"文件,磁盘写保护!\n",pfilename); system("pause"); exit(0); } else { rewind(*fphead); fwrite(score,sizeof(int),1,*fphead); fclose(*fphead); }}void gotoxy(int x,int y)//光标定位,光标定位函数SetConsoleCursorPosition是左上角位置是0,0然后向左向下延伸{COORD pos;pos.X=2*y;pos.Y=x;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);}void color(int a)//颜色函数{SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),a);} void Refresh(int q[][22], int grade, int gamespeed, int length,int score) // 输出贪吃蛇棋盘{ int i,j; for(i=0;i<22;i++) { for(j=0;j<22;j++) { if(q[i][j]==0)//输出棋盘空白 { gotoxy(i,j); color(11); cout<<"■"; } if(q[i][j]==1||q[i][j]==2)//输出棋盘墙壁 { gotoxy(i,j); color(11); cout<<"□"; } if(q[i][j]==3)//输出蛇头 { gotoxy(i,j); color(14); cout<<"★"; } if(q[i][j]==4)//输出蛇身 { gotoxy(i,j); color(12); cout<<"◆"; } if(q[i][j]==5)//输出果子 { gotoxy(i,j); color(12); cout<<"●"; } } if(i==0) cout << "\t***********************"; if(i==1) cout << "\t等级为:" << grade;//显示等级 if(i==3) cout << "\t自动前进时间"; if(i==4) cout << "\t间隔为:" << gamespeed << "ms";//显示时间 if(i==6) cout << "\t历史最高分为:" << score << "分"; if(i==7) cout << "\t你现在得分为:" << (length+(grade-1)*8)*10 << "分"; if(i==8) cout << "\t**********************"; if(i==9) cout << "\t游戏说明:"; if(i==10) cout << "\t(1)用小键盘方向键控制"; if(i==11) cout << "\t蛇头运动方向;"; if(i==12) cout << "\t(2)蛇每吃一个果子蛇身"; if(i==13) cout << "\t增加一节;"; if(i==14) cout << "\t(3)蛇咬到自己或碰到墙"; if(i==15) cout << "\t壁游戏结束。"; if(i==18) cout << "\t**********************"; if(i==19) cout << "\tC/C++语言作业:"; if(i==20) cout << "\tzjlj,2015.03.16 "; }} int main(int argc, char *argv[]){ int tcsQipan[22][22]; // 贪吃蛇棋盘是一个二维数组(如22*22,包括墙壁) int i,j,score,directiontemp; FILE *fpini;//*fpini 信息文件 readini(&fpini, &score, argv);//读取ini文件的最高纪录 if (score<0)//最高成绩小于零设置为零,初建文件会是负数 score=0; while(1) { for(i=1;i<=20;i++) for(j=1;j<=20;j++) tcsQipan[i][j]=0; //贪吃蛇棋盘相应坐标标上中间空白部分的标志0 for(i=0;i<=21;i++) tcsQipan[0][i] = tcsQipan[21][i] = 1; //贪吃蛇棋盘相应坐标标上上下墙壁的标志1 for(i=1;i<=20;i++) tcsQipan[i][0] = tcsQipan[i][21] = 2; //贪吃蛇棋盘相应坐标标上左右墙壁的标志2 int tcsZuobiao[2][500]; //蛇的坐标数组 for(i=0; i<4; i++) { tcsZuobiao[0][i] = 1;//蛇身和蛇头的x坐标 tcsZuobiao[1][i] = i + 1;//蛇身和蛇头的y坐标 } int head = 3,tail = 0;//标示蛇头和蛇尾的数组偏移量 for(i=1;i<=3;i++) tcsQipan[1][i]=4; //蛇身 tcsQipan[1][4]=3; //蛇头 int x1, y1; // 随机出果子 srand(time(0));//设置随机种子 do { x1=rand()%20+1; y1=rand()%20+1; } while(tcsQipan[x1][y1]!=0);//如果不是在空白处重新出果子 tcsQipan[x1][y1]=5;//贪吃蛇棋盘相应坐标标上果子的标志5 color(12); cout<<"\n\n\t\t\t\t贪吃蛇游戏即将开始 !"<=0;i--) { start=clock(); while(clock()-start<=1000); system("cls"); if(i>0) cout << "\n\n\t\t\t\t进入倒计时:" << i << endl; //倒计时显示 else Refresh(tcsQipan,grade,gamespeed,length,score); //初始棋盘显示 } int timeover=1,otherkey=1;//初始化超时时间和按键判断参数 char direction = 77; // 设置初始情况下,向右运动 int x=tcsZuobiao[0][head],y=tcsZuobiao[1][head];//保存蛇头坐标到x,y变量 while(1)//运行一局游戏 { start = clock(); while((timeover=((starttemp=clock())-start<=gamespeed))&&!kbhit());//如果有键按下或时间超过自动前进时间间隔则终止循环 if(direction==72||direction==80||direction==75 ||direction==77) directiontemp=direction;//保留上一次方向按键 //starttemp=gamespeed+start-starttemp;//保留停留时间 if(timeover) { #if (DEBUG==1) direction = getch();//调试代码 #else if((direction =getch())==-32) direction = getch(); #endif } #if (DEBUG==1)//调试代码 start=clock(); while(clock()-start<=2000); gotoxy(24,4); cout << "\t按键ASCII代码"<<(int)direction<<" "<=(length+(grade-1)*8)*10)//判断是否破记录 { gotoxy(10,7); color(12); cout << "闯关失败 加油耶!" << endl; fclose(fpini);//关闭ini文件 } else { gotoxy(10,7); color(12); cout << "恭喜您打破记录" << endl; score=(length+(grade-1)*8)*10; writeini(&fpini, &score, argv);//写入ini文件的最高纪录 } gotoxy(23,12); cout << "按回车键重新开始,按ESC退出游戏" << endl;//显示的提示 break;//退出该局游戏 } if(tcsQipan[x][y]!=0&&!(x==x1&&y==y1)&&tcsQipan[x][y]!=3) // 蛇头碰到蛇身,结束本局游戏 { gotoxy(22,12); cout << "\t游戏已结束!" << endl; if(score>=(length+(grade-1)*8)*10)//判断是否破记录 { gotoxy(10,7); color(12); cout << "闯关失败 加油耶!" << endl; fclose(fpini);//关闭ini文件 } else { gotoxy(10,7); color(12); cout << "恭喜您打破记录" << endl; score=(length+(grade-1)*8)*10; writeini(&fpini, &score, argv);//写入ini文件的最高纪录 } gotoxy(23,12); cout << "按回车键重新开始,按ESC退出游戏" << endl;//显示的提示 break;//退出该局游戏 } /* 游戏运行时的核心算法开始 */ if(x==x1 && y==y1) // 吃果子,长度加1 { length ++; if(length>=8)//长度大于等于8重新计算长度,等级加1 { length -= 8;//重新计算长度 grade ++;//等级加1 if(gamespeed>50)//控制最快速度为50 gamespeed = 550 - grade * 50; // 改变自动前进时间间隔 } tcsQipan[x][y]= 3;//贪吃蛇棋盘相应坐标现在蛇头标志改为蛇头标志3 tcsQipan[tcsZuobiao[0][head]][tcsZuobiao[1][head]] = 4;//贪吃蛇棋盘相应坐标原来蛇头标志改为蛇身标志4 head = (head+1)%400;//防止数组越界 tcsZuobiao[0][head] = x;//蛇头的x坐标 tcsZuobiao[1][head] = y;//蛇头的y坐标 do//随机出果子 { x1=rand()%20+1; y1=rand()%20+1; } while(tcsQipan[x1][y1]!=0);//如果不是在空白处重新出果子 tcsQipan[x1][y1]=5;//贪吃蛇棋盘相应坐标标上果子的标志5 gotoxy(22,12); cout << "\t游戏进行中!" << endl; Refresh(tcsQipan,grade,gamespeed,length,score); } else // 不吃果子 { if(otherkey) { tcsQipan [tcsZuobiao[0][tail]][tcsZuobiao[1][tail]]=0; tail=(tail+1)%400;//防止数组越界 tcsQipan [tcsZuobiao[0][head]][tcsZuobiao[1][head]]=4; head=(head+1)%400;//防止数组越界 tcsZuobiao[0][head]=x;//蛇头的x坐标 tcsZuobiao[1][head]=y;//蛇头的y坐标 tcsQipan[tcsZuobiao[0][head]][tcsZuobiao[1][head]]=3; gotoxy(22,12); cout << "\t游戏进行中!" << endl; Refresh(tcsQipan,grade,gamespeed,length,score); } else { gotoxy(22,12); cout << "\t游戏暂停中!" << endl; } } /* 游戏运行时的核心算法结束 */ } while(1) { while(!kbhit()); if((direction =getch())==13)//按回车键开始下一局 break; if(direction ==27)//按ESC退出游戏 exit(0); } system("cls");//清除屏幕重新开始 } return 0;}