《C语言课程设计与游戏开发实践课程》34章总结,EasyX常用函数

目录

一、知道点归纳

  第三章 数组在游戏的使用

  第四章  easyX总结

二、代码实现

  第三章  

    3.2消砖块

    3.3空战游戏

    3.4贪吃蛇

  第四章 

    4.2多球反弹

    4.3实时钟表

    4.4Easy实现消砖块

一、知识点归纳

  第三章 数组在游戏的使用

  1 数组的使用
  2 3.1生命游戏
  3 将画面当二维数组,每次循环更新一遍数组的值
  4 int cells[High][Width]; // 所有位置细胞生1或死0
  5 
  6 3.2消砖块
  7 将整个画面当作二维数组,填充要素:砖块、球、挡板。
  8 需要用到大量判断语句,每次循环都要重新执行,对时间复杂度上不够优秀,可以单独维护砖块的二维数组,减少show()的判断次数
  9 int canvas[High][Width] = {0}; // 二维数组存储游戏画布中对应的元素
 10 void startup()  // 数据初始化
 11 {
 12        canvas[ball_x][ball_y] = 1;    
 13     int k,i;
 14     for (k=left;k<=right;k++)  // 挡板
 15         canvas[position_x][k] = 2;    
 16     for (k=0;k<Width;k++)  // 加几排砖块
 17         for (i=0;i<High/4;i++)  
 18             canvas[i][k] = 3;
 19 }
 20 void updateWithoutInput()  // 与用户输入无关的更新
 21 {
 22         if (canvas[ball_x-1][ball_y]==3)//有砖块消砖块
 23         {
 24             ball_vx = -ball_vx;
 25             canvas[ball_x-1][ball_y] = 0;
 26             printf("\a");
 27         }
 28 }
 29 
 30 3.3空战游戏
 31 用数组存储多台敌机,enemy_x[i],enemy_y[i],i号敌机的xy坐标。
 32 这里可以运用结构体数组,会让结构更紧凑。
 33 typedef struct
 34 {
 35     int x,y;
 36 } enemy[10];
 37 
 38 用二维数组,方便对画面进行大改动例如发射散弹,积分增加,散弹半径增加,触发敌机变快。同时可以做到连续发射子弹。
 39 对画面遍历一遍,在有子弹的位置,遍历一遍敌机数组,判断是否击中,没有则向上移动。
 40 for (k=0;k<EnemyNum;k++)
 41                 {
 42                     if ((i==enemy_x[k]) && (j==enemy_y[k]))  // 子弹击中敌机
 43                     {
 44                         score++;                // 分数加1
 45                         if (score%5==0 && EnemyMoveSpeed>3)   // 达到一定积分后,敌机变快
 46                             EnemyMoveSpeed--;
 47                         if (score%5==0)   // 达到一定积分后,子弹变厉害
 48                             BulletWidth++;
 49                         canvas[enemy_x[k]][enemy_y[k]] = 0;
 50                         enemy_x[k] = rand()%2;           // 产生新的飞机
 51                         enemy_y[k] = rand()%Width;
 52                         canvas[enemy_x[k]][enemy_y[k]] = 3;
 53                         canvas[i][j] = 0;      // 子弹消失
 54                     }
 55                 }
 56 
 57 多台敌机,统一的逻辑,都自动下落,当任一台跑出都要重新生成。
 58 EnemyMoveSpeed用于更改敌机移动速度,当得分到一定值,该值减小,敌机移动速度变快
 59 if (enemy_x[k]>High)   // 敌机跑出显示屏幕
 60         {
 61             canvas[enemy_x[k]][enemy_y[k]] = 0;
 62             enemy_x[k] = rand()%2;           // 产生新的飞机
 63             enemy_y[k] = rand()%Width;
 64             canvas[enemy_x[k]][enemy_y[k]] = 3;
 65             score--;  // 减分
 66         }
 67 
 68         if (speed == EnemyMoveSpeed)
 69         {
 70             // 敌机下落
 71             for (k=0;k<EnemyNum;k++)
 72             {
 73                 canvas[enemy_x[k]][enemy_y[k]] = 0;
 74                 enemy_x[k]++;            
 75                 speed = 0;
 76                 canvas[enemy_x[k]][enemy_y[k]] = 3;
 77             }
 78         }
 79 怎么实现发射散弹
 80     else if (input == ' ')  // 发射子弹
 81         {
 82             int left = position_y-BulletWidth;//发射一排子弹
 83             int right = position_y+BulletWidth;
 84             if (left<0)    left = 0; //这防止子弹溢出
 85             if (right>Width-1)
 86                 right = Width-1;
 87             int k;
 88             for (k=left;k<=right;k++) // 发射闪弹
 89                 canvas[position_x-1][k] = 2; // 发射子弹的初始位置在飞机的正上方
 90         }
 91 
 92 当得分到5 10 15 时子弹宽带增加,但是,我觉得这里可能有一点不会逻辑,因为存在敌机跑出屏幕减分的情况,单纯判断mod5,会出现5 10 5 的情况,按原文代码还是会使得子弹宽度增加。
 93 原文:
 94  if (score%5==0)   // 达到一定积分后,子弹变厉害
 95         BulletWidth++;
 96 
 97 我的想法:
 98 方法一:用一个全局变量记录得分最大值
 99 int scoremax=0;
100 if(score%5==0&&scoremax<score)
101 {
102          BulletWidth++;
103          scoremax=score;
104 }
105 方法二:BulletWidth = score/5,使得直接关联。
106 
107 3.4贪吃蛇
108 用数组实现蛇:
109 canvas[High/2][Width/2] = 1;//定蛇头
110 for (i=1;i<=4;i++)
111     canvas[High/2][Width/2-i] = i+1;
112 蛇移动:逻辑是>0的值加一,将最大值改为0,对应移动方向(上下左右)0改为1。这里不能直接判断蛇尾为6(吃食物后,最值会改变)
113 void moveSnakeByDirection()
114 {
115     int i,j;
116     for (i=1;i<High-1;i++)
117         for (j=1;j<Width-1;j++)
118             if (canvas[i][j]>0)
119                 canvas[i][j]++; //全加一
120 
121     int oldTail_i,oldTail_j,oldHead_i,oldHead_j;
122     int max = 0;
123 
124     for (i=1;i<High-1;i++)
125         for (j=1;j<Width-1;j++)
126             if (canvas[i][j]>0)
127             {
128                 if (max<canvas[i][j])
129                 {
130                     max = canvas[i][j];//找最值,更新蛇尾
131                     oldTail_i = i;
132                     oldTail_j = j;
133                 }
134                 if (canvas[i][j]==2)//记录旧蛇头
135                 {
136                     oldHead_i = i;
137                     oldHead_j = j;
138                 }
139             }
140 
141     int newHead_i,newHead_j;
142 
143     if (moveDirection==1) // 向上移动
144     {
145         newHead_i = oldHead_i-1;
146         newHead_j = oldHead_j;
147     }
148     if (moveDirection==2) // 向下移动
149     {
150         newHead_i = oldHead_i+1;
151         newHead_j = oldHead_j;
152     }
153     if (moveDirection==3) // 向左移动
154     {
155         newHead_i = oldHead_i;
156         newHead_j = oldHead_j-1;
157     }
158     if (moveDirection==4) // 向右移动
159     {
160         newHead_i = oldHead_i;
161         newHead_j = oldHead_j+1;
162     }
163 }
164 判断游戏结束:只看新蛇头的位置,碰到自身(>0),或者碰到墙壁(-1165 if (canvas[newHead_i][newHead_j]>0 || canvas[newHead_i][newHead_j]==-1)
166     {
167         printf("游戏失败!\n");
168         Sleep(2000);
169         system("pause");
170         exit(0);
171     }
172 吃食物后,蛇身变长,出现新食物
173 if (canvas[newHead_i][newHead_j]==-2)
174     {
175         canvas[food_x][food_y] = 0;
176         // 产生一个新的食物
177         food_x = rand()%(High-5) + 2;
178         food_y = rand()%(Width-5) + 2;
179         canvas[food_x][food_y] = -2;
180         // 原来的旧蛇尾留着,长度自动+1
181     }
182 
183     

  第四章  easyX总结

 1 EasyX常用函数
 2 
 3 cleardevice();//用背景色清空屏幕
 4 initgraph(width,height) ;//初始化绘图窗口
 5 closegraph();//关窗口
 6 
 7 RGB(byRed,byGreen,byBlue);//RGB三原色的值设颜色
 8 getbkcolor();//获取当前背景色
 9 setbkcolor();//设置背景颜色
10 getbkmode();//获取当前文字背景样式
11 setbkmode();//设置文字背景
12 getfillcolor();//获取填充颜色
13 setfillcolor();//设置填充颜色,可以填写BALCK,WHITE,BLUE,GREEN,RED,BROWN,YELLOW
14 setlinecolor();//设置线条颜色,填写内容同上
15 setcolor();//设置前景色
16 setfillstyle();//设置填充样式
17 void setfillstyle(
18     int style,
19     long hatch = NULL,
20     IMAGE* ppattern = NULL
21 );
22 style可以填写
23 Macro               Value    Description
24 BS_SOLID                0             全填
25 BS_NULL               1             不填充
26 BS_HATCHED        2             图案填充
27 BS_PATTERN        3             自定义填充样式hatch
28 BS_DIBPATTERN    5             自定义图像填充
29 
30 setlinestyle();//设置线条样式
31 Value             Description
32 PS_SOLID             The line is solid.
33 PS_DASH             Line is:------------
34 PS_DOT             Line is:············
35 PS_DASHDOT     Line is:-·-·-·-·-·-·
36 PS_DASHDOTDOT    Line is:-··-··-··-··
37 
38 circle( x,y, radius);//画一个坐标(x,y)半径为radius的圆
39 line(x1,y1,x2,y2);//画直线(x1,y1),(x2,y2)为直线的两端点的线
40 putpixel(x,y,c);//画点(x,y),像素的颜色为c
41 solidrectangle(x1,y1,x2,y2);//画填充矩形,(x1,y1)为左上角,(x2,y2)右下角
42 
43 对文字的操作
44 gettextcolor();//获取文字颜色
45 settextcolor(COLORREF color);//设置文字颜色,BLUE等
46 
47 对图片的操作
48 {
49     initgraph(640, 480);
50     IMAGE img(200, 200);//创建200*200的图片对象
51     SetWorkingImage(&img);//用于设置当前绘图设备
52     line(0, 100, 200, 100);
53     line(100, 0, 100, 200);
54     circle(100, 100, 50);//绘制一个图案
55     SetWorkingImage();//设置绘图对象到窗口
56     putimage(220, 140, &img);//显示图片对象到窗口
57     _getch();
58    closegraph();}
 1 Sleep有明显画面闪烁
 2 用 BeginBatchDraw();FlushBatchDraw();EndBatchDraw();
 3 BeginBatchDraw();//开始批量绘图
 4     while (1)
 5     {
 6         FlushBatchDraw();//执行批量绘制
 7         
 8         // 延时
 9         Sleep(3);
10     }
11     EndBatchDraw();//结束批量绘制

调用outtextxy()函数会报错
原因:Unicode编码,不论中文还是英文都是用2个字节表示;
解决方法:项目属性——字符集———使用多字节字符集

二、代码实现

  第三章  

    3.2消砖块 

  1 #pragma warning(disable:4996);
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <conio.h>
  5 #include <windows.h>
  6 
  7 #define High 15  // 游戏画面尺寸
  8 #define Width 20
  9 
 10 // 全局变量
 11 int ball_x, ball_y; // 小球的坐标
 12 int ball_vx, ball_vy; // 小球的速度
 13 int position_x, position_y; // 挡板中心坐标
 14 int ridus;  // 挡板半径大小
 15 int left, right; // 挡板左右位置
 16 int canvas[High][Width] = { 0 }; // 二维数组存储游戏画布中对应的元素
 17 // 0为空格,1为小球O,2为挡板*,3为方块#
 18 
 19 void gotoxy(int x, int y)  //光标移动到(x,y)位置
 20 {
 21     HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
 22     COORD pos;
 23     pos.X = x;
 24     pos.Y = y;
 25     SetConsoleCursorPosition(handle, pos);
 26 }
 27 
 28 void startup()  // 数据初始化
 29 {
 30     ridus = 5;
 31     position_x = High - 1;
 32     position_y = Width / 2;
 33     left = position_y - ridus;
 34     right = position_y + ridus;
 35 
 36     ball_x = position_x - 1;
 37     ball_y = position_y;
 38     ball_vx = -1;
 39     ball_vy = 1;
 40     canvas[ball_x][ball_y] = 1;
 41 
 42     int k, i;
 43     for (k = left;k <= right;k++)  // 挡板
 44         canvas[position_x][k] = 2;
 45 
 46     for (k = 0;k < Width;k++)  // 加几排砖块
 47         for (i = 0;i < High / 4;i++)
 48             canvas[i][k] = 3;
 49 }
 50 
 51 void show()  // 显示画面
 52 {
 53     gotoxy(0, 0);    // 光标移动到原点位置,以下重画清屏
 54     int i, j;
 55     for (i = 0;i < High;i++)
 56     {
 57         for (j = 0;j < Width;j++)
 58         {
 59             if (canvas[i][j] == 0)
 60                 printf(" ");   //   输出空格
 61             else if (canvas[i][j] == 1)
 62                 printf("0");   //   输出小球0
 63             else if (canvas[i][j] == 2)
 64                 printf("*");   //   输出挡板*
 65             else if (canvas[i][j] == 3)
 66                 printf("#");   //   输出砖块#
 67         }
 68         printf("|\n"); // 显示右边界
 69     }
 70     for (j = 0;j < Width;j++)
 71         printf("-"); // 显示下边界
 72     printf("\n");
 73 }
 74 
 75 void updateWithoutInput()  // 与用户输入无关的更新
 76 {
 77     if (ball_x == High - 2)
 78     {
 79         if ((ball_y >= left) && (ball_y <= right))   // 被挡板挡住
 80         {
 81         }
 82         else    // 没有被挡板挡住
 83         {
 84             printf("游戏失败\n");
 85             system("pause");
 86             exit(0);
 87         }
 88     }
 89 
 90     static int speed = 0;
 91     if (speed < 7)
 92         speed++;
 93     if (speed == 7)
 94     {
 95         speed = 0;
 96 
 97         canvas[ball_x][ball_y] = 0;
 98         // 更新小球坐标
 99         ball_x = ball_x + ball_vx;
100         ball_y = ball_y + ball_vy;
101         canvas[ball_x][ball_y] = 1;
102 
103         // 碰到边界后反弹        
104         if ((ball_x == 0) || (ball_x == High - 2))
105             ball_vx = -ball_vx;
106         if ((ball_y == 0) || (ball_y == Width - 1))
107             ball_vy = -ball_vy;
108 
109         // 碰到砖块后反弹
110         if (canvas[ball_x - 1][ball_y] == 3)
111         {
112             ball_vx = -ball_vx;
113             canvas[ball_x - 1][ball_y] = 0;
114             printf("\a");
115         }
116     }
117 }
118 
119 void updateWithInput()  // 与用户输入有关的更新
120 {
121     char input;
122     if (kbhit())  // 判断是否有输入
123     {
124         input = getch();  // 根据用户的不同输入来移动,不必输入回车
125         if (input == 'a' && left > 0)
126         {
127             canvas[position_x][right] = 0;
128             position_y--;  // 位置左移
129             left = position_y - ridus;
130             right = position_y + ridus;
131             canvas[position_x][left] = 2;
132         }
133         if (input == 'd' && right < Width - 1)
134         {
135             canvas[position_x][left] = 0;
136             position_y++;  // 位置右移
137             left = position_y - ridus;
138             right = position_y + ridus;
139             canvas[position_x][right] = 2;
140         }
141     }
142 }
143 
144 int main()
145 {
146     startup();  // 数据初始化    
147     while (1)  //  游戏循环执行
148     {
149         show();  // 显示画面
150         updateWithoutInput();  // 与用户输入无关的更新
151         updateWithInput();     // 与用户输入有关的更新
152     }
153     return 0;
154 }
3.2消砖块

    3.3空战游戏

  1 #pragma warning(disable:4996);
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <conio.h>
  5 #include <windows.h>
  6 
  7 #define High 15  // 游戏画面尺寸
  8 #define Width 25
  9 #define EnemyNum 5 // 敌机个数
 10 
 11 // 全局变量
 12 int position_x, position_y; // 飞机位置
 13 int enemy_x[EnemyNum], enemy_y[EnemyNum];  // 敌机位置
 14 int canvas[High][Width] = { 0 }; // 二维数组存储游戏画布中对应的元素
 15                         // 0为空格,1为飞机*,2为子弹|,3为敌机@
 16 int score; // 得分
 17 int BulletWidth; // 子弹宽度
 18 int EnemyMoveSpeed; // 敌机移动速度
 19 
 20 void gotoxy(int x, int y)  //光标移动到(x,y)位置
 21 {
 22     HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
 23     COORD pos;
 24     pos.X = x;
 25     pos.Y = y;
 26     SetConsoleCursorPosition(handle, pos);
 27 }
 28 
 29 void startup() // 数据初始化
 30 {
 31     position_x = High - 1;
 32     position_y = Width / 2;
 33     canvas[position_x][position_y] = 1;
 34     int k;
 35     for (k = 0;k < EnemyNum;k++)
 36     {
 37         enemy_x[k] = rand() % 2;
 38         enemy_y[k] = rand() % Width;
 39         canvas[enemy_x[k]][enemy_y[k]] = 3;
 40     }
 41     score = 0;
 42     BulletWidth = 0;
 43     EnemyMoveSpeed = 20;
 44 }
 45 
 46 void show()  // 显示画面
 47 {
 48     gotoxy(0, 0);  // 光标移动到原点位置,以下重画清屏
 49     int i, j;
 50     for (i = 0;i < High;i++)
 51     {
 52         for (j = 0;j < Width;j++)
 53         {
 54             if (canvas[i][j] == 0)
 55                 printf(" ");   //   输出空格
 56             else if (canvas[i][j] == 1)
 57                 printf("*");   //   输出飞机*
 58             else if (canvas[i][j] == 2)
 59                 printf("|");   //   输出子弹|
 60             else if (canvas[i][j] == 3)
 61                 printf("@");   //  输出飞机@
 62         }
 63         printf("\n");
 64     }
 65     printf("得分:%d\n", score);
 66     Sleep(20);
 67 }
 68 
 69 void updateWithoutInput()  // 与用户输入无关的更新
 70 {
 71     int i, j, k;
 72     for (i = 0;i < High;i++)
 73     {
 74         for (j = 0;j < Width;j++)
 75         {
 76             if (canvas[i][j] == 2)
 77             {
 78                 for (k = 0;k < EnemyNum;k++)
 79                 {
 80                     if ((i == enemy_x[k]) && (j == enemy_y[k]))  // 子弹击中敌机
 81                     {
 82                         score++;                // 分数加1
 83                         if (score % 5 == 0 && EnemyMoveSpeed > 3)   // 达到一定积分后,敌机变快
 84                             EnemyMoveSpeed--;
 85                         if (score % 5 == 0)   // 达到一定积分后,子弹变厉害
 86                             BulletWidth++;
 87                         canvas[enemy_x[k]][enemy_y[k]] = 0;
 88                         enemy_x[k] = rand() % 2;           // 产生新的飞机
 89                         enemy_y[k] = rand() % Width;
 90                         canvas[enemy_x[k]][enemy_y[k]] = 3;
 91                         canvas[i][j] = 0;      // 子弹消失
 92                     }
 93                 }
 94                 // 子弹向上移动
 95                 canvas[i][j] = 0;
 96                 if (i > 0)
 97                     canvas[i - 1][j] = 2;
 98             }
 99         }
100     }
101 
102     static int speed = 0;
103     if (speed < EnemyMoveSpeed)
104         speed++;
105 
106     for (k = 0;k < EnemyNum;k++)
107     {
108         if ((position_x == enemy_x[k]) && (position_y == enemy_y[k]))  // 敌机撞到我机
109         {
110             printf("失败!\n");
111             Sleep(3000);
112             system("pause");
113             exit(0);
114         }
115 
116         if (enemy_x[k] > High)   // 敌机跑出显示屏幕
117         {
118             canvas[enemy_x[k]][enemy_y[k]] = 0;
119             enemy_x[k] = rand() % 2;           // 产生新的飞机
120             enemy_y[k] = rand() % Width;
121             canvas[enemy_x[k]][enemy_y[k]] = 3;
122             score--;  // 减分
123         }
124 
125         if (speed == EnemyMoveSpeed)
126         {
127             // 敌机下落
128             for (k = 0;k < EnemyNum;k++)
129             {
130                 canvas[enemy_x[k]][enemy_y[k]] = 0;
131                 enemy_x[k]++;
132                 speed = 0;
133                 canvas[enemy_x[k]][enemy_y[k]] = 3;
134             }
135         }
136     }
137 }
138 
139 void updateWithInput()  // 与用户输入有关的更新
140 {
141     char input;
142     if (kbhit())  // 判断是否有输入
143     {
144         input = getch();  // 根据用户的不同输入来移动,不必输入回车
145         if (input == 'a' && position_y > 0)
146         {
147             canvas[position_x][position_y] = 0;
148             position_y--;  // 位置左移
149             canvas[position_x][position_y] = 1;
150         }
151         else if (input == 'd' && position_y < Width - 1)
152         {
153             canvas[position_x][position_y] = 0;
154             position_y++;  // 位置右移
155             canvas[position_x][position_y] = 1;
156         }
157         else if (input == 'w')
158         {
159             canvas[position_x][position_y] = 0;
160             position_x--;  // 位置上移
161             canvas[position_x][position_y] = 1;
162         }
163         else if (input == 's')
164         {
165             canvas[position_x][position_y] = 0;
166             position_x++;  // 位置下移
167             canvas[position_x][position_y] = 1;
168         }
169         else if (input == ' ')  // 发射子弹
170         {
171             int left = position_y - BulletWidth;
172             int right = position_y + BulletWidth;
173             if (left < 0)
174                 left = 0;
175             if (right > Width - 1)
176                 right = Width - 1;
177             int k;
178             for (k = left;k <= right;k++) // 发射闪弹
179                 canvas[position_x - 1][k] = 2; // 发射子弹的初始位置在飞机的正上方
180         }
181     }
182 }
183 
184 int main()
185 {
186     startup();  // 数据初始化    
187     while (1) //  游戏循环执行
188     {
189         show();  // 显示画面
190         updateWithoutInput();  // 与用户输入无关的更新
191         updateWithInput();  // 与用户输入有关的更新
192     }
193     return 0;
194 }
3.3空战游戏

    3.4贪吃蛇

  1 #pragma warning(disable:4996);
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <conio.h>
  5 #include <windows.h>
  6 
  7 #define High 20  // 游戏画面尺寸
  8 #define Width 30
  9 
 10 // 全局变量
 11 int moveDirection; // 小蛇移动位置,上下左右分别用1,2,3,4表示
 12 int food_x, food_y; // 食物的位置
 13 int canvas[High][Width] = { 0 }; // 二维数组存储游戏画布中对应的元素
 14     // 0为空格0,-1为边框#,-2为食物F,1为蛇头@,大于1的正数为蛇身*
 15 
 16 void gotoxy(int x, int y)  //光标移动到(x,y)位置
 17 {
 18     HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
 19     COORD pos;
 20     pos.X = x;
 21     pos.Y = y;
 22     SetConsoleCursorPosition(handle, pos);
 23 }
 24 
 25 // 移动小蛇
 26 // 第一步扫描数组canvas所有元素,找到正数元素都+1
 27 // 找到最大元素(即蛇尾巴),把其变为0
 28 // 找到=2的元素(即蛇头),再根据输出的上下左右方向,把对应的另一个像素值设为1(新蛇头)
 29 void moveSnakeByDirection()
 30 {
 31     int i, j;
 32     for (i = 1;i < High - 1;i++)
 33         for (j = 1;j < Width - 1;j++)
 34             if (canvas[i][j] > 0)
 35                 canvas[i][j]++;
 36 
 37     int oldTail_i, oldTail_j, oldHead_i, oldHead_j;
 38     int max = 0;
 39 
 40     for (i = 1;i < High - 1;i++)
 41         for (j = 1;j < Width - 1;j++)
 42             if (canvas[i][j] > 0)
 43             {
 44                 if (max < canvas[i][j])
 45                 {
 46                     max = canvas[i][j];
 47                     oldTail_i = i;
 48                     oldTail_j = j;
 49                 }
 50                 if (canvas[i][j] == 2)
 51                 {
 52                     oldHead_i = i;
 53                     oldHead_j = j;
 54                 }
 55             }
 56 
 57     int newHead_i, newHead_j;
 58 
 59     if (moveDirection == 1) // 向上移动
 60     {
 61         newHead_i = oldHead_i - 1;
 62         newHead_j = oldHead_j;
 63     }
 64     if (moveDirection == 2) // 向下移动
 65     {
 66         newHead_i = oldHead_i + 1;
 67         newHead_j = oldHead_j;
 68     }
 69     if (moveDirection == 3) // 向左移动
 70     {
 71         newHead_i = oldHead_i;
 72         newHead_j = oldHead_j - 1;
 73     }
 74     if (moveDirection == 4) // 向右移动
 75     {
 76         newHead_i = oldHead_i;
 77         newHead_j = oldHead_j + 1;
 78     }
 79 
 80     // 新蛇头如果吃到食物
 81     if (canvas[newHead_i][newHead_j] == -2)
 82     {
 83         canvas[food_x][food_y] = 0;
 84         // 产生一个新的食物
 85         food_x = rand() % (High - 5) + 2;
 86         food_y = rand() % (Width - 5) + 2;
 87         canvas[food_x][food_y] = -2;
 88 
 89         // 原来的旧蛇尾留着,长度自动+1
 90     }
 91     else // 否则,原来的旧蛇尾减掉,保持长度不变
 92         canvas[oldTail_i][oldTail_j] = 0;
 93 
 94     // 是否小蛇和自身撞,或者和边框撞,游戏失败
 95     if (canvas[newHead_i][newHead_j] > 0 || canvas[newHead_i][newHead_j] == -1)
 96     {
 97         printf("游戏失败!\n");
 98         Sleep(2000);
 99         system("pause");
100         exit(0);
101     }
102     else
103         canvas[newHead_i][newHead_j] = 1;
104 }
105 
106 void startup() // 数据初始化
107 {
108     int i, j;
109 
110     // 初始化边框
111     for (i = 0;i < High;i++)
112     {
113         canvas[i][0] = -1;
114         canvas[i][Width - 1] = -1;
115     }
116     for (j = 0;j < Width;j++)
117     {
118         canvas[0][j] = -1;
119         canvas[High - 1][j] = -1;
120     }
121 
122     // 初始化蛇头位置
123     canvas[High / 2][Width / 2] = 1;
124     // 初始化蛇身,画布中元素值分别为2,3,4,5....
125     for (i = 1;i <= 4;i++)
126         canvas[High / 2][Width / 2 - i] = i + 1;
127 
128     // 初始小蛇向右移动
129     moveDirection = 4;
130 
131     food_x = rand() % (High - 5) + 2;
132     food_y = rand() % (Width - 5) + 2;
133     canvas[food_x][food_y] = -2;
134 }
135 
136 void show()  // 显示画面
137 {
138     gotoxy(0, 0);  // 光标移动到原点位置,以下重画清屏
139     int i, j;
140     for (i = 0;i < High;i++)
141     {
142         for (j = 0;j < Width;j++)
143         {
144             if (canvas[i][j] == 0)
145                 printf(" ");   //   输出空格
146             else if (canvas[i][j] == -1)
147                 printf("#");   //   输出边框#
148             else if (canvas[i][j] == 1)
149                 printf("@");   //   输出蛇头@
150             else if (canvas[i][j] > 1)
151                 printf("*");   //   输出蛇身*
152             else if (canvas[i][j] == -2)
153                 printf("F");   //   输出食物F
154         }
155         printf("\n");
156     }
157     Sleep(100);
158 }
159 
160 void updateWithoutInput()  // 与用户输入无关的更新
161 {
162     moveSnakeByDirection();
163 }
164 
165 void updateWithInput()  // 与用户输入有关的更新
166 {
167     char input;
168     if (kbhit())  // 判断是否有输入
169     {
170         input = getch();  // 根据用户的不同输入来移动,不必输入回车
171         if (input == 'a')
172         {
173             moveDirection = 3;   // 位置左移
174             moveSnakeByDirection();
175         }
176         else if (input == 'd')
177         {
178             moveDirection = 4;  // 位置右移
179             moveSnakeByDirection();
180         }
181         else if (input == 'w')
182         {
183             moveDirection = 1;  // 位置上移
184             moveSnakeByDirection();
185         }
186         else if (input == 's')
187         {
188             moveDirection = 2;   // 位置下移
189             moveSnakeByDirection();
190         }
191     }
192 }
193 
194 int main()
195 {
196     startup();  // 数据初始化    
197     while (1) //  游戏循环执行
198     {
199         show();  // 显示画面
200         updateWithoutInput();  // 与用户输入无关的更新
201         updateWithInput();  // 与用户输入有关的更新
202     }
203     return 0;
204 }
贪吃蛇

  第四章 

    4.2多球反弹

  1 #pragma warning(disable:4996);
  2 
  3 #include <graphics.h>
  4 #include <conio.h>
  5 #include <math.h>
  6 #define High 480  // 游戏画面尺寸
  7 #define Width 640
  8 #define BallNum 15 // 小球个数
  9 
 10 int main()
 11 {
 12     float ball_x[BallNum], ball_y[BallNum]; // 小球的坐标
 13     float ball_vx[BallNum], ball_vy[BallNum]; // 小球的速度
 14     float radius;  // 小球的半径
 15     int i, j;
 16 
 17     radius = 20;
 18 
 19     for (i = 0;i < BallNum;i++) // 随机小球的位置与速度
 20     {
 21         ball_x[i] = rand() % int(Width - 4 * radius) + 2 * radius;
 22         ball_y[i] = rand() % int(High - 4 * radius) + 2 * radius;
 23         ball_vx[i] = (rand() % 2) * 2 - 1;
 24         ball_vy[i] = (rand() % 2) * 2 - 1;
 25     }
 26 
 27     initgraph(Width, High);
 28     BeginBatchDraw();
 29 
 30     while (1)
 31     {
 32         // 绘制黑线、黑色填充的圆
 33         setcolor(BLACK);
 34         setfillcolor(BLACK);
 35         for (i = 0;i < BallNum;i++)
 36             fillcircle(ball_x[i], ball_y[i], radius);
 37 
 38         // 更新小圆坐标
 39         for (i = 0;i < BallNum;i++)
 40         {
 41             ball_x[i] = ball_x[i] + ball_vx[i];
 42             ball_y[i] = ball_y[i] + ball_vy[i];
 43 
 44             // 把超出边界的小球拉回来
 45             if (ball_x[i] < radius)
 46                 ball_x[i] = radius;
 47             if (ball_y[i] < radius)
 48                 ball_y[i] = radius;
 49             if (ball_x[i] > Width - radius)
 50                 ball_x[i] = Width - radius;
 51             if (ball_y[i] > High - radius)
 52                 ball_y[i] = High - radius;
 53         }
 54 
 55         // 判断是否和墙壁碰撞
 56         for (i = 0;i < BallNum;i++)
 57         {
 58             if ((ball_x[i] <= radius) || (ball_x[i] >= Width - radius))
 59                 ball_vx[i] = -ball_vx[i];
 60             if ((ball_y[i] <= radius) || (ball_y[i] >= High - radius))
 61                 ball_vy[i] = -ball_vy[i];
 62         }
 63 
 64         float minDistances2[BallNum][2]; // 记录某个小球,距离它最近的小球的距离,这个小球的下标
 65         for (i = 0;i < BallNum;i++)
 66         {
 67             minDistances2[i][0] = 9999999;
 68             minDistances2[i][1] = -1;
 69         }
 70 
 71         // 求解所有小球两两之间的距离平方
 72         for (i = 0;i < BallNum;i++)
 73         {
 74             for (j = 0;j < BallNum;j++)
 75             {
 76                 if (i != j) // 自己和自己不需要比
 77                 {
 78                     float dist2;
 79                     dist2 = (ball_x[i] - ball_x[j]) * (ball_x[i] - ball_x[j])
 80                         + (ball_y[i] - ball_y[j]) * (ball_y[i] - ball_y[j]);
 81                     if (dist2 < minDistances2[i][0])
 82                     {
 83                         minDistances2[i][0] = dist2;
 84                         minDistances2[i][1] = j;
 85                     }
 86                 }
 87             }
 88         }
 89 
 90         // 判断球之间是否碰撞
 91         for (i = 0;i < BallNum;i++)
 92         {
 93             if (minDistances2[i][0] <= 4 * radius * radius) // 最小距离小于阈值,发生碰撞
 94             {
 95                 j = minDistances2[i][1];
 96                 // 交换速度                
 97                 int temp;
 98                 temp = ball_vx[i]; ball_vx[i] = ball_vx[j]; ball_vx[j] = temp;
 99                 temp = ball_vy[i]; ball_vy[i] = ball_vy[j]; ball_vy[j] = temp;
100 
101                 minDistances2[j][0] = 999999999; // 避免交换两次速度,又回去了
102                 minDistances2[j][1] = -1;
103             }
104         }
105 
106         // 绘制黄线、绿色填充的圆
107         setcolor(YELLOW);
108         setfillcolor(GREEN);
109         for (i = 0;i < BallNum;i++)
110             fillcircle(ball_x[i], ball_y[i], radius);
111 
112         FlushBatchDraw();
113 
114         // 延时
115         Sleep(3);
116     }
117     EndBatchDraw();
118     closegraph();
119     return 0;
120 }
4.2多球反弹

    4.3实时钟表

  1 #pragma warning(disable:4996);
  2 
  3 #include <graphics.h>
  4 #include <conio.h>
  5 #include <math.h>
  6 
  7 #define High 480  // 游戏画面尺寸
  8 #define Width 640
  9 #define    PI    3.14159
 10 
 11 int main()
 12 {
 13     initgraph(Width, High);        // 初始化 640 x 480 的绘图窗口    
 14     int center_x, center_y;      // 中心点的坐标,也是表的中心
 15     center_x = Width / 2;
 16     center_y = High / 2;
 17     int secondLength = Width / 5;           // 秒针的长度
 18     int minuteLength = Width / 6;           // 分针的长度
 19     int hourLength = Width / 7;             // 时针的长度
 20 
 21     int secondEnd_x, secondEnd_y;    // 秒针的终点
 22     int minuteEnd_x, minuteEnd_y;    // 分针的终点
 23     int hourEnd_x, hourEnd_y;    // 时针的终点
 24     float secondAngle;       // 秒钟对应的角度
 25     float minuteAngle;       // 分钟对应的角度
 26     float hourAngle;         // 时钟对应的角度
 27 
 28     SYSTEMTIME ti;                // 定义变量保存当前时间
 29 
 30     BeginBatchDraw();
 31     while (1)
 32     {
 33         // 绘制一个简单的表盘
 34         setlinestyle(PS_SOLID, 1);
 35         setcolor(WHITE);
 36         circle(center_x, center_y, Width / 4);
 37 
 38         // 画刻度
 39         int x, y, i;
 40         for (i = 0; i < 60; i++)
 41         {
 42             x = center_x + int(Width / 4.3 * sin(PI * 2 * i / 60));
 43             y = center_y + int(Width / 4.3 * cos(PI * 2 * i / 60));
 44 
 45             if (i % 15 == 0)
 46                 bar(x - 5, y - 5, x + 5, y + 5);
 47             else if (i % 5 == 0)
 48                 circle(x, y, 3);
 49             else
 50                 putpixel(x, y, WHITE);
 51         }
 52 
 53         outtextxy(center_x - 25, center_y + Width / 6, "我的时钟");
 54 
 55         GetLocalTime(&ti);        // 获取当前时间
 56         // 秒钟角度变化
 57         secondAngle = ti.wSecond * 2 * PI / 60;  // 一圈一共2*PI,一圈60秒,一秒钟秒钟走过的角度为2*PI/60
 58         // 分钟角度变化
 59         minuteAngle = ti.wMinute * 2 * PI / 60 + secondAngle / 60;  // 一圈一共2*PI,一圈60分,一分钟分钟走过的角度为2*PI/60
 60         // 时钟角度变化
 61         hourAngle = ti.wHour * 2 * PI / 12 + minuteAngle / 12;  // 一圈一共2*PI,一圈12小时,一小时时钟走过的角度为2*PI/12        
 62         // 由角度决定的秒针端点坐标
 63         secondEnd_x = center_x + secondLength * sin(secondAngle);
 64         secondEnd_y = center_y - secondLength * cos(secondAngle);
 65 
 66         // 由角度决定的分针端点坐标
 67         minuteEnd_x = center_x + minuteLength * sin(minuteAngle);
 68         minuteEnd_y = center_y - minuteLength * cos(minuteAngle);
 69 
 70         // 由角度决定的时针端点坐标
 71         hourEnd_x = center_x + hourLength * sin(hourAngle);
 72         hourEnd_y = center_y - hourLength * cos(hourAngle);
 73 
 74         setlinestyle(PS_SOLID, 2);
 75         setcolor(YELLOW);
 76         line(center_x, center_y, secondEnd_x, secondEnd_y); // 画秒针
 77 
 78         setlinestyle(PS_SOLID, 5);
 79         setcolor(BLUE);
 80         line(center_x, center_y, minuteEnd_x, minuteEnd_y); // 画分针
 81 
 82         setlinestyle(PS_SOLID, 10);
 83         setcolor(RED);
 84         line(center_x, center_y, hourEnd_x, hourEnd_y); // 画时针
 85 
 86         FlushBatchDraw();
 87         Sleep(10);
 88 
 89         setcolor(BLACK);
 90         setlinestyle(PS_SOLID, 2);
 91         line(center_x, center_y, secondEnd_x, secondEnd_y);  // 隐藏前一帧的秒针
 92         setlinestyle(PS_SOLID, 5);
 93         line(center_x, center_y, minuteEnd_x, minuteEnd_y); // 隐藏前一帧的分针
 94         setlinestyle(PS_SOLID, 10);
 95         line(center_x, center_y, hourEnd_x, hourEnd_y); // 隐藏前一帧的时针
 96     }
 97 
 98     EndBatchDraw();
 99     getch();                // 按任意键继续    
100     closegraph();            // 关闭绘图窗口
101     return 0;
102 }
4.3实时时钟

    4.4Easy实现消砖块

  1 #pragma warning(disable:4996);
  2 
  3 #include <conio.h>
  4 #include <graphics.h>
  5 
  6 #define High 480  // 游戏画面尺寸
  7 #define Width 640
  8 #define Brick_num 10 // 砖块个数
  9 
 10 // 全局变量
 11 int ball_x, ball_y; // 小球的坐标
 12 int ball_vx, ball_vy; // 小球的速度
 13 int radius;  // 小球的半径
 14 int bar_x, bar_y; // 挡板中心坐标
 15 int bar_high, bar_width;  // 挡板的高度和宽度
 16 int bar_left, bar_right, bar_top, bar_bottom; // 挡板的上下左右位置坐标
 17 
 18 int isBrickExisted[Brick_num]; // 每个砖块是否存在,1为存在,0为没有了
 19 int brick_high, brick_width; // 每个砖块的高度和宽度
 20 
 21 void startup()  // 数据初始化
 22 {
 23     ball_x = Width / 2;
 24     ball_y = High / 2;
 25     ball_vx = 1;
 26     ball_vy = 1;
 27     radius = 20;
 28 
 29     bar_high = High / 20;
 30     bar_width = Width / 2;
 31     bar_x = Width / 2;
 32     bar_y = High - bar_high / 2;
 33     bar_left = bar_x - bar_width / 2;
 34     bar_right = bar_x + bar_width / 2;
 35     bar_top = bar_y - bar_high / 2;
 36     bar_bottom = bar_y + bar_high / 2;
 37 
 38     brick_width = Width / Brick_num;
 39     brick_high = High / Brick_num;
 40 
 41     int i;
 42     for (i = 0;i < Brick_num;i++)
 43         isBrickExisted[i] = 1;
 44 
 45     initgraph(Width, High);
 46     BeginBatchDraw();
 47 }
 48 
 49 void clean()  // 消除画面
 50 {
 51     setcolor(BLACK);
 52     setfillcolor(BLACK);
 53     fillcircle(ball_x, ball_y, radius);     // 绘制黑线、黑色填充的圆
 54     bar(bar_left, bar_top, bar_right, bar_bottom);    // 绘制黑线、黑色填充的挡板
 55 
 56     int i, brick_left, brick_right, brick_top, brick_bottom;
 57     for (i = 0;i < Brick_num;i++)
 58     {
 59         brick_left = i * brick_width;
 60         brick_right = brick_left + brick_width;
 61         brick_top = 0;
 62         brick_bottom = brick_high;
 63         if (!isBrickExisted[i])     // 砖块没有了,绘制黑色
 64             fillrectangle(brick_left, brick_top, brick_right, brick_bottom);
 65     }
 66 }
 67 
 68 void show()  // 显示画面
 69 {
 70     setcolor(YELLOW);
 71     setfillcolor(GREEN);
 72     fillcircle(ball_x, ball_y, radius);    // 绘制黄线、绿色填充的圆
 73     bar(bar_left, bar_top, bar_right, bar_bottom);    // 绘制黄线、绿色填充的挡板
 74 
 75     int i, brick_left, brick_right, brick_top, brick_bottom;
 76 
 77     for (i = 0;i < Brick_num;i++)
 78     {
 79         brick_left = i * brick_width;
 80         brick_right = brick_left + brick_width;
 81         brick_top = 0;
 82         brick_bottom = brick_high;
 83 
 84         if (isBrickExisted[i])     // 砖块存在,绘制砖块
 85         {
 86             setcolor(WHITE);
 87             setfillcolor(RED);
 88             fillrectangle(brick_left, brick_top, brick_right, brick_bottom);    // 绘制砖块
 89         }
 90     }
 91 
 92     FlushBatchDraw();
 93     // 延时
 94     Sleep(3);
 95 }
 96 
 97 void updateWithoutInput()  // 与用户输入无关的更新
 98 {
 99     // 挡板和小圆碰撞,小圆反弹
100     if (((ball_y + radius >= bar_top) && (ball_y + radius < bar_bottom - bar_high / 3))
101         || ((ball_y - radius <= bar_bottom) && (ball_y - radius > bar_top - bar_high / 3)))
102         if ((ball_x >= bar_left) && (ball_x <= bar_right))
103             ball_vy = -ball_vy;
104 
105     // 更新小圆坐标
106     ball_x = ball_x + ball_vx;
107     ball_y = ball_y + ball_vy;
108 
109     // 小圆和边界碰撞
110     if ((ball_x == radius) || (ball_x == Width - radius))
111         ball_vx = -ball_vx;
112     if ((ball_y == radius) || (ball_y == High - radius))
113         ball_vy = -ball_vy;
114 
115     // 判断小圆是否和某个砖块碰撞
116     int i, brick_left, brick_right, brick_bottom;
117     for (i = 0;i < Brick_num;i++)
118     {
119         if (isBrickExisted[i])     // 砖块存在,才判断
120         {
121             brick_left = i * brick_width;
122             brick_right = brick_left + brick_width;
123             brick_bottom = brick_high;
124             if ((ball_y == brick_bottom + radius) && (ball_x >= brick_left) && (ball_x <= brick_right))
125             {
126                 isBrickExisted[i] = 0;
127                 ball_vy = -ball_vy;
128             }
129         }
130     }
131 }
132 
133 void updateWithInput()  // 与用户输入有关的更新
134 {
135     char input;
136     if (kbhit())  // 判断是否有输入
137     {
138         input = getch();  // 根据用户的不同输入来移动,不必输入回车
139         if (input == 'a' && bar_left > 0)
140         {
141             bar_x = bar_x - 15;  // 位置左移
142             bar_left = bar_x - bar_width / 2;
143             bar_right = bar_x + bar_width / 2;
144         }
145         if (input == 'd' && bar_right < Width)
146         {
147             bar_x = bar_x + 15;  // 位置右移
148             bar_left = bar_x - bar_width / 2;
149             bar_right = bar_x + bar_width / 2;
150         }
151         if (input == 'w' && bar_top > 0)
152         {
153             bar_y = bar_y - 15;  // 位置左移
154             bar_top = bar_y - bar_high / 2;
155             bar_bottom = bar_y + bar_high / 2;
156         }
157         if (input == 's' && bar_bottom < High)
158         {
159             bar_y = bar_y + 15;  // 位置右移
160             bar_top = bar_y - bar_high / 2;
161             bar_bottom = bar_y + bar_high / 2;
162         }
163     }
164 }
165 
166 void gameover()
167 {
168     EndBatchDraw();
169     closegraph();
170 }
171 
172 int main()
173 {
174     startup();  // 数据初始化    
175     while (1)  //  游戏循环执行
176     {
177         clean();  // 把之前绘制的内容取消
178         updateWithoutInput();  // 与用户输入无关的更新
179         updateWithInput();     // 与用户输入有关的更新
180         show();  // 显示新画面
181     }
182     gameover();     // 游戏结束、后续处理
183     return 0;
184 }
4.4反弹球消砖块

 

 4.5鼠标交互的反弹器

  1 #pragma warning(disable:4996);
  2 #include <conio.h>
  3 #include <graphics.h>
  4 
  5 #define High 480  // 游戏画面尺寸
  6 #define Width 640
  7 #define Brick_num 10 // 砖块个数
  8 
  9 // 全局变量
 10 int ball_x, ball_y; // 小球的坐标
 11 int ball_vx, ball_vy; // 小球的速度
 12 int radius;  // 小球的半径
 13 int bar_x, bar_y; // 挡板中心坐标
 14 int bar_high, bar_width;  // 挡板的高度和宽度
 15 int bar_left, bar_right, bar_top, bar_bottom; // 挡板的上下左右位置坐标
 16 
 17 int isBrickExisted[Brick_num]; // 每个砖块是否存在,1为存在,0为没有了
 18 int brick_high, brick_width; // 每个砖块的高度和宽度
 19 
 20 void startup()  // 数据初始化
 21 {
 22     ball_x = Width / 2;
 23     ball_y = High / 2;
 24     ball_vx = 1;
 25     ball_vy = 1;
 26     radius = 20;
 27 
 28     bar_high = High / 20;
 29     bar_width = Width / 2;
 30     bar_x = Width / 2;
 31     bar_y = High - bar_high / 2;
 32     bar_left = bar_x - bar_width / 2;
 33     bar_right = bar_x + bar_width / 2;
 34     bar_top = bar_y - bar_high / 2;
 35     bar_bottom = bar_y + bar_high / 2;
 36 
 37     brick_width = Width / Brick_num;
 38     brick_high = High / Brick_num;
 39 
 40     int i;
 41     for (i = 0;i < Brick_num;i++)
 42         isBrickExisted[i] = 1;
 43 
 44     initgraph(Width, High);
 45     BeginBatchDraw();
 46 }
 47 
 48 void clean()  // 消除画面
 49 {
 50     setcolor(BLACK);
 51     setfillcolor(BLACK);
 52     fillcircle(ball_x, ball_y, radius);     // 绘制黑线、黑色填充的圆
 53     bar(bar_left, bar_top, bar_right, bar_bottom);    // 绘制黑线、黑色填充的挡板
 54 
 55     int i, brick_left, brick_right, brick_top, brick_bottom;
 56     for (i = 0;i < Brick_num;i++)
 57     {
 58         brick_left = i * brick_width;
 59         brick_right = brick_left + brick_width;
 60         brick_top = 0;
 61         brick_bottom = brick_high;
 62         if (!isBrickExisted[i])     // 砖块没有了,绘制黑色
 63             fillrectangle(brick_left, brick_top, brick_right, brick_bottom);
 64     }
 65 }
 66 
 67 void show()  // 显示画面
 68 {
 69     setcolor(YELLOW);
 70     setfillcolor(GREEN);
 71     fillcircle(ball_x, ball_y, radius);    // 绘制黄线、绿色填充的圆
 72     bar(bar_left, bar_top, bar_right, bar_bottom);    // 绘制黄线、绿色填充的挡板
 73 
 74     int i, brick_left, brick_right, brick_top, brick_bottom;
 75 
 76     for (i = 0;i < Brick_num;i++)
 77     {
 78         brick_left = i * brick_width;
 79         brick_right = brick_left + brick_width;
 80         brick_top = 0;
 81         brick_bottom = brick_high;
 82 
 83         if (isBrickExisted[i])     // 砖块存在,绘制砖块
 84         {
 85             setcolor(WHITE);
 86             setfillcolor(RED);
 87             fillrectangle(brick_left, brick_top, brick_right, brick_bottom);    // 绘制砖块
 88         }
 89     }
 90 
 91     FlushBatchDraw();
 92     // 延时
 93     Sleep(3);
 94 }
 95 
 96 void updateWithoutInput()  // 与用户输入无关的更新
 97 {
 98     // 挡板和小圆碰撞,小圆反弹
 99     if (((ball_y + radius >= bar_top) && (ball_y + radius < bar_bottom - bar_high / 3))
100         || ((ball_y - radius <= bar_bottom) && (ball_y - radius > bar_top - bar_high / 3)))
101         if ((ball_x >= bar_left) && (ball_x <= bar_right))
102             ball_vy = -ball_vy;
103 
104     // 更新小圆坐标
105     ball_x = ball_x + ball_vx;
106     ball_y = ball_y + ball_vy;
107 
108     // 小圆和边界碰撞
109     if ((ball_x == radius) || (ball_x == Width - radius))
110         ball_vx = -ball_vx;
111     if ((ball_y == radius) || (ball_y == High - radius))
112         ball_vy = -ball_vy;
113 
114     // 判断小圆是否和某个砖块碰撞
115     int i, brick_left, brick_right, brick_bottom;
116     for (i = 0;i < Brick_num;i++)
117     {
118         if (isBrickExisted[i])     // 砖块存在,才判断
119         {
120             brick_left = i * brick_width;
121             brick_right = brick_left + brick_width;
122             brick_bottom = brick_high;
123             if ((ball_y == brick_bottom + radius) && (ball_x >= brick_left) && (ball_x <= brick_right))
124             {
125                 isBrickExisted[i] = 0;
126                 ball_vy = -ball_vy;
127             }
128         }
129     }
130 }
131 
132 void updateWithInput()  // 与用户输入有关的更新
133 {
134     MOUSEMSG m;        // 定义鼠标消息
135     if (MouseHit())  //这个函数用于检测当前是否有鼠标消息
136     {
137         m = GetMouseMsg();      // 获取一条鼠标消息
138         if (m.uMsg == WM_MOUSEMOVE)
139         {
140             // 鼠标移动时,挡板的位置等于鼠标所在的位置
141             bar_x = m.x;
142             bar_y = m.y;
143             bar_left = bar_x - bar_width / 2;
144             bar_right = bar_x + bar_width / 2;
145             bar_top = bar_y - bar_high / 2;
146             bar_bottom = bar_y + bar_high / 2;
147         }
148         else if (m.uMsg == WM_LBUTTONDOWN)
149         {
150             // 按下鼠标左键,初始化小球的位置为挡板上面中心
151             ball_x = bar_x;
152             ball_y = bar_top - radius - 3;
153         }
154     }
155 }
156 
157 void gameover()
158 {
159     EndBatchDraw();
160     closegraph();
161 }
162 
163 int main()
164 {
165     startup();  // 数据初始化    
166     while (1)  //  游戏循环执行
167     {
168         clean();  // 把之前绘制的内容取消
169         updateWithoutInput();  // 与用户输入无关的更新
170         updateWithInput();     // 与用户输入有关的更新
171         show();  // 显示新画面
172     }
173     gameover();     // 游戏结束、后续处理
174     return 0;
175 }
鼠标交互的反弹器
原文地址:https://www.cnblogs.com/sylvia1111/p/15600334.html