博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
cocos2dx的发展的例子2048(加入动画版)
阅读量:7156 次
发布时间:2019-06-29

本文共 18632 字,大约阅读时间需要 62 分钟。

网上找了很多写作教程2048。只是不知道卡的移动动画,我写了一个完美的动画版少。

开发步骤:

1,一个设计CardSprite类。

2,设计主游戏场景GameScene,实现游戏逻辑,加入动画逻辑。

3,加入游戏胜利或者游戏失败的层。加入历史分数存储。

4。加入声音等其它元素,专门弄了一个声音预载入的场景。主场景加入声音切换变量存储。

贴上主场景关键代码:

GameScene.h

#pragma once#include "cocos2d.h"#include "cardSprite.h"#include "MenuLayer.h"class GameScene :public cocos2d::Layer{public:	static cocos2d::Scene* createScene();	virtual bool init();	CREATE_FUNC(GameScene);public:	//触摸监听	virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event); //注意这里要加命名空间作用域cocos2d	virtual void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *event);    //上下左右滑动动作	bool moveLeft();	bool moveRight();	bool moveUp();	bool moveDown();	//创建4*4卡片矩阵	void createCardArr(Size size);	void randomCreateCard();	//推断游戏赢输	void checkGameWin();	void checkGameOver();	void restart(Ref *sender); //又一次開始游戏菜单项private:	int score;  //当前分数	int bestScore; //最好分数	bool sound; //声音变量	cocos2d::LabelTTF *scoreLabel;	LabelTTF *restartBtn; //又一次開始的button	LabelTTF *isSoundBtn; //声音切换button	CardSprite *cardArr[4][4];  //数字卡片矩阵	CardSprite *cardArrAction[4][4]; //用于动画的暂时数字卡片矩阵	Point startPt; //触摸開始点	int offsetX, offsetY;  //触摸水平和竖直方向偏移量	MenuLayer *menuLayer; //菜单层	timeval tv; //当前时间};

GameScene.cpp

/**game:2048*author:tashaxing*time:2014/10/12*/#include "GameScene.h"#include "SimpleAudioEngine.h"using namespace cocos2d;using namespace CocosDenshion;Scene* GameScene::createScene(){	auto scene = Scene::create();	auto layer = GameScene::create();	scene->addChild(layer);	return scene;}bool GameScene::init(){	if (!Layer::init())		return false;	//获得屏幕尺寸和原点	Size visibleSize = Director::getInstance()->getVisibleSize();	Vec2 origin = Director::getInstance()->getVisibleOrigin();    //加入背景	auto gameBkGround = LayerColor::create(Color4B(180, 170, 160, 255));	this->addChild(gameBkGround);	//加入标题	auto title = LabelTTF::create("My2048", "Arial", 60);	title->setColor(Color3B(255, 255, 153));	title->setPosition(Point(visibleSize.width / 2, visibleSize.height - 50));	this->addChild(title);	//加入restartbutton  	restartBtn = LabelTTF::create("Restart", "Arial", 40);	restartBtn->setColor(Color3B(204, 255, 253));	restartBtn->setPosition(Point(visibleSize.width / 2, visibleSize.height - 110));	this->addChild(restartBtn);	//加入声音切换button	//初始化获取最好分数和声音变量,第一次启动应用的话xml里没有不论什么值。所以以下的会返回0和false	sound = UserDefault::getInstance()->getBoolForKey("SOUND");	if (sound)		isSoundBtn = LabelTTF::create("Sound On", "Arial", 40);	else		isSoundBtn = LabelTTF::create("Sound Off", "Arial", 40);	isSoundBtn->setColor(Color3B(204, 255, 253));	isSoundBtn->setPosition(Point(visibleSize.width / 2, 50));	this->addChild(isSoundBtn);	//加入游戏分数  	auto slabel = LabelTTF::create("Score", "Arial", 30);	slabel->setPosition(Point(visibleSize.width / 5, visibleSize.height - 150));	this->addChild(slabel);    score = 0;    scoreLabel = LabelTTF::create("0", "Arial", 30);	scoreLabel->setColor(Color3B(0, 255, 37));	scoreLabel->setPosition(Point(visibleSize.width / 2+30, visibleSize.height - 150));	this->addChild(scoreLabel);	bestScore = UserDefault::getInstance()->getIntegerForKey("BEST");		//初始化卡片	createCardArr(visibleSize);	randomCreateCard();	randomCreateCard();		//加入触摸监听	auto listener = EventListenerTouchOneByOne::create();	listener->onTouchBegan = CC_CALLBACK_2(GameScene::onTouchBegan, this);	listener->onTouchEnded = CC_CALLBACK_2(GameScene::onTouchEnded, this);	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);	return true;}void GameScene::restart(Ref* sender){	//转场,又一次開始游戏	Director::getInstance()->replaceScene(TransitionFade::create(0.7f, GameScene::createScene()));}bool GameScene::onTouchBegan(Touch *touch, Event *event){	gettimeofday(&tv, NULL); //记录当前时间	startPt = touch->getLocation(); //保存開始触摸点	//推断假设触摸点在restartbutton区域内则又一次開始	if (restartBtn->getBoundingBox().containsPoint(restartBtn->convertToNodeSpace(touch->getLocation())))		Director::getInstance()->replaceScene(TransitionFade::create(0.7f, GameScene::createScene()));	//声音开关	if (isSoundBtn->getBoundingBox().containsPoint(isSoundBtn->convertToNodeSpace(touch->getLocation())))	{		sound = !sound;		UserDefault::getInstance()->setBoolForKey("SOUND", sound);		if (sound)			isSoundBtn->setString("Sound On");		else			isSoundBtn->setString("Sound Off");	}	return true;}void GameScene::onTouchEnded(Touch *touch, Event *event){	timeval tv_end;	gettimeofday(&tv_end, NULL);	if (tv_end.tv_sec - tv.tv_sec > 3)	{		//开个后门,用来測试游戏赢了		cardArr[0][3]->setNumber(2048);		checkGameWin();	}	auto endPt = touch->getLocation();  //获得触摸结束点	offsetX = endPt.x - startPt.x;  //计算偏移	offsetY = endPt.y - startPt.y;	bool isTouch = false; 	if (abs(offsetX) > abs(offsetY))  //推断为方向	{		if (offsetX < -5)			isTouch = moveLeft();		else if (offsetX > 5)			isTouch = moveRight();	}	else	{		if (offsetY > 5)   //注意这里的纵向坐标别弄反			isTouch = moveDown();		else if (offsetY<-5)			isTouch = moveUp();	}	if (isTouch)  //假设滑动成功则推断	{		scoreLabel->setString(String::createWithFormat("%d", score)->getCString());		//这三个的顺序不能乱		checkGameWin();		randomCreateCard();		checkGameOver();	}}void GameScene::createCardArr(Size size){	int space = 5; //卡片间的间隔	int cardSize = (size.width - 4 * space) / 4;		//创建卡片矩阵	for (int i = 0; i < 4; i++)	{		for (int j = 0; j < 4; j++)		{			//最左边留白12,最以下留白size.height/6			//坐标从左下角算起,右为正。上为正			CardSprite *card = CardSprite::createCard(0, cardSize, cardSize, cardSize*i + 12, cardSize*j + 12 + size.height / 6);			this->addChild(card);  //一定要把card加入到子节点才干渲染出来			cardArr[i][j] = card;  //存到卡片矩阵		}	}	//创建暂时卡片矩阵。用于动画,每一个动画卡片相应一个实际卡片的动画,这是个技巧,而且动画层在卡片层之上,所以后加入,也能够设置addchild层次	for (int i = 0; i < 4; i++)	{		for (int j = 0; j < 4; j++)		{			//最左边留白12。最以下留白size.height/6			CardSprite *card = CardSprite::createCard(0, cardSize, cardSize, cardSize*i + 12, cardSize*j + 12 + size.height / 6);			this->addChild(card);			cardArrAction[i][j] = card;			//一開始把这层所有因此			auto hide = Hide::create();			cardArrAction[i][j]->getCardLayer()->runAction(hide);		}	}}void GameScene::randomCreateCard(){	//在随机位置生成卡片	int row = CCRANDOM_0_1() * 4;	int col = CCRANDOM_0_1() * 4;	if (cardArr[row][col]->getNumber() > 0)  //假设有数字。则递归调用		randomCreateCard();	else	{		cardArr[row][col]->setNumber(CCRANDOM_0_1() * 10 < 1 ? 4 : 2); //有10%的几率生成4		//用动画效果生成		auto action = Sequence::createWithTwoActions(ScaleTo::create(0, 0), ScaleTo::create(0.3f, 1));  //在0.3秒内从小缩放到大		cardArr[row][col]->getCardLayer()->runAction(action);  //用卡片的层而不是卡片精灵本身做动作是为了使用局部坐标缩放	}}//向左滑动游戏逻辑,其它方向相似bool GameScene::moveLeft(){	//是否有移动的逻辑变量,假设没有不论什么移动。则不须要随机生成卡片。也不检验赢输,这一点非常关键,否则非常easy出bug	bool moved = false;	//计算移动的步进间距	auto cardSize = (Director::getInstance()->getVisibleSize().width - 5 * 4) / 4;	//y表示行标号,x表示列标号	for (int y = 0; y < 4; y++)  //最外层的行遍历能够先无论	{		for (int x = 0; x < 4; x++)   //内部的N^2复杂度的相似冒泡排序		{			for (int x1 = x + 1; x1 < 4; x1++)			{				if (cardArr[x1][y]->getNumber()>0)  //x右边的卡片有数字才动作				{					if (cardArr[x][y]->getNumber() == 0)					{						//专门弄一个动画层卡片实现定位、显现、移动、隐藏系列动画						auto place = Place::create(Point(cardSize*x1 + 12, cardSize*y + 12 + Director::getInstance()->getVisibleSize().height / 6));						cardArrAction[x1][y]->setNumber(cardArr[x1][y]->getNumber());  //每次都又一次把动画卡片又一次定位到实际相应的卡片位置,并设置同样的数字						auto show = Show::create();						auto move = MoveBy::create(0.1f, Point(-cardSize*(x1 - x), 0));  //注意移动的距离						auto hide = Hide::create();						cardArrAction[x1][y]->getCardLayer()->runAction(Sequence::create(place, show, move, hide, NULL));								//假设x位置是空卡片。就把x1卡片移到x处,x1处变成空卡片						cardArr[x][y]->setNumber(cardArr[x1][y]->getNumber());						cardArr[x1][y]->setNumber(0);						x--;  //再扫描一遍,确保所有结果正确						moved = true;					}					else if (cardArr[x][y]->getNumber() == cardArr[x1][y]->getNumber())					{						auto place = Place::create(Point(cardSize*x1 + 12, cardSize*y + 12 + Director::getInstance()->getVisibleSize().height / 6));						cardArrAction[x1][y]->setNumber(cardArr[x1][y]->getNumber());						auto show = Show::create();						auto move = MoveBy::create(0.1f, Point(-cardSize*(x1 - x), 0));  //注意移动的距离						auto hide = Hide::create();						cardArrAction[x1][y]->getCardLayer()->runAction(Sequence::create(place, show, move, hide, NULL));						//假设x位置非空,且与x1处数字同样,则乘2						cardArr[x][y]->setNumber(cardArr[x][y]->getNumber() * 2);						cardArr[x1][y]->setNumber(0);												//数字合并动画						auto merge = Sequence::create(ScaleTo::create(0.1f, 1.2f), ScaleTo::create(0.1f, 1.0f), NULL);						cardArr[x][y]->getCardLayer()->runAction(merge);												score += cardArr[x][y]->getNumber();												//播放得分声音						if (sound)							SimpleAudioEngine::getInstance()->playEffect("get.mp3");						moved = true;					}					break;   //此处break防止出现连续乘2的bug				}			}		}	}	return moved;}bool GameScene::moveRight(){	bool moved = false;	//计算移动的步进间距	auto cardSize = (Director::getInstance()->getVisibleSize().width - 5 * 4) / 4;	//y表示行标号。x表示列标号	for (int y = 0; y < 4; y++)  //最外层的行遍历能够先无论	{		for (int x = 3; x >=0; x--)   //内部的N^2复杂度的相似冒泡排序		{			for (int x1 = x -1; x1 >= 0; x1--)			{				if (cardArr[x1][y]->getNumber()>0)  //x左边的卡片有数字才动作				{					if (cardArr[x][y]->getNumber() == 0)					{						auto place = Place::create(Point(cardSize*x1 + 12, cardSize*y + 12 + Director::getInstance()->getVisibleSize().height / 6));						cardArrAction[x1][y]->setNumber(cardArr[x1][y]->getNumber());						auto show = Show::create();						auto move = MoveBy::create(0.1f, Point(-cardSize*(x1 - x), 0));  //注意移动的距离						auto hide = Hide::create();						cardArrAction[x1][y]->getCardLayer()->runAction(Sequence::create(place, show, move, hide, NULL));						//假设x位置是空卡片,就把x1卡片移到x处,x1处变成空卡片						cardArr[x][y]->setNumber(cardArr[x1][y]->getNumber());						cardArr[x1][y]->setNumber(0);						x++;						moved = true;					}					else if (cardArr[x][y]->getNumber() == cardArr[x1][y]->getNumber())					{						auto place = Place::create(Point(cardSize*x1 + 12, cardSize*y + 12 + Director::getInstance()->getVisibleSize().height / 6));						cardArrAction[x1][y]->setNumber(cardArr[x1][y]->getNumber());						auto show = Show::create();						auto move = MoveBy::create(0.1f, Point(-cardSize*(x1 - x), 0));  //注意移动的距离,此处算出来为正						auto hide = Hide::create();						cardArrAction[x1][y]->getCardLayer()->runAction(Sequence::create(place, show, move, hide, NULL));						//假设x位置非空,且与x1处数字同样,则乘2						cardArr[x][y]->setNumber(cardArr[x][y]->getNumber() * 2);						cardArr[x1][y]->setNumber(0);						auto merge = Sequence::create(ScaleTo::create(0.1f, 1.2f), ScaleTo::create(0.1f, 1.0f), NULL);						cardArr[x][y]->getCardLayer()->runAction(merge);						score += cardArr[x][y]->getNumber();						if (sound)							SimpleAudioEngine::getInstance()->playEffect("get.mp3");						moved = true;					}					break;   //此处break防止出现连续乘2的bug				}			}		}	}	return moved;}bool GameScene::moveUp()   //这里的“上”是逻辑上往坐标值小的方向,在屏幕上实际是往下动{	bool moved=false;	//计算移动的步进间距	auto cardSize = (Director::getInstance()->getVisibleSize().width - 5 * 4) / 4;	//y表示行标号。x表示列标号	for (int x = 0; x < 4; x++)  //最外层的列遍历能够先无论	{		for (int y = 0; y < 4; y++)   //内部的N^2复杂度的相似冒泡排序		{			for (int y1 = y + 1; y1 < 4; y1++)			{				if (cardArr[x][y1]->getNumber()>0)  //x下边的卡片有数字才动作				{					if (cardArr[x][y]->getNumber() == 0)					{						auto place = Place::create(Point(cardSize*x + 12, cardSize*y1 + 12 + Director::getInstance()->getVisibleSize().height / 6));						cardArrAction[x][y1]->setNumber(cardArr[x][y1]->getNumber());						auto show = Show::create();						auto move = MoveBy::create(0.1f, Point(0 ,- cardSize*(y1 - y)));  //注意移动的距离						auto hide = Hide::create();						cardArrAction[x][y1]->getCardLayer()->runAction(Sequence::create(place, show, move, hide, NULL));												//假设x位置是空卡片,就把x1卡片移到x处,x1处变成空卡片						cardArr[x][y]->setNumber(cardArr[x][y1]->getNumber());						cardArr[x][y1]->setNumber(0);						y--;						moved = true;					}					else if (cardArr[x][y]->getNumber() == cardArr[x][y1]->getNumber())					{						auto place = Place::create(Point(cardSize*x + 12, cardSize*y1 + 12 + Director::getInstance()->getVisibleSize().height / 6));						cardArrAction[x][y1]->setNumber(cardArr[x][y1]->getNumber());						auto show = Show::create();						auto move = MoveBy::create(0.1f, Point(0, -cardSize*(y1 - y)));  //注意移动的距离						auto hide = Hide::create();						cardArrAction[x][y1]->getCardLayer()->runAction(Sequence::create(place, show, move, hide, NULL));						//假设x位置非空,且与x1处数字同样。则乘2						cardArr[x][y]->setNumber(cardArr[x][y]->getNumber() * 2);						cardArr[x][y1]->setNumber(0);						auto merge = Sequence::create(ScaleTo::create(0.1f, 1.2f), ScaleTo::create(0.1f, 1.0f), NULL);						cardArr[x][y]->getCardLayer()->runAction(merge);						score += cardArr[x][y]->getNumber();						if (sound)							SimpleAudioEngine::getInstance()->playEffect("get.mp3");						moved = true;					}					break;   //此处break防止出现连续乘2的bug				}			}		}	}	return moved;}bool GameScene::moveDown()   //这里的“下”是逻辑上往坐标值小的方向,在屏幕上实际是往上动{	bool moved=false;	//计算移动的步进间距	auto cardSize = (Director::getInstance()->getVisibleSize().width - 5 * 4) / 4;	//y表示行标号,x表示列标号	for (int x = 0; x < 4; x++)  //最外层的列遍历能够先无论	{		for (int y = 3; y >= 0; y--)   //内部的N^2复杂度的相似冒泡排序		{			for (int y1 = y - 1; y1 >= 0; y1--)			{				if (cardArr[x][y1]->getNumber()>0)  //x上边的卡片有数字才动作				{					if (cardArr[x][y]->getNumber() == 0)					{						auto place = Place::create(Point(cardSize*x + 12, cardSize*y1 + 12 + Director::getInstance()->getVisibleSize().height / 6));						cardArrAction[x][y1]->setNumber(cardArr[x][y1]->getNumber());						auto show = Show::create();						auto move = MoveBy::create(0.1f, Point(0, -cardSize*(y1 - y)));  //注意移动的距离						auto hide = Hide::create();						cardArrAction[x][y1]->getCardLayer()->runAction(Sequence::create(place, show, move, hide, NULL));						//假设x位置是空卡片,就把x1卡片移到x处。x1处变成空卡片						cardArr[x][y]->setNumber(cardArr[x][y1]->getNumber());						cardArr[x][y1]->setNumber(0);						y++;						moved = true;					}					else if (cardArr[x][y]->getNumber() == cardArr[x][y1]->getNumber())					{						auto place = Place::create(Point(cardSize*x + 12, cardSize*y1 + 12 + Director::getInstance()->getVisibleSize().height / 6));						cardArrAction[x][y1]->setNumber(cardArr[x][y1]->getNumber());						auto show = Show::create();						auto move = MoveBy::create(0.1f, Point(0, -cardSize*(y1 - y)));  //注意移动的距离						auto hide = Hide::create();						cardArrAction[x][y1]->getCardLayer()->runAction(Sequence::create(place, show, move, hide, NULL));						//假设x位置非空,且与x1处数字同样,则乘2						cardArr[x][y]->setNumber(cardArr[x][y]->getNumber() * 2);						cardArr[x][y1]->setNumber(0);						auto merge = Sequence::create(ScaleTo::create(0.1f, 1.2f), ScaleTo::create(0.1f, 1.0f), NULL);						cardArr[x][y]->getCardLayer()->runAction(merge);						score += cardArr[x][y]->getNumber();						if (sound)							SimpleAudioEngine::getInstance()->playEffect("get.mp3");						moved = true;					}					break;   //此处break防止出现连续乘2的bug				}			}		}	}	return moved;}void GameScene::checkGameWin(){	bool isWin = false;	for (int i = 0; i < 4; i++)		for (int j = 0; j < 4; j++)			if (2048 == cardArr[i][j]->getNumber())				isWin = true;	if (isWin)	{		//播放音效		if (sound)			SimpleAudioEngine::getInstance()->playEffect("gamewin.mp3");		//有一个2048游戏就是赢了		/*初始化菜单层*/		menuLayer = MenuLayer::create(Color4B(0, 0, 0, 100));		this->addChild(menuLayer);		auto menuSize = menuLayer->getContentSize();		//加入标题		auto menuTitle = LabelTTF::create("YOU WIN", "Arial", 30);		menuTitle->setPosition(menuSize.width / 2, menuSize.height / 2 + 50);		menuLayer->addChild(menuTitle);		//加入当前分数		auto menuscoreLabel = LabelTTF::create(String::createWithFormat("current: %d", score)->getCString(), "Arial", 20);		menuscoreLabel->setPosition(menuSize.width / 2, menuSize.height / 2);		menuLayer->addChild(menuscoreLabel);		//加入最好分数		bestScore = UserDefault::getInstance()->getIntegerForKey("BEST");		if (score > bestScore)		{			bestScore = score;			UserDefault::getInstance()->setIntegerForKey("BEST", bestScore);		}		auto menuBestscoreLabel = LabelTTF::create(String::createWithFormat("best: %d", bestScore)->getCString(), "Arial", 20);		menuBestscoreLabel->setPosition(menuSize.width / 2, menuSize.height / 2 - 30);		menuLayer->addChild(menuBestscoreLabel);		MenuItemFont::setFontName("Arial");		MenuItemFont::setFontSize(25);		auto menuItemRestart = MenuItemFont::create("Restart", this, menu_selector(GameScene::restart));		menuItemRestart->setColor(Color3B(255, 255, 0));		auto menu = Menu::create(menuItemRestart, NULL);		menuLayer->addChild(menu);		menu->setPosition(Point(menuSize.width / 2, menuSize.height / 2 - 80));	}}void GameScene::checkGameOver(){	bool isGameOver = true;	//以下情况则游戏继续	for (int j = 0; j < 4; j++)	{		for (int i = 0; i < 4; i++)		{			if ((cardArr[i][j]->getNumber()==0)||				(i>0 && cardArr[i][j]->getNumber() == cardArr[i - 1][j]->getNumber()) ||				(i<3 && cardArr[i][j]->getNumber() == cardArr[i + 1][j]->getNumber()) ||				(j>0 && cardArr[i][j]->getNumber() == cardArr[i][j - 1]->getNumber()) ||				(j<3 && cardArr[i][j]->getNumber() == cardArr[i][j + 1]->getNumber()))			{				isGameOver = false;			}		}	}	//否则游戏结束	if (isGameOver)	{		if (sound)			SimpleAudioEngine::getInstance()->playEffect("gameover.mp3");		/*初始化菜单层*/		menuLayer = MenuLayer::create(Color4B(0, 0, 0, 100));		this->addChild(menuLayer);		auto menuSize = menuLayer->getContentSize();		//加入标题		auto menuTitle = LabelTTF::create("GAME OVER", "Arial", 30);		menuTitle->setPosition(menuSize.width / 2, menuSize.height / 2 + 50);		menuLayer->addChild(menuTitle);		//加入当前分数		auto menuscoreLabel = LabelTTF::create(String::createWithFormat("current: %d", score)->getCString(), "Arial", 20);		menuscoreLabel->setPosition(menuSize.width / 2, menuSize.height / 2);		menuLayer->addChild(menuscoreLabel);		//加入最好分数		bestScore = UserDefault::getInstance()->getIntegerForKey("BEST");		if (score > bestScore)		{			bestScore = score;			UserDefault::getInstance()->setIntegerForKey("BEST", bestScore);		}		auto menuBestscoreLabel = LabelTTF::create(String::createWithFormat("best: %d", bestScore)->getCString(), "Arial", 20);		menuBestscoreLabel->setPosition(menuSize.width / 2, menuSize.height / 2 - 30);		menuLayer->addChild(menuBestscoreLabel);		MenuItemFont::setFontName("Arial");		MenuItemFont::setFontSize(25);		auto menuItemRestart = MenuItemFont::create("Restart", this, menu_selector(GameScene::restart));		menuItemRestart->setColor(Color3B(255, 255, 0));		auto menu = Menu::create(menuItemRestart, NULL);		menuLayer->addChild(menu);		menu->setPosition(Point(menuSize.width / 2, menuSize.height / 2 - 80));	}		}
关键点:

1。专门弄了一个4*4的卡片暂时矩阵做为动画层,也就是有16个卡片专门负责相应卡片的动画(卡片生成的动画是实际卡片。这个是例外)。

2,关于游戏逻辑中每次移动后面都有一个break

假设不加这个break就会出现:

  • 本来是 2 2 4 2 
    向左滑动应该是 4 4 2 0 
    结果是: 8 2 0 0    
加上break就正常了。

游戏截图:

  

源码

csdn下载:

github下载:

版权声明:本文博客原创文章。博客,未经同意,不得转载。

你可能感兴趣的文章
JS监听对象属性读写的5种方法
查看>>
多个wifi路由器组建一个wifi网络增加网络覆盖范围
查看>>
作为“创业导师”的天使投资人
查看>>
改变世界梦想的创业者
查看>>
国产数据库一览表
查看>>
获取url的参数包括中文参数
查看>>
ios 中使用 block
查看>>
详解Google Authenticator工作原理
查看>>
树莓派设置屏幕待机时间
查看>>
mysql问题汇总
查看>>
php/Java Web国际化的联合解决方案
查看>>
AndroidStudio环境的搭建
查看>>
Postgresql数据类型
查看>>
django-ckeditor 使用
查看>>
布隆过滤器
查看>>
jquary
查看>>
Spring Cloud搭建微服务架构----前言
查看>>
延时任务怎么搞
查看>>
MSql中的延迟
查看>>
android tools的添加路径设置过程
查看>>