zoukankan      html  css  js  c++  java
  • C语言 —— 贪吃蛇

    参考视频:https://www.bilibili.com/video/av29580072/?p=1

    GreedySnake.h

     1 #ifndef GREEDYSNAKE_H_INCLUDED
     2 #define GREEDYSNAKE_H_INCLUDED
     3 
     4 
     5 #define SNAKE_LENGTH 20   //蛇的长度最大为20
     6 #define true  1
     7 #define false 0
     8 enum {UP = -1, DOWN = 1, LEFT = -2, RIGHT = 2};
     9 
    10 typedef int bool;
    11 
    12 void FirstPage();                   //设置起始游戏界面
    13 void TestSpace();                   //按空格开始游戏
    14 void ShowBackground();              //展示游戏背景
    15 void SetSnakeRandPos();             //为蛇产生一个随机的位置
    16 void DrawSnake();                   //画蛇
    17 void SnakeMove();                   //蛇动
    18 void DestroySnake();                //销毁蛇
    19 void ChangeDir();                   //蛇随着方向键动起来
    20 bool IsSnakeDie();                  //判断蛇是否死亡
    21 void ProduceFood();                 //随机位置产生食物
    22 void SnakeGrowUp();                 //蛇变长
    23 void PrintScore();                  //打印分数
    24 
    25 
    26 #endif // GREEDYSNAKE_H_INCLUDED

    GreedySnake.c

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <conio.h>
      5 #include <windows.h>
      6 #include <time.h>
      7 #include "GreedySnake.h"
      8 
      9 //把所有元素置为0
     10 //snake[0][0]表示蛇头的行,snake[0][1]表示蛇头的列,snake[0][2]表示蛇头移动的方向
     11 int g_arrSnake[SNAKE_LENGTH][3] = { 0 };
     12 
     13 int g_iSnakeLength = 2; //初始长度为3,但数组下标从0开始,故此处为2
     14 
     15 char g_arrBackGround[20][50] =
     16 {
     17     "████████████████████████
    ",    //一个█占两个字节,占两个字符的位置
     18     "█                                            █
    ",
     19     "█                                            █
    ",
     20     "█                                            █
    ",
     21     "█                                            █
    ",
     22     "█                                            █
    ",
     23     "█                                            █
    ",
     24     "█                                            █
    ",
     25     "█                                            █
    ",
     26     "█                                            █
    ",
     27     "█                                            █
    ",
     28     "█                                            █
    ",
     29     "█                                            █
    ",
     30     "█                                            █
    ",
     31     "█                                            █
    ",
     32     "█                                            █
    ",
     33     "█                                            █
    ",
     34     "█                                            █
    ",
     35     "█                                            █
    ",
     36     "████████████████████████
    "
     37 };
     38 
     39 int g_iSnakeDir = LEFT;     //蛇的方向,默认向左
     40 bool g_bIsProFood = true;         //蛇产生食物的标记
     41 int g_iRow;  //食物的行坐标
     42 int g_iCol;  //食物的列坐标
     43 
     44 int g_iScore = 0;   //分数
     45 
     46 
     47 
     48 void FirstPage()         //设置起始游戏界面
     49 {
     50     for (int i = 0; i < 20; ++i)
     51         printf(" ");
     52     for (int i = 0; i < 60; ++i)
     53         printf("*");
     54     printf("
    ");
     55 
     56     for (int j = 0; j < 5; ++j)
     57     {
     58         for (int i = 0; i < 20; ++i)
     59             printf(" ");
     60         printf("*");
     61         for (int i = 0; i < 58; ++i)
     62             printf(" ");
     63         printf("*
    ");
     64     }
     65 
     66     for (int i = 0; i < 20; ++i)
     67         printf(" ");
     68     printf("*");
     69     for (int i = 0; i < 15; ++i)
     70         printf(" ");
     71     printf("《 欢迎来到贪吃蛇的世界!》");
     72     for (int i = 0; i < 16; ++i)
     73         printf(" ");
     74     printf("*
    ");
     75 
     76     for (int i = 0; i < 20; ++i)
     77         printf(" ");
     78     printf("*");
     79     for (int i = 0; i < 15; ++i)
     80         printf(" ");
     81     printf("《  请按空格键开始游戏   》");
     82     for (int i = 0; i < 16; ++i)
     83         printf(" ");
     84     printf("*
    ");
     85 
     86     for (int j = 0; j < 10; ++j)
     87     {
     88         for (int i = 0; i < 20; ++i)
     89             printf(" ");
     90         printf("*");
     91         for (int i = 0; i < 58; ++i)
     92             printf(" ");
     93         printf("*
    ");
     94     }
     95 
     96     for (int i = 0; i < 20; ++i)
     97         printf(" ");
     98     for (int i = 0; i < 60; ++i)
     99         printf("*");
    100     for (int i = 0; i < 8; ++i)
    101         printf("
    ");
    102 }
    103 
    104 void TestSpace()     //按空格开始游戏
    105 {
    106     char c;
    107     while ((c = getch()) != ' ')     //getch()在头文件<conio>内
    108     {
    109 
    110     }
    111     system("cls");                  //清屏
    112 }
    113 
    114 void ShowBackground()              //展示游戏背景
    115 {
    116     for (int i = 0; i < 20; ++i)
    117         printf(g_arrBackGround[i]);
    118 }
    119 
    120 void SetSnakeRandPos()    //设置蛇的初始位置,默认蛇的身子为三节,向左移动
    121 {
    122     int x, y;
    123     srand((unsigned)time(NULL));
    124     x = rand()% 20 + 1;         //因为蛇的身子起始为三节,所以x的范围为1-20(蛇不能起始就撞墙)
    125     y = rand()% 18 + 1;
    126 
    127     g_arrSnake[0][0] = y;      //行     注意:x,y和初始背景中的行列刚好是反的
    128     g_arrSnake[0][1] = x * 2;  //列     注意:一个█占两个字节,所以算其坐标时要乘以2
    129     g_arrSnake[0][2] = LEFT;   //方向
    130 
    131     g_arrSnake[1][0] = y;
    132     g_arrSnake[1][1] = x * 2 + 2;
    133     g_arrSnake[1][2] = LEFT;
    134 
    135     g_arrSnake[2][0] = y;
    136     g_arrSnake[2][1] = x * 2 + 4;
    137     g_arrSnake[2][2] = LEFT;
    138 
    139     DrawSnake();
    140 }
    141 
    142 void DrawSnake()   //展示蛇
    143 {
    144     //因为一个█占两个字节,所以不能直接用strcpy(&arrBackGround[arrSnake[i][0]][arrSnake[i][1]],"█");否则会把拷贝进来,导致出错
    145     //由于前面把arrSnake的所有元素都置为了0,所以当arrSnake[i][0]为0时,代表那个坐标处没有蛇的身子
    146     for (int i = 0; g_arrSnake[i][0] != 0; ++i)
    147         strncpy(&g_arrBackGround[g_arrSnake[i][0]][g_arrSnake[i][1]], "", 2);     //注意取地址符&不能漏掉!
    148 }
    149 
    150 
    151 void DestroySnake()                //销毁蛇
    152 {
    153     for (int i = 0; g_arrSnake[i][0] != 0; ++i)
    154         strncpy(&g_arrBackGround[g_arrSnake[i][0]][g_arrSnake[i][1]], "  ", 2);       //注意取地址符&不能漏掉!
    155 
    156 }
    157 
    158 void SnakeMove()       //蛇动
    159 {
    160     DestroySnake();
    161     for(int i = SNAKE_LENGTH - 1; i >= 1; --i)
    162     {
    163         if(g_arrSnake[i][0] != 0)
    164         {
    165             //把前一个节点的值,赋给当前节点
    166             g_arrSnake[i][0] = g_arrSnake[i-1][0];
    167             g_arrSnake[i][1] = g_arrSnake[i-1][1];
    168             g_arrSnake[i][2] = g_arrSnake[i-1][2];
    169         }
    170     }
    171 
    172     g_arrSnake[0][2] = g_iSnakeDir;     //设置蛇头方向
    173 
    174     //处理第一个节点(蛇头)
    175     if(g_arrSnake[0][2] == LEFT || g_arrSnake[0][2] == RIGHT)   //左右移动,列加减2
    176     {
    177         g_arrSnake[0][1] += g_arrSnake[0][2];
    178     }
    179     else
    180     {
    181         g_arrSnake[0][0] += g_arrSnake[0][2];                   //上下移动,行加减1
    182     }
    183 
    184     DrawSnake();
    185 
    186 }
    187 
    188 void ChangeDir()       //改变方向
    189 {
    190     //不能用getchar(), 会回显,并且要按回车之后才会开始读取
    191     //不能用getch(), 同步检测
    192 
    193     //异步检测
    194     if(GetAsyncKeyState('W'))
    195     {
    196         if (g_arrSnake[0][2] != DOWN)    //蛇不能回头
    197            g_iSnakeDir = UP;
    198     }
    199 
    200     if(GetAsyncKeyState('S'))
    201     {
    202         if (g_arrSnake[0][2] != UP)
    203             g_iSnakeDir = DOWN;
    204     }
    205 
    206     if(GetAsyncKeyState('A'))
    207     {
    208         if (g_arrSnake[0][2] != RIGHT)
    209            g_iSnakeDir = LEFT;
    210     }
    211 
    212     if(GetAsyncKeyState('D'))
    213     {
    214         if (g_arrSnake[0][2] != LEFT)
    215             g_iSnakeDir = RIGHT;
    216     }
    217 }
    218 
    219 bool IsSnakeDie()   //蛇死亡判断(包括撞墙和吃自己,两种情况)
    220 {
    221     if(g_arrSnake[0][2] == LEFT || g_arrSnake[0][2] == RIGHT)   //如果蛇左右移动,则判断蛇头的左右是否是"█",如果是,则判定为蛇死亡
    222     {
    223         if(!strncmp(&g_arrBackGround[g_arrSnake[0][0]][g_arrSnake[0][1]+g_arrSnake[0][2]], "", 2))   //注意取地址符&不能漏掉!
    224             return true;
    225     }
    226     else                                              //如果蛇上下移动,则判断蛇头的上下是否是"█"
    227     {
    228         if(!strncmp(&g_arrBackGround[g_arrSnake[0][0]+g_arrSnake[0][2]][g_arrSnake[0][1]], "", 2))
    229             return true;
    230     }
    231     return false;
    232 }
    233 
    234 void ProduceFood()                 //随机位置产生食物
    235 {
    236     //判断是否产生新的食物
    237     if(g_bIsProFood == false)
    238         return;
    239 
    240     bool bFlag = true;
    241     srand((unsigned)time(NULL));
    242 
    243     while(1)     //产生合法的食物,即食物不与蛇的身子重合
    244     {
    245         g_iRow = rand()% 18 + 1;   //
    246         g_iCol = rand()% 22 + 1;
    247 
    248         for (int i = 0; g_arrSnake[i][0] != 0; i++)   //遍历蛇
    249             if (g_iRow == g_arrSnake[i][0] && g_iCol == g_arrSnake[i][1])       //如果在食物产生在蛇身上
    250             {
    251                 bFlag = false;
    252                 break;
    253             }
    254 
    255         if(bFlag == true)
    256             break;
    257     }
    258 
    259     strncpy(&g_arrBackGround[g_iRow][g_iCol*2],  "", 2);
    260     g_bIsProFood = false;
    261 }
    262 
    263 void SnakeGrowUp()                 //蛇变长
    264 {
    265     if(g_iRow == g_arrSnake[0][0] && g_iCol*2 == g_arrSnake[0][1])    //注意:列要乘以2
    266     {
    267         if (UP == g_arrSnake[g_iSnakeLength][2])
    268         {
    269             g_arrSnake[g_iSnakeLength+1][0] = g_arrSnake[g_iSnakeLength][0]+1;
    270             g_arrSnake[g_iSnakeLength+1][1] = g_arrSnake[g_iSnakeLength][0];
    271             g_arrSnake[g_iSnakeLength+1][2] = g_arrSnake[g_iSnakeLength][2];
    272         }
    273         else if (DOWN == g_arrSnake[g_iSnakeLength][2])
    274         {
    275             g_arrSnake[g_iSnakeLength+1][0] = g_arrSnake[g_iSnakeLength][0]-1;
    276             g_arrSnake[g_iSnakeLength+1][1] = g_arrSnake[g_iSnakeLength][0];
    277             g_arrSnake[g_iSnakeLength+1][2] = g_arrSnake[g_iSnakeLength][2];
    278         }
    279         else if (LEFT == g_arrSnake[g_iSnakeLength][2])
    280         {
    281             g_arrSnake[g_iSnakeLength+1][0] = g_arrSnake[g_iSnakeLength][0];
    282             g_arrSnake[g_iSnakeLength+1][1] = g_arrSnake[g_iSnakeLength][0]+2;
    283             g_arrSnake[g_iSnakeLength+1][2] = g_arrSnake[g_iSnakeLength][2];
    284         }
    285         else if (RIGHT == g_arrSnake[g_iSnakeLength][2])
    286         {
    287             g_arrSnake[g_iSnakeLength+1][0] = g_arrSnake[g_iSnakeLength][0];
    288             g_arrSnake[g_iSnakeLength+1][1] = g_arrSnake[g_iSnakeLength][0]-2;
    289             g_arrSnake[g_iSnakeLength+1][2] = g_arrSnake[g_iSnakeLength][2];
    290         }
    291         g_iSnakeLength++;
    292         g_bIsProFood = true;
    293         g_iScore++;
    294     }
    295 
    296 }
    297 
    298 void PrintScore()                  //打印分数
    299 {
    300     COORD rd;
    301     //设置光标位置
    302     rd.X = 59;
    303     rd.Y = 10;
    304     SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), rd);
    305     printf("分数");
    306 
    307     rd.X = 60;
    308     rd.Y = 11;
    309     //设置光标位置
    310     SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), rd);
    311     //打印
    312     printf ("%d", g_iScore);
    313 }

    main.c

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <conio.h>
     4 #include <windows.h>
     5 #include <time.h>
     6 #include "GreedySnake.h"
     7 
     8 
     9 int main()
    10 {
    11     FirstPage();
    12     TestSpace();
    13     system("cls");
    14     SetSnakeRandPos();
    15     ShowBackground();
    16 
    17     while (1)
    18     {
    19         system("cls");
    20         ProduceFood();
    21         SnakeGrowUp();
    22         ChangeDir();
    23 
    24         if(IsSnakeDie())
    25         {
    26             printf("snake die!
    ");
    27             break;
    28         }
    29 
    30         SnakeMove();
    31         ShowBackground();
    32         PrintScore();
    33 
    34         Sleep(500);
    35     }
    36     system("pause");
    37     return 0;
    38 }
  • 相关阅读:
    C# Lambda表达式
    .NET轻量级MVC框架:Nancy入门教程(一)——初识Nancy
    SQL中的case when then else end用法
    WPF gif图片不动问题解决
    async(C# 参考)
    File类 ReadAllBytes() ReadAllLines() ReadAllText()
    二维码生成的常用数据格式
    在chrome console加入jquery库
    Reflector反编译WinForm程序重建项目资源和本地资源
    使用Settings.settings存储用户的个性化配置
  • 原文地址:https://www.cnblogs.com/FengZeng666/p/9694965.html
Copyright © 2011-2022 走看看