zoukankan      html  css  js  c++  java
  • C语言用面向对象的思想写贪吃蛇

      大概一年前这时候,接触C语言一个月,那时候知之甚少,对面向对象只觉”可远观而不可亵玩“,而且会看到很多言论说C语言就是面向过程的语言,C++就是面向对象的语言。不过,不记得什么时候在网上看到过一篇博文,大概是说如何优雅的写C语言。其中颇有印象的就是通过结构的函数指针模拟C++中的类。

      今天粗略尝试了一下,写的是之前写过的贪吃蛇。的确,用面向对象的思维写让我的思维变的更加清晰,因为这个游戏(以及大多数显示事物)的天然属性就是对象。

      此外,这次从最关键最核心的写起,如此写起来真是越写越轻松。因为如果关键部分写不出来,其他写的再好也没用。所以这次的顺序大概是:能移动的蛇--->能吃食物并变长--->能判断自己是否死亡--->其他修饰功能。

      最后,调试无误后。在发布代码前写了写注释。发现自己现在命名编码规范了不少,所以注释也并不多。曾经看到一种观点就是,注释关键部分就足够了,最好的注释就是良好的命名习惯、编码风格和清晰的逻辑

      不过,由于没有太多的规划,都是自己在路上零散构思的,代码还是不够紧凑,逻辑还可以优化。

      头文件

      1 #ifndef _HEAD_H_
      2 #define _HEAD_H_
      3 #include <stdio.h>
      4 #include <windows.h>//
      5 int Score = -1;
      6 typedef struct node1
      7 {
      8     int x;
      9     int y;
     10     struct node1 *next;
     11 }SnakeBody;
     12 typedef struct node2
     13 {
     14     int x;
     15     int y;//location
     16     char Status;
     17     char Direction;
     18     void (*MoveUp)(struct node2 *);
     19     void (*MoveDown)(struct node2 *);
     20     void (*MoveRight)(struct node2 *);
     21     void (*MoveLeft)(struct node2 *);
     22     void (*GrowUp)(struct node2 *);
     23     int (*IsDie)(struct node2 *);
     24     SnakeBody *next;
     25 }SnakeHead;
     26 void HideCursor()
     27 {
     28     CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
     29     SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
     30 }
     31 void SetPosition(int x, int y)
     32 {
     33     COORD pos;
     34     HANDLE hOutput;
     35     pos.X = x;
     36     pos.Y = y;
     37     hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
     38     SetConsoleCursorPosition(hOutput, pos);
     39 }
     40 void Print(SnakeHead *H)
     41 {
     42     SetPosition(H->x, H->y);
     43     printf("@");//mean snake head
     44     SnakeBody *temp = H->next;
     45     while(NULL != temp)
     46     {
     47         SetPosition(temp->x, temp->y);
     48         printf("+");//means snake body
     49         temp = temp->next;
     50     }
     51 }
     52 void Move(SnakeHead *H)
     53 {
     54     SnakeBody *temp = H->next;
     55     while (NULL != temp->next->next)
     56     {
     57         temp = temp->next;
     58     }
     59     temp->next->next = H->next;
     60     H->next = temp->next;
     61     SetPosition(temp->next->x, temp->next->y);
     62     printf(" ");
     63     temp->next = NULL;
     64     H->next->x = H->x;
     65     H->next->y = H->y;
     66 }
     67 void _MoveUp(SnakeHead *H)
     68 {
     69     Move(H);
     70     H->y--;
     71 }
     72 void _MoveDown(SnakeHead *H)
     73 {
     74     Move(H);
     75     H->y++;
     76 }
     77 void _MoveRight(SnakeHead *H)
     78 {
     79     Move(H);
     80     H->x++;    
     81 }
     82 void _MoveLeft(SnakeHead *H)
     83 {
     84     Move(H);
     85     H->x--;
     86 }
     87 void _GrowUp(SnakeHead *H)
     88 {
     89     SnakeBody *temp = (SnakeBody *)malloc(sizeof(SnakeBody));
     90     temp->x = H->x;
     91     temp->y = H->y;
     92     temp->next = H->next;
     93     H->next =  temp;
     94     switch (H->Direction)
     95     {
     96         case 'U':
     97         {
     98             H->y--;
     99             break;
    100         }
    101         case 'D':
    102         {
    103             H->y++;
    104             break;
    105         }
    106         case 'L':
    107         {
    108             H->x--;
    109             break;
    110         }
    111         case 'R':
    112         {
    113             H->x++;
    114             break;
    115         }
    116         default:
    117         {
    118             break;
    119         }
    120     }
    121     Print(H);
    122 }
    123 const int Left = 3;
    124 const int Right = 34;
    125 const int Top = 3;
    126 const int Bottom = 27;
    127 void BuildWall()
    128 {
    129     for (int x = Left; x <= Right; x++)
    130     {
    131         SetPosition(x, Top);
    132         printf("-");
    133         SetPosition(x, Bottom);
    134         printf("-");
    135     }
    136     for (int y = Top; y <= Bottom; y++)
    137     {
    138         SetPosition(Left, y);
    139         printf("|");
    140         SetPosition(Right, y);
    141         printf("|");
    142     }
    143     //some hint
    144     SetPosition(15, 1);
    145     printf("Snake");
    146     SetPosition(20, 2);
    147     printf("zhaoyu");
    148     SetPosition(37, 7);
    149     printf("F1:Slow Down");
    150     SetPosition(37, 9);
    151     printf("F2:Speed Up");
    152     SetPosition(37, 11);
    153     printf("F3:Speed Up++");
    154     SetPosition(37, 15);
    155     printf("Score:");
    156 }
    157 void CreateFood(int *x, int *y, SnakeHead *H)
    158 {
    159     int flag = 1;
    160     int i = 0, j = 0; 
    161     //make sure in the wall && not on snake
    162     SnakeBody *temp = H->next;
    163     while (1 == flag)
    164     {
    165         i = rand()%30;
    166         i += 4;
    167         j = rand()%24;
    168         j += 4;
    169         flag = 0;
    170         if (i == H->x && j == H->y)
    171         {
    172             flag = 1;
    173             continue;
    174         }
    175         temp = H->next;
    176         while (NULL != temp)
    177         {
    178             if (i == temp->x && j == temp->y)
    179             {
    180                 flag = 1;
    181                 break;
    182             }
    183             temp = temp->next;
    184         }
    185     }
    186 
    187     *x = i;
    188     *y = j;
    189     SetPosition(i, j);
    190     printf("$");//dollar mead food!
    191     SetPosition(45, 15);
    192     //once food created ,score plus 1
    193     printf("%d", ++Score);
    194 }
    195 int Die(SnakeHead *H)
    196 {
    197     //out the wall will die
    198     if (H->x <= Left || H->x >= Right || H->y >= Bottom || H->y <= Top)
    199     {
    200         return 1;//die
    201     }
    202     // crush into itself will die
    203     SnakeBody *temp = H->next;
    204     while (NULL !=temp)
    205     {
    206         if (H->x == temp->x && H->y == temp->y)
    207         {
    208             return 1;
    209         }
    210         temp = temp->next;
    211     }
    212     // 0 mean not die
    213     return 0;
    214 }
    215 #endif

      源文件

      1 #include "head.h"
      2 
      3 
      4 void StartGame()
      5 {    
      6     //Create a snake
      7     SnakeBody *temp = (SnakeBody *)malloc(sizeof(SnakeBody));
      8     SnakeHead *Head = (SnakeHead *)malloc(sizeof(SnakeHead));
      9     Head->Direction = 'L';
     10     Head->Status = 1;
     11     Head->x = 10;
     12     Head->y = 10;
     13     //assign some functions to snake
     14     Head->MoveUp = _MoveUp;
     15     Head->MoveDown = _MoveDown;
     16     Head->MoveRight = _MoveRight;
     17     Head->MoveLeft = _MoveLeft;
     18     Head->GrowUp = _GrowUp;
     19     Head->IsDie = Die;
     20     temp->x = 11;
     21     temp->y = 10;
     22     temp->next = NULL;
     23     Head->next = temp;
     24     // create snake body
     25     for (int i = 0; i < 5; i++)
     26     {
     27         SnakeBody *move = (SnakeBody *)malloc(sizeof(SnakeBody));
     28         move->x = temp->x + 1;
     29         move->y = temp->y;
     30         temp->next = move;
     31         temp = move;
     32         move->next = NULL;
     33     }
     34     //Init food
     35     int Foodx = 0, Foody = 0;
     36     CreateFood(&Foodx, &Foody, Head);
     37     int Speed = 10;
     38     while (1 == Head->Status)
     39     {
     40         //print the snake
     41         Print(Head);
     42         //judge is or not die
     43         if((*Head->IsDie)(Head))
     44         {
     45             break;
     46         }
     47         //get direction
     48         if(GetAsyncKeyState(VK_UP) && 'D' != Head->Direction)
     49         {
     50             Head->Direction = 'U';
     51         }
     52         else if (GetAsyncKeyState(VK_DOWN) && 'U' != Head->Direction)
     53         {
     54             Head->Direction = 'D';
     55         }
     56         else if (GetAsyncKeyState(VK_RIGHT) && 'L' != Head->Direction)
     57         {
     58             Head->Direction = 'R';
     59         }
     60         else if (GetAsyncKeyState(VK_LEFT) && 'R' != Head->Direction)
     61         {
     62             Head->Direction = 'L';
     63         }
     64         //move
     65         switch (Head->Direction)
     66         {
     67             case 'U':
     68             {
     69                 //judge is there a food
     70                 if (Head->x == Foodx && Head->y - 1 == Foody)
     71                 {
     72                     (*Head->GrowUp)(Head);
     73                     CreateFood(&Foodx, &Foody, Head);
     74                 }
     75                 else//Just move
     76                 {
     77                     (*Head->MoveUp)(Head);
     78                 }
     79                 break;
     80             }
     81             case 'D':
     82             {
     83                 if (Head->x == Foodx && Head->y + 1 == Foody)
     84                 {
     85                     (*Head->GrowUp)(Head);
     86                     CreateFood(&Foodx, &Foody, Head);
     87                 }
     88                 else
     89                 {
     90                     (*Head->MoveDown)(Head);
     91                 }
     92                 break;
     93             }
     94             case 'R':
     95             {
     96                 if (Head->x + 1 == Foodx && Head->y == Foody)
     97                 {
     98                     (*Head->GrowUp)(Head);
     99                     CreateFood(&Foodx, &Foody, Head);
    100                 }
    101                 else
    102                 {
    103                     (*Head->MoveRight)(Head);    
    104                 }
    105                 
    106                 break;
    107             }
    108             case 'L':
    109             {
    110                 if (Head->x - 1 == Foodx && Head->y == Foody)
    111                 {
    112                     (*Head->GrowUp)(Head);
    113                     CreateFood(&Foodx, &Foody, Head);
    114                 }
    115                 else
    116                 {
    117                     (*Head->MoveLeft)(Head);
    118                 }
    119                 break;
    120             }
    121             default:
    122             {
    123                 break;
    124             }
    125         }
    126         //control 
    127         if (GetAsyncKeyState(VK_F1) && Speed > 6)
    128         {
    129             Speed -= 5;
    130         }
    131         else if (GetAsyncKeyState(VK_F2) && Speed < 30)
    132         {
    133             Speed += 5;
    134         }
    135         else if (GetAsyncKeyState(VK_F3))
    136         {
    137             Speed += 10;
    138         }
    139         if ('L' == Head->Direction ||'R' == Head->Direction)
    140         {
    141             Sleep(1000/Speed);
    142         }
    143         else
    144         {
    145             Sleep(2000/Speed);
    146         }
    147     }
    148 }
    149 int main(int argc, char const *argv[])
    150 {
    151     //init
    152     system("cls");
    153     system("mode con cols=50 lines=30");//no space around equal sign    
    154     BuildWall();
    155     HideCursor();
    156     StartGame();
    157     SetPosition(36, 20);
    158     printf("Enter to exit!");
    159     getchar();
    160     return 0;
    161 }

       运行:

        

      后记:

      1、函数指针与函数名

      函数名与函数指针都是一样的,即都是函数指针。函数名是一个函数指针常量,而函数指针是一个函数数指针变量。

      一般的C语言书籍都不会谈及这些近乎奇淫技巧的东东。

      2、GetAsyncKeyState函数

      这个函数按下之后其状态会一直存在,我在写俄罗斯方块就大受其害。以下面代码为例。你只需要按一下F1就可以跳出循环了,而不是1000下。因为按下一次之后其状态就始终为真了,除非你按下别的键。

     1 #include <stdio.h>
     2 #include <windows.h>
     3 int main(int argc, char const *argv[])
     4 {
     5     int i = 0;
     6     while (1)
     7     {
     8         if (GetAsyncKeyState(VK_F1))
     9         {
    10             i++;
    11         }
    12         if (i >= 1000)
    13         {
    14             break;
    15         }
    16     }
    17     printf("%d
    ", i);
    18     return 0;
    19 }

      

  • 相关阅读:
    转载: RAID详解[RAID0/RAID1/RAID10/RAID5]
    用户交互式命令:read
    linux下fdisk分区管理、文件系统管理、挂载文件系统等
    linux文件系统下的特殊权限
    find命令详解
    python3中 getpass模块使用
    个人shell积累
    手把手教你利用爬虫爬网页(Python代码)
    数通HCIP-ospf知识点
    HCIE之路--超全ospf思维导图
  • 原文地址:https://www.cnblogs.com/zhaoyu1995/p/5447214.html
Copyright © 2011-2022 走看看