Unity StrangeIoC框架_strige ioc-程序员宅基地

技术标签: strangeIoc  Unity  

Unity StrangeIoC(一)



正式之前先说说基础的概念:
首先是MVC框架,MVC框架的思路是将业务逻辑、数据、界面显示分离,网上很多关于MVC的资料,这里不再过多的描述了。
下面截图来自wikipedia的mvc框架:
然后是控制反转(包括依赖注入和依赖查找),控制反转也是著名框架spring框架的核心。
对于控制反转(Inversion of Control,缩写IOC)的依赖注入,先用一个C#示例代码演示一下。比如设计一个玩家攻击敌人的游戏,玩家可以装备手枪,步枪。最简单的代码设计实现如下:

public   class   Player
{
     public   string   gunName =  "ShouQiang" ;
     public   void   Attack(Enemy enemy)
     {
         if (gunName ==  "ShouQiang" )
             enemy.hp -= 10;
         else   if (gunName =  '' BuQiang")
         ememy.hp -= 20;
     }
}

如上述代码,假如项目中多了一个(机枪),需要重写player类,重写攻击逻辑(if..else)设计不合理。重新设计,代码可以用下面的方实现:

public   interface   IGun {
     voidAttack(Enemy eneny);
}
public   class   ShouQiang : IGun
{
     public   void   Attack(Enemy eneny)
     {
         enemy.hp -=10;
     }
}
public   class   BuQiang : IGun
{
     public   void   Attack(Enemy enemy)
     {
         enemy.hp -= 20;
     }
}
public   class   Player
{
     public   IGun gun = newShouQiang(); 
     public   void   Attack(Enemy enemy)
     {
         gun. Attack(enemy);
     }
}
public   class   Eneny
{
     public   int   hp;
}

如果再增加机枪,直接增加一个机枪类继承IGun接口就可以了 playe类中
public IGun gun = new ShouQiang();简单实现了一个注入.

下面正式介绍strangeioc.
正如strangeioc描述的一样,总体上说它是根据控制反转和解耦和原理设计的,支持依赖注入. 继续引入一个示例,如果写一个单玩家游戏,死亡后将最高分数提交到facebook ,代码如下:

public   class   MyShip: MonoBehaviour {
     private   FacebookService facebook;
     private   int   myScore,
     void   Awake()
     {
         facebook = FacebookService.getlnstance(),
     }
     void   onDie()
     {
         if   (score > highScore) 
             facebook.PostScore(myScore),
     }
}

这样做有两个问题:
1.ship作为控制角色,但是除了要通知facebook上传分数还要处理代码逻辑.将自身与游戏逻辑与 facebook逻辑关联(髙耦合)
2.FacebookService是单键,如果我们改为要提交到Twitter..or Google+... 怎么办?或者FacebookService里面的方法有变更怎么办?
如果代码如上,需要重构很多代码才能完成相应的功能,但是通过引入ioc,重构将会方便很多。

public   class   MyShip : MonoBehavior
{
     void   OnDie()
     {
         dispatcher.Dispatch(GameEvent.SHIP_DEAD);
     }
}

视图模块出发了死亡逻辑,它(View)需要知道的仅仅是这些就够了,然后将死亡消息发送出去。
某个模块的代码用来接收死亡消息,然后做出处理,如下:

public   class   OnShipDeathCommand: EventCommand
{
     [Inject]
     ISocialService socialService { get set ,}

     [Inject]
     IScoreModel scoreModel { get   set ,}

     public   override   void   Execute()
     {
         if   (scoreModel.score > scoreModel.highScore) 
             socialService.PostScore(scoreModel.score);
     }
}

[Inject]标签实现接口,而不是实例化类 

#if UNITY_ANDROID
injectionBinder.Bind<ISocialService>().To<GoogleService>().AsSingleton();
#else
injectionBinder.Bind<ISocialService>().To<FacebookService>().AsSingleton(); 
#endif
//...or...
//injectionBinder.Bind<ISocialService>().To<MultiServiceResolver>().AsSingleton();
 
injectionBinder.Bind<IScoreModel>() To<ScoreMcxiel>() AsSIngleton();
commandBinder.Bind(GameEvent.SHIP_DEAD , OnShipDeathCommand);

用IOC(控制反转)我们不用关注具体逻辑,也不同自己再创建单键。
ship触发Command来执行逻辑,每个模块之间都是独立的。
1> commandBinder.Bind(GameEvent.SHIP_DEAD , OnShipDeathCommand);
将事件和对应逻辑绑定在了一起。

2> dispatcher.Dispatch(GameEvent.SHIP_DEAD)
就是发出事件,但是具体做什么事情不需要了解。




Unity StrangeIoC(二)



strangeioc第一大部分:1.Binding(绑定)

strange的核心是绑定,我们可以将一个或者多个对象与另外一个或者多个对象绑定(连接)在一起。将接口与类绑定来实现接口,将事件与事件接受绑定在一起。或者绑定两个类,一个类被创建的时候另一个自动创建。如果你再Unity里面用过SendMessage方法,或者一个类引用另一个类,再或者式if...else语句,从某种形式上来说也是一种绑定。

但是直接绑定是有问题的,导致代码不易修改(不再是高聚合低耦合).比如一个spaceship类,里面包含gun发射和键盘控制功能,当需求变更为使用鼠标控制时,你就需要重新修改spaceship方法,但是仅仅是控制功能的需求改变了,为什么要重写spaceship方法呢?
如果你自定义一个鼠标控制类(mousecontrol)。然后spaceship里面调用鼠标控制类,你还是采用的直接绑定的方法。当需求变为键盘控制的时候,你又要去重新修改spaceship去调用键盘控制的class。

strange可以实现间接绑定从而使你的代码减轻对其他模块的依赖(低耦合)。这是面向对象编程(Object-Oriented Programming)的根基和宗旨。通过strangeioc绑定你的代码会变得更加灵活。

The structure of a binding

strange的binding由两个必要部分和一个可选部分组成,必要部分是a key and a value, key触发value,因此一个事件可以触发回调,一个类的实例化可以触发另一个类的实例化。可选部分是name,它可以区分使用相同key的两个binding。下面的三种绑定方法其实都是一样的,语法不同而已:

1.Bind<IDrive>().To<WarpDrive>();

2.Bind(typeof(IDrive)).To(typeof(WarpDrive));

3.IBinding binding = Bind<IDrive>();
bingding.To<WarpDrive>();


bind是key,to是value。
当使用非必要部分Name时,如下:

Bind<IComputer>().To<SuperComputer>().ToName("DeepThought");


MVCSContext式推荐的版本,它包含下面介绍的所有拓展,是使用strange最简单的途径


strangeioc第二大部分:2.Extensions

看strange的介绍,它是一个依赖注入框架,虽然它具有依赖注入的功能,但是核心思想还是绑定。

接下来讲介个关于binder(绑定)的扩展。


The injection extension(注入)

在binder扩展中最接近Inversion-of-Control(IoC)控制反转思想的是注入。
大家应该很熟悉接口的使用方法,接口本身没有是实现方法,只是定义类中的规则:

interface   ISpaceship
{
     void   input( float   angle, float   velocity);
     IWeapon weapon{  get set ; }
}

使用另一个类来实现这个接口:

class   Spaceship : ISpaceship
{
     public   void   input( float   angle, float   velocity)
     {
         //do stuff here
     }
     IWeapon weapon{  get set ; }
}


如果采用上面的写法,Spaceship类里面不用再写检测输入(input)的功能了,只需要处理输入就可以了,不再需要武器逻辑,仅仅式注入武器实例就可以了。到现在已经迈出一大步了。但是出现了一个问题,谁告诉spaceship,我们使用何种武器?我们可以采用工厂模式给weapon赋值具体的武器实例,简单的工厂模式如下:

public   interface   IWeapon
{    
     void   Attack();
}
public   class   BuQiang : IWeapon
{
     public   void   Attack(){ //敌人掉血逻辑
 
     }
}
public   class   ShouQiang : IWeapon
{
     public   void   Attack() { //敌人掉血逻辑
 
     }
}

上面创建好了武器的约定接口和两种武器,下面创建武器工厂:

public   class   MeaponFactory 
{
     public   IWeapon GetWeapon( string   name)
     {
         if (name ==  "BuQiang"
             return   new   BuQiang(); 
         else   if   (name ==  "ShouQiang"
             return   new   ShouQiang(); 
         return   null ;
     }
}

取武器直接使用

IWeapon weapon =  new   WeaponFactory().GetWeapon( "BuQiang" );

(ps. 也有人说,取武器直接IWeapon weapon = new BuQiang();使用工厂反而麻烦,但是如果我们可以从美国军械库去到步枪,手枪。中国军械库也可以去到步枪,手枪。使用工厂模式就方便了许多:

IWeapon weapon =  new   AmericaWeaponFactory().GetWeapon( "BuQiang" );
IWeapon weapon =  new   ChinaWeaponFactory().GetWeapon( "BuQiang" );

但是这样做并没有解决根本问题,factorymanager需要包括/返回各种武器的实例。现在我们引入一个全新的模式:Dependency Injection(DI)依赖注入:

DI模式中一个类对另一个类的引用,通过发射的方式实现(比如我们的ISpaceship中的weapon不再直接复制类的实例/或者通过工厂赋值类的实例(这样它们之间仍旧存在引用关系))而是通过反射(Reflection)的方式实现。

首先我将IWeapon和具体的手枪实例绑定:

injectionBinder.Bind<IWeapon>().To<ShouQiang>();

然后ISpaceship中weapon赋值如下:

[Inject]
public IWeapon weapon { get; set; }


当然如果有多个实现方式可以使用如下方式:

injectionBinder.Bind<IWeapon>().To<ShouQiang>().ToName( "ShouQiang" );
injectionBinder.Bind<IWeapon>().To<BuQiang>().ToName( "BuQiang" );

然后ISpaceship中weapon赋值如下:

[Inject( "BuQiang" )]
public   IWeapon weapon {  get set ; }
 
或者:

[Inject( "ShouQiang" )]
public   IWeapon weapon {  get set ; }




Unity StrangeIoC(三)


第二个扩展部分:

The reflector extension(反射)

List<Type> list =  new   List<Type>();
 
list.Add(tpyeof(Borg));
list.Add( typeof (DeathStar));
list.Add( typeof (Galactus));
list.Add( typeof (Berserker));
 
//count should equal 4, verifying that all four classes were reflected
int   count = injectionBinder.Reflect(list);

看官网介绍,可以批量反射,全部反射等待.. injectionBinder.ReflectAll();

下面接着说扩展部分中的第三个扩展(调度器)

The dispatcher extension

从原理上来说dispatcher相当于观察者模式中的公告板,允许客户监听他,并且告知当前发生的事件。但在strangeioc中,通过EventDispatcher方式实现,EventDispatcher绑定触发器来触发带参数/不带参数的方法。
触发器通常是string或者是枚举类型(触发器你可以理解为key,或者事件的名称,名称对应着触发的方法).
如果事件有返回值,他将存在IEvent,编辑逻辑实现这个接口就能得到返回值,标注的strangeioc事件叫做TmEvent.如果你在用MVCSContext,有个全局的EventDispatcher叫:contextDispatcher会自动注入,你可以用它来传递事件。

There's also acrossContextDispatcher for communicating between Contexts。
同样有一个accossContextDispatcher可以在contexts传递事件。
使用EventDispatcher需要做两个事情就可以,调度/设置事件和监听事件。

dispatcher.AddListener("FIRE_MISSILE",onMissleFire);

然后事件就会处于监听状态,直到FIRE_MISSLE事件被触发,然后执行相应的onMissleFire方法。

当然Key也可以不适用字符串而是枚举类型。

相关的几个Api:

dispatcher.AddListener("FIRE_MISSILE",onMissleFire);
dispatcher.RemoveListener("FIRE_MISSILE",onMissleFire);
dispatcher.UpdateListener("FIRE_MISSILE",onMissleFire);

派发消息:

dispatcher.Dispatch("FIRE_MISSLE")。




Unity StrangeIoC(四)




继续扩展部分的第四个扩展(命令)

The command extension

除了将事件绑定到方法以外,还可以将他们与命令绑定。命令式mvc框架的指挥者。
在strangeioc的MVCSContext中,CommandBinder监听所有来自dispatcher分发的事件.
Signals(上文提到的消息(signal)与事件(event))也可以绑定到command.

using   strange.extensions.command.impl; 
using   com.example.spacebattle.utils; 
namespace   com.example.spacebattle.controller
{
     class   StartGameCommand : EventCommand
     {
         [Inject]
         public   ITimer ganeTimer {  get set ; }
         overridepublic  void   Execute()
         {
             gameTimer.start();
             dispatcher.dispatch(GameEvent.STARTED);
         }
     }
}

如果是有网络请求,有返回,可以采用这样的方法实现:

using   strange.extensions.command.impl; 
using   com.example.spacebattle.service;
namespace   com.example.spacebattle.controller
{
     class   PostScoreCommand : EventCommand
     {
         [Inject]
         IServer gameServe {  get set   ;} 
         override   public   void   Execute()
         {
             Retain();
             int   score = ( int )evt.data;
             gameServer.dispatcher.AddListener(
                         ServerEvent.SUCCESS, onSuccess);               
             gameServer.dispatcher.AddListener(
                         ServerEvent.FAILURE, onFailure);    
             gaweServer.send(score);
         }
         private   void   onSuccess()
         {
             gameServer.dispatcher.RemoveListener(
                         ServerEvent.SUCCESS, onSuccess);     
             gameServer.dispatcher.RemoveListener(
                         ServerEvent.FAILURE, onFailure); 
             //…do something to report success…
             Release();
         }
         private   void   onFailure( object   payload)
         {
             gameServer.dispatcher.RemoveListener(
                         ServerEvent.SUCCESS, onSuccess);     
             gameServer.dispatcher.RemoveListener(
                         ServerEvent.FAIlURE, onFailure);
             //...do sowething to report failure...
             Release();
         }
     }
}


将命令和该类绑定起来

commandBinder.Bind(ServerEvent.POST_SCORE).To<PostScoreCommand>();

命令绑定多个事件:

commandBinder.Bind(GameEvent.HIT).To<DestroyEnemyCommand>()
.To<UpdateScoreCommand>();
解除绑定:

commandBinder.Unbind(GameEvent.POST_SCORE);

按顺序触发命令绑定事件:

commandBinder.Bind(GameEvent.HIT).InSequence()
.To<CheckLevelClearedCommand>()
.To<EndLevelCommand>()
.To<GameOverCommand>();






Unity StrangeIoC(五)



扩展部分的第五个扩展

The signal extension(消息)

消息是一种代替EventDispatcher的分发机制,与EventDispatcher相比,消息1.分发结果不再创建实例,因此也不需要回收更多的垃圾。2.更安全,当消息与回调不匹配时,就会断开执行。官网也推荐使用signal来兼容后续版本。

Signal< int > signalDispatchesInt =  new   Signal< int >(); 
Signal< string > signalDispatchesString =  new   Signal< string >();

//Add a callback with an int parameter
signalDispatchesInt AddListener(callbacklnt);
//Add a callback with a string parameter    
signalDispatchesString AddListener(callbackString); 
 
signalDispatchesInt.Oispatch(42);  //dispatch an int 
signalDispatchesString.Oispatch( "Ender Wiggin" );  //dispatch a string

void   callbacklnt( int   value)
{
//Do something with this int
}

void   callbackString( string   value)
{
//Do something with this string
}

消息最多可以使用四个参数:

//works
Signal signal0 =  new   Signal();
 
//works
Signal<SomeValueObject> signal1 =   new   Signal<SomeValueObject>();
 
//works
Signal< int , string > signal2 =   new   Signal< int , string >();
 
//works
Signal< int , int > signal3 =   new   Signal< int , int >();
 
//works
Signal<SomeValueObject, int , string ,MonoBehavior> signal4 =   new  
Signal<SomeValueObject, int , string ,MonoBehavior>();
 
//FAILS!!!!  Too many params.
Signal< int , string ,Vector2,Rect> signal5 =   new  
Signal< int , string ,Vector2,Rect>();

消息绑定:
commandBinder.Bind<SomeSignal>().To<SomeCommand>();

看下一个示例:
commandBinder.Bind<ShipDestroyedSignal>().To<ShipDestroyedCommand>();

然后:

[Inject]
public   ShipDestroyedSignal shipDestroyedSignal{  get set ; }
 
// imagining that the Mediator holds avalue for this ship
private   int   basePointValue;
 
//Something happened that resulted in destruction
private   void   OnShipDestroyed()
{
     shipDestroyedSignal.Dispatch(view,basePointValue);
}

再然后:

using   System;
using   strange.extensions.command.impl;
using   UnityEngine;
 
namespace   mynamespace
{
     //Note how we extend Command,not EventCommand
     public   class   ShipDestroyedCommand: Command
     {
         [inject]
         public   MonoBehavior view{  get set ; }
 
         [inject]
         public   int   basePointValue{  get set ; }
 
         public   override   void   Execute()
         {
             //Do unspeakable things to the destroyed ship
         }
     }
}

再给出一个strangeios的demo里面的代码:


using   System;
using   UnityEngine;
using   strange.extensions.context.api;
using   strange.extensions.context.impl;
using   strange.extensions.dispatcher.eventdispatcher.api;
using   strange.extensions.dispatcher.eventdispatcher.impl;
using   strange.extensions.command.api;
using   strange.extensions.command.impl;
 
namespace   strange.examples.signals
{
   public   class   SignalsContext : MVCSContext
   {
       public   SignalsContext (MonoBehaviour view) :  base (view)
       {
       }
       public   SignalsContext (MonoBehaviour view, 
ContextStartupFlags flags)
  :  base (view, flags)
       {
       }
    
       // Unbind the default EventCommandBinder and rebind the SignalCommandBinder
       protected   override   void   addCoreComponents()
       {
          base .addCoreComponents();
         injectionBinder.Unbind<ICommandBinder>();
         injectionBinder.Bind<ICommandBinder>()
.To<SignalCommandBinder>().ToSingleton();
       }
          
       // Override Start so that we can fire the StartSignal 
       override   public   IContext Start()
       {
          base .Start();
          StartSignal startSignal= (StartSignal)injectionBinder
.GetInstance<StartSignal>()
          startSignal.Dispatch();
          return   this ;
      }
          
       protected   override   void   mapBindings()
       {
          injectionBinder.Bind<IExampleModel>()
.To<ExampleModel>().ToSingleton();
          injectionBinder.Bind<IExampleService>()
.To<ExampleService>().ToSingleton();
          mediationBinder.Bind<ExampleView>().To<ExampleMediator>();
            
          commandBinder.Bind<CallWebServiceSignal>()
.To<CallWebServiceCommand>();
              
          //StartSignal is now fired instead of the START event.
          //Note how we've bound it "Once". This means that the mapping goes away as soon as the command fires.
          commandBinder.Bind<StartSignal>().To<StartCommand>().Once();
              
          //In MyFirstProject, there's are SCORE_CHANGE and FULFILL_SERVICE_REQUEST Events.
          //Here we change that to a Signal. The Signal isn't bound to any Command,
          //so we map it as an injection so a Command can fire it, and a Mediator can receive it
          injectionBinder.Bind<ScoreChangedSignal>().ToSingleton();
          injectionBinder.Bind<FulfillWebServiceRequestSignal>()
.ToSingleton();
         }
     }
}

signal 既可以通过command添加绑定监听也可以通过AddLister




Unity StrangeIoC(六)


继续扩展部分的下一个扩展

The mediation extension(调节器(中介模式))

mediationContext是唯一一个专为Unity设计的部分,因为mediation关系的式对view(GameObject)的操作,由于view部分天生的不确定性,我们推荐view由两种不同的monobehavior组成:View and Mediator.

view就是mvc中的v,一个view就是一个你可以编写逻辑,控制可见部分的monobehavior.
这个类可以附加(拖拽)到Unity编辑器来关联GameObject.但是不建议吧mvc的models和controller写在view中。

Mediator类的职责是知晓view和整个应用的运行。它也会获取整个app中分发和接受的时间和消息,但是因为mediator的设计,建议使用命令模式(command)来做这部分的功能。

mediator示例:

using   strange.extensions.mediation.ipml; 
using   com.example.spacebattle.events; 
using   com.example.spacebattle.model; 
namespace   com.example.spacebattle.view 
{
     class   DashboardMediator : EventMediator
     {
         [Inject]
         public   DashboardView view {  get set ; } 
         override   public   void   OnRegister()
         {
             view.init();
             dispatcher.Addlistener
                     (ServiceEvent.FULFILL_ONLINE_PLAYERS, onPlayers); 
             dispatchers Dispatch
                     (ServiceEvent.REQUEST_ONLINE_PLAYERS);
         }
         override   public   void   OnRemove()
         {
             dispatcher.RemoveListener
                     (ServiceEvent.FULFILl_ONLINE_PLAYERS, onPlayers);
         }
         private   void   onPlayers(IEvent evt)
         {
             IPlayers[] playerList = evt.data  as   IPlayers[];
             view.updatePlayeCount(playerlist. Length);
         }
     }
}

示例说明:

1.当完成注入之后,DashboardView变为当前的场景所挂载的view.
2.当完成注入之后(可以理解为结构体的方式) OnRegister()方法会立即执行。可以用这个方法来做初始化。
3.contextDispatcher可以扩展任何的EventMediator。
4.OnRemove()清理使用,当一个view在被销毁前调用,并且要移除你所添加的所有监听器。
5.示例中的view暴力ultimate两个接口,但是在程序设计的时候你可能会更多,但是有一条理念:中介者不处理GameObject相关属性更新。
可以这样来绑定:

mediationBinder.Binder<DashboardView>().To<DashboardMediator>();

注意:
1.并不是所有MonoBehavior都需要限定成view.
2.中介者绑定是实例对实例的,也就是说一个view一定是对应一个mediator,如果有多个view那么一定有多个mediator。


继续另外一个扩展:

The context extension

MVCSContext包括
EventDispatcher(事件分发),
InjectionBinder(注入绑定),
MediationBinder(中介绑定),
CommandBinder(命令绑定)。


可以重新将CommandBinder 绑定到SinalCommandBinder。 命令和中介依托注入,context以为命令和中介的绑定提供关联。

建立一个项目需要从重新定义MVCSContext或者Context,一个app也可以包含多个Contexts,这样可以使你的app更高的模块化,因此,一个app可以独立的设计为聊天模块,社交模块,最终他们会整合到一起成为一个完整的app。





Unity StrangeIoC(七)



strangeioc第三大部分:3.MVCSContext

这一部分讲的是如何使用MVCSContext创建一个app.
MVCSContext式通过使用strangeioc的方式,将所有的小的模块/架构,整合到一个易用的包中。它是以mvcs(s meaning service)的架构来设计的。

1.app的入口是一个monobehavior来扩展的mvcscontext。
2.用mvcs的子类来执行各种绑定。
3.dispatcher(分发器)可以让你在整个app中发送时间,在mvcscontext中它们发送的是TmEvents,你可以重写context来使用signal(消息)的方式发送。
4.commands(命令)会被IEvents或者Signal触发,触发之后会执行一段逻辑。
5.model存储状态。
6.services与app之外的部分通信(比如接入facebook)。





版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/y1196645376/article/details/52746251

智能推荐

hdu 1229 还是A+B(水)-程序员宅基地

文章浏览阅读122次。还是A+BTime Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 24568Accepted Submission(s): 11729Problem Description读入两个小于10000的正整数A和B,计算A+B。...

http客户端Feign——日志配置_feign 日志设置-程序员宅基地

文章浏览阅读419次。HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息。FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。BASIC:仅记录请求的方法,URL以及响应状态码和执行时间。NONE:不记录任何日志信息,这是默认值。配置Feign日志有两种方式;方式二:java代码实现。注解中声明则代表某服务。方式一:配置文件方式。_feign 日志设置

[转载]将容器管理的持久性 Bean 用于面向服务的体系结构-程序员宅基地

文章浏览阅读155次。将容器管理的持久性 Bean 用于面向服务的体系结构本文将介绍如何使用 IBM WebSphere Process Server 对容器管理的持久性 (CMP) Bean的连接和持久性逻辑加以控制,使其可以存储在非关系数据库..._javax.ejb.objectnotfoundexception: no such entity!

基础java练习题(递归)_java 递归例题-程序员宅基地

文章浏览阅读1.5k次。基础java练习题一、递归实现跳台阶从第一级跳到第n级,有多少种跳法一次可跳一级,也可跳两级。还能跳三级import java.math.BigDecimal;import java.util.Scanner;public class Main{ public static void main(String[]args){ Scanner reader=new Scanner(System.in); while(reader.hasNext()){ _java 递归例题

面向对象程序设计(荣誉)实验一 String_对存储在string数组内的所有以字符‘a’开始并以字符‘e’结尾的单词做加密处理。-程序员宅基地

文章浏览阅读1.5k次,点赞6次,收藏6次。目录1.串应用- 计算一个串的最长的真前后缀题目描述输入输出样例输入样例输出题解2.字符串替换(string)题目描述输入输出样例输入样例输出题解3.可重叠子串 (Ver. I)题目描述输入输出样例输入样例输出题解4.字符串操作(string)题目描述输入输出样例输入样例输出题解1.串应用- 计算一个串的最长的真前后缀题目描述给定一个串,如ABCDAB,则ABCDAB的真前缀有:{ A, AB,ABC, ABCD, ABCDA }ABCDAB的真后缀有:{ B, AB,DAB, CDAB, BCDAB_对存储在string数组内的所有以字符‘a’开始并以字符‘e’结尾的单词做加密处理。

算法设计与问题求解/西安交通大学本科课程MOOC/C_算法设计与问题求解西安交通大学-程序员宅基地

文章浏览阅读68次。西安交通大学/算法设计与问题求解/树与二叉树/MOOC_算法设计与问题求解西安交通大学

随便推点

[Vue warn]: Computed property “totalPrice“ was assigned to but it has no setter._computed property "totalprice" was assigned to but-程序员宅基地

文章浏览阅读1.6k次。问题:在Vue项目中出现如下错误提示:[Vue warn]: Computed property "totalPrice" was assigned to but it has no setter. (found in <Anonymous>)代码:<input v-model="totalPrice"/>原因:v-model命令,因Vue 的双向数据绑定原理 , 会自动操作 totalPrice, 对其进行set 操作而 totalPrice 作为计..._computed property "totalprice" was assigned to but it has no setter.

basic1003-我要通过!13行搞定:也许是全网最奇葩解法_basic 1003 case 1-程序员宅基地

文章浏览阅读60次。十分暴力而简洁的解决方式:读取P和T的位置并自动生成唯一正确答案,将题给测点与之对比,不一样就给我爬!_basic 1003 case 1

服务器浏览war文件,详解将Web项目War包部署到Tomcat服务器基本步骤-程序员宅基地

文章浏览阅读422次。原标题:详解将Web项目War包部署到Tomcat服务器基本步骤详解将Web项目War包部署到Tomcat服务器基本步骤1 War包War包一般是在进行Web开发时,通常是一个网站Project下的所有源码的集合,里面包含前台HTML/CSS/JS的代码,也包含Java的代码。当开发人员在自己的开发机器上调试所有代码并通过后,为了交给测试人员测试和未来进行产品发布,都需要将开发人员的源码打包成Wa..._/opt/bosssoft/war/medical-web.war/web-inf/web.xml of module medical-web.war.

python组成三位无重复数字_python组合无重复三位数的实例-程序员宅基地

文章浏览阅读3k次,点赞3次,收藏13次。# -*- coding: utf-8 -*-# 简述:这里有四个数字,分别是:1、2、3、4#提问:能组成多少个互不相同且无重复数字的三位数?各是多少?def f(n):list=[]count=0for i in range(1,n+1):for j in range(1, n+1):for k in range(1, n+1):if i!=j and j!=k and i!=k:list.a..._python求从0到9任意组合成三位数数字不能重复并输出

ElementUl中的el-table怎样吧0和1改变为男和女_elementui table 性别-程序员宅基地

文章浏览阅读1k次,点赞3次,收藏2次。<el-table-column prop="studentSex" label="性别" :formatter="sex"></el-table-column>然后就在vue的methods中写方法就OK了methods: { sex(row,index){ if(row.studentSex == 1){ return '男'; }else{ return '女'; }..._elementui table 性别

java文件操作之移动文件到指定的目录_java中怎么将pro.txt移动到design_mode_code根目录下-程序员宅基地

文章浏览阅读1.1k次。java文件操作之移动文件到指定的目录_java中怎么将pro.txt移动到design_mode_code根目录下

推荐文章

热门文章

相关标签