坦克大战----Ubuntu终端游戏

本文介绍了一个基于Ubuntu终端的坦克大战游戏实现。游戏利用C++编写,使用list容器存储敌方坦克和子弹,通过概率分配实现敌方坦克的智能行为。玩家需要击败所有敌方坦克以获胜。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

还是为了更好对学习的知识进行巩固,所以又基于ubuntu的终端写了坦克大战的游戏。此坦克大战只有一张地图,玩家的坦克需要击败所有敌方的坦克才能胜利,而敌方杀死玩家坦克或者大本营被敌方攻克玩家都算失败。
本代码中用到的c++新知识是list容器。
本代码中的敌方坦克存放在一个list容器中,所有子弹也是存放在一个list容器中,通过采用对敌方坦克的行为赋以不同概率来实现敌方坦克的行动。
具体代码如下:

TankWar.h

#ifndef TANK_WAR_H
#define TANK_WAR_H

#include <iostream>
#include <ctime>
#include <cstdlib>
#include <pthread.h>
#include <vector>
#include <list>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <errno.h>
#include <linux/input.h>
#include <stdexcept>

using namespace std;


enum {DIR_UP=0,DIR_DOWN,DIR_LEFT,DIR_RIGHT};                //坦克及炮弹朝向
enum {EMPTY=0,WALL,NORMAL_BULLET,LIGHT_BULLET,TANK,BOSS};   //地图上的所有可能的单元
enum {NORMAL=0,LIGHT};                                      //炮弹类型:普通炮弹,激光
enum {LEFT_BORN=0,CENTER_BORN,RIGHT_BORN};                  //敌人出现的地点:左上角  中间上方  右上角

//炮弹
typedef struct Bullet                           
{
    //炮弹坐标
    int x;              
    int y;
    short type;//炮弹类型
    short direction;//炮弹朝向
} Bullet;
//坦克
typedef struct Tank
{
    //坦克中心坐标
    int centX;
    int centY;
    //坦克使用的炮弹类型
    short bulletType;
    //坦克的朝向
    short direction;
} Tank;
//大本营的boss
typedef struct Boss
{
    //boss坐标
    int centX;
    int centY;
    //判断boss是否存活
    bool alive;
} Boss;

class TankWar
{
    private:
        Tank theGod;                                                    //英雄坦克
        Boss boss;                                                      //大本营
        list<Bullet > bull;                                             //保存所有炮弹的list容器
        list<Tank > enemy;                                              //保存所有敌方坦克的list容器
        bool    gameEnd;                                                //游戏结束标记
        short   map[100][100];                                          //游戏区域
        unsigned char screenWidth,screenHeight;                         //游戏区域宽度和高度
        short   EnemyNumOnScreen;                                       //在游戏区域内的敌人数量
        short   EnemyNumUnderScreen;                                    //还能上战场的敌人数量
    public:
        TankWar(unsigned char=30 ,unsigned char = 30,short = 20);       //构造函数
        void GameStart();                                               //开始游戏
    private:
        void InitMap();                                                 //初始化地图
        void GameOverNotice(string);                                    //游戏结束提示
        void TankMove(Tank&,short);                                     //移动坦克
        void MoveLeft(Tank&);                                           //向左移动坦克
        void MoveRight(Tank&);                                          //向右移动坦克
        void MoveUp(Tank&);                                             //向上移动坦克
        void MoveDown(Tank&);                                           //向下移动坦克
        void CreatEnemy();                                              //生成一个敌人
        bool BornPlaceOk(short);                                        //判断敌人出生点是否适合敌人出生
        void CreatTankGod();                                            //创造英雄坦克
        void CreatBoss();                                               //创造大本营
        void ShowScreen();                                              //打印当前屏幕
        void RedescribeTank(Tank&,short);                               //重新构成坦克
        void KeyControl();                                              //按键控制
        void EnemyControl();                                            //控制敌人
        void BulletControl();                                           //控制子弹
        void TankShoot(Tank&);                                          //坦克射击
        bool MoveBullet(Bullet&);                                       //移动炮弹
        void TankAutoRun(Tank&);                                        //敌方坦克自行移动
        bool TargetInFront(Tank&);                                      //判断前方是否有攻击目标
        void CloseToGodTank(Tank&);                                     //向英雄坦克靠近
        void CloseToHome(Tank&);                                        //向大本营靠近
    private:
        static void *_Key_Control(void *);
        static void *_Enemy_Control(void *);
        static void *_Bullet_Control(void *);
    private:
        inline void EraseCurrentTank(Tank tank)                         //擦除当前坦克在地图上的痕迹
        {
            for(int r = tank.centY-1;r<=tank.centY+1;r++)
            {
                for(int c=tank.centX-1;c <= tank.centX+1;c++)
                {
                    map[c][r] = EMPTY;
                }
            }
        }
        inline void EraseBoss(Boss &boss)                               //擦除大本营
        {
            for(int r = boss.centY-1;r<=boss.centY+1;r++)
            {
                for(int c=boss.centX-1;c<=boss.centX+1;c++)
                {
                    map[c][r] = EMPTY;
                }
            }
        }
};

#endif

TankWar.cpp

#include <iostream>
#include "TankWar.h"

TankWar::TankWar(unsigned char width, unsigned char height,short enemyNum)
{
    for(int i=0;i<height;i++)
    {
        for(int j=0;j<width;j++)
        {
            map[j][i] = EMPTY;
        }
    }
    srand(time(0));
    EnemyNumOnScreen = 0;
    EnemyNumUnderScreen = enemyNum;
    screenWidth = width;
    screenHeight = height;
    CreatBoss();
    CreatTankGod();
    InitMap();
    ShowScreen();
}
void TankWar::InitMap()
{
    //BOSS外围修筑保护墙
    for(int r = boss.centY-2;r<= boss.centY+1;r++)
        map[boss.centX-2][r] = WALL;
    for(int r = boss.centY-2;r<= boss.centY+1;r++)
        map[boss.centX+2][r] = WALL;
    for(int c = boss.centX-1;c<= boss.centX+1;c++)
        map[c][boss.centY-2] = WALL;
    //战场区域砖块
    for(int r = 6;r<=screenHeight - 8;r++)
    {
        for(int c=0;c<screenWidth;c++)
        {
            map[c][r] = WALL;
        }
    }

}
void TankWar::GameStart()
{
    gameEnd = false;
    pthread_t id_key_ctl = 1,id_enemy = 2, id_bullet = 3;
    pthread_create(&id_key_ctl,NULL,&_Key_Control,this);
    pthread_create(&id_enemy,NULL,&_Enemy_Control,this);
    pthread_create(&id_bullet,NULL,&_Bullet_Control,this);
    while(!gameEnd)
    {
        if(EnemyNumUnderScreen + EnemyNumOnScreen == 0)
            gameEnd = true;
        if(boss.alive == false)
            gameEnd = true;
    }
    pthread_join(id_key_ctl,NULL);
    pthread_join(id_enemy,NULL);
    pthread_join(id_bullet,NULL);
    if(boss.alive) GameOverNotice("You Win");
    else GameOverNotice("You Loss");
}
void TankWar::ShowScreen()
{
    system("clear");
    for(int i=0;i<screenWidth+2;i++)
        cout<<"_";
    cout<<endl;
    for(int r=0;r < screenHeight;r++)
    {
        cout << "|";
        for(int c=0;c < screenWidth;c++)
        {
            switch(map[c][r])
            {
                case EMPTY: cout<<" ";break;
                case WALL: cout<< "#";break;
                case NORMAL_BULLET:cout<<"*";break;
                case LIGHT_BULLET:cout<<"|";break;
                case TANK: cout<<"+";break;
                case BOSS: cout<<"^";break;
            }
        }
        cout << "|" << endl;
    }
    for(int i=0;i<screenWidth+2;i++)
        cout<< "-";
    cout << endl;
    cout << "Enemy: "<< EnemyNumUnderScreen<<endl;
};
void TankWar::CreatBoss()
{
    boss.centX = screenWidth/2;
    boss.centY = screenHeight - 2;
    for(int r = boss.centY-1;r<=boss.centY+1;r++)
    {
        for(int c = boss.centX-1;c<=boss.centX+1;c++)
            map[c][r] = BOSS;
    }
    boss.alive = true;
}
void TankWar::CreatTankGod()
{
    theGod.centX = boss.centX-4;
    theGod.centY = boss.centY;
    theGod.direction = DIR_UP;
    theGod.bulletType = LIGHT;
    for(int r = theGod.centY;r<=theGod.centY+1;r++)
    {
        for(int c=theGod.centX-1;c<=theGod.centX+1;c++)
            map[c][r] = TANK;
    }
    map[theGod.centX][theGod.centY-1] = TANK;
}
void TankWar::MoveLeft(Tank& tank)
{
    if(tank.centX-2 < 0 && tank.direction == DIR_LEFT) return;
    for(int r = tank.centY-1;r <= tank.centY+1;r++)
    {
        if(map[tank.centX-2][r] != EMPTY && tank.direction == DIR_LEFT) return;
    }
    EraseCurrentTank(tank);
    if(tank.direction == DIR_LEFT) tank.centX--;
    RedescribeTank(tank,DIR_LEFT);
}
void TankWar::MoveRight(Tank& tank)
{
    if(tank.centX+2 == screenWidth && tank.direction == DIR_RIGHT) return;
    for(int r = tank.centY-1;r <= tank.centY+1;r++)
    {
        if(map[tank.centX+2][r] != EMPTY && tank.direction == DIR_RIGHT) return;
    }
    EraseCurrentTank(tank);
    if(tank.direction == DIR_RIGHT) tank.centX++;
    RedescribeTank(tank,DIR_RIGHT);
}
void TankWar::MoveUp(Tank& tank)
{
    if(tank.centY-2 < 0 && tank.direction == DIR_UP) return;
    for(int c = tank.centX-1;c <= tank.centX+1;c++)
    {
        if(map[c][tank.centY-2] != EMPTY && tank.direction == DIR_UP) return;
    }
    EraseCurrentTank(tank);
    if(tank.direction == DIR_UP) tank.centY--;
    RedescribeTank(tank,DIR_UP);
}
void TankWar::MoveDown(Tank& tank)
{
    if(tank.centY+2 == screenHeight && tank.direction == DIR_DOWN) return;
    for(int c = tank.centX-1;c <= tank.centX+1;c++)
    {
        if(map[c][tank.centY+2] != EMPTY && tank.direction == DIR_DOWN) return;
    }
    EraseCurrentTank(tank);
    if(tank.direction == DIR_DOWN) tank.centY++;
    RedescribeTank(tank,DIR_DOWN);
}
void TankWar::TankShoot(Tank& tank)
{
    Bullet b;
    switch(tank.direction)
    {
        case DIR_UP:   b.x = tank.centX;  b.y = tank.centY-2;break;
        case DIR_DOWN: b.x = tank.centX;  b.y = tank.centY+2;break;
        case DIR_LEFT: b.x = tank.centX-2;b.y = tank.centY;break;
        case DIR_RIGHT:b.x = tank.centX+2;b.y = tank.centY;break;
    }
    b.type = tank.bulletType;
    b.direction = tank.direction;
    bull.push_back(b);
}
void TankWar::RedescribeTank(Tank& tank,short direction)
{
    for(int r = tank.centY-1;r <= tank.centY+1;r++)
    {
        for(int c = tank.centX-1;c<=tank.centX+1;c++)
        {
            map[c][r] = TANK;
        }
    }
    switch(direction)
    {
        case DIR_UP:map[tank.centX-1][tank.centY-1] = EMPTY;
                    map[tank.centX+1][tank.centY-1] = EMPTY;
                    break;
        case DIR_DOWN:map[tank.centX-1][tank.centY+1] = EMPTY;
                    map[tank.centX+1][tank.centY+1] = EMPTY;
                    break;
        case DIR_LEFT:map[tank.centX-1][tank.centY-1] = EMPTY;
                    map[tank.centX-1][tank.centY+1] = EMPTY;
                    break;
        case DIR_RIGHT:map[tank.centX+1][tank.centY-1] = EMPTY;
                    map[tank.centX+1][tank.centY+1] = EMPTY;
                    break;
    }
    tank.direction = direction;
}
void *TankWar::_Key_Control(void *param)
{
    TankWar *p = (TankWar *)param;
    p->KeyControl();
}
void *TankWar::_Enemy_Control(void *param)
{
    TankWar *p = (TankWar *)param;
    p->EnemyControl();
}
void *TankWar::_Bullet_Control(void *param)
{
    TankWar *p = (TankWar *)param;
    p->BulletControl();
}
void TankWar::KeyControl()
{
    struct input_event ev_key;
    int result = open("/dev/input/event3",O_RDONLY);
    if(result < 0)
    {
        cout << "Link to keyboard fail!" <<endl;
        exit(0);
    }
    while(!gameEnd)
    {
        int count = read(result,&ev_key,sizeof(struct input_event));
        if(ev_key.type == EV_KEY && ev_key.value == 0)
        {
            switch(ev_key.code)
            {
                case KEY_W:MoveUp(theGod);break;
                case KEY_A:MoveLeft(theGod);break;
                case KEY_S:MoveDown(theGod);break;
                case KEY_D:MoveRight(theGod);break;
                case KEY_J:TankShoot(theGod);break;
                case KEY_Q:gameEnd = true;break;
            }
        }
        ShowScreen();
    }
    close(result);
}
void TankWar::EnemyControl()
{
    while(!gameEnd)
    {
        if(EnemyNumUnderScreen > 0 && EnemyNumOnScreen < 3)
        {
            CreatEnemy();
        }
        for(list<Tank>::iterator enm = enemy.begin();enm != enemy.end();enm++)
        {
            int oper = 0;
            if(TargetInFront(*enm))
            {
                oper = rand()%100;
                if(oper < 50)
                {
                    TankAutoRun(*enm);
                }
                else
                {
                    TankShoot(*enm);
                }
            }
            else
            {
                oper = rand()%100;
                if(oper < 40)
                {
                    CloseToGodTank(*enm);
                }
                else if(oper < 80)
                {
                    CloseToHome(*enm);
                }
                else 
                {
                    TankAutoRun(*enm);
                }
            }
        }
        clock_t startTime = clock();
        while(clock() < (startTime + 1000000)) ;
        ShowScreen();
    }
}
void TankWar::CreatEnemy()
{
    Tank enm = {0};
    enm.centY = 1;
    enm.bulletType = NORMAL;
    enm.direction = DIR_DOWN;
    if(BornPlaceOk(LEFT_BORN))
    {
        enm.centX = 1;
    }
    else if(BornPlaceOk(CENTER_BORN))
    {
        enm.centX = screenWidth/2;
    }
    else if(BornPlaceOk(RIGHT_BORN))
    {
        enm.centX = screenWidth-2;
    }
    else return ;
    enemy.push_back(enm);
    for(int r=enm.centY-1;r<=enm.centY+1;r++)
    {
        for(int c=enm.centX-1;c<=enm.centX+1;c++)
        {
            map[c][r] = TANK;
        }
    }
    map[enm.centX-1][enm.centY+1] = EMPTY;
    map[enm.centX+1][enm.centY+1] = EMPTY;
    EnemyNumOnScreen++;
    EnemyNumUnderScreen--;
}
bool TankWar::BornPlaceOk(short place)
{
    int x = 0,y = 1;
    switch(place)
    {
        case LEFT_BORN: x = 1;break;
        case CENTER_BORN: x = screenWidth/2;break;
        case RIGHT_BORN: x = screenWidth-2;break;
    }
    for(int r = y-1;r<= y+1;r++)
    {
        for(int c = x-1;c <= x+1;c++)
        {
            if(map[x][y] != EMPTY) return false;
        }
    }
    return true;
}
void TankWar::BulletControl()
{
    while(!gameEnd)
    {
        try
        {
            for(list<Bullet>::iterator b = bull.begin();b != bull.end();b++)
            {
                if(!MoveBullet(*b)) 
                {
                    bull.erase(b);
                    b--;
                }
            }
        }
        catch(runtime_error err)
        {
            cerr<<err.what()<<endl;
        }
        clock_t startTime = clock();
        while(clock() < (startTime + 200000)) ;
        ShowScreen();
    }
}
bool TankWar::MoveBullet(Bullet& bullet)
{
    Bullet b = bullet;
    if(map[b.x][b.y] != NORMAL_BULLET && map[b.x][b.y] != LIGHT_BULLET && map[b.x][b.y] != EMPTY)
    {
        map[b.x][b.y] = EMPTY;
        return false;
    }
    map[b.x][b.y] = EMPTY;
    switch(bullet.direction)
    {
        case DIR_UP:   b.y--;break;
        case DIR_DOWN: b.y++;break;
        case DIR_LEFT: b.x--;break;
        case DIR_RIGHT:b.x++;break;
    }
    if(b.x < 0 || b.x == screenWidth ||b.y < 0||b.y == screenHeight) return false;
    switch(map[b.x][b.y])
    {
        case WALL: map[b.x][b.y] = EMPTY; return false;
        case NORMAL_BULLET: 
        case LIGHT_BULLET:
            map[b.x][b.y] = EMPTY;
            for(list<Bullet>::iterator bl = bull.begin();bl != bull.end();bl++)
            {
                if((*bl).x == b.x &&(*bl).y == b.y)
                {
                    bull.erase(bl);
                    return false;
                }
            }
        case TANK:
            for(list<Tank>::iterator enm = enemy.begin();enm != enemy.end();enm++)
            {
                if((*enm).centX-1 <= b.x && (*enm).centX+1 >=b.x && (*enm).centY-1<=b.y &&(*enm).centY +1 >= b.y)
                {
                    EraseCurrentTank(*enm); 
                    enemy.erase(enm);
                    EnemyNumOnScreen--;
                    return false;
                }
            }
            EraseCurrentTank(theGod);
            boss.alive = false;
            return false;
        case BOSS:
            EraseBoss(boss);
            boss.alive = false;
            return false;
    }
    bullet = b;
    switch(bullet.type)
    {
        case NORMAL: map[bullet.x][bullet.y] = NORMAL_BULLET;break;
        case LIGHT:  map[bullet.x][bullet.y] = LIGHT_BULLET;break;
    }
    return true;
}
void TankWar::TankAutoRun(Tank& tank)
{
    unsigned char count = 0;
    unsigned char dir[4] = {0};     //保存坦克可以移动的方向,若该方向为可移动,保存为1
    unsigned char arr[4] = {0};
    if(tank.centY-2 > 0 && map[tank.centX-1][tank.centY-2] == EMPTY &&map[tank.centX][tank.centY-2]==EMPTY && map[tank.centX+1][tank.centY-2] == EMPTY)  
    {
        dir[DIR_UP] = 1;
        arr[count++] = DIR_UP;
    }
    if(tank.centX+2 < screenWidth && map[tank.centX+2][tank.centY-1] == EMPTY &&map[tank.centX+2][tank.centY]==EMPTY && map[tank.centX+2][tank.centY+1] == EMPTY)  
    {
        dir[DIR_RIGHT] = 1;
        arr[count++] = DIR_RIGHT;
    }
    if(tank.centX-2 > 0 && map[tank.centX-2][tank.centY-1] == EMPTY &&map[tank.centX-2][tank.centY]==EMPTY && map[tank.centX-2][tank.centY+1] == EMPTY)  
    {
        dir[DIR_LEFT] = 1;
        arr[count++] = DIR_LEFT;
    }
    if(tank.centY+2 < screenHeight && map[tank.centX-1][tank.centY+2] == EMPTY &&map[tank.centX][tank.centY+2]==EMPTY && map[tank.centX+1][tank.centY+2] == EMPTY)  
    {
        dir[DIR_DOWN] = 1;
        arr[count++]  = DIR_DOWN;
    }
    if(count == 0) return ;
    short oper = rand()%count;
    TankMove(tank,oper);
}
void TankWar::TankMove(Tank& tank,short dir)
{
    switch(dir)
    {
        case DIR_LEFT: MoveLeft(tank);break;
        case DIR_RIGHT:MoveRight(tank);break;
        case DIR_UP:   MoveUp(tank);break;
        case DIR_DOWN: MoveDown(tank);break;
    }
}
bool TankWar::TargetInFront(Tank& tank)
{
    if(tank.direction == DIR_UP)
    {
        for(int i=tank.centY - 2;i>=0;i--)
        {
            if(tank.centX <= theGod.centX+1 &&tank.centX>=theGod.centX-1 &&tank.centY >= theGod.centY)
                return true;
            for(int j=tank.centX-1;j<=tank.centX+1;j++)
            {
                if(map[j][i] == WALL || map[j][i]==NORMAL_BULLET || map[j][i]==LIGHT_BULLET || map[j][i] == BOSS)
                    return true;
            }
        }
        return false;
    }
    if(tank.direction == DIR_DOWN)
    {
        for(int i=tank.centY + 2;i<screenHeight;i++)
        {
            if(tank.centX <= theGod.centX+1 &&tank.centX>=theGod.centX-1 &&tank.centY <= theGod.centY)
                return true;
            for(int j=tank.centX-1;j<=tank.centX+1;j++)
            {
                if(map[j][i] == WALL || map[j][i]==NORMAL_BULLET || map[j][i]==LIGHT_BULLET || map[j][i] == BOSS)
                    return true;
            }
        }
        return false;
    }
    if(tank.direction == DIR_LEFT)
    {
        for(int i=tank.centX - 2;i>=0;i--)
        {
            if(tank.centY <= theGod.centY+1 &&tank.centY>=theGod.centY-1 &&tank.centX >= theGod.centX)
                return true;
            for(int j=tank.centY-1;j<=tank.centY+1;j++)
            {
                if(map[i][j] == WALL || map[i][j]==NORMAL_BULLET || map[i][j]==LIGHT_BULLET || map[i][j] == BOSS)
                    return true;
            }
        }
        return false;
    }
    if(tank.direction == DIR_RIGHT)
    {
        for(int i=tank.centX + 2;i< screenWidth;i++)
        {
            if(tank.centY <= theGod.centY+1 &&tank.centY>=theGod.centY-1 &&tank.centX <= theGod.centX)
                return true;
            for(int j=tank.centY-1;j<=tank.centY+1;j++)
            {
                if(map[i][j] == WALL || map[i][j]==NORMAL_BULLET || map[i][j]==LIGHT_BULLET || map[i][j] == BOSS)
                    return true;
            }
        }
        return false;
    }

}
void TankWar::CloseToGodTank(Tank& tank)
{
    int dir = 0;
    if(tank.centY < theGod.centY && tank.centX < theGod.centX) 
    {
        dir = rand()%100;
        if(dir < 50)    MoveDown(tank);
        else    MoveRight(tank);
    }
    if(tank.centY > theGod.centY && tank.centX < theGod.centX)
    {
        dir = rand()%100;
        if(dir < 50)    MoveUp(tank);
        else    MoveRight(tank);
    }
    if(tank.centY < theGod.centX && tank.centX >theGod.centX)
    {
        dir = rand()%100;
        if(dir < 50)    MoveDown(tank);
        else    MoveLeft(tank);
    }
    if(tank.centX > theGod.centX && tank.centX > theGod.centX)
    {
        dir = rand()%100;
        if(dir < 50)    MoveUp(tank);
        else    MoveLeft(tank);
    }
}
void TankWar::CloseToHome(Tank& tank)
{   
    int dir = 0;
    if(tank.centY < boss.centY && tank.centX < boss.centX) 
    {
        dir = rand()%100;
        if(dir < 50)    MoveDown(tank);
        else    MoveRight(tank);
    }
    if(tank.centY > boss.centY && tank.centX < boss.centX)
    {
        dir = rand()%100;
        if(dir < 50)    MoveUp(tank);
        else    MoveRight(tank);
    }
    if(tank.centY < boss.centX && tank.centX > boss.centX)
    {
        dir = rand()%100;
        if(dir < 50)    MoveDown(tank);
        else    MoveLeft(tank);
    }
    if(tank.centX > boss.centX && tank.centX > boss.centX)
    {
        dir = rand()%100;
        if(dir < 50)    MoveUp(tank);
        else    MoveLeft(tank);
    }
}
void TankWar::GameOverNotice(string str)
{
    system("clear");
    cout <<str <<endl;
    cout << "Congratulation!"<<endl;
}

main.cpp

#include <iostream>
#include "TankWar.h"

using namespace std;
int main()
{
    TankWar tank(30,20,20);
    tank.GameStart();
    return 0;
}

makefile

TankWar: main.o TankWar.o
    g++ -lpthread  main.o TankWar.o -o TankWar
main.o: main.cpp TankWar.h
    g++ -c main.cpp
TankWar.o: TankWar.cpp
    g++ -c TankWar.cpp
clean:
    rm *.o

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值