|
|
楼主 |
发表于 2020-6-26 21:37:29
来自手机
|
显示全部楼层
本帖最后由 jhanker 于 2026-10-23 06:54 编辑
C++语言贪吃蛇源代码
没有版权问题欢迎随时修改,适合初学者
下面是源代码及下载链接
- /*
- C++贪吃蛇游戏,zjlj,2015.3.16
- */
- #define DEBUG 0 //当程序在调试阶段时 DEBUG为 1
- #include<iostream>
- #include<windows.h>
- #include<time.h>
- #include<conio.h>
- using 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贪吃蛇游戏即将开始 !"<<endl;//准备开始
- long start,starttemp;
- int grade = 1, length = 4; //设置初始等级和蛇的初始长度
- int gamespeed = 500; //设置初始前进时间间隔
- for(i=3;i>=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<<" "<<endl;
- #endif
- if(!(direction==72||direction==80||direction==75 ||direction==77))
- {
- otherkey=0;// 按键非方向键,otherkey设置为0
- }
- else
- {
- otherkey=1;// 按键为方向键,otherkey设置为1
- }
- if(direction==72 && directiontemp==80)//忽略反方向按键
- {
- direction=32;
- otherkey=0;
- //start = clock();
- //while(clock()-start<=starttemp);
- }
- else if(direction==80 && directiontemp==72)
- {
- direction=32;//设置按键为非方向键
- otherkey=0;// 按键为非方向键,otherkey设置为0
- // start = clock();
- //while(clock()-start<=starttemp);//补偿等待时间
- }
- else if(direction==75 && directiontemp==77)
- {
- direction=32;
- otherkey=0;
- //start = clock();
- //while(clock()-start<=starttemp);
- }
- else if(direction==77 && directiontemp==75)
- {
- direction=32;
- otherkey=0;
- //start = clock();
- //while(clock()-start<=starttemp);
- }
-
-
- switch(direction)//判断方向键
- {
- case 72: x= tcsZuobiao[0][head]-1; y= tcsZuobiao[1][head];break; // 向上
- case 80: x= tcsZuobiao[0][head]+1; y= tcsZuobiao[1][head];break; // 向下
- case 75: x= tcsZuobiao[0][head]; y= tcsZuobiao[1][head]-1;break; // 向左
- case 77: x= tcsZuobiao[0][head]; y= tcsZuobiao[1][head]+1;break; // 向右
- default: break;
- }
-
-
- if(x==0 || x==21 ||y==0 || y==21) // 蛇头碰到墙壁,结束本局游戏
- {
- 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(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;
- }
复制代码
下载链接
|
-
运行效果图
|