前段时间一直在忙。没有时间更新博客。今天还是抽点时间把最后一小部分游戏的实现放上来吧。

BaseLayer.h:

#import <GameKit/GameKit.h>
#import "cocos2d.h"#import "AppDelegate.h"
#import "PersonSprite.h"
#import "PriestSprite.h"
#import "DevilSprite.h"
#import "BoatSprite.h"
#import "BankSprite.h"@interface BaseLayer : CCLayer <MoveSpriteDelegate>@property (strong,nonatomic) BankSprite* rightBank;
@property (strong,nonatomic) BankSprite* leftBank;@property (strong,nonatomic) BoatSprite* boat;@property (assign,nonatomic) int time;      //set the timer+(CCScene *) scene;@end

记得在(2)讲PersonSprite的时候讲过,我们须要BaseLayer来取代PersonSprite来移动图层上的精灵。

因此我们在BaseLayer头文件定义的时候就须要遵守MoveSpriteDelegate协议了。(忘记了的能够翻回文章(2)看一下详细细节)看看BaseLayer的类成员。一共同拥有两个河岸和一条船,另一个整数记录剩余时间。因为BaseLayer并不须要开放变量给其它类使用,所以这些河岸对象和船的定义放在头文件中还是实现文件中的匿名类别区域里面关系都不大。我把这几个类成员放在这里是想将整个游戏的框架表示得清晰一些。

严格地来说,放在.m文件的扩展类别区域更为安全。

有人可能会问:“为什么不把6个过河的人也定义在头文件中呢?”事实上我觉得这样做也是能够的,仅仅是由于考虑到BaseLayer对人和船、河岸的处理是不一样的:对于人来说,BaseLayer是通过代理的形式操作人的。即当玩家点击某个人的时候。事件从该人相应的PersonSprite对象開始传递,而PersonSprite通过delegate的形式交由BaseLayer来实现。在delegate參数传递的过程中,BaseLayer是知道哪个人产生了事件的(能够类比一下UIButton。当点击button产生事件的时候,Controller接收到事件时是能够知道由哪个button被按下导致触发了事件的)。故对于BaseLayer来说。须要使用到PersonSprite的情况仅仅有:1. 对PersonSprite的初始化。 2. 调用托付函数moveSprite。

所以并不须要把PersonSprite也作为成员变量;而对于船来说。由于其是由BaseLayer直接操纵的(控制船的移动),故在BaseLayer中会有多个函数使用到BoatSprite的对象。因此将BoatSprite设置为BaseLayer的成员变量更为方便。BankSprite同理。

来到.m文件,首先看一下静态变量以及扩展类别的声明:

#import "BaseLayer.h"
#import "PublicArg.h"
#import  "SimpleAudioEngine.h"
#include "AI.h"static NSString *PRIEST_IMAGE_NAME = @"priest.png";
static NSString *DEVIL_IMAGE_NAME =  @"devil.png";
static NSString *BOAT_IMAGE_NAME = @"boat.png";
static NSString *BACKGROUND_IMAGE_NAME = @"background.jpg";
static NSString *WATER_IMAGE_NAME = @"water.png";static NSString *BG_MUSIC = @"background.mp3";
static NSString *CLICK_EFF = @"click.mp3";
static NSString *FAIL_EFF = @"fail.mp3";
static NSString *PERSON_EFF = @"person.mp3";
static NSString *WATER_EFF = @"water.wav";
static NSString *WIN_EFF = @"win.mp3";static int timeLimit = 200;         //set the time limit@interface BaseLayer()@property (strong,nonatomic) AppController *delegate;//list the items here because the title would be changed
@property CCMenuItem *beginItem;
@property CCMenuItem *helpItem;
@property CCMenuItem *pauseItem;
@property CCMenuItem *resumeItem;
@property CCMenuItem *endItem;
@property CCMenuItem *transitItem;
@property CCLabelTTF *timeShow;@property CCMenu *goMenu;
@property CCMenu *systemMenu;@property CCSprite *water;@end

静态变量中设置的都是图片的地址以及倒计时的总时长。而类别扩展中我定义了一些button成员变量。这些就是游戏中的菜单。

因为点击不同选项的时候有可能造成其它选项的转台变化(如点击暂停的时候。helpbutton应该是不可用的)。所以我将这些button都放到成员变量中统一管理。注意到最后另一个water的sprite对象,这个是画面中在船上面的水图层,用来遮挡船的下沿,让效果更逼真一些。

看看几个初始化函数:

+(CCScene *) scene
{CCScene *scene = [CCScene node];BaseLayer *layer = [BaseLayer node];[scene addChild: layer];return scene;
}//initialize instance
-(id) init
{if( (self=[super init]) ) {//initiate the game state_delegate = [[UIApplication sharedApplication] delegate];_delegate.gameState = BeforeGame;_delegate.screenSize = [[CCDirector sharedDirector] winSize];//initiate the public arguments[PublicArg sharedArg];//set the background image which is also a spriteCCSprite *background = [CCSprite spriteWithFile:BACKGROUND_IMAGE_NAME];[background setScale:0.5f];[background setPosition:ccp(_delegate.screenSize.width/2, _delegate.screenSize.height/2)];[self addChild:background];[self initMenu];//preload the background music & effects//[[SimpleAudioEngine sharedEngine] preloadBackgroundMusic:BG_MUSIC];//[[SimpleAudioEngine sharedEngine] preloadEffect:CLICK_EFF];//[[SimpleAudioEngine sharedEngine] preloadEffect:FAIL_EFF];//[[SimpleAudioEngine sharedEngine] preloadEffect:PERSON_EFF];//[[SimpleAudioEngine sharedEngine] preloadEffect:WATER_EFF];//[[SimpleAudioEngine sharedEngine] preloadEffect:WIN_EFF];}return self;
}-(void)initSprites
{//set the 2 banks & 6 persons_rightBank = [[BankSprite alloc] initWithSide:Right];    //start place_leftBank = [[BankSprite alloc]initWithSide:Left];       //end place_rightBank.tag = 101;_leftBank.tag = 100;[self addChild:_rightBank];[self addChild:_leftBank];for(int i = 0;i<3;++i){PriestSprite *temp_priest = [PriestSprite initPriestWithFile:PRIEST_IMAGE_NAME withNumber:i];DevilSprite *temp_devil = [DevilSprite initDevilWithFile:DEVIL_IMAGE_NAME withNumber:i];temp_priest.delegate = self;temp_devil.delegate = self;temp_priest.tag = i;temp_devil.tag = i + 3;[self addChild:temp_priest];[self addChild:temp_devil];}//set the boat_boat = [BoatSprite initBoatWithFile:BOAT_IMAGE_NAME];[self addChild:_boat];//set the water_water = [CCSprite spriteWithFile:WATER_IMAGE_NAME];[_water setScale:0.5];[_water setPosition:ccp(_delegate.screenSize.width/2-40, _delegate.screenSize.height/2)];[self addChild:_water];
}-(void)initMenu
{//set the menu list[CCMenuItemFont setFontSize:28];_beginItem = [CCMenuItemFont itemWithString:@"Start" target:self selector:@selector(beginGame)];_helpItem = [CCMenuItemFont itemWithString:@"Help" target:self selector:@selector(help)];_pauseItem = [CCMenuItemFont itemWithString:@"Pause" target:self selector:@selector(pauseGame)];_resumeItem = [CCMenuItemFont itemWithString:@"Resume" target:self selector:@selector(resumeGame)];_endItem = [CCMenuItemFont itemWithString:@"End" target:self selector:@selector(endGame)];_systemMenu = [CCMenu menuWithItems:_beginItem, _pauseItem, _resumeItem, _endItem, _helpItem, nil];[_systemMenu alignItemsHorizontallyWithPadding:45.0];[_systemMenu setPosition:ccp( _delegate.screenSize.width/2 , _delegate.screenSize.height/2 + 100)];[self addChild:_systemMenu];_transitItem = [CCMenuItemFont itemWithString:@"Go" target:self selector:@selector(transit)];[_transitItem setColor:ccc3(0, 0, 0)];[_transitItem setVisible:NO];_goMenu = [CCMenu menuWithItems:_transitItem, nil];[_goMenu setPosition:ccp( _delegate.screenSize.width/2 , _delegate.screenSize.height/2 +10)];[self addChild:_goMenu];//set the items[_resumeItem setIsEnabled:NO];[_endItem setIsEnabled:NO];[_pauseItem setIsEnabled:NO];[_helpItem setIsEnabled:NO];//set the time shower_timeShow = [[CCLabelTTF alloc] init];[_timeShow setFontName:@"Marker Felt"];[_timeShow setPosition:ccp(_delegate.screenSize.width/2, _delegate.screenSize.height/2 + 50)];[_timeShow setFontSize:24.0f];[self addChild:_timeShow];
}

顺带打开AppDelegate.h:

#import <UIKit/UIKit.h>
#import "cocos2d.h"typedef enum
{Left = 100,Right = 101,BOAT = 102
} Side;//list out the game state
typedef enum
{BeforeGame,     //state: before game startInGame,         //state: game runningBlockGame,      //state: boat is moving the nothing can be donePauseGame,      //state: game pauseEndGame         //state: game end
} GameState;// Added only for iOS 6 support
@interface MyNavigationController : UINavigationController <CCDirectorDelegate>
@end@interface AppController : NSObject <UIApplicationDelegate>
{UIWindow *window_;MyNavigationController *navController_;CCDirectorIOS *__unsafe_unretained director_;                         // weak ref
}@property (nonatomic, strong) UIWindow *window;
@property (readonly) MyNavigationController *navController;
@property (unsafe_unretained, readonly) CCDirectorIOS *director;@property (assign,nonatomic) CGSize screenSize;         //the screen size
@property (assign,nonatomic) GameState gameState;       //game state@end

Scene函数是BaseLayer的初始化函数:首先建立一个新的场景。然后向场景中增加BaseLayer布景。大多数Layer都有Scene这个函数。这个是由系统自己主动生成的。在init函数中,初始化了delegate变量。delegate是AppDelegate的单例。

在AppDelegate的头文件里,我们能够知道它记录了游戏的状态和屏幕大小。由于这些是与游戏总体有关的变量,所以放在了全局的AppDelegate中,并在BaseLayer中使用delegate对其进行引用。

之后创建了一个background对象并增加到布景中。同一时候初始化菜单以及计时器。

在initSprite方法中。我们初始化了6个人而且分别以tag值0到5记录他们。这是为后面将其放在岸上的指定位置做准备的。

接下来看看代理方法moveSprite的实现:

#pragma mark MoveSprite Delegate
-(void)moveSprite:(PersonSprite *)sprite
{if (_delegate.gameState != InGame)return;//[[SimpleAudioEngine sharedEngine]playEffect:PERSON_EFF];PublicArg *arg = [PublicArg sharedArg];switch (sprite.personSide) {case Left: case Right:     //person is on the left{//when person and boat are at different sideif ( (sprite.personSide == Left && _boat.boatSide == Right) ||(sprite.personSide == Right && _boat.boatSide == Left))return;//go on the boatswitch (_boat.priestNumber + _boat.devilNumber ) {case 0:{[sprite setPosition:ccp(_boat.position.x-20, _boat.position.y+25)];[_boat.personList addObject:sprite];break;}case 1:{[_boat.personList addObject:sprite];PersonSprite *temp = [_boat.personList objectAtIndex:0];[sprite setPosition:ccp(2 * _boat.position.x - temp.position.x, _boat.position.y+25)];break;}case 2:  return;}if ([sprite isKindOfClass:[PriestSprite class]]){_boat.priestNumber++;BankSprite * temp_bamk = (BankSprite *)[self getChildByTag:sprite.personSide];temp_bamk.priestNumber --;}else if ([sprite isKindOfClass:[DevilSprite class]]){_boat.devilNumber++;BankSprite * temp_bamk = (BankSprite *)[self getChildByTag:sprite.personSide];temp_bamk.devilNumber --;}[sprite setPersonSide:BOAT];break;}case BOAT:      //person is on the boat{if ([sprite isKindOfClass:[PriestSprite class]]){if (_boat.boatSide == Left){[sprite setPosition:ccp(arg.priest_begin_left.x + sprite.number * arg.person_interval, arg.priest_begin_left.y )];[sprite setPersonSide:Left];_leftBank.priestNumber ++;}else if (_boat.boatSide == Right){[sprite setPosition:ccp(arg.priest_begin_right.x + sprite.number * arg.person_interval, arg.priest_begin_right.y )];[sprite setPersonSide:Right];_rightBank.priestNumber ++;}_boat.priestNumber--;}else if ([sprite isKindOfClass:[DevilSprite class]]){if (_boat.boatSide == Left){[sprite setPosition:ccp(arg.devil_begin_left.x + sprite.number * arg.person_interval, arg.devil_begin_left.y )];[sprite setPersonSide:Left];_leftBank.devilNumber++;}else if (_boat.boatSide == Right){[sprite setPosition:ccp(arg.devil_begin_right.x + sprite.number * arg.person_interval, arg.devil_begin_right.y )];[sprite setPersonSide:Right];_rightBank.devilNumber ++;}_boat.devilNumber--;}[_boat.personList removeObject:sprite];if([self judgeWin]){[[SimpleAudioEngine sharedEngine] stopBackgroundMusic];[[SimpleAudioEngine sharedEngine]playEffect:WIN_EFF];[_timeShow setString:@"Win!"];[_timeShow setColor:ccc3(255.0, 215.0, 0.0)];_delegate.gameState = EndGame;[self clearItem];}break;}}//set the go button according to the number of persons on the boatif (_boat.priestNumber + _boat.devilNumber > 0) [_transitItem setIsEnabled:YES];else                                            [_transitItem setIsEnabled:NO];
}

当游戏不是在“游戏中”状态时(InGame)。点击精灵应当不会响应,这个非常easy理解。最重要的是理解一下moveSprite究竟会面对哪些情况,以及在每种情况下做了什么事情:当玩家点击一个牧师/魔鬼的时候,这人有可能在船上。也有可能在岸上。于是我们分下面情况讨论:

1. 当人在岸上时。上船的时候要推断船上有没有人,来决定人在船上的位置。

(避免在船上出现人物重叠的情况)

2. 当人在船上时,查看船在哪个岸边,然后将人物放上去就可以。

接下来是船过河的函数,比較简单。仅仅需改变船的side属性,然后对船和船上的人都设置移动就可以。

-(void)transit
{if (_boat.priestNumber + _boat.devilNumber == 0)    return;[[SimpleAudioEngine sharedEngine]playEffect:WATER_EFF];_delegate.gameState = BlockGame;     // sprites can not be moved[_transitItem setIsEnabled:NO];[_helpItem setIsEnabled:NO];int moveDis = 0;if (_boat.boatSide == Right){moveDis = -160;_boat.boatSide = Left;}else if (_boat.boatSide == Left){moveDis = 160;_boat.boatSide = Right;}CCMoveBy *move = [CCMoveBy actionWithDuration:1.0 position:ccp(moveDis, 0)];id clear = [CCCallFunc actionWithTarget:self selector:@selector(clear)];[_boat runAction:[CCSequence actions:move,clear, nil]];//move the persons on the boatfor(int i = 0;i< _boat.priestNumber + _boat.devilNumber ;++i){CCMoveBy *myMove =[CCMoveBy actionWithDuration:1.0 position:ccp(moveDis, 0)];PersonSprite *sprite = [_boat.personList objectAtIndex:i];[sprite runAction:myMove];}
}

推断成功与失败的函数:

-(BOOL)judgeWin
{if (_leftBank.priestNumber == 3 && _leftBank.devilNumber == 3)return true;return false;
}-(BOOL)judgeLose
{int leftPriestNumber = _leftBank.priestNumber + abs(_boat.boatSide - Right) * _boat.priestNumber;int rightPriestNumber = _rightBank.priestNumber + abs(_boat.boatSide - Left) * _boat.priestNumber;int leftDevilNumber = _leftBank.devilNumber + abs(_boat.boatSide - Right) * _boat.devilNumber;int rightDevilNumber = _rightBank.devilNumber + abs(_boat.boatSide - Left) * _boat.devilNumber;if ( (leftDevilNumber > leftPriestNumber && leftPriestNumber > 0 ) ||(rightDevilNumber > rightPriestNumber && rightPriestNumber >0))return true;
}

用于游戏状态转换的函数(開始、暂停、结束、继续等)

-(void)beginGame
{//play background music[[SimpleAudioEngine sharedEngine] playBackgroundMusic:BG_MUSIC loop:YES];[[SimpleAudioEngine sharedEngine]playEffect:CLICK_EFF];_delegate.gameState = InGame;[self initTimer:timeLimit];[self schedule:@selector(updateTimeDisplay) interval:1];[_beginItem setIsEnabled:NO];[_pauseItem setIsEnabled:YES];[_endItem setIsEnabled:YES];[_helpItem setIsEnabled:YES];[_transitItem setVisible:YES];[_transitItem setIsEnabled:NO];[_timeShow setColor:ccc3(255.0f, 255.0f, 255.0f)];NSString *time = [NSString stringWithFormat:@"%.2d:%.2d", _time / 60, _time % 60];[_timeShow setString:time];[self removePreviousSprite];[self initSprites];
}-(void)pauseGame
{[[SimpleAudioEngine sharedEngine] pauseBackgroundMusic];[[SimpleAudioEngine sharedEngine]playEffect:CLICK_EFF];_delegate.gameState = PauseGame;[self unschedule:@selector(updateTimeDisplay)];[_resumeItem setIsEnabled:YES];[_pauseItem setIsEnabled:NO];[_helpItem setIsEnabled:NO];[_transitItem setVisible:NO];
}-(void)resumeGame
{[[SimpleAudioEngine sharedEngine] resumeBackgroundMusic];[[SimpleAudioEngine sharedEngine]playEffect:CLICK_EFF];_delegate.gameState = InGame;[_resumeItem setIsEnabled:NO];[_pauseItem setIsEnabled:YES];[_helpItem setIsEnabled:YES];[_transitItem setVisible:YES];[self schedule:@selector(updateTimeDisplay) interval:1];
}-(void)endGame
{[[SimpleAudioEngine sharedEngine]stopBackgroundMusic];[[SimpleAudioEngine sharedEngine]playEffect:CLICK_EFF];_delegate.gameState = EndGame;[self clearItem];[self setTime:0];NSString *time = [NSString stringWithFormat:@"%.2d:%.2d",_time / 60, _time % 60];[_timeShow setString:time];[self clearGame];
}

清空屏幕上的sprites。用于一场游戏结束后清空屏幕上元素,避免内存泄露。

-(void)clearItem
{[_resumeItem setIsEnabled:NO];[_endItem setIsEnabled:NO];[_pauseItem setIsEnabled:NO];[_beginItem setIsEnabled:YES];[_helpItem setIsEnabled:NO];[_transitItem setVisible:NO];[self unschedule:@selector(updateTimeDisplay)];
}-(void)clear
{_delegate.gameState = InGame;     // sprites can not be moved[_transitItem setIsEnabled:YES];[_helpItem setIsEnabled:YES];if([self judgeLose]){[[SimpleAudioEngine sharedEngine] stopBackgroundMusic];[[SimpleAudioEngine sharedEngine]playEffect:FAIL_EFF];_delegate.gameState = EndGame;[_timeShow setString:@"Lose!"];[_timeShow setColor:ccc3(255.0, 0.0, 0.0)];_delegate.gameState = EndGame;[self clearItem];}
}//remove the sprites of last scene
-(void)removePreviousSprite
{for(int i = 0;i<6;++i){PersonSprite *temp = (PersonSprite *)[self getChildByTag:i];if (temp != NULL) [self removeChildByTag:i];}if (_boat != NULL)      [self removeChild:_boat];if (_rightBank != NULL) [self removeChild:_rightBank];if (_leftBank != NULL)  [self removeChild:_leftBank];if (_water != NULL)     [self removeChild:_water];
}-(void)clearGame
{//change to a new scene[[CCDirector sharedDirector]replaceScene:[BaseLayer scene]];
}

其它辅助函数:

-(void)updateTimeDisplay
{_time--;NSString *time = [NSString stringWithFormat:@"%.2d:%.2d",_time / 60, _time % 60];[_timeShow setString:time];if (_time <= 0)        [self endGame];
}-(void)initTimer:(int)interval
{_time = interval;
}

最后是help函数。help功能主要做的是依据当前游戏中人物的位置,自己主动为玩家走下一步。算是一种比較简单的决策的体现吧。

原理非常easy。就是找出一条能通关的路径,然后把各种合理的游戏状态连接到路径上。即设置一个有限状态机,储存路径图,给定输入和当前状态后,系统便能算出下一个状态。

help函数:

-(void)help
{[[SimpleAudioEngine sharedEngine]playEffect:CLICK_EFF];int leftPriestNumber = _leftBank.priestNumber + abs(_boat.boatSide - Right) * _boat.priestNumber;int rightPriestNumber = _rightBank.priestNumber + abs(_boat.boatSide - Left) * _boat.priestNumber;int leftDevilNumber = _leftBank.devilNumber + abs(_boat.boatSide - Right) * _boat.devilNumber;int rightDevilNumber = _rightBank.devilNumber + abs(_boat.boatSide - Left) * _boat.devilNumber;int boatSide = _boat.boatSide - 100;int deltaPriest = 0, deltaDevil = 0;getHelp(leftPriestNumber,leftDevilNumber,rightPriestNumber,rightDevilNumber,boatSide,deltaPriest,deltaDevil);int tempNum = _boat.priestNumber + _boat.devilNumber;for(int i = 0;i< tempNum ; ++i)[self moveSprite:[_boat.personList objectAtIndex:0]];int i = 0;while (deltaPriest > 0) {PriestSprite *mySprite = (PriestSprite *)[self getChildByTag:i];if (mySprite.personSide == _boat.boatSide){[self moveSprite:mySprite];deltaPriest --;}i++;}i = 3;while (deltaDevil > 0) {DevilSprite *mySprite = (DevilSprite *)[self getChildByTag:i];if (mySprite.personSide == _boat.boatSide){[self moveSprite:mySprite];deltaDevil --;}i++;}[self transit];
}

这里调用的是一个AI.cpp文件。cpp文件里储存了路径。

AI.h:

#ifndef RiverCrossing_AI_h
#define RiverCrossing_AI_hstruct state{int boat_side;int left_pastor;int left_devil;int right_pastor;int right_devil;
};
//
//void initWays(int * ways);
//int  hash(state s);
//state deHash(int key);
//void change(state now,state next,
//            int & pastor,int & devil);
/*input:stateboat_side(0=left,1=right)return:void*/
void getHelp (int left_pastor,int left_devil, int right_pastor,int right_devil, int boat_side,int& pastor,int &devil);#endif

AI.cpp:

#include "AI.h"
#include<iostream>
#include<cmath>
using namespace std;void initWays(int * ways)
{ways[10033]=231;ways[231]=10132;ways[10132]=330;ways[330]=10231;ways[10231]=2211;ways[2211]=11122;ways[11122]=3102;ways[3102]=13003;ways[13003]=3201;ways[3201]=13102;ways[13102]=3300;ways[3300] = 3300;ways[1122]=10132;ways[132]=10033;
}int  hash(state s)
{int key;key=s.boat_side*10000+s.left_pastor*1000+s.left_devil*100+s.right_pastor*10+s.right_devil;return key;
}state deHash(int key)
{int boat_side=key/10000;int left_pastor=key%10000/1000;int left_devil=key%1000/100;int right_pastor=key%100/10;int right_devil=key%10;struct state s={boat_side,left_pastor,left_devil,right_pastor,right_devil};return s;
}void change(state now,state next,int & pastor,int & devil)
{pastor=abs(now.left_pastor-next.left_pastor);devil=abs(now.left_devil-next.left_devil);
}/*
input:stateboat_side(0=left,1=right)
return:void*/
void getHelp(int left_pastor,int left_devil,int right_pastor,int right_devil,int boat_side,int & pastor,int & devil)
{int ways[13334];initWays(ways);struct state now={boat_side,left_pastor,left_devil,right_pastor,right_devil};int now_state_key=hash(now);int next_state_key=ways[now_state_key];struct state next=deHash(next_state_key);change(now,next,pastor,devil);
}

特别注意一下。在.m文件里要想编译cpp文件,须要把.m的后缀改为.mm才行。

用cocos2d 2.1制作一个过河小游戏(4): 游戏主逻辑BaseLayer设计相关推荐

  1. 用cocos2d 2.1制作一个过河小游戏(1): 总概

    今天老师布置了任务,要大家分小组设计"牧师与恶魔过河"的游戏并使用cocos2d框架实现.虽然之前自己一直有跟随兴趣学习iOS开发,但是先前所有的开发都只是基于简单应用的,很少涉及 ...

  2. python连连看小游戏_利用Python制作一个连连看小游戏,边学边玩!

    导语 今天我们将制作一个连连看小游戏,让我们愉快地开始吧~ 开发工具 Python版本:3.6.4 相关模块: pygame模块: 以及一些Python自带的模块 环境搭建 安装Python并添加到环 ...

  3. 如何制作一个横版格斗过关游戏 2 Cocos2d x 2 0 4

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 在第一篇 ...

  4. 如何制作一个微信小程序【微信小程序是怎么做的】

    为什么现在这么多人使用微信小程序呢?因为微信小程序除了便捷易开发,公司企业可以用来做小程序展示官网,商家也可以做小程序商城,甚至个人也可以拥有自己的小程序.那么如何制作一个微信小程序?微信小程序是怎么 ...

  5. 不用写一行代码,就能用ivx制作一个“微信小程序“,超牛逼

    今天需要为大家介绍一款神器ivx. 它是通用无代码开发平台,是面向新一代全栈开发人员的通过不编写代码的方式实现快速开发的软件开发平台,提供图形化逻辑编排编程语言.抽象组件.集成开发环境等能力,能够支持 ...

  6. 小福利,用Excel VBA编程制作一个变色小游戏

    小福利,用Excel VBA编程制作一个变色小游戏 设计思想:在正方形的四条边上都是设置循环函数,不断改变颜色和单元格里面的数值. Option ExplicitSub 按钮1_Click() Dim ...

  7. PyQt5制作一个爬虫小工具,爬取雪球网上市公司的财务数据

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. 以下文章来源于可以叫我才哥 ,作者:可以叫我才哥 最近有朋友需要帮忙写个爬虫脚本,爬取雪球网一些上 ...

  8. android打地鼠设计报告,android开发中利用handler制作一个打地鼠小游戏

    android开发中利用handler制作一个打地鼠小游戏 发布时间:2020-11-25 15:21:11 来源:亿速云 阅读:136 作者:Leah 这期内容当中小编将会给大家带来有关androi ...

  9. PyQt5制作一个爬虫小工具,获取某网上市公司的财务数据可视化

    最近有朋友需要帮忙写个爬虫脚本,爬取雪球网一些上市公司的财务数据.盆友希望可以根据他自己的选择进行自由的抓取,所以简单给一份脚本交给盆友,盆友还需要自己搭建python环境,更需要去熟悉一些参数修改的 ...

最新文章

  1. 利用Swarmkit构建Windows/Linux混合Docker集群
  2. 模拟浏览器自动化测试工具Selenium之六设置代理篇
  3. Perl迎来25岁生日
  4. 【微信插件】P3微信插件测试使用步骤
  5. linux 安装jdk tomcat mysql
  6. css实现三栏布局的几种方法及优缺点
  7. 永久居家办公,你愿意吗?
  8. 先装vs还是先装sql_止回阀该装在出口阀前还是阀后?
  9. iso 9000下载_ISO 9000 | 软件工程
  10. SRCNN中的PSNR计算问题
  11. 手机wifi的mac地址是什么??
  12. Android中怎么破解游戏之修改金币数
  13. 最优化-(黄金分割法)0.618法
  14. 计算机视觉:图片的马赛克、毛玻璃效果和图片的融合
  15. 采集网易云上面的MV保存方法
  16. Flink实操 : 广播变量/累加器/分布式缓存
  17. 结合MongoDB开发LBS应用(mongodb geo)
  18. 程序员10大境界【走在路上,潜心修行】
  19. 2022年春招最新消息:IT互联网行业平均薪资18500元
  20. android 使用kotlin 获取设备id

热门文章

  1. 猿人学题库第一题——无混淆js加密
  2. 恒源云(GPUSHARE)_CV论文笔记之CE-FPN(通道增强特征金字塔网络)
  3. 场效应管理解笔记(N沟道结型场效应管)
  4. 为什么我会选择 AI-TestOps 让测试更智能
  5. 【我的保研经验】从中科院--计算所--到--自动化所--再到--空天院(电子所)二部--保研一路走来的欢乐与辛酸~《公开版》
  6. FFmpeg进阶: 音频滤镜大全
  7. mysql thd_MySQL 5.7: 数据库THD连接管理重构
  8. excel合并工具如何实现分类合并
  9. 大数据之Spark案例实操完整使用(第六章)
  10. Tabulator 交互式数据表格 javascript 库示例