• C 简易贪吃蛇的编写


      不多废话,直接进入正题——用C编写简易贪吃蛇。附上拙劣的源码 * c-snake *

      首先说明使画面动起来的原理:通过 system("cls"); 清除当前控制台的显示,再printf下一步画面进行显示,以此循环形成动画效果(类似手翻书)。因为这是在控制台,难免会有晃眼的感觉,并且不存在美工一说,所以就将就下吧。

      有了使画面动起来的方法,接下来就是贪吃蛇游戏本体的制作思路了,可将游戏本体分解为以下3个部分:

    1、边界,即墙:圈定一个范围,蛇只能在墙内移动,食物只能生成在墙内

    2、蛇:游戏主角,可视为2部分组成——蛇头和蛇身。蛇头引导了蛇身前行的方向,也用于判定蛇是否吃到食物

    3、食物:蛇的猎物,被蛇吃掉后会触发2个事件——蛇身加长、重新生成一个食物

      将本体分解完后,就是解析游戏方式:蛇会自动向蛇头朝向进行移动,玩家需要控制蛇头的方向进行移动,抛却理论不说(理论上可以将蛇身占满整个边界内部),游戏结束的情况有2种:撞墙和撞身

      用人话将贪吃蛇游戏理了一遍,接下来就是将人话变成真正的设计思路:

    1、边界的描述:可看作一个二维数组,四周为墙,用“*”表示;内部为空,用“ ”表示

    2、蛇的描述:由蛇头和蛇身组成,而蛇头可看作蛇身的特殊部分,因此实际并无蛇头一说,仅仅是表示方式不同罢了(蛇头用“@”表示,蛇身用“#”表示),从而将蛇头和蛇身的描述问题转为了蛇身的描述。而蛇身应当如何描述?蛇身由一个又一个的、连续的点组成,因此,该问题实质便是如何去描述一个点。在二维坐标中,点便是用x和y描述,所以蛇的每个蛇身(点)都需要储存x和y这2个”标识符”,同时又需要储存多个xy对,显而易见,依旧是用一个二维数组去描述蛇

    3、食物的描述:食物本质上依旧是一个点,但和蛇身不同,食物有且仅有1个,所以用一个一维数组即可描述食物

    4、蛇的移动:什么是移动?移动即为位置的改变,所以在确定了方向后,我们要做的仅仅是将蛇头向该方向移动后,后面的蛇身依次覆盖前一个蛇身/头,即拷贝前一个蛇身所储存的xy坐标。当吃到食物时,应当将长度+1

    5、蛇的移动方向控制:那么如何控制蛇头所指向的方向呢?虽然方向是蛇头的属性之一,但可将其从蛇中分离出去,定义一个单独的变量去描述方向。当有键盘敲击输入事件发生时,获取输入值并判断输入值与方向的关系,更新方向即可

    6、食物的消失与生成:当蛇头与食物的坐标相同时,食物应当消失(被吃),消失后应当生成一个新的食物,而生成食物的x和y应为随机数,且需在墙内,不能生成在蛇上

    7、游戏的结束:判断蛇头的位置即可(撞墙:当蛇头的位置处于墙上时;撞身:当蛇头的位置处于蛇身上时)

      

      有了思路,代码其实就自然而然的写出来了:

        定义部分:

     1 /*
     2     若内部场地大小为x*y:
     3     墙定义为char wall[y+2][x+2],+2是因为2边的边界
     4     蛇定义为int snake[x*y][3],snake[i][0]表示x坐标,snake[i][1]表示y坐标,snake[i][2]表示该蛇身是否存在。当然亦可定义为snake[x*y][2],初始化为0,判断x和y值是否为0去确定该蛇身是否存在
     5     食物定义为int food[3],food[0]表示x坐标,food[1]表示y坐标,food[2]表示食物是否已经存在
     6     移动的方向定义为int direction,1/2/3/4分别对应4个方向
     7 */
     8 
     9 char wall[22][42];
    10 int snake[800][3];
    11 int food[3];
    12 int direction = 2;    //方向:1-上 2-右 3-下 4-左
    define

     

        功能模块部分:

     1 //初始化围墙属性
     2 void init_wall()
     3 {
     4     extern char wall[22][42];
     5     int i,j;
     6     for(i = 0; i < 22; i++)
     7     {
     8         for(j = 0; j < 42; j++)
     9         {
    10             if(i == 0 || i == 21)
    11                 wall[i][j] = '*';
    12             else if(j == 0 || j == 41)
    13                 wall[i][j] = '*';
    14             else
    15                 wall[i][j] = ' ';
    16         }
    17     }
    18 }
    init_wall
     1 //初始化蛇属性
     2 void init_snake()
     3 {
     4     /*    
     5         snake[i][0]为x坐标
     6         snake[i][1]为y坐标
     7         snake[i][2]值为1或0 1表示存在 0表示不存在
     8     */
     9     extern int snake[800][3];
    10     snake[0][0] = 11;
    11     snake[0][1] = 11;
    12     snake[0][2] = 1;
    13     snake[1][0] = 10;
    14     snake[1][1] = 11;
    15     snake[1][2] = 1;
    16     snake[2][0] = 9;
    17     snake[2][1] = 11;
    18     snake[2][2] = 1;
    19 }
    init_snake
     1 //初始化食物属性
     2 void init_food()
     3 {
     4     /*
     5         food[0]为x坐标
     6         food[1]为y坐标
     7         food[2]值为1或0 1表示不存在 0表示存在
     8     */
     9     extern int food[3];
    10     extern int snake[800][3];
    11     
    12     int x,y;
    13     int flag = 1;    //是否在蛇身的标志 1表示在 0表示不在
    14     food[2] = 0;    //生成食物 置0
    15     
    16     while(flag)
    17     {
    18         srand(time(0));
    19         x = rand()%40+1;
    20         y = rand()%20+1;
    21         int i;
    22         for(i = 0; i < 800; i++)
    23         {
    24             if(snake[i][2])
    25             {
    26                 if(snake[i][0] == x && snake[i][1] == y)
    27                     break;
    28             }
    29             else
    30                 flag = 0;
    31         }
    32     }
    33     food[0] = x;
    34     food[1] = y;
    35 }
    init_food
     1 //在墙中生成蛇和食物
     2 void change()
     3 {
     4     extern char wall[22][42];
     5     extern int snake[800][3];
     6     extern int food[3];
     7     int i;
     8     
     9     if(food[2])
    10     {
    11         init_food();
    12     }
    13     
    14     wall[food[1]][food[0]] = 'O';    //食物
    15     
    16     for(i = 0; i < 800; i++)
    17     {
    18         if(snake[i][2])
    19         {
    20             int x = snake[i][0];
    21             int y = snake[i][1];
    22             if(i == 0)
    23                 wall[y][x] = '@';    //蛇头
    24             else
    25                 wall[y][x] = '#';    //蛇身
    26         }
    27     }
    28 }
    change
     1 //判断是否吃到食物
     2 int ifEat()
     3 {
     4     extern int snake[800][3];
     5     extern int food[3];
     6     extern int score;
     7     
     8     if(snake[0][0] == food[0] && snake[0][1] == food[1])
     9     {
    10         food[2] = 1;
    11         return 1;    //吃到返回1
    12     }
    13     return 0;        //没吃到返回0
    14 }
    ifEat
     1 //判断是否撞墙或自身
     2 int ifBreak()
     3 {
     4     extern int snake[800][3];
     5     int i;
     6     
     7     if(snake[0][0] == 0 || snake[0][0] == 41 || snake[0][1] == 0 || snake[0][1] == 21)
     8         return 1;
     9     for(i = 1; i < 800; i++)
    10     {
    11         if(snake[0][0] == snake[i][0] && snake[0][1] == snake[i][1])
    12             return 1;
    13     }
    14     return 0;
    15 }
    ifBreak
     1 //获取输入的方向
     2 void getKey()
     3 {
     4     char ch;
     5     if(_kbhit())
     6     {
     7         ch = _getch();
     8     }
     9     switch(ch)
    10     {
    11         case 'w':
    12         case 'W':
    13             if(direction != 3)
    14                 direction = 1;
    15             break;
    16         case 'd':
    17         case 'D':
    18             if(direction != 4)
    19                 direction = 2;
    20             break;
    21         case 's':
    22         case 'S':
    23             if(direction != 1)
    24                 direction = 3;
    25             break;
    26         case 'a':
    27         case 'A':
    28             if(direction != 2)
    29                 direction = 4;
    30             break;
    31         default:
    32             break;
    33     }
    34 }
    getKey
     1 //移动
     2 void move()
     3 {
     4     extern int direction;
     5     extern int snake[800][3];
     6     extern int score;
     7     int i = score - 1;
     8     int x,y;
     9     
    10     switch(direction)
    11     {
    12         case 1:
    13             x = 0;
    14             y = -1;
    15             break;
    16         case 2:
    17             x = 1;
    18             y = 0;
    19             break;
    20         case 3:
    21             x = 0;
    22             y = 1;
    23             break;
    24         case 4:
    25             x = -1;
    26             y = 0;
    27             break;
    28         default:
    29             break;
    30     }
    31     
    32     if(ifEat())
    33     {
    34         snake[score][0] = snake[score-1][0];
    35         snake[score][1] = snake[score-1][1];
    36         snake[score][2] = 1;
    37         score++;
    38     }
    39     
    40     while(i > 0)
    41     {
    42         if(snake[i][2] != 0)
    43         {
    44             snake[i][0] = snake[i-1][0];
    45             snake[i][1] = snake[i-1][1];
    46         }
    47         i--;
    48     }
    49     
    50     snake[0][0] += x;
    51     snake[0][1] += y;
    52 }
    move
     1 //打印
     2 void print_all()
     3 {
     4     extern char wall[22][42];
     5     int i,j;
     6     for(i = 0; i < 22; i++)
     7     {
     8         for(j = 0; j < 42; j++)
     9         {
    10             printf("%c", wall[i][j]);
    11         }
    12         printf("\n");
    13     }
    14 }
    print_all

        最后只需在main中按照顺序将各个模块进行调用即可

     1 void main()
     2 {
     3     extern char wall[22][42];
     4     extern int snake[800][3];
     5     extern int score;
     6     int speed = 400;
     7     int spot = 8;
     8     
     9     init_snake();
    10     init_food();
    11     
    12     while(1)
    13     {
    14         getKey();
    15         system("cls");
    16         init_wall();
    17         move();
    18         change();
    19         print_all(wall[22][42]);
    20         if(ifBreak())
    21             break;
    22         Sleep(speed);
    23         if(score == spot)
    24         {
    25             speed = 0.9*speed;
    26             spot += 5;
    27         }
    28     }
    29     printf("Game Over\n");
    30     printf("score:%d\n",score);
    31     system("pause");
    32 }
    main
  • 相关阅读:
    C#操作SQLite 报错 (Attempt to write a readonly database)
    JS判断字符输入个数(数字英文长度记为1,中文记为2,超过长度自动截取)
    JueryUI插件的简单应用(一):介绍及第一个示例
    在VS2008(Winform)中使用WebService
    Oracle触发器使用
    C# 创建Windows服务。服务功能:定时操作数据库
    aspnet前后台条件下根目录的读取
    xshell实现端口转发
    (转)使用FreeType实现矢量字体的粗体、斜体、描边、阴影效果
    D3D坐标系统和几何DirectX Griaphic学习
  • 原文地址:https://www.cnblogs.com/s1165482267/p/7798443.html
Copyright © 2020-2023  润新知