C++实习

来源:互联网 发布:中国荒漠化 知乎 编辑:程序博客网 时间:2024/06/05 20:01
C++暑假实习的前三天的任务就是用C语言做一个贪吃蛇的小游戏,然后开始跟着老师一起做核心功能板块,最后由我们自己去改善和美化我们的程序。下面就介绍一下这个简单的贪吃蛇游戏的实现过程。虽然是个小程序,但是其代码也有一定长度,并且其逻辑性很强,要实现程序的逻辑,必须要模块化地进行编写。以下叙述一下鄙人的思想

1、如何产生一条蛇?

首先用一个符号来作为我们的蛇身,并确定我们蛇的起始位置,规定我们蛇的起始长度,即可,蛇的身体可以用一个数组来存储,而蛇的初始位置可由我们的系统函数确定:

HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);        SetConsoleCursorPosition(hOut,temp);

2、蛇如何进行运动?

蛇的移动即是我们数组的移动,而根据蛇的运动规律,点的移动新坐标即是前面一个点的旧坐标,因此,点的移动很简单。

3、运动的方向我们如何去控制?

方向的控制和我们蛇的移动息息相关,我们通过得到键盘的输入来控制相应的蛇的移动方向,这里用到了一个按键响应函数:

kbhit();

4、运动的范围该如何设置?

所谓运动的范围,不过是我们给蛇画的一个牢笼,任意在屏幕上用光标设置函数即可确定,就像打印蛇身一样来打印我们的地图。

5、蛇要吃的食物如何产生?

蛇的食物肯定是由随机数产生,然后我们要控制这个随机数在我们画的地图里面产生。

6、蛇如何吃食物?以及设置吃食物后的效果?

吃食物,即是蛇头和食物的坐标一致,然后食物的位置由蛇身代替,我们将蛇走过的轨迹置空,即可屏蔽蛇身的路径。然后当蛇头与食物相遇,我们即可将蛇的长度加1或其他效果

7、蛇要死亡,怎么个死法?

蛇的死法千种万种,可以吃毒食物而死,可以撞到我们的地图框而死,也可以吃到自己而死………………………….

如果能把上面的思路理清,那么写一个贪吃蛇的小游戏也就不难了,下面是我的具体实现代码:

// myproject.cpp : Defines the entry point for the console application.//#include <stdio.h>#include <stdlib.h>#include <windows.h>#include <conio.h >#include <time.h>#define InitLEN   10  //蛇初始长度#define MAXLEN 100  //蛇最大长度#define HIGH 20   //地图高#define WIDTH  40  //地图宽int SnakeLEN=0;   //蛇的长度int score=0;       //得分int barrier_num =0;  //所有障碍物组成点的个数int half;       //#define HPRIZON       1//#define VERTICAL  2COORD arr[MAXLEN];COORD tmp_arr[50];COORD food_pos;COORD map_pos;COORD tmp_wall;COORD tmp_barrier;#define RIGHT 39#define LEFT  37#define UP    38#define DOWN  40HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);  //坐标void clearSnake();  //蛇路径清除函数void showSnake();   //蛇的显示函数void creatFood();   //产生食物void creatMap();    //产生地图void die();         //蛇的死亡方式void barrier_save();  void creatBarrier(COORD pos,int dir,int len);  //void crossWall();struct wall{    int dir;    int len;    COORD bPos;};struct wall wall_arr[50];void draw_frame(int W,int H,int initX,int initY)   //顺时针画框函数W、H为长度高度;initX ,initY为其实坐标 {    COORD pos1={initX,initY};    int i;    for(i= 0; i< W;i++)    {        pos1.X++;        SetConsoleCursorPosition(hOut,pos1);        printf(".");    }    for(i= 0; i< H;i++)    {        pos1.Y++;        SetConsoleCursorPosition(hOut,pos1);        printf(".");    }    for(i= 0; i< W;i++)    {        pos1.X--;        SetConsoleCursorPosition(hOut,pos1);        printf(".");    }    for(i= 0; i< H;i++)    {        pos1.Y--;        SetConsoleCursorPosition(hOut,pos1);        printf(".");    }}void InitSnake(COORD SnakeHead){    int i;    COORD temp = SnakeHead;    for( i=0 ; i< InitLEN ; i++ )    {           arr[i]=temp;        HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);        SetConsoleCursorPosition(hOut,temp);  //API中定位光标位置的函数        printf("@");        temp.X--;    }    SnakeLEN = InitLEN;}void move(int dir){    int i;    Sleep(100);    clearSnake();    //将蛇头状态给蛇身    for( i=0;i<SnakeLEN-1;i++)    {        arr[SnakeLEN-1-i] = arr[SnakeLEN-2-i];    }    switch(dir){    case RIGHT:        {            arr[0].X++;   //蛇头运动            break;          }    case LEFT:        {            arr[0].X--;            break;          }    case UP:        {            arr[0].Y--;            break;          }    case DOWN:        {            arr[0].Y++;            break;          }    default:        break;    }    die();    if(food_pos.X == arr[0].X && food_pos.Y == arr[0].Y )    //头的坐标和食物坐标相同(吃食物变长)    {        creatFood();        SnakeLEN++;        COORD pos2={WIDTH+12,2};   //写计分位置的初始坐标,因为之前方框的起始坐标为(10,1),所以这里都加1。        SetConsoleCursorPosition(hOut,pos2);        score++;        printf("%d",score);        printf(" ");        //打印空白用于覆盖上一次计分    }void showSnake(){       int i;    for( i=0; i < SnakeLEN;i++)    {        SetConsoleCursorPosition(hOut,arr[i]);        if(i == 0)        {            printf("@");        }        else        {            printf("*");        }    }}void clearSnake()   {       int i;    for( i=0; i < SnakeLEN;i++)    {        SetConsoleCursorPosition(hOut,arr[i]);        printf(" ");    }}void barrier_save()      //保存所有生成的障碍物的点(所有障碍物由点组成){    tmp_arr[barrier_num]=tmp_barrier;    barrier_num++;           //全局变量}void creatBarrier(COORD pos,int dir,int len){    int i =0;    tmp_barrier=pos;    for(;i < len; i++)    {        static int j=0;        SetConsoleCursorPosition(hOut,tmp_barrier);        printf("+");        if(dir == 1 )        {            tmp_barrier.X++;            barrier_save();    //每次改变都会获得一个新的点,需要把这个点记录下来。        }        else         {            tmp_barrier.Y++;            barrier_save();        }        barrier_save();    }}void kbctrl(){       char ch = 'd';    int dir=RIGHT;    while(1)    {           if(kbhit())      //加入键盘控制,判断是否有按键        {            ch=getch();        }        switch(ch)      //判断是否是 'a' 's'        {            case 'd':                      {                   dir = RIGHT;                move(dir);                break;            }            case 's':            {                dir = DOWN;                move(dir);                break;            }            case 'a':            {                dir = LEFT;                move(dir);                break;            }            case 'w':            {                   dir = UP;                move(dir);                break;            }            default:            {                move(dir);                break;            }        }    }}void creatFood(){    srand((unsigned)time(NULL));    int x = (rand()%(WIDTH-1)+1);  //-1为了产生随机数小于WIDTH,+1为了使产生随机数大于0    int y = (rand()%(HIGH-1)+1);    food_pos.X =x;    food_pos.Y =y;    SetConsoleCursorPosition(hOut,food_pos);    printf("o");}void myexit(){    COORD exit_pos={WIDTH+2,HIGH+2};    SetConsoleCursorPosition(hOut,exit_pos);    printf("GAME OVER!");    exit(0);}//死亡的方式:void die(){    int i;    for(i = 1;i < SnakeLEN-1;i++ )   //吃到自己,就会死掉。    {        if(arr[0].X == arr[i].X && arr[0].Y == arr[i].Y)        {            myexit();           }    }    if(arr[0].X >= WIDTH || arr[0].X <= 0 || arr[0].Y >= HIGH || arr[0].Y <= 0 )   //撞墙就死掉    {        myexit();    }    for(i = 0;i < 50;i++ )   //撞到障碍物,死掉    {        if(arr[0].X == tmp_arr[i].X && arr[0].Y == tmp_arr[i].Y)        {            myexit();        }    }}/*计分板*/void score_frame(){    //计分方框    draw_frame(10,5,WIDTH+10,0);    COORD pos1={WIDTH+11,1};    SetConsoleCursorPosition(hOut,pos1);    printf("得分:");    //计分    COORD pos2={WIDTH+12,2};   //写计分位置的初始坐标,因为之前方框的起始坐标为(10,1),所以这里都加1。    SetConsoleCursorPosition(hOut,pos2);    printf("%d",score);}int main(int argc, char* argv[]){    system("title 贪吃蛇");    COORD pos={5,3};    crossWall();    draw_frame(WIDTH,HIGH,0,0);    score_frame();    InitSnake(pos);    creatFood();/*      while(1)    {        move(RIGHT);        if(kbhit())        {            ch=getch();            break;        }       }*/      kbctrl();    printf("\n");    return 0;}/////////////////*穿墙超级蛇*/void crossWall(){    srand((unsigned)time(NULL));    int i =0;    for ( ; i < 5 ; i++)    {        tmp_wall.X=(rand()%(WIDTH-3)+3);        tmp_wall.Y=(rand()%(HIGH-3)+3);    //  tmp_arr[i] = tmp_wall;        half = (rand()%2+1);   //随机获得 1 或者 2 ,两者概率都为二分之一        creatBarrier(tmp_wall,half,3);    }}

代码还存在很多缺陷,需要大家一起晚上以及发散思维添加功能。