第一次发博客,用C++写一个下五子棋的小AI

第一次发博客,用C++写一个下五子棋的小AI

刚学C++一两年,试着写了一个下五子棋的小AI,核心的代码放在了gamemode.h和gamemode.cpp里面。毕竟本人是新手,所以做的比较粗糙,还望各位包涵(嘿嘿)。
1、其实调用这个AI的方式很简单,就是将棋盘状态保存在int Pad[15][15]这个数组里面(0表示该出没有棋子,1表示该处有白棋,-1表示该处有黑棋),然后如果调用void CulResult()这个函数,它就会根据棋盘上现在的状态计算出下一步的下棋位置(不管白棋还是黑棋都一样),并将这个位置储存在ivalue、jvalue这两个变量里(ivalue、jvalue分别表示行和列的坐标值,取值是1-15)。
2、在棋盘上下子的时候,可以调用bool CheckAndSet(CPoint point,bool type)这个函数,point表示下棋的位置,type表示下棋的种类。 这个函数会将type与turn做比较,检查是否轮到正确的下棋方下棋,如果下棋方正确则下棋并且返回true,下期方错误则会返回false。这个CPoint是引用的一个头文件里的,如果你没有的话请自己加一个这个类,只需要两个整型变量x、y就行了。然后调用完bool CheckAndSet(CPoint point,bool type)之后如果下棋成功了,建议调用一下bool ChangeTurn(),改变现在下一步的下棋方。另一种在棋盘上下棋的方式就是直接改int pad[15][15]数组的值,我觉得为了方便调试就把它设置为public了。
3、每下完一步棋都可以调用int checkwin()来检查现在是否有一方获胜了,如果白子赢了返回1,黑子赢了返回-1。
4、在声明一个gamemode类型的变量时,构造函数里的bool参数是指定玩家棋子的种类。在定义完gamemode变量以后要设置一下turn的值,也就是谁最先下棋。

最后说一下,我觉得我这个黑子、白子的次序和玩家、电脑的次序弄的有点乱,可能并不合理,但是改起来又有点麻烦,如果大家有建议欢迎提出。我会在之后上传一个我写好的工程,在我的资源里,可以直接用vs2012打开运行。但是在运行的时候先全屏,不然棋盘显示不全,
gamemode.h:

#include "math.h"
#include "stdafx.h"

struct TRNA		//定义链表的结构体
{
	int type;
	int i;
	int j;
	TRNA *before;
	TRNA *next;
};

struct check
{
	int type;
	int value;
};

class gamemode		//定义五子棋的类
{
public:
	int pad[15][15];		//储存棋盘当前的状态
	bool turn;      //true表示轮到白子,false表示轮到黑子。
	bool player;    //player表示玩家的子类型,true表示白子,false表示黑子。
	int ivalue;		//储存每一轮计算机计算的最终结果在数组中的行值
	int jvalue;		//储存每一轮计算机计算的最终结果在数组中的列值
	float tend;		//算法的下棋倾向,0-1表示偏向防守,1-2表示偏向攻击,1表示均衡

public:
	gamemode(bool player);		//参数player是初始化玩家的棋子类型,ture表示白子,false表示黑子
	bool CheckAndSet(CPoint point,bool type);	//检查棋子并下子
	bool ChangeTurn();			//获取当前下棋方,并在获取后自动切换下棋方
	void CulResult();		//调用4*2次SingleCul,获取所有扫描结果并相加
	int checkwin();		//检查是否有一方获取了胜利,1表示玩家获胜,-1表示电脑获胜,0表示没有人获胜


private:
	int location[15][15];
	int longitude[15][15];		//存储纵向扫描白子优先度结果
	int latitude[15][15];		//存储横向扫描白子优先度结果
	int LtoR[15][15];		//存储左上到右下扫白子描优先度结果
	int RtoL[15][15];		//存储右上到左下扫白子描优先度结果
	int longitude2[15][15];		//存储纵向扫描黑子优先度结果
	int latitude2[15][15];		//存储横向扫描黑子优先度结果
	int LtoR2[15][15];		//存储左上到右下扫黑子描优先度结果
	int RtoL2[15][15];		//存储右上到左下扫黑子描优先度结果
	float result1[15][15];		//存储白子最终扫描结果
	float result2[15][15];		//存储黑子最终扫描结果

	void SingleCul(TRNA* linktable,int target[15][15]);		//输入扫描结果的链表以及存储的数组,进行单次的扫描
	void initialize();		//初始化存储扫描存储空间的函数
	TRNA* getlon();		//获取纵向扫描结果
	TRNA* getla();		//获取横向扫描结果
	TRNA* getLtoR();		//获取左上到右下扫描结果
	TRNA* getRtoL();		//获取右上到左下扫描结果

};

gamemode.cpp:

#include "stdafx.h"
#include "gamemode.h"

struct recorder
{
	int i,j,type;
};

void release(TRNA* target)		//释放链表
{
	target = target->next;
	for (; target->next != NULL; target = target->next)
	{
		delete target->before;
	}
	delete target;
}

/*
check _3a[3]={{0,10},{1,0},{0,10}};
check _5a[5]={{1,0},{0,30},{0,30},{1,0},{0,0}};
check _5b[5]={{1,0},{1,0},{0,60},{1,0},{1,0}};
check _5c[5]={{1,0},{1,0},{1,0},{0,60},{1,0}};
check _5d[5]={{0,0},{1,0},{0,30},{1,0},{0,0}};
check _6a[6]={{0,0},{0,15},{0,15},{1,0},{1,0},{-1,0}};
check _6b[6]={{0,30},{1,0},{0,30},{1,0},{0,0},{-1,0}};
check _6c[6]={{0,0},{0,30},{1,0},{1,0},{0,30},{0,0}};
check _6d[6]={{0,30},{0,30},{1,0},{1,0},{1,0},{-1,0}};
check _6e[6]={{0,30},{1,0},{1,0},{0,60},{1,0},{0,30}};
check _6f[6]={{0,30},{1,0},{1,0},{0,30},{1,0},{-1,0}};
check _6g[6]={{0,30},{1,0},{0,30},{1,0},{1,0},{-1,0}};
check _6h[6]={{0,60},{1,0},{1,0},{1,0},{1,0},{-1,0}};
check -6i[6]={{0,0},{0,30},{0,30},{1,0},{1,0},{0,0}};
check _7a[7]={{0,0},{0,30},{1,0},{1,0},{0,30},{0,30},{0,0}};
check _7b[7]={{0,0},{0,30},{1,0},{0,30},{1,0},{0,30},{0,0}};
check _7c[7]={{-1,0},{0,0},{1,0},{1,0},{0,30},{0,30},{0,0}};
check _7d[7]={{0,30},{0,60},{1,0},{1,0},{1,0},{0,60},{0,30}};
check _7e[7]={{0,30},{0,60},{1,0},{1,0},{1,0},{0,30},{-1,0}};
check _7f[7]={{-1,0},{0,30},{1,0},{1,0},{1,0},{0,30},{-1,0}};
*/

check _3group[3] = {{0,5},{1,0},{0,5}};
check _5group[5][5] = {{{1,0},{0,30},{0,30},{1,0},{0,0}}  ,{{1,0},{1,0},{0,100},{1,0},{1,0}}  ,{{1,0},{1,0},{1,0},{0,100},{1,0}} ,{{0,0},{1,0},{0,30},{1,0},{0,0}},{{0,100},{1,0},{1,0},{1,0},{1,0}}};
check _6group[10][6] = {{{0,0},{0,15},{0,15},{1,0},{1,0},{-1,0}} ,{{0,30},{1,0},{0,30},{1,0},{0,0},{-1,0}}  ,{{0,0},{0,30},{1,0},{1,0},{0,30},{0,0}}  ,{{0,37},{0,37},{1,0},{1,0},{1,0},{-1,0}},
{{0,37},{1,0},{1,0},{0,67},{1,0},{0,37}}  ,{{0,37},{1,0},{1,0},{0,37},{1,0},{-1,0}}  ,{{0,30},{1,0},{1,0},{0,30},{1,0},{-1,0}}  ,{{0,100},{1,0},{1,0},{1,0},{1,0},{-1,0} },{{0,0},{0,30},{0,30},{1,0},{1,0},{0,0}},
{{0,37},{0,67},{1,0},{1,0},{1,0},{0,37}}};
check _7group[6][7] = {{{0,0},{0,30},{1,0},{1,0},{0,30},{0,30},{0,0}} ,{{0,0},{0,30},{1,0},{0,30},{1,0},{0,30},{0,0}}  ,{{-1,0},{0,0},{1,0},{1,0},{0,30},{0,30},{0,0}}  ,
{{0,37},{0,67},{1,0},{1,0},{1,0},{0,67},{0,37}}  ,{{0,37},{0,67},{1,0},{1,0},{1,0},{0,37},{-1,0}} ,{{-1,0},{0,37},{1,0},{1,0},{1,0},{0,37},{-1,0}}};

check WinCon[5]={{1,0},{1,0},{1,0},{1,0},{1,0}};


gamemode::gamemode(bool play) :player(play)
{
	int i, j;
	tend=1;
	int a=0,b=0,max=0;
	for (i = 0; i<15; i++)
		for (j = 0; j<15; j++)
		{
			pad[i][j] = 0;
			longitude[i][j] = 0;
			latitude[i][j] = 0;
			LtoR[i][j] = 0;
			RtoL[i][j] = 0;
			result1[i][j] = 0;
			result1[i][j] = 0;
		}
	for(i=0;i<14;i++)
		for(j=0;j<14;j++)
		{
			a=i-7;
			b=j-7;
			a=a<0?-a:a;
			b=b<0?-b:b;
			max=a>b?a:b;
			location[i][j]=7-max;
		}
}


bool gamemode::CheckAndSet(CPoint point, bool type)
{
	int x, y;
	x=point.x;
	y=point.y;
	if (gamemode::pad[y - 1][x - 1] == 0)
	{
		if(type==player)
		{
			pad[y - 1][x - 1] = 1;
			return true;
		}
		else if(type!=player)
		{
			pad[y - 1][x - 1] = -1;
			return true;
		}
	}
	else
	{
		return false;
	}
}

bool gamemode::ChangeTurn()
{
	turn = !turn;
	return !turn;
}

void gamemode::initialize()
{
	int i, j;
	for (i = 0; i<15; i++)
		for (j = 0; j<15; j++)
		{
			longitude[i][j] = 0;
			latitude[i][j] = 0;
			LtoR[i][j] = 0;
			RtoL[i][j] = 0;
			longitude2[i][j] = 0;
			latitude2[i][j] = 0;
			LtoR2[i][j] = 0;
			RtoL2[i][j] = 0;
			result1[i][j] = 0;
			result2[i][j] = 0;
		}
}

TRNA* gamemode::getlon()
{
	int i, j;
	TRNA* start = new(TRNA);
	start->before = NULL;
	TRNA* p = start;
	for (j = 0; j<15; j++)
	{
		for (i = 0; i<15; i++)
		{
			p->type = pad[i][j];
			p->i = i;
			p->j = j;
			p->next = new(TRNA);
			p->next->before = p;
			p = p->next;
			p->next = NULL;
		}
		p->type = -2;
		p->next = new(TRNA);
		p->next->before = p;
		p = p->next;
		p->next = NULL;
	}
	return start;
}

TRNA* gamemode::getla()
{
	int i, j;
	TRNA* start = new(TRNA);
	start->before = NULL;
	TRNA* p = start;
	for (i = 0; i<15; i++)
	{
		for (j = 0; j<15; j++)
		{
			p->type = pad[i][j];
			p->i = i;
			p->j = j;
			p->next = new(TRNA);
			p->next->before = p;
			p = p->next;
			p->next = NULL;
		}
		p->type = -2;
		p->next = new(TRNA);
		p->next->before = p;
		p = p->next;
		p->next = NULL;
	}
	return start;
}

TRNA* gamemode::getLtoR()
{
	int i, j;
	TRNA* start = new(TRNA);
	start->before = NULL;
	TRNA* p = start;
	for (j = 0; j<11; j++)
	{
		int k = j;
		for (i = 0; k<15; i++, k++)
		{
			p->type = pad[i][k];
			p->i = i;
			p->j = k;
			p->next = new(TRNA);
			p->next->before = p;
			p = p->next;
			p->next = NULL;
		}
		p->type = -2;
		p->next = new(TRNA);
		p->next->before = p;
		p = p->next;
		p->next = NULL;
	}
	for (i = 1; i<11; i++)
	{
		int k = i;
		for (j = 0; k<15; j++, k++)
		{
			p->type = pad[k][j];
			p->i = k;
			p->j = j;
			p->next = new(TRNA);
			p->next->before = p;
			p = p->next;
			p->next = NULL;
		}
		p->type = -2;
		p->next = new(TRNA);
		p->next->before = p;
		p = p->next;
		p->next = NULL;
	}
	return start;
}

TRNA* gamemode::getRtoL()
{
	int i, j;
	TRNA* start = new(TRNA);
	start->before = NULL;
	TRNA* p = start;
	for (j = 14; j >= 4; j--)
	{
		int k = j;
		for (i = 0; k >= 0; i++, k--)
		{
			p->type = pad[i][k];
			p->i = i;
			p->j = k;
			p->next = new(TRNA);
			p->next->before = p;
			p = p->next;
			p->next = NULL;
		}
		p->type = -2;
		p->next = new(TRNA);
		p->next->before = p;
		p = p->next;
		p->next = NULL;
	}
	for (i = 1; i<11; i++)
	{
		int k = i;
		for (j = 14; k<15; j--, k++)
		{
			p->type = pad[k][j];
			p->i = k;
			p->j = j;
			p->next = new(TRNA);
			p->next->before = p;
			p = p->next;
			p->next = NULL;
		}
		p->type = -2;
		p->next = new(TRNA);
		p->next->before = p;
		p = p->next;
		p->next = NULL;
	}
	return start;
}

void gamemode::SingleCul(TRNA* linktable, int target[15][15])
{
	TRNA *start, *end, *allend;
	int i, j;
	for (start = linktable, end = start->next->next->next; end->next != NULL; start = start->next, end = end->next)
	{
		TRNA* temp;
		bool flag;
		for (i = 0, temp = start; i<3; i++, temp = temp->next)
		{
			flag = false;
			if (temp->type == _3group[i].type)
				flag = true;
			else
				break;
		}
		if (flag)
		{
			for (temp = start, i = 0; temp != end; temp = temp->next, i++)
			{
				if (_3group[i].value>target[temp->i][temp->j])
				{
					target[temp->i][temp->j] = _3group[i].value;
				}
			}
		}
	}
	for (i = 0; i<5; i++)
	{
		for (start = linktable, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
		{
			TRNA* temp;
			bool flag;
			for (j = 0, temp = start; j<5; j++, temp = temp->next)
			{
				flag = false;
				if (temp->type == _5group[i][j].type)
					flag = true;
				else
					break;
			}
			if (flag)
			{
				for (temp = start, j = 0; temp != end; temp = temp->next, j++)
				{
					if (_5group[i][j].value>target[temp->i][temp->j])
					{
						target[temp->i][temp->j] = _5group[i][j].value;
					}
				}
			}
		}
	}
	allend = end->before->before;
	for (i = 0; i<5; i++)
	{
		for (start = allend, end = start->before->before->before->before->before; end->before != NULL; start = start->before, end = end->before)
		{
			TRNA* temp;
			bool flag;
			for (j = 0, temp = start; j<5; j++, temp = temp->before)
			{
				flag = false;
				if (temp->type == _5group[i][j].type)
					flag = true;
				else
					break;
			}
			if (flag)
			{
				for (temp = start, j = 0; temp != end; temp = temp->before, j++)
				{
					if (_5group[i][j].value>target[temp->i][temp->j])
					{
						target[temp->i][temp->j] = _5group[i][j].value;
					}
				}
			}
		}
	}
	for (i = 0; i<10; i++)
	{
		for (start = linktable, end = start->next->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
		{
			TRNA* temp;
			bool flag;
			for (j = 0, temp = start; j<6; j++, temp = temp->next)
			{
				flag = false;
				if (temp->type == _6group[i][j].type)
					flag = true;
				else
					break;
			}
			if (flag)
			{
				for (temp = start, j = 0; temp != end; temp = temp->next, j++)
				{
					if (_6group[i][j].value>target[temp->i][temp->j])
					{
						target[temp->i][temp->j] = _6group[i][j].value;
					}
				}
			}
		}
	}
	for (i = 0; i<10; i++)
	{
		for (start = allend, end = start->before->before->before->before->before; end->before != NULL; start = start->before, end = end->before)
		{
			TRNA* temp;
			bool flag;
			for (j = 0, temp = start; j<6; j++, temp = temp->before)
			{
				flag = false;
				if (temp->type == _6group[i][j].type)
					flag = true;
				else
					break;
			}
			if (flag)
			{
				for (temp = start, j = 0; temp != end; temp = temp->before, j++)
				{
					if (_6group[i][j].value>target[temp->i][temp->j])
					{
						target[temp->i][temp->j] = _6group[i][j].value;
					}
				}
			}
		}
	}
	for (i = 0; i<6; i++)
	{
		for (start = linktable, end = start->next->next->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
		{
			TRNA* temp;
			bool flag;
			for (j = 0, temp = start; j<7; j++, temp = temp->next)
			{
				flag = false;
				if (temp->type == _7group[i][j].type)
					flag = true;
				else
					break;
			}
			if (flag)
			{
				for (temp = start, j = 0; temp != end; temp = temp->next, j++)
				{
					if (_7group[i][j].value>target[temp->i][temp->j])
					{
						target[temp->i][temp->j] = _7group[i][j].value;
					}
				}
			}
		}
	}
	for (i = 0; i<6; i++)
	{
		for (start = allend, end = start->before->before->before->before->before; end->before != NULL; start = start->before, end = end->before)
		{
			TRNA* temp;
			bool flag;
			for (j = 0, temp = start; j<7; j++, temp = temp->before)
			{
				flag = false;
				if (temp->type == _7group[i][j].type)
					flag = true;
				else
					break;
			}
			if (flag)
			{
				for (temp = start, j = 0; temp != end; temp = temp->before, j++)
				{
					if (_7group[i][j].value>target[temp->i][temp->j])
					{
						target[temp->i][temp->j] = _7group[i][j].value;
					}
				}
			}
		}
	}
}

void gamemode::CulResult()
{
	gamemode::initialize();
	TRNA* LO = gamemode::getlon();
	TRNA* LA = gamemode::getla();
	TRNA* LT = gamemode::getLtoR();
	TRNA* RT = gamemode::getRtoL();
	gamemode::SingleCul(LO, gamemode::longitude);
	gamemode::SingleCul(LA, gamemode::latitude);
	gamemode::SingleCul(LT, gamemode::LtoR);
	gamemode::SingleCul(RT, gamemode::RtoL);
	TRNA* temp;
	for (temp = LO; temp->next != NULL; temp = temp->next)
	{
		temp->type = temp->type * -1;
	}
	for (temp = LA; temp->next != NULL; temp = temp->next)
	{
		temp->type = temp->type * -1;
	}
	for (temp = LT; temp->next != NULL; temp = temp->next)
	{
		temp->type = temp->type * -1;
	}
	for (temp = RT; temp->next != NULL; temp = temp->next)
	{
		temp->type = temp->type * -1;
	}
	gamemode::SingleCul(LO, gamemode::longitude2);
	gamemode::SingleCul(LA, gamemode::latitude2);
	gamemode::SingleCul(LT, gamemode::LtoR2);
	gamemode::SingleCul(RT, gamemode::RtoL2);
	int i, j;
	recorder Max={0,0,0};
	for (i = 0; i<15; i++)
	{
		for (j = 0; j<15; j++)
		{
			result1[i][j] = longitude[i][j] + latitude[i][j] + LtoR[i][j] + RtoL[i][j];
		}
	}
	for (i = 0; i<15; i++)
	{
		for (j = 0; j<15; j++)
		{
			result2[i][j] = longitude2[i][j] + latitude2[i][j] + LtoR2[i][j] + RtoL2[i][j];
		}
	}
	for (i = 0; i<15; i++)
	{
		for (j = 0; j<15; j++)
		{
			if (Max.type < (result1[i][j] + tend * result2[i][j] + location[i][j]))
			{
				Max.type = result1[i][j] + tend * result2[i][j] + location[i][j];
				Max.i = i;
				Max.j = j;
			}
		}
	}
	gamemode::ivalue = Max.i;
	gamemode::jvalue = Max.j;
	release(LA);
	release(LO);
	release(LT);
	release(RT);
}

int gamemode::checkwin()
{
	int i, j;
	gamemode::initialize();
	TRNA* LO = gamemode::getlon();
	TRNA* LA = gamemode::getla();
	TRNA* LT = gamemode::getLtoR();
	TRNA* RT = gamemode::getRtoL();
	TRNA *start, *end, *allend;
	for (start = LO, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
	{
		TRNA* temp;
		bool flag;
		for (i = 0, temp = start; i<5; i++, temp = temp->next)
		{
			flag = false;
			if (temp->type == WinCon[i].type)
				flag = true;
			else
				break;
		}
		if (flag)
			return 1;
	}
	for (start = LA, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
	{
		TRNA* temp;
		bool flag;
		for (i = 0, temp = start; i<5; i++, temp = temp->next)
		{
			flag = false;
			if (temp->type == WinCon[i].type)
				flag = true;
			else
				break;
		}
		if (flag)
			return 1;
	}
	for (start = LT, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
	{
		TRNA* temp;
		bool flag;
		for (i = 0, temp = start; i<5; i++, temp = temp->next)
		{
			flag = false;
			if (temp->type == WinCon[i].type)
				flag = true;
			else
				break;
		}
		if (flag)
			return 1;
	}
	for (start = RT, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
	{
		TRNA* temp;
		bool flag;
		for (i = 0, temp = start; i<5; i++, temp = temp->next)
		{
			flag = false;
			if (temp->type == WinCon[i].type)
				flag = true;
			else
				break;
		}
		if (flag)
			return 1;
	}
	TRNA *temp;
	for (temp = LO; temp->next != NULL; temp = temp->next)
	{
		temp->type = temp->type * -1;
	}
	for (temp = LA; temp->next != NULL; temp = temp->next)
	{
		temp->type = temp->type * -1;
	}
	for (temp = LT; temp->next != NULL; temp = temp->next)
	{
		temp->type = temp->type * -1;
	}
	for (temp = RT; temp->next != NULL; temp = temp->next)
	{
		temp->type = temp->type * -1;
	}

	for (start = LO, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
	{
		TRNA* temp;
		bool flag;
		for (i = 0, temp = start; i<5; i++, temp = temp->next)
		{
			flag = false;
			if (temp->type == WinCon[i].type)
				flag = true;
			else
				break;
		}
		if (flag)
			return -1;
	}
	for (start = LA, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
	{
		TRNA* temp;
		bool flag;
		for (i = 0, temp = start; i<5; i++, temp = temp->next)
		{
			flag = false;
			if (temp->type == WinCon[i].type)
				flag = true;
			else
				break;
		}
		if (flag)
			return -1;
	}
	for (start = LT, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
	{
		TRNA* temp;
		bool flag;
		for (i = 0, temp = start; i<5; i++, temp = temp->next)
		{
			flag = false;
			if (temp->type == WinCon[i].type)
				flag = true;
			else
				break;
		}
		if (flag)
			return -1;
	}
	for (start = RT, end = start->next->next->next->next->next; end->next != NULL; start = start->next, end = end->next)
	{
		TRNA* temp;
		bool flag;
		for (i = 0, temp = start; i<5; i++, temp = temp->next)
		{
			flag = false;
			if (temp->type == WinCon[i].type)
				flag = true;
			else
				break;
		}
		if (flag)
			return -1;
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值