Scratz さんのプロフィールScratz 的小果园フォトブログリストその他 ツール ヘルプ
2008/07/22

《三国志 X》快速修炼手册

能力系列
统率、武力、智力、政治、魅力
  到巴蜀地方任一城市接受“灵山巡礼”的任务,完成后各项能力会加 1,等 180 天期满后再回酒家,任务失败,所以又可以再次接受这个任务,如此循环。缺点是这 180 天内无法接受其它酒家任务。

内政系列
农业、商业、技术
  多做相关内政即可。不一定要太守命令,花自己的钱去做也值得,还能提高名声。
修筑
  在天水接受“修复长城”的任务,地点固定,方便快捷。
治安
  驱逐恶棍,天天向上。
征兵、训练
  多打几仗经验值自然就够了。

战斗系列
突击、火矢、齐攻、镇静、鼓舞、奇袭、隐密
  依然是多打仗就行了。最好是能当上太守(君主就不说了),不然电脑每次都给你一队“软绵绵”的弓兵,绝对把你郁闷死。

计略系列
内讧、止行、引诱、混乱、天文、石阵
  战场上疯狂鼓舞,计略经验会飞速增长。“天文”和“石阵”所需的内政经验请参考上面的“内政系列”。
地理
  所需的“谍报”经验除了调查都市情报,利用“见闻”发现在野武将能更快提升。

单挑系列
恢复、集气、气焰、反击、反斩、三段、螺旋
  不断进出敌方的某个都市,潜入方法选“强行”,无限虐侍卫……

舌战系列
威压、抗辩、反论、曲义、道破、挑衅、怒骂
  不断进出敌方的某个都市,潜入方法选“笼络”(需要“名士”称号),继续虐侍卫……

称号系列
军师
  继续在战场上疯狂鼓舞……
名士
  名声的增长速度其实很快……
提督
  如果嫌水战机会少,就多造船吧。
间谍
  参考“计略系列”中的“地理”。
酒豪
  在会稽接受“采买高级酒”的任务,地点基本固定,方便快捷。
医师
  参考“内政系列”。
仙人
  习得“天文”后在战场上多来几次“变天”或“风变”。

成都公交卡作弊用法二则

  自从成都公交开始实行两小时内无限免费换乘以来,我们这些刷卡一族确实得到了极大的实惠。不过经过我最近的一些小小“实践”,找到了两条作弊用法。
  第一条和空调车有关。刷卡乘车,普通车扣一次,而空调车要扣两次,但是如果先上普通车再转乘空调车的话,不会再扣。于是如果在首次乘车时,可以先上普通车随便坐一两站,甚至刷卡不上车,再换乘空调车,就能省一次了。当然可能会耽搁一点时间。此法也可用于对付晚上十点后多扣一次,只要在十点前在任意普通车上刷掉一次就行了。
  如果说第一条有点谋私利的话,第二条就算得上“大公无私”了。你就在一个车站“蹲点”,每来一辆车就随便帮一个人刷卡,然后继续。两小时内只扣一次,却能帮很多人免费上车,因为系统只会认为你在不断转车。下班的时候不妨帮帮同事,赢得好名声呵呵。当然此法也有局限性,就是每辆车只能送走一个人。
2008/07/03

How to write a plug-in with Java?

    As you have guessed, plug-ins in Java are nothing more than some jar files and configurations (usually XML files). The main application reads the configurations and use reflection to load classes from plugins at runtime. In this article, we're going to write a simple movie manager to show how plug-ins work in Java.
    The movie manager manages wants to manage as many movies as it can, so we can't hard code movies into the manager itself. In this case, movies are very suitable be implemented as plug-ins. The manager reads some configurations and load these plug-ins at runtime. To connect the manager and the plug-ins, a movie interface is also needed. After loading plug-ins, the manager just manages a list of movie interfaces, and this is a good example of the design princple: "Program to an interface, not an implementation." The picture below shows the structure of the movie manager.

The Structure of The Movie Manager

    So it's time for coding. Let's first look at the movie interface. For simplicity, we write only one method to get the movie's name, and you can add your own as you wish.

package com.zhyi.plugintest.lib;

/**
 * This interface connects the movie manger and the movie plugins. Any movie
 * plug-in must provide at least one class that implements this interface.
 */
public interface Movie {

    /**
     * Get the name of the movie.
     * @return The name of the movie.
     */
    public String getName();

}

    They are nothing special than some very simple implementations of the Movie interface. The following is a example for "The Terminator". By the way, our former super hero Arnold is more than 60 years old now, ohhhhh...

package com.zhyi.plugintest.plugina;

import com.zhyi.plugintest.lib.Movie;

/**
 * The Terminator.
 */
public class Terminator implements Movie {

    public String getName() {
        return "The Terminator";
    }

}

    See the full source code for a full view of the plug-ins. I have written two plug-ins, and maybe you'd like to add more. But for now, let's turn to the confugurations. It's a simple XML file that is to be read by the manager.

<?xml version="1.0" encoding="UTF-8"?><plugins>
    <plugin>
        <jar>plugins/MoviePluginA.jar</jar>
        <class>com.zhyi.plugintest.plugina.Matrix</class>
        <class>com.zhyi.plugintest.plugina.Terminator</class>
    </plugin>
    <plugin>
        <jar>plugins/MoviePluginB.jar</jar>
        <class>com.zhyi.plugintest.pluginb.TheLordOfTheRings</class>
    </plugin>
</plugins>

    I won't bore you with useless words because the XML file explains itself very well. The last and the most important part is the manager. We have two classes there, one for the main class (MovieManagerTest) and one for the real management tasks - loading and playing movies (MovieManager).
    Let's start form MovieManagerTest. It has one main method with one single line, and that's all!

package com.zhyi.plugintest;

/**
 * A simple test for the movie manager.
 */
public class MovieManagerTest {

    /**
     * The main method.
     * @param args The command arguments. Not used here.
     */
    public static void main(String[] args) {
        new MovieManager().playAll();
    }

}

     As for MovieManager, it holds a list of movies that are read from plug-ins.

private List<Movie> movies;

     The application needs only one movie manager, so we use the singlton pattern. This can also prevent plug-ins be loaded more than once.

private static MovieManager movieManager = new MovieManager();

/**
 * Constructs a new movie manager.
 */
private MovieManager() {
    movies = new ArrayList<Movie>();

    // If you buy this movie manager, you'll get a free copy of "Indiana
    // Jones". For more movies, please go to our online store and purchase
    // movie plug-ins. It's cheap, safe, and fast!
    movies.add(new Movie() {
        public String getName() {
            return "Indiana Jones";
        }
    });

    try {
        loadMovies();
    } catch (Exception ex) {
        ex.printStackTrace();
    }


/**
 * Get the unique instance of the movie manager.
 * @return The unique instance of the movie manager.
 */
public static MovieManager getInstance() {
    return movieManager;
}

     We load all movies when MovieManager is being constructed. The loadMovies() method is alittle verbose, but most part of the code is for parsing the XML configuration file. If you are comfortable with DOM, it's very straight forward.

private void loadMovies() throws Exception {
    File cfg = new File("plugin.xml");
    Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(cfg);
    Element root = (Element) document.getElementsByTagName("plugins").item(0);
    NodeList plugins = root.getElementsByTagName("plugin");
    int count = plugins.getLength();
    URL[] jars = new URL[count];
    List<String> classes = new ArrayList<String>();
    for (int i = 0; i < count; i++) {
        Element plugin = (Element) plugins.item(i);
        if (plugin.getTagName().equals("plugin")) {
            Node jar = plugin.getElementsByTagName("jar").item(0);
            String jarFile = jar.getTextContent().trim();
            jars[i] = new File(jarFile).toURI().toURL();
            NodeList classNodes = plugin.getElementsByTagName("class");
            for (int j = 0; j < classNodes.getLength(); j++) {
                Node clazz = classNodes.item(j);
                classes.add(clazz.getTextContent().trim());
            }
        }
    }
    loadPlugin(jars, classes);
}

     The loadPlugin() method does the actual job of reflection, and also very simple.

private void loadPlugin(URL[] jars, List<String> classes) throws Exception {
    ClassLoader loader = new URLClassLoader(jars);
    for (String clazz : classes) {
        System.out.println(clazz);
        Class<?> c = loader.loadClass(clazz);
        Object o = c.newInstance();
        if (o instanceof Movie) {
            movies.add((Movie) o);
        }
    }
}

     The real last and also the simplest method is to play all movies. You can write your own code to play a specific movie if you like.

public void playAll() {
    for (Movie movie : movies) {
        System.out.println("Playing: " + movie.getName());
    }
}

    I leave the task of running the movie manager for you. You need to be careful with the directory structure. Here's the out put on my machine:

Playing: Indiana Jones
Playing: The Matrix
Playing: The Terminator
Playing: The Lord Of The Rings

    Couldn't be simpler, right? Again, be sure to check out the the full source code.

我回来了!

近段时间真是波折多多。不过总算还好。
刚刚把 SkyDrive 开通了,以后就不会继续在 BlogJava 的博客上写了。