计算机软件实习(二)贪吃蛇游戏实现

基于C++的贪吃蛇游戏实现

实验内容:
(1)实现贪吃蛇游戏基本功能,屏幕上随机出现一个“食物”,称为豆子,上下左右
控制“蛇”的移动,吃到“豆子”以后“蛇”的身体加长一点,得分增加,“蛇”碰到边界或,
蛇头与蛇身相撞,蛇死亡,游戏结束。为游戏设计初始欢迎界面,游戏界面,游戏
结束界面。
(2)进行交互界面的设计,要有开始键、暂停键和停止退出的选项。对蛇吃到豆子进
行分值计算,可以设置游戏速度,游戏音乐等拓展元素。
(3)选做:
① AI 贪吃蛇,结合 A*算法和适当的策略,设计能吃满屏的贪吃蛇。
② 俄罗斯方块游戏的设计与开发,俄罗斯方块的基本规则是,随机生成
不同类型的方块,支持其移动,旋转和摆放,使排列成完整的一行或多行消除得分。

开发心得:
因为visual 6.0在贪吃蛇实现的使用过程中出现了一些问题,在后面我的开发工具换成了Visual Studio 2019。在贪吃蛇游戏的实现过程中,使用了一些未知的MFC控件,了解了一些关于笔刷的知识,遇到了一些没遇到过的断点问题,虽然没有完美的实现贪吃蛇,但基本的一些功能还是实现了。
开发流程
1,首先是MFC的图形界面设计,经过上次计算机的实现,贪吃蛇相对更熟练了些,设置静态文本与Combo Box与图片框,调整编辑框与按钮。
在这里插入图片描述
2.图形界面设计完后,对两个按钮写入消息响应的代码,然后在类视图页面添加相应的函数和变量到***Dlg.cpp,主要是对游戏的初始化与结束,蛇的设定,食物的设定,移动的限定以及蛇是否存活的检查。新建一个类来对蛇的移动进行具体化的规定。

代码实现:
***Dlg.cpp


// TCSDlg.cpp: 实现文件
//
#include "iostream"
#include "pch.h"
#include "framework.h"
#include "TCS.h"
#include "TCSDlg.h"
#include "afxdialogex.h"
#include "Snack.h"
#include <random>
#include "windows.h"
#include "mmsystem.h" 
#include "CInfoDlg.h"

#pragma comment(lib, "WINMM.LIB")

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

using namespace std;
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CTCSDlg 对话框



CTCSDlg::CTCSDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_TCS_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	pen1.CreatePen(PS_SOLID, 4, RGB(174, 221, 129));
}

void CTCSDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	//  DDX_Control(pDX, IDC_COMBO_speed, Box);
	DDX_Control(pDX, IDC_COMBO_speed, Box);
	DDX_Control(pDX, IDC_EDIT_score, EDIT_Score);
}

BEGIN_MESSAGE_MAP(CTCSDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_Stop, &CTCSDlg::OnBnClickedButtonStop)
	ON_BN_CLICKED(IDC_BUTTON_Start, &CTCSDlg::OnBnClickedButtonStart)
	ON_WM_TIMER()
	ON_CBN_SELCHANGE(IDC_COMBO_speed, &CTCSDlg::OnCbnSelchangeCombospeed)
	ON_WM_WINDOWPOSCHANGING()
END_MESSAGE_MAP()


// CTCSDlg 消息处理程序

BOOL CTCSDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CTCSDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CTCSDlg::OnPaint()
{
	/*if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
	*/

	CRect rect;
	(this->GetDlgItem(IDC_game))->GetWindowRect(&rect);  // 获取控件相对于屏幕的位置
	ScreenToClient(rect); // 转化为相对于客户区的位置
	GetDlgItem(IDC_game)->MoveWindow(rect.left, rect.top + 4, 760, 600, false);

	CDC* pClientDC = GetDC();
	(this->GetDlgItem(IDC_game))->GetWindowRect(&rect);  // 获取控件相对于屏幕的位置
	ScreenToClient(rect); // 转化为相对于客户区的位置
	CPen pen(PS_SOLID, 6, RGB(6, 128, 67));
	CPen pen2(PS_SOLID, 10, RGB(174, 221, 129));
	CPen* oldPen = pClientDC->SelectObject(&pen2);
	pClientDC->Rectangle(rect);
	rect.left -= 5;
	rect.right += 5;
	rect.top -= 5;
	rect.bottom += 5;
	pClientDC->SelectObject(&pen);
	pClientDC->Rectangle(rect);
	pen.DeleteObject();
	pen2.DeleteObject();
	pClientDC->DeleteDC();

	// 画刷初始化
	CBitmap bodybmp, headbmp, beanbmp, bgbmp;
	bgbmp.LoadBitmapW(IDB_BITMAP1);
	beanbmp.LoadBitmapW(IDB_BITMAP2);
	bodybmp.LoadBitmapW(IDB_BITMAP3);
	headbmp.LoadBitmapW(IDB_BITMAP4);
	m_brush[0].CreatePatternBrush(&bodybmp);
	m_brush[1].CreatePatternBrush(&headbmp);
	m_brush[2].CreatePatternBrush(&beanbmp);
	m_brush[3].CreatePatternBrush(&bgbmp);

	// 控件初始化
	Box.SetCurSel(1);
	EDIT_Score.SetReadOnly(1);
	m_showFont1.CreatePointFont(200, L"黑体");
	GetDlgItem(IDC_EDIT_score)->SetFont(&m_showFont1);
	GetDlgItem(IDC_BUTTON_Start)->SetFont(&m_showFont1);
	GetDlgItem(IDC_BUTTON_Stop)->SetFont(&m_showFont1);
	m_showFont2.CreatePointFont(150, L"Consolas");
	GetDlgItem(IDC_Score)->SetFont(&m_showFont2);
	GetDlgItem(IDC_Speed)->SetFont(&m_showFont2);
	m_showFont3.CreatePointFont(100, L"Consolas");

	OnBnClickedButtonStop();

	SnackInit();

	CPaintDC pDC(this);
}

HCURSOR CTCSDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CTCSDlg::SnackInit()
{
	// 游戏区
	CDC* pdc = GetDlgItem(IDC_game)->GetWindowDC();

	// 棋盘初始化
	CBrush* pOldBrs = pdc->SelectObject(&m_brush[3]);
	CPen* pOldPen = pdc->SelectObject(&pen1);
	for (int i = 0; i < 30; i++) {
		for (int j = 0; j < 38; j++) {
			m_map[i][j].left = 0 + j * 20;
			m_map[i][j].right = 20 + j * 20;
			m_map[i][j].top = 0 + i * 20;
			m_map[i][j].bottom = 20 + i * 20;
			pdc->SelectObject(&m_brush[3]);
			pdc->Rectangle(m_map[i][j]);
			//pdc->SelectObject(&pen1);
			//pdc->Rectangle(m_map[i][j]);
		}
	}
	pdc->SelectObject(&pOldBrs);

	// 蛇初始化
	my_snake.init();
	score = 0;
	START = false;
	DEAD = false;
	srand((unsigned)time(NULL));
	drawSnake();
	setBean();


	// 控件初始化
	EDIT_Score.SetWindowTextW(_T("0"));
	SetDlgItemText(IDC_BUTTON_Start, _T("start"));
}

void CTCSDlg::OnBnClickedButtonStop()
{
	// TODO: 在此添加控件通知处理程序代码
	// 重新开始
	gameOver();
	SnackInit();
	this->GetDlgItem(IDC_game)->SetFocus();
}

void CTCSDlg::OnBnClickedButtonStart()
{
	// TODO: 在此添加控件通知处理程序代码
	CString start, pause;
	start = "start";
	pause = "pause";
	if (DEAD == false) {
		if (START) {
			START = false;
			KillTimer(1);
			SetDlgItemText(IDC_BUTTON_Start, start);
		}
		else {
			if (INIT) {
				INIT = false;
				SnackInit();
			}
			START = true;
			SetTimer(1, speed, NULL);
			SetDlgItemText(IDC_BUTTON_Start, pause);
		}
		this->GetDlgItem(IDC_game)->SetFocus();
	}
}

void CTCSDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	// main function about snake
	UpdateData(true);
	if (START && DEAD == false) {
		switch (my_snake.direc)
		{
		case 1:MvUp(); break;
		case 2:MvDown(); break;
		case 3:MvLeft(); break;
		case 4:MvRight(); break;
		default:
			break;
		}
		if (checkLive() == false) {
			DEAD = true;
			CString str;
			str.Format(_T("sorry, your score is %d ~ \n\n Please try again ~ "), score);
			//str = TEXT("sorry, your score is " + str + " ~ \n\n Please try again~");

			/*CInfoDlg dlg(NULL, m_showFont1, str);
			CInfoDlg dlg;
			INT_PTR nres = dlg.DoModal();
			if (IDOK == nres) {
				OnBnClickedButtonStop();
			}*/

			if (MessageBox(str, TEXT("INFO"), MB_ICONINFORMATION) == IDOK) {
				OnBnClickedButtonStop();
			}
			gameOver();
		}
		eatBean();
		// drawSnake();
	}

	CDialogEx::OnTimer(nIDEvent);
}

bool CTCSDlg::setBean()
{
	srand((unsigned)time(NULL));
	bool setB = false;
	bool safe = true;
	while (safe) {
		pos.x = rand() % 30;
		pos.y = rand() % 38;
		for (int i = 0; i < my_snake.len; i++) {
			if (pos.x == my_snake.body[i].x && pos.y == my_snake.body[i].y) {
				safe = false; break;
			}
		}
		if (safe) {
			setB = true;
			safe = false;
		}
		else safe = true;
	}
	CDC* pdc = GetDlgItem(IDC_game)->GetWindowDC();
	CBrush* pOldBrs = pdc->SelectObject(&m_brush[2]);
	pdc->Rectangle(m_map[pos.x][pos.y]);
	pdc->SelectObject(&pen1);
	pdc->Rectangle(m_map[pos.x][pos.y]);
	pdc->SelectObject(&pOldBrs);
	pdc->DeleteDC();
	return setB;
}

void CTCSDlg::drawSnake()
{
	CDC* pdc = GetDlgItem(IDC_game)->GetWindowDC();
	CBrush* pOldBrs = pdc->SelectObject(&m_brush[0]);
	for (int i = 1; i < my_snake.len; i++) {
		pdc->SelectObject(&m_brush[0]);
		pdc->Rectangle(m_map[my_snake.body[i].x][my_snake.body[i].y]);
		pdc->SelectObject(&pen1);
		pdc->Rectangle(m_map[my_snake.body[i].x][my_snake.body[i].y]);
	}
	pdc->SelectObject(&m_brush[1]);
	pdc->Rectangle(m_map[my_snake.body[0].x][my_snake.body[0].y]);
	pdc->SelectObject(&pen1);
	pdc->Rectangle(m_map[my_snake.body[0].x][my_snake.body[0].y]);
	pdc->SelectObject(&pOldBrs);
	pdc->DeleteDC();
}

void CTCSDlg::MvUp()
{
	CDC* pdc = GetDlgItem(IDC_game)->GetWindowDC();
	// 将最后一个恢复背景色
	CBrush* pOldBrs = pdc->SelectObject(&m_brush[3]);
	pdc->Rectangle(m_map[my_snake.body[my_snake.len - 1].x][my_snake.body[my_snake.len - 1].y]);
	pdc->SelectObject(&pen1);
	pdc->Rectangle(m_map[my_snake.body[my_snake.len - 1].x][my_snake.body[my_snake.len - 1].y]);
	pdc->SelectObject(pOldBrs);
	my_snake.UpMove();
	drawSnake();
}

void CTCSDlg::MvDown()
{
	CDC* pdc = GetDlgItem(IDC_game)->GetWindowDC();
	CBrush* pOldBrs = pdc->SelectObject(&m_brush[3]);
	pdc->Rectangle(m_map[my_snake.body[my_snake.len - 1].x][my_snake.body[my_snake.len - 1].y]);
	pdc->SelectObject(&pen1);
	pdc->Rectangle(m_map[my_snake.body[my_snake.len - 1].x][my_snake.body[my_snake.len - 1].y]);
	pdc->SelectObject(pOldBrs);
	my_snake.DownMove();
	drawSnake();
}

void CTCSDlg::MvLeft()
{
	CDC* pdc = GetDlgItem(IDC_game)->GetWindowDC();
	CBrush* pOldBrs = pdc->SelectObject(&m_brush[3]);
	pdc->Rectangle(m_map[my_snake.body[my_snake.len - 1].x][my_snake.body[my_snake.len - 1].y]);
	pdc->SelectObject(&pen1);
	pdc->Rectangle(m_map[my_snake.body[my_snake.len - 1].x][my_snake.body[my_snake.len - 1].y]);
	pdc->SelectObject(pOldBrs);
	my_snake.LeftMove();
	drawSnake();
}

void CTCSDlg::MvRight()
{
	CDC* pdc = GetDlgItem(IDC_game)->GetWindowDC();
	CBrush* pOldBrs = pdc->SelectObject(&m_brush[3]);
	pdc->Rectangle(m_map[my_snake.body[my_snake.len - 1].x][my_snake.body[my_snake.len - 1].y]);
	pdc->SelectObject(&pen1);
	pdc->Rectangle(m_map[my_snake.body[my_snake.len - 1].x][my_snake.body[my_snake.len - 1].y]);
	pdc->SelectObject(pOldBrs);
	my_snake.RightMove();
	drawSnake();
}

void CTCSDlg::eatBean()
{
	if (pos.x == my_snake.body[0].x && pos.y == my_snake.body[0].y) {
		my_snake.len++;
		setBean();
		score = score + (abs(pos.x - my_snake.body[0].x) + abs(pos.y - my_snake.body[0].y));
		CString str;
		str.Format(_T("%d"), score);
		EDIT_Score.SetWindowTextW(str);
	}
}

bool CTCSDlg::checkLive()
{
	// 判断是否出界
	if (my_snake.body[0].x < 0 || my_snake.body[0].x >= 30 || my_snake.body[0].y < 0 || my_snake.body[0].y >= 38) return false;
	// 判断是否撞到了自己
	for (int i = 1; i < my_snake.len; i++) {
		if (my_snake.body[0].x == my_snake.body[i].x && my_snake.body[0].y == my_snake.body[i].y) return false;
	}
	return true;
}

void CTCSDlg::gameOver()
{
	KillTimer(1);
	START = false;
}

void CTCSDlg::OnCbnSelchangeCombospeed()
{
	// TODO: 在此添加控件通知处理程序代码
	//KillTimer(1);
	CString mode;
	Box.GetLBText(Box.GetCurSel(), mode);
	int tmp = 0;
	tmp = mode[0] - '0';
	speed = 300 / tmp;
	SetTimer(1, speed, NULL);
	this->GetDlgItem(IDC_game)->SetFocus();
}

BOOL CTCSDlg::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类
	if (START && DEAD == false) {
		if (my_snake.direc != 2 && (pMsg->wParam == VK_UP || pMsg->wParam == 'w' || pMsg->wParam == 'W')) my_snake.direc = 1;
		else if (my_snake.direc != 1 && (pMsg->wParam == VK_DOWN || pMsg->wParam == 's' || pMsg->wParam == 'S')) my_snake.direc = 2;
		else if (my_snake.direc != 4 && (pMsg->wParam == VK_LEFT || pMsg->wParam == 'a' || pMsg->wParam == 'A')) my_snake.direc = 3;
		else if (my_snake.direc != 3 && (pMsg->wParam == VK_RIGHT || pMsg->wParam == 'd' || pMsg->wParam == 'D')) my_snake.direc = 4;
	}
	/*if (pMsg->message == WM_KEYDOWN)
	{
		if (pMsg->hwnd == GetDlgItem(IDC_EDIT_score)->m_hWnd)
		{
			return true;
		}
	}*/

	//return CDialogEx::PreTranslateMessage(pMsg);
	return FALSE;
}

void CTCSDlg::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{
	CDialogEx::OnWindowPosChanging(lpwndpos);

	// TODO: 在此处添加消息处理程序代码
	// 获取屏幕宽度
	int nMaxX = GetSystemMetrics(SM_CXSCREEN);
	// 获取屏幕高度
	int nMaxY = GetSystemMetrics(SM_CYSCREEN);

	// 判断窗口X坐标有无超过左边桌面。
	if (lpwndpos->x < 0)
	{
		lpwndpos->x = 0;
	}

	// 判断窗口X坐标有无超过右边桌面。
	if (lpwndpos->x + lpwndpos->cx > nMaxX)
	{
		lpwndpos->x = nMaxX - lpwndpos->cx;
	}

	// 判断窗口Y坐标有无超过顶部桌面。
	if (lpwndpos->y < 0)
	{
		lpwndpos->y = 0;
	}

	// 判断窗口Y坐标有无超过底部桌面。
	if (lpwndpos->y + lpwndpos->cy > nMaxY)
	{
		lpwndpos->y = nMaxY - lpwndpos->cy;
	}
}

新建的类:

#pragma once
struct Point  // 具体的每一个点
{
	int x;
	int y;
};

class CSnake
{
public:
	CSnake();
	~CSnake(); 
	int len;  // 蛇的长度
	Point body[1255];  // 蛇的身体
	int direc;   // 运动方向
	void UpMove();  // 向上运动
	void DownMove();  // 向下运动 
	void LeftMove();  // 向左运动
	void RightMove();  // 向右运动
	void init();


private:

};

#include "pch.h"
#include "framework.h"
#include "TCS.h"
#include "TCSDlg.h"
#include "Snack.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CSnake::CSnake()
{
	// 初始化蛇的长度为1, 向右运动, 头的位置为(10, 10)
	len = 1;
	direc = 4; // 上下左右1,2,3,4
	body[0].x = 10;
	body[0].y = 10;
}

CSnake::~CSnake()
{
}

void CSnake::UpMove()
{
	for (int i = len - 1; i > 0; --i) {
		body[i].x = body[i - 1].x;
		body[i].y = body[i - 1].y;
	}
	body[0].x--;
	direc = 1;
}

void CSnake::DownMove()
{
	for (int i = len - 1; i > 0; --i) {
		body[i].x = body[i - 1].x;
		body[i].y = body[i - 1].y;
	}
	body[0].x++;
	direc = 2;
}

void CSnake::LeftMove()
{
	for (int i = len - 1; i > 0; --i) {
		body[i].x = body[i - 1].x;
		body[i].y = body[i - 1].y;
	}
	body[0].y--;
	direc = 3;
}

void CSnake::RightMove()
{
	for (int i = len - 1; i > 0; --i) {
		body[i].x = body[i - 1].x;
		body[i].y = body[i - 1].y;
	}
	body[0].y++;
	direc = 4;
}

void CSnake::init()
{
	body[0].x = 10;
	body[0].y = 10;
	len = 1;
	direc = 4;
}

运行结果:
在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
计算机软件实习实习要求可以包括以下方面: 1. 技术能力:具备一定的计算机软件开发技术基础,包括编程语言、数据结构与算法、数据库等方面的知识。能够熟练运用相关开发工具和技术,如Java、Python、C++等编程语言,掌握常用框架和库的使用。 2. 系统理解与分析能力:能够理解和分析软件系统的需求,并提供相应的功能设计和实现。具备系统分析和设计的基本能力,包括需求分析、系统架构设计、模块划分等。 3. 问题解决能力:具备独立解决问题的能力,能够分析和定位软件开发过程中遇到的问题,并提供相应的解决方案。熟悉常见的调试技巧和工具,能够进行错误排查和修复。 4. 团队合作能力:具备良好的团队合作精神和沟通能力,能够与团队成员协作完成项目任务。理解并遵守团队开发规范和流程,有良好的沟通和协调能力。 5. 学习能力和创新意识:具备快速学习新技术和新知识的能力,能够持续关注行业发展动态,保持对新技术的探索和学习。具备创新意识,能够提供新颖的解决方案和想法。 6. 项目管理能力:具备一定的项目管理能力,包括时间管理、任务分配和进度控制等。能够按时完成任务,保证项目的质量和进度。 这些是计算机软件实习的一般要求,具体要求可能会根据实习岗位和公司的不同而有所差异。在实习期间,学生应努力学习和实践,提高自身的技术能力和综合素质,同时注重与导师和团队成员的交流和合作,积极参与项目并展现出良好的职业态度和工作表现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值