服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言数组实现打砖块游戏

C语言数组实现打砖块游戏

2022-11-29 13:49无限的菜鸟 C/C++

这篇文章主要为大家详细介绍了C语言数组实现打砖块游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了C语言数组实现打砖块游戏的具体代码,供大家参考,具体内容如下

这次我们使用数组来改进打砖块游戏

反弹的球

首先我们实现一个可以在荧幕上反弹的小球。使用二维数组 int canvas[High][Width] ( 和js的canvas没有一毛钱关系)来储存画布上的所有元素,值为0时输出空格,值为1时输出小球。

设小球坐标为(ball_x, ball_y),则有canvas[ball_x][ball_y] = 1 ,且暂时将其他元素的值设为0。

每次更新小球位置时将原位置元素设为0,将新位置元素设为1即可。

注意:gotoxy函数用于清屏重画,很久以前讲过的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <cwindow.h>
// 画面尺寸设定
#define High 15
#define Width 20
 
//全局变量
int ball_x,ball_y;    //小球坐标
int ball_vx,ball_vy;//小球速度
int canvas[High][Width] = [0];
 
void gotoxy(int x, int y)    //移动光标便于清屏重画
{
    HANDLE handle = GetStdHandle(STD_UOTPUT_HANDLE);
    CROOD pos;
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(handle, pos);
}
 
void startup()                //数据初始化
{
    ball_x = 0;
    ball_y = Width/2;
    ball_vx = 1;
    ball_vy = 1;
    canvas[ball_x][ball_y] = 1;
}
 
void show()
{
    gotoxy(0, 0);
    int i,j;
    for(i=0; i<High; i++)
    {
        for(j=0; j<Width; j++)
        {
            if (canvas[i][j] == 0)
                printf(" ");//输出空格
            else if (canvas[i][j] == 1)
                printf("O");//输出小球
        }
        printf("|\n");//每画完一行显示边界并换行
    }
    for(j=0; j<Width; j++)
        printf("-");//最后画下边界
}
 
void updateWithoutInput()    //无关输入的更新
{
    //小球移动
    canvas[ball_x][ball_y] = 0;
    ball_x = ball_x + ball_vx;
    ball_y = ball_y + ball_vy;
    //反弹判断
    if ((ball_x == 0)||(ball_x == High - 1))
        ball_vx = -ball_vx;
    if ((ball_y == 0)||(ball_y == Width - 1))
        ball_vy = -ball_vy;
            
    canvas[ball_x][ball_y] = 1;
    //休眠时间,避免刷新过快
    sleep(50);
}
 
void updateWithInput()
{}
 
int main()
{
    startup();
    while(1)
    {
        show();
        updateWithoutInput();
        updateWithInput();
    }
    return 0;
}

这里要注意的是:

  • updateWithInput留空,因为现在还没有用户操作的功能实现。
  • main是死循环,所以测试时要注意,当然也可以改进。

增加挡板

现在我们可以新定义,当数组中某一元素值为2时,输出挡板“ * ”。

并且为updateWithInput增加移动挡板的功能,每次移动一个单位作为其速度(当然可以改成别的数)。

挡板的刷新方式和小球一样,先将原位置清零然后把新位置元素改为2。

需要增加的内容如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
//全局变量
int position_x,position_y; //挡板中心坐标
int ridus;    //挡板半径,就是延伸的长度
int left,right;    //挡板左右位置
 
//初始化
ridus = 5;
position_x = High - 1;
position_y = Width/2;
left = position_y - ridus;
right = position_x + ridus;
 
int k;
for(k=left; k<=right; k++)
    canvas[position_x][k] = 2;
 
//输出部分
...
else if (canvas[i][j] == 2)
    printf("*");
...
 
//更新部分(与输入无关)
if (ball_x == High - 2)
{
    //判断是否挡住
    if ((ball_y >= left)&&(ball_y <= right))
    {
        printf("\a");
    }
    else    //未挡住
    {
        printf("游戏失败\n");
        printf("pause");
        exit(0);
    }
}
 
//与输入有关的更新
void updateWithInput()
{
    char input;
    if (kbhit())    //判断是否有输入
        input = getch();
    if ((input == 'a')&&(left > 0))//左移
    {
        canvas[position_x][right] = 0;
        position_y --;
        left = position_y - ridus;
        right = position_x + ridus;
        canvas[position_x][left] = 2;
    }
    if ((input == 'd')&&(right < Width -1))//右移
    {
        canvas[position_x][left] = 0;
        position_y ++;
        left = position_y - ridus;
        right = position_x + ridus;
        canvas[position_x][right] = 2;    
    }
}

打砖块

这部分内容就和之前的内容一样了。

需要增加的内容有:

1. 初始砖块
2. 小球碰到砖块的判定
3. 碰到砖块后的更新(砖块消失、小球反弹)

具体代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//初始化
int k,i;
 
for(k=0; k<Width; k++)
    for(i=0; i<high/4; i++)    //这里是画砖块,可以根据修改 i 的范围改变砖块的排数
        canvas[i][k] = 3;
//输出
...
else if (canvas[i][j] == 3)
    printf("#");
...
//碰到砖块后
if (canvas[ball_x + ball_vx][ball_y + ball_vy] == 3)
{
    canvas[ball_x + ball_vx][ball_y + ball_vy] = 0;
    ball_vx = -ball_vx;
    ball_vy = -ball_vy;
    printf("\a");
}

最后

1. 坐标系是x轴向下,y 轴向右。
2. 实际对碰撞的判定是在斜方向上,当然可以改进判定内容。
3. 游戏胜利条件还没有完善。

全代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <cwindow.h>
// 画面尺寸设定
#define High 15
#define Width 20
 
//全局变量
int ball_x,ball_y;    //小球坐标
int ball_vx,ball_vy;//小球速度
int canvas[High][Width] = [0];
int position_x,position_y; //挡板中心坐标
int ridus;    //挡板半径,就是延伸的长度
int left,right;    //挡板左右位置
 
void gotoxy(int x, int y)    //移动光标便于清屏重画
{
    HANDLE handle = GetStdHandle(STD_UOTPUT_HANDLE);
    CROOD pos;
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(handle, pos);
}
 
void startup()                //数据初始化
{
    ball_x = 0;
    ball_y = Width/2;
    ball_vx = 1;
    ball_vy = 1;
    canvas[ball_x][ball_y] = 1;
 
    ridus = 5;
    position_x = High - 1;
    position_y = Width/2;
    left = position_y - ridus;
    right = position_x + ridus;
 
    int k,i;
    for(k=left; k<=right; k++)
    canvas[position_x][k] = 2;
 
    for(k=0; k<Width; k++)
        for(i=0; i<high/4; i++)    //这里是画砖块,可以根据修改 i 的范围改变砖块的排数
            canvas[i][k] = 3;
}
 
void show()
{
    gotoxy(0, 0);
    int i,j;
    for(i=0; i<High; i++)
    {
        for(j=0; j<Width; j++)
        {
            if (canvas[i][j] == 0)
                printf(" ");//输出空格
            else if (canvas[i][j] == 1)
                printf("O");//输出小球
            else if (canvas[i][j] == 2)
                printf("*");
            else if (canvas[i][j] == 3)
                printf("#");
        }
        printf("|\n");//每画完一行显示边界并换行
    }
    for(j=0; j<Width; j++)
        printf("-");//最后画下边界
}
 
void updateWithoutInput()    //无关输入的更新
{
    if (canvas[ball_x + ball_vx][ball_y + ball_vy] == 3)
    {
        canvas[ball_x + ball_vx][ball_y + ball_vy] = 0;
        ball_vx = -ball_vx;
        ball_vy = -ball_vy;
        printf("\a");
    }
    if (ball_x == High - 2)
    {
        //判断是否挡住
        if ((ball_y >= left)&&(ball_y <= right))
        {
            printf("\a");
        }
        else    //未挡住
        {
            printf("游戏失败\n");
            printf("pause");
            exit(0);
        }
    }
    //小球移动
    canvas[ball_x][ball_y] = 0;
    ball_x = ball_x + ball_vx;
    ball_y = ball_y + ball_vy;
    //反弹判断
    if ((ball_x == 0)||(ball_x == High - 1))
        ball_vx = -ball_vx;
    if ((ball_y == 0)||(ball_y == Width - 1))
        ball_vy = -ball_vy;
            
    canvas[ball_x][ball_y] = 1;
    //休眠时间,避免刷新过快
    sleep(50);
}
 
void updateWithInput()
{
    char input;
    if (kbhit())    //判断是否有输入
        input = getch();
    if ((input == 'a')&&(left > 0))//左移
    {
        canvas[position_x][right] = 0;
        position_y --;
        left = position_y - ridus;
        right = position_x + ridus;
        canvas[position_x][left] = 2;
    }
    if ((input == 'd')&&(right < Width -1))//右移
    {
        canvas[position_x][left] = 0;
        position_y ++;
        left = position_y - ridus;
        right = position_x + ridus;
        canvas[position_x][right] = 2;    
    }
}
 
int main()
{
    startup();
    while(1)
    {
        show();
        updateWithoutInput();
        updateWithInput();
    }
    return 0;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/weixin_54597744/article/details/119033545

延伸 · 阅读

精彩推荐
  • C/C++C++ 递归遍历文件并计算MD5的实例代码

    C++ 递归遍历文件并计算MD5的实例代码

    在本篇文章里小编给大家整理的是一篇关于C++ 递归遍历文件并计算MD5的实例代码,有兴趣的朋友们可以学习参考下。...

    lyshark8312021-11-30
  • C/C++你真的懂C++中的namespace用法

    你真的懂C++中的namespace用法

    命名空间(namespace)为防止名字冲突提供了更加可控的机制,命名空间分割了全局命名空间,其中每个命名空间是一个作用域,今天通过本文给大家分享C++中...

    赚钱养个小智障- ̗̀(๑ᵔ4972021-11-16
  • C/C++C语言算法金手指摩尔投票法手撕绝大多数问题

    C语言算法金手指摩尔投票法手撕绝大多数问题

    这篇文章主要为大家介绍了C语言法之金手指摩尔投票法手撕绝大多数问题的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助 ...

    乔乔家的龙龙9622022-09-21
  • C/C++Qt在vs2019中使用及设置方法

    Qt在vs2019中使用及设置方法

    这篇文章主要介绍了Qt在vs2019中使用及设置方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面...

    WTQRookie11752021-09-22
  • C/C++C语言打印正方形实例代码

    C语言打印正方形实例代码

    大家好,本篇文章主要讲的是C语言打印正方形实例代码,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览...

    天笙月3422022-08-03
  • C/C++关于C++继承你可能会忽视的点

    关于C++继承你可能会忽视的点

    继承是面向对象三大特性之一,有些类与类之间存在特殊的关系,下面这篇文章主要给大家介绍了关于C++继承你可能会忽视的点,文中通过实例代码介绍的非常...

    ^jhao^10722022-09-26
  • C/C++C 字符串数组排序的小例子

    C 字符串数组排序的小例子

    C 字符串数组排序的小例子,需要的朋友可以参考一下...

    C语言教程网1842020-11-19
  • C/C++C++指针与引用的异同

    C++指针与引用的异同

    这篇文章主要介绍了C++指针与引用的异同,文章以C++指针与引用的相关资料结合指针和引用的相同点和区别展开详细内容,需要的朋友可以参考一下...

    梁唐10422022-02-23