小项目-贪吃蛇


老师布置的寒假作业:写个贪吃蛇 

以前没写过 所以写的超级长,不过好歹写完了。错误数据的判断和明显的bug还没有做。放出来先做个纪念。

注解非常非常非常非常详细

#include
#include
#include//代码的x代表行,y代表列 如果按照笛卡尔坐标系的话这里的x,y是反过来的 
#include<string.h>
#include
#include
#include
#define MAXNX 20//地图高 
#define MAXNY 70//地图宽
int a[MAXNX][MAXNY];//1是蛇身体用@表示 2是墙壁用*表示  0是空地用一个空格表示 -1是食物用&表示 
void menu_1();//打印主页面
void shuaxin(); //刷新屏幕 
void x_1();//开始游戏 
void x_2();//查看排行榜 
void x_3();//清空排行榜 
void x_4();//游戏设置 
void drt();//设置方向
void move();//移动 
void draw();//画食物 
void rank();//读入排行榜 
void n_rank();//写入排行榜 
int drt1=1,drt_x[MAXNX],drt_y[MAXNY],tail=3;//drt1默认方向向右 1右 2下 3左 4上 ;drt_x,drt_y是蛇身体,tail是蛇长度 
int fx,fy;//食物的x,y坐标 
int flag;//撞墙判断 =1时撞墙 
int score;//得分 1个10分 
int rank1[11];//排行榜 
int stop;//暂停游戏 用于设置、查看排行榜等界面 
unsigned long times;//刷新时间 ms 
FILE *fp;
int main(){
    fp=fopen("排行榜.text","r");
    if(fp==NULL){
        fp=fopen("排行榜.text","w+");
        fprintf(fp,"游戏得分排行榜\n");
        for(int i=1;i<=10;i++) fprintf(fp,"%d 0\n",i);
        fclose(fp);
        fp=fopen("游戏设置.text","w+");
        fprintf(fp,"游戏刷新率:50");
        fclose(fp);
    }
    else fclose(fp);
    menu_1();
    return 0;
}
void menu_1(){
    fp=fopen("游戏设置.text","r+");//初始化游戏刷新率
    fscanf(fp,"游戏刷新率:%d",&times);
    fclose(fp);
    system("cls");//清空屏幕 
    int tem_menu_1;
    printf(" _______________________________________________________________________\n");
    printf("|                                                                       |\n");
    printf("|");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
    printf("               欢迎游玩贪吃蛇,祝你有个愉快而有趣的体验                ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
    printf("|\n");
    printf("|");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
    printf("            Welcome to visit Game, and wish you a pleasant             ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
    printf("|\n");
    printf("|");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
    printf("                    and interesting experience.                        ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
    printf("|\n");
    printf("|                                                                       |\n");
    printf("|                         WSAD 控制方向                                 |\n");
    printf("|                      输入相应的数字进行操作                           |\n");
    printf("|                                                                       |\n");
    printf("|         ● 1 开始游戏            ● 2 查看排行榜                      |\n");
    printf("|                                                                       |\n");
    printf("|                                                                       |\n");
    printf("|         ● 3 清除排行榜          ● 4 游戏刷新率设置                  |\n");
    printf("|                                                                       |\n");
    printf("|                        ●  0 退出游戏                                 |\n");
    printf("|_______________________________________________________________________|\n");
    fflush(stdin);//清空输入缓冲区
    scanf("%d",&tem_menu_1);
    switch(tem_menu_1){
        case 1:
            stop=1;
            x_1();
            
            break;
        case 2:
            x_2();
            break;
        case 3:
            x_3();
            break;
        case 4:
            x_4();
            break;
        case 0:
            system("cls");//清空屏幕 
            printf("游戏结束,感谢游玩。");
            exit(0);
            break;
        default:
            fflush(stdin);//清空输入缓冲区 
            system("cls");//清空屏幕 
            printf("输入错误,请重新输入。\n");
            menu_1();
            break;
    }
    
}
void x_1(){//开始游戏 
    score=0;rank(); //分数初始化,排行榜初始化 
    for(int i=0;i//初始化地图 
        for(int j=0;j0;
    }
    memset(drt_x,-1,sizeof(drt_x));memset(drt_y,-1,sizeof(drt_y));//初始化蛇身体
    drt_x[0]=MAXNX-2;drt_x[1]=MAXNX-2;drt_x[2]=MAXNX-2;
    drt_y[0]=3;drt_y[1]=2;drt_y[2]=1;tail=3; 
    a[MAXNX-2][1]=1;a[MAXNX-2][2]=1;a[MAXNX-2][3]=1;//创建蛇身体 
    draw();//初始化食物位置; 
    drt1=1;//初始化方向 
    //初始化墙壁 开始 
    for(int i=0;i0][i]=2;
    for(int i=0;i1][i]=2;
    for(int i=0;i0]=2;
    for(int i=0;i1]=2;
    //初始化墙壁 结束 
    
    while(stop){
        if(_kbhit()){//如果按了按键 
            drt();
        }
        move();
        shuaxin();//打印地图 
        Sleep(times);
    }
}
void x_2(){//查看排行榜 
    system("cls");//清空屏幕 
    fflush(stdin);//清空输入缓冲区 
    printf("========排行榜========\n");
    for(int i=1;i<=10;i++) printf("====第%d名:%d====\n",i,rank1[i]);
    printf("3秒后返回主菜单");
    Sleep(3000);menu_1();
}
void x_3(){//清空排行榜 
    system("cls");//清空屏幕 
    fflush(stdin);//清空输入缓冲区 
    fp=fopen("排行榜.text","r+");
    fprintf(fp,"游戏得分排行榜\n");
    for(int i=1;i<=10;i++) fprintf(fp,"%d 0\n",i);
    fclose(fp);
    rank();
    printf("清空成功!\n");
    printf("3秒后返回主菜单");
    Sleep(3000);menu_1();
}
void x_4(){//游戏设置 
    FILE *fp_x_4;
    system("cls");//清空屏幕 
    fflush(stdin);//清空输入缓冲区 
    fp_x_4=fopen("游戏设置.text","r+");
    printf("目前的刷新速度:%d\n请输入需要的刷新速度(整数ms):\n",times);
    scanf("%d",&times);
    fprintf(fp_x_4,"游戏刷新率:%d",times);
    fclose(fp_x_4);
    printf("设置成功!3秒后返回主菜单");
    Sleep(3000);menu_1();
}
void shuaxin(){
    system("cls");//清空屏幕 
    if(flag==1){//撞到之后 
        printf("游戏结束!你的得分是:%d。3秒后返回主菜单。",score);flag=0;stop=0;
        n_rank();rank();
        Sleep(3000);menu_1();
    }
    else{
        for(int i=0;i//打印地图 
            for(int j=0;j){
                if(a[i][j]==2){
                    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
                    printf("*");
                    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
                }
                else if(a[i][j]==1){
                    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
                    printf("@");
                    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
                }
                else if(a[i][j]==-1){
                    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
                    printf("&"); 
                    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
                }
                else printf(" ");
            }
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
            switch(i){
                case 0://得分 
                    printf("-------得分-------:%d",score);
                    break;
                case 1://排行榜 
                    printf(" --排行榜-- ");break;
                case 2:printf("|  第1-%d  |",rank1[1]);break;
                case 3:printf("|  第2-%d  |",rank1[2]);break;
                case 4:printf("|  第3-%d  |",rank1[3]);break;
                case 5:printf("|  第4-%d  |",rank1[4]);break;
                case 6:printf("|  第5-%d  |",rank1[5]);break;
                case 7:printf("|  第6-%d  |",rank1[6]);break;
                case 8:printf("|  第7-%d  |",rank1[7]);break;
                case 9:printf("|  第8-%d  |",rank1[8]);break;
                case 10:printf("|  第9-%d  |",rank1[9]);break;
                case 11:printf("|  第10-%d |",rank1[10]);break;
                case 12:printf("============",rank1[10]);break;
            }
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
            printf("\n");
        }
        
    }
    
}
void drt(){
    switch(_getch()){//改变方向 
        case 'd':case 'D':
        if(drt1!=3)drt1=1;break;
        case 's':case 'S':
        if(drt1!=4)drt1=2;break;
        case 'a':case 'A':
        if(drt1!=1)drt1=3;break;
        case 'w':case 'W':
        if(drt1!=2)drt1=4;break;
    }
}
void move(){
    int tem_fx=fx,tem_fy=fy;//用于在吃掉食物后食物刷新前食物的位置,判断头可以出现在该位置 
    if(drt_x[0]!=fx || drt_y[0]!=fy){
        a[drt_x[tail-1]][drt_y[tail-1]]=0;//蛇尾巴标记为 0 
    }
    
    else{
        tail++;score+=10;
        a[fx][fy]=1;//这里设置是为了防止画的食物和身体(也就是头)重合 
        draw();
    }
    for(int i=tail-1;i>0;i--){//蛇身体坐标集体移动一格 
        drt_x[i]=drt_x[i-1];
        drt_y[i]=drt_y[i-1];
        
    }
    switch(drt1){//蛇头位移方向 
        case 1: 
        if(a[drt_x[0]][drt_y[0]+1]==0 || drt_y[0]+1==tem_fy){
            drt_y[0]+=1;a[drt_x[0]][drt_y[0]]=1;
        }
        else flag=1;//移动的地方不是空地或者食物 
        break;
        case 2:
        if(a[drt_x[0]+1][drt_y[0]]==0 || drt_x[0]+1==tem_fx){
            drt_x[0]+=1;a[drt_x[0]][drt_y[0]]=1;
        }
        else flag=1;
        break;
        case 3:if(a[drt_x[0]][drt_y[0]-1]==0 || drt_y[0]-1==tem_fy){
            drt_y[0]-=1;a[drt_x[0]][drt_y[0]]=1;
        }
        else flag=1;
        break;
        case 4:if(a[drt_x[0]-1][drt_y[0]]==0 || drt_x[0]-1==tem_fx){
            drt_x[0]-=1;a[drt_x[0]][drt_y[0]]=1;
        }
        else flag=1;
        break;
    }
    
    
}
void draw(){
    while(fx<=0 || fy<=0 || fx>=MAXNX-1 || fy>=MAXNY-1 || a[fx][fy]!=0){
        srand(time(NULL));
        fx=rand()%MAXNX;
        fy=rand()%MAXNY;
    }
    a[fx][fy]=-1;
}
void rank(){
    int tem;char s[1000];
    FILE *fp_rank;
    fp_rank=fopen("排行榜.text","r+");
    fscanf(fp_rank,"%s",s);
    for(int i=1;i<=10;i++) fscanf(fp_rank,"%d %d",&tem,&rank1[i]);
    fclose(fp_rank);
} 
void n_rank(){
    FILE *fp_n_rank;
    if(score>rank1[10]){
        int i;
        for(i=10;i>0 &&rank1[i]);
        if(i==0){
            for(int j=10;j>=2;j--) rank1[j]=rank1[j-1];
            rank1[1]=score;
        }
        else{
            for(int j=10;j>i+1;j--) rank1[j]=rank1[j-1];
            score=rank1[i+1];
        }
        fp_n_rank=fopen("排行榜.text","w");
        fprintf(fp_n_rank,"游戏得分排行榜\n");
        for(int i=1;i<=10;i++) fprintf(fp_n_rank,"%d %d\n",i,rank1[i]);
        fclose(fp_n_rank);
    }
    
}