关于作者

姓名:李果

性别:男

出生日期:1982-09-14

地区:北京-北京

联系电话:13811503147

QQ:4201436婚否:未婚
用户名:gophinight
笔名:刀剑啸
地区: 北京-北京
行业:其他

日历  

快速登录

+ 用户名:
+ 密 码:

在线留言



J2ME的朋友

我的好友

某爷爷的博客

http://www.blogcn.com/u2/82/27/weijiushun/index.html

访问统计:
文章个数:124
评论个数:277
留言条数:15




Powered by BlogDriver 2.1

谁与争锋刀剑啸(诚挚结交天下好友)

 

程序员一个底层的群体,有人把程序员跟妓女相比,把我们的工作比作是卖身,诚然,有一定的道理。我的路,从一行行代码中走过来,从一个个Bug中走过来,从一天天进步中走过来。回首望去,满目沧然。 今天的我,算成功,还是失败,算优秀,还是平庸,我想,作为一个程序员,我是平庸的,但作为一个朋友,我是优秀的。 以我为友者,我欢迎,鄙视我者,我亦欢迎,支持使我进步,鄙视使我自省。 我自是那秋风中一把晃悠晃悠的刀,划开厚厚的泥土。 有愿意和我交流的朋友可以给我发Mail:gophinight@163.com

文章

欢迎大家加入我的J2me交流群,50011472,500人的超级群,4653875,200人的高级群  (作者置顶)
建立这个群的目的就是为了把业内的老鸟小鸟菜鸟都聚在一起,共同交流J2me技术,让大家都成为好朋友,共同进步,群里会热心回答大家的问题,群共享里有很多很有用的资料和工具,能够给大家带来很好的帮助 ,目前主群已满,请大家加二群,谢谢

- 作者: 刀剑啸 2008年07月10日, 星期四 13:54  回复(0) |  引用(0) 加入博采

欢迎J2me的爱好者共同研究技术问题  (作者置顶)
我的邮箱是gophinight@163.com,欢迎J2me的爱好者们一起来共同研究技术问题,如果是新学者有什么技术问题,可以给我发邮件,我会及时回复,尽量给你解答^_^

- 作者: 刀剑啸 2006年07月19日, 星期三 17:14  回复(2) |  引用(0) 加入博采

J2ME开发入门  (作者置顶)
唉,本来想写一个长一些的文章,但越写越乱,算了,就写了一点点体会,大家凑合着看吧
                       J2ME开发的一些体会
  J2ME方面开发的资料,确实是少之又少,一般给新手推荐的都是王森先生的《PDA与手机开发入门》一书,然而该书其实并不适合新人阅读,该书的前几章花了很大篇幅来讲解命令行调试J2ME程序的方法和很多要点,其实这些东西,作为一个初级的J2ME开发者来说,完全没有必要学习和掌握,反而只会给自己平添很多负担。现在做J2ME开发,大多都有了IDE(集成开发环境),比如JBEclipse什么的,就算是用最简单的WTK,也不需要进行path的配置等操作,所以初学者完全可以跳过这些内容,直接上手。我的认为,做程序开发,重在实践经验,而不是理论研究,因此,新人完全可以直接从J2ME的程序流程入手,直接进入,而不需要去了解太多基本概念,比如什么是API,什么是MIDP,什么是JDK等等。这些东西我到现在也不是很清楚,但并不影响我进行开发,我是讲究实用主义的,因此,本文的基调就在于讲述一些实用的开发方法。另外首先要声明:本文中的一切开发调试都是在WTK环境下进行的,请读者注意。
一.学习J2ME需要的基础知识
J2ME本身是Java语言的一部分,因此,对Java语言有一定了解是必要的,而Java语言本身是面向对象编程的一种语言,因此,对类与对象的概念要有必要的了解,而这些内容在本文中就不进行介绍了。另外,本文行文中对API的介绍很简略,因此,读者应该自己多查阅API中的相关内容。
二.J2ME开发环境简介
J2ME的开发环境如前文所述,目前主要有JBEclipseWTK三种方式,其中前面两者都是集成开发环境,在编程上比较方便,有智能联想等功能,而WTK相对只提供了手动编译和打包,并且没有Debug功能。但WTK不需要多余的配置,对各种模拟器可以说是即插即用,而且在WTK下的程序目录简洁明了,方便查询。这几种开发环境各有长短处,所以大家可以自己选择,不过对新手来说,还是建议采用WTK,因为刚接触J2ME开发,与其把时间花在配置上,还不如花在编程上。
三.J2ME程序流程
我的感觉,每门语言都有自己的固定格式,就跟写文章的几要素一样,总有开头,结尾等等。而了解一门语言的格式,是学习这门语言最先要掌握的内容。
如果把程序流程比做是一个管道工程的话,那么每门语言里都有一个管道的入口,在J2ME里,这个入口就是MIDlet类,这个类一般也称为J2ME的主类,每个程序,都有一个或多个固定的主类,在这里,我们只谈一般的情况,即只有一个MIDlet主类的情况,大家看API即可知道,MIDlet类有几个固定方法,startApp(),pauseApp(),destroyApp(),这些方法就像是管道工程(以下的讲述里,我都把编程比作是管道工程)中的几个关键阀门,一个J2ME程序启动后,便先经历MIDlet的构造方法,然后进入startApp()方法,当有特殊情况挂起的时候,便会进入pauseApp方法,当程序结束时,便经由destroyApp方法退出。一个J2ME程序可以没有其他类,但不能没有MIDlet类,只要有一个完整的主类,便是一个完整的J2ME程序。比如非常精典的"HelloWorld",便只有一个MIDlet

我觉得,J2ME实际上是一个很标准的顺序流程语言,J2ME中没有真正的多线程,很多情况下,一个J2ME程序的运行,我们都可以对他的流程进行完全的跟踪。这在调试方面是非常方便的。

在这里还要解释一点,J2ME程序中,屏幕对象是一个比较重要的对象,你的所有操作,你所要表达的意思,都需要在屏幕上描绘出来,因此,对屏幕的操作也是最基本和最重要的一个操作,因此,J2ME程序的操作其实就是对DisplayDisplay上的Displayable(包括FormTextBoxListCanvas等等)对象进行控制。也就是说,让程序在合适的时候,把需要的Displayable显示在屏幕上。使用的方法,即是Display.setCurrent()方法。

在屏幕对象的操作上,我要解释一下,J2ME默认的屏幕只有一个,即是当前屏幕,所有操作都是对当前屏幕进行操作,因此,当你在主类中将一个Canvas对象设置为当前屏幕后,则主类已经处于脱屏状态,脱屏状态下的对象无法进行直接操作。这一点需要注意。所有外界的操作均只能作用于当前屏幕上显示的Displayable对象,无论是FormList,或者是Canvas。此时对脱屏类的操作只能通过静态方法或者是该类的一个实例来进行。

J2ME的游戏中最简单的一种游戏流程是这样,即一个主类和一个Canvas类,主类入口处定义一个Canvas对象,并且此Canvas对象继承一个Runnable接口,再定义一个基于此对象的线程,然后将此Canvas对象设为当前屏幕对象,并启动线程,即用线程的start()方法,启动线程后,Canvas里的run方法便开始运行,而run方法通常要用repaint()方法来刷屏,因此流程就是按paint()->run->paint().....这样的过程往复,其中如果还有键盘输入,则keyPressed()等方法就穿插在中间。基本上J2ME的程序就是按这样的流程来走,因此在开发和调试中只要对这个流程进行必要的跟踪就可以了。
四.J2ME中常用的类
J2ME中常用的类有MIDletFormListCanvasStringCommand,Graphics等等。
其中Graphics作为游戏开发中的核心类,自然需要熟练的掌握。
Graphics中如下的重要方法需要掌握:
setColor(int 设置的颜色)
setFont(Font 设置的字体)
drawRect(int 起点坐标x,int 起点坐标y,int ,int )
fillRect(int 起点坐标x,int 起点坐标y,int ,int )
drawImage(Image 要画的图形对象,int 起点坐标x,int起点坐标y,int 基点类型)
drawLine(int 起点坐标x,int起点坐标y,int 终点坐标x,int 终点坐标y)
drawString(String 要写的字符串, int 起点坐标x,int起点坐标y,int 基点类型)
在这里要说明一下什么是基点类型,基点是标志你设置的起点坐标在整个要绘制的对象(不论是图像还是文字)中的位置,如左上,右下,正中间等等。
常用的值有020:左上,17:正中间,24:右上,36:左下,40:右下。

除此之外,还有几个重要方法
addCommand,removeCommand,这两个方法是对Command的添加和取消的操作,很常用。
而谈到Command,自然就要涉及到commandListener这个接口,按钮的监听需要通过这个接口来进行,也就是要重载接口中的commandAction()方法。过在使用这个接口的时候,不要忘了对当前的对象设置setCommandListener(this)。
另外,对于String类,substring方法应该掌握
而对于Form这些高级控件,可用方法不多,看看API即可。
五.J2ME中的线程
J2ME中的线程是Thread类,而实现线程有两种方法,一种是继承Runnable接口,一种是TimerTimerTask。而不管是哪种线程,其本质都是在运行其中的run方法。在这里要注意,Runnable接口的run方法和TimerTaskrun方法又是不同的,因为他们的运行机制不同。Runnable接口是靠线程的休眠或等待来实现线程的刷新,而TimerTask是按照事先给定的时间间隔来自动刷新。对Runnable接口,一旦run方法结束后,则线程就结束了,因此Runnable线程里的run方法要写成循环方式,一般是while(isRunning)的形式,要结束的时候把isRunning设为false,而TimerTask则不用,因为他是定时刷新。但这样也有个问题,就是如果TimerTaskrun方法写得过长,执行时间超过了设置的线程间隔时间,就会出现线程重叠的情况。线程重叠会造成诸如游戏速度突然加快等Bug
Runnable接口定义的线程里,有两种等待方法,一种是wait,一种是sleep,如果使用wait方法,则要注意在线程run方法里,用synchonized标志符将该线程设置为同步锁定状态,否则会出现java.lang.IllegalMonitorStateException异常,大致意思是线程当前请求的监视器对象不能响应,因为被别的线程占用了。

线程在J2ME里非常重要,一切动态效果(当然这是游戏的前提)都是通过线程来操作,因此,对线程的控制是值得研究的一个问题。如何优化代码,使线程能够在足够短的间隔时间内正常刷新,换言之,这就是大家讨论的FPS问题。程序优化做得好,则线程间隔时间可以足够短,使得FPS可以足够高,游戏的流畅度当然就越高。
六.J2ME开发中的好习惯
1.       多写注释,完备的注释不管是对你自己,还是对别人,都是很有好处的,在调试中也会起很大的帮助。
2.       在重要流程的各个环节设置一些监听点,其实很简单,就是用symstem.out.println()来输出一些标志符号就可以了,这样可以监听你的程序在运行的时候,走到哪一步。
3.       不要写太多的类,尽量整合资源,不用的变量或者方法,尽量去掉。
4.       熟练掌握各种常见的异常,不要太依赖于问别人和翻书,这些应该是一个合格的程序员应该熟练于心的东西。
5.       对不熟悉的类,应该多写小代码来实验其用法,别人讲的永远不如自己研究出来的结果牢靠。

- 作者: gophinight 2005年03月21日, 星期一 17:01  回复(17) |  引用(0) 加入博采

如何用WTK+UltraEditor的开发环境来进行编程(新手请看)  (作者置顶)
。。。。。。。。。。。。。。。。。

目前做J2ME开发的环境很多,常用的一般是JB,Eclipse,UltraEditor+WTK,这个随个人喜好,我个人用的是最后一种环境,所以写篇小文来介绍一下如何用这个开发环境来进行程序开发。

简单地说,WTK是一个编译和调试的工具,可以加载很多模拟器作为模拟运行的环境,而UltraEditor是一个比较优秀的编辑器,在程序的格式排版方面作得比较好。下面我们就用这个环境来做大家耳熟能详的HelloWolrd的例子。

首先,打开WTK,然后选择新建工程,同JB,Eclipse一样,WTK也是以工程作为管理的基本单位,一个完整的程序就是一个工程。在新建工程里有两个东东需要填写,第一是工程名,这个可以乱填,想写什么都行,呵呵,第二是你的工程的主类名,这个要注意,你将要新建的主类文件必须与这个主类名相同,填完这两个东东,确定就OK了。

接下来,让我们打开WTK目录下的Apps文件夹,你就会发现里面多了一个你刚才建的工程目录,打开这个目录,下面有这样几个文件夹,bin,classes,src,res,在bin目录里还有两个文件,一个Jad,一个MF,不过你大可不去管他,呵呵,而其他文件夹都是空的。好啦,现在该是写代码的时候了。在写代码之前,要交代一下这几个目录的作用,Bin是存放你将来打包的程序包的地方,Classes自然不用说,是放编译好的类文件的地方,SRC是存放源文件的地方,而RES,则是存放资源文件比如图片呀文本呀什么的地方。

打开UltraEditor,新建一个文件,然后直接先保存,路径嘛,自然是刚才的SRC文件夹,文件名呢,前面已经说过了,是你建的主类名,在这里,有必要解释一下什么是主类。在J2ME的程序里,有且只有一个主类,这个主类是一个继承于MIDlet的类,他是整个程序的运行入口,程序的主线程就是由这个主类开始的。一般来说,一个游戏是由一个主类,若干或一个Canvas类(画布),若干个自建的类,一个RMS类以及一堆计时器类(如果有必要的话)构成的,嗯,闲话暂且不提,建好这个主类文件后,干什么呢,呵呵,自然是写我们的代码了。HelloWorld的代码想必大家随便从某个角落都可以顺手拣到,这里就贴一段。

import javax.microedition.midlet.*;

public class HelloWorld extends MIDlet

{

     public HelloWorld()

     {

     }

     public void startApp()

    {

            System.out.println("HelloWorld");

    }

    public void pauseApp()

   {

   }

   public void destroyApp(boolean unditional)

  {

   }

}

写完之后保存,然后切换到WTK,选择Build(不要告诉我你没有看到哟),然后WTK会开始编译程序,如果你有什么语法上的错误,他就会在控制台中提示你,自然啦,这个程序是没有错的,于是会告诉你Build Successfull!,接下来,选择Run来运行你的程序,于是,一个手机模拟器面板出现啦^_^,上面会显示你的程序名,还有一个launch按钮,嗯,点击进去,好,你就会发现控制台上打出了我们的HelloWorld啦。

接下来你可以用WTK来为程序打包,选择project->package->create package,好啦,WTK就开始给我们的程序打包了,这种方式打的包是没有混淆过的包,至于混淆与非混淆的区别,我们在这里就不细说啦。打完包后,赶紧去你的目录里看看吧,在Bin目录下就出现一个Jar文件啦。这个文件就可以装到手机里去玩啦^*^(&(&)(&)*()(当然前提是你做了一个游戏,HelloWorld么,免了吧,哈哈)

怎么样,简单吧。WTK里还有不少可设置的东西,我们最常用到的是这样三个东东,在WTK中选择Setting,然后转到最后一个选项卡,你会发现有三个内容可以编辑,这三个内容依次是程序名,Icon和Class,程序名可以不管,con嘛,自然是图标啦,我们做好的游戏,装到手机上后都希望有一个好看的图标来标识嘛,怎么办呢,找一张图片,40上的就用16×16的就行啦,然后取名为Icon(图片必须是Png格式的).png,当然名字可以随意取啦,然后把这个图片放到RES目录下,这样你的程序装到手机上后就有图标啦。至于第三个内容,Class,这个很重要,他标识的是你的主类的路径,有很多朋友把自己的程序从JB下转移到WTK下编译会出错,会提示ClassNotFoundException异常,就是这个路径惹的祸啦。JB下一般都是自动给你的程序加上Package的,比如同样是HelloWorld这个程序,可能在JB下就是作为一个包(比如叫Hello)下的代码存在,那么,你在Class这里就应该填上/Hello/HelloWorld,这样修改过后,再编译,就不会再出错啦。^_^

好啦,就写这么多,希望给大家一些提示和帮助。

- 作者: gophinight 2004年12月21日, 星期二 03:18  回复(1) |  引用(0) 加入博采

用字符串进行加法和乘法的算法

在J2me开发中我们有可能会遇到需要将一个很大很大的数进行运算的情况,这个所谓很大就是说数的位数已经远远超过了int,甚至double的情况,因此是不能直接进行运算的,只能将这个数转化成字符串来进行运算,下面就给出加法和乘法的代码,并由之推出的一个大数阶乘的代码

 /*字符串加法*/
 public String StringAdd(String s1,String s2)
 {
  String smin,smax;
  if(s1.length()>s2.length())
  {
   smax=s1;
   smin=s2;
  }
  else
  {
   smax=s2;
   smin=s1;
  }
  int a,b,c=0,d,p;
  d=smax.length()-1;
  p=smin.length()-1;
  String result="";
  while(d>=0)
  {
   if(p>=0)
    a=Integer.parseInt(smin.substring(p,p+1));
   else
    a=0;
   b=Integer.parseInt(smax.substring(d,d+1));
   c=a+b+c;
   result=c%10+result;
   c=c/10;
   p--;
   d--;
  }
  if(c!=0)
   result=String.valueOf(c)+result;
  return result;
 }

 /*字符串乘法*/
 public String StringMul(String s1,String s2)
 {
  String smin,smax;
  if(s1.length()>s2.length())
  {
   smax=s1;
   smin=s2;
  }
  else
  {
   smax=s2;
   smin=s1;
  }
  int a,b,c=0;
  String result="0",tempResult="",tempZero="";
  for(int i=smin.length()-1;i>=0;i--)
  {
   b=Integer.parseInt(smin.substring(i,i+1));
   if(b!=1)
   {
    for(int j=smax.length()-1;j>=0;j--)
    {

     a=Integer.parseInt(smax.substring(j,j+1));
     c=a*b+c;
     tempResult=c%10+tempResult;
     c=c/10;
    }
    if(c!=0)
     tempResult=c+tempResult;
   }
   else
    tempResult=smax+tempResult;
   result=StringAdd(tempResult,result);
   tempZero+="0";
   c=0;
   tempResult=tempZero;
  }
  return result;
 }

 /*大数阶乘*/
 public String stepMul(int x)
 {
  return x==1?"1":(this.StringMul(String.valueOf(x),stepMul(x-1)));
 }

运算得到的结果自然也是一个字符串

- 作者: 刀剑啸 2008年07月16日, 星期三 09:46  回复(0) |  引用(0) 加入博采

低级界面中实现输入法

呵呵,在游戏或者应用开发中,在高级界面和低级界面之间的切换总是一件让人头疼的事情,高级界面方便,但是难看,低级界面美观,但是一直以来因为在输入法上存在困难(主要是指中文),所以很多产品都是使用了两种界面并存的方式,但我一直想放弃高级界面,采用低级界面来保持产品界面风格的统一,经过N天的努力,终于整成了一套比较好用的输入法,从此可以告别高级界面了,^_^

先讲讲这个输入法的原理,首先程序会从字库文件中将拼音和相应的文字读进内存,其中拼音会放在一个数组里,用来查找,然后字库里的字会以拼音为Key存入一个哈希表,查找的时候,首先根据按键上的字母组合在拼音表里查找是否有适配的拼音,如果有完整适配的拼音则直接从哈希表从取出相应的文字以供选择,下面就给出相应的代码

public class InputMethod implements Const
{
 Hashtable hashtable=new Hashtable();
 String[] wordKey;
 int[] inputKey=new int[10];
 int currentPos;
 String[] currentInputPad;//当前的输入显示板
 public Vector keyAvailable=new Vector(0,1);
 Vector wordsBuffer;//上一级的读音的缓存
 int select,charSelect;
 int screenW,screenH;
 int num_row;//每行的字數
 int charPage;//頁數
 public String inputChar;//輸入的字符
 int inputMode;//输入类型 0字母 1数字 2拼音
 String[] inputModeTxt={"abc","123","拼音"};br /> public String content[]={"","",""};//输入的内容,第一维是实际内容,第二维和第三维是用于有光标定位显示的内容
 public int charPos;//光标位置
 long time1,time2;//按键的时间
 int charKeyPos;//字母的切换
 String[][] charKey=new String[][]{
   {"a","b","c"},
   {"d","e","f"},
   {"g","h","i"},
   {"j","k","l"},
   {"m","n","o"},
   {"p","q","r","s"},
   {"t","u","v"},
   {"w","x","y","z"}
 };
 public InputMethod(int w,int h)
 {
  screenW=w;
  screenH=h;
  num_row=(w-10)/20;
  charPage=0;
  cls();
  readWords();
 }
 /*清空缓存*/
 public void cls()
 {
  currentPos=0;
  wordsBuffer=new Vector(0,1);
  for(int i=0;i<inputKey.length;i++)
   inputKey[i]=-1;
 }
 /*清空输入内容*/
 public void clsContent()
 {
  content=new String[]{"","",""};
  charPos=0;
  charSelect=0;
 }
 public void doUp()
 {
  if(select>0)
   select--;
  currentInputPad=null;
 }
 public void doDown()
 {
  if(select<keyAvailable.size()-1)
   select++;
  currentInputPad=null;
 }
 public void drawInput(Graphics g)
 {
  try
  {
   int starty;
   if(inputMode==2)
   {
    if(keyAvailable!=null&&keyAvailable.size()>0)
    {
     starty=240-keyAvailable.size()*20;
     if(keyAvailable.size()>0)
      PaintCanvas.drawBox(g, 0, starty, 50,keyAvailable.size()*20, 0xffff00);
     g.setColor(0);
     for(int i=0;i<keyAvailable.size();i++)
     {
      if(i==select)
       g.setColor(0x00ff00);
      else
       g.setColor(0x0000ff);
      g.fillRect(0,starty+i*18,50,18);
      g.setColor(-1);
      String key=(String)keyAvailable.elementAt(i);
      g.drawString(key,10,starty+i*18,0);
      if(i==select)
      {
       /*查找相应的拼音*/
       for(int m=0;m<wordKey.length;m++)
       {
        /*如果完全适配,就从哈希表里取出相应的字*/
        if(key.equals(wordKey[m]))
        {
         currentInputPad=(String[])hashtable.get(key);
         break;
        }
       }
      }
     }
    }

    if(currentInputPad!=null)
    {
     starty=screenH-65;
     drawTextBox(g,0xefefef,0x121212,0x2d3f4d,2,starty,screenW-4,25,2,0);
     g.setColor(0xffff00);
     for(int i=charPage*num_row;i<(charPage+1)*num_row;i++)
     {
      System.out.println(i+"."+charPage+"."+num_row+"."+charSelect);
      if(i>currentInputPad.length-1)
       return;
      if(i==charSelect)
      {
       g.setColor(-1);
       g.drawRect(3+(i-charPage*num_row)*20,starty+1,16,20);
      }
      g.setColor(0xffff00);
      g.drawString(currentInputPad[i],5+(i-charPage*num_row)*20,starty+2,0);
     }
    }
   }
   PaintCanvas.drawStringShadow(g,-1,0,0,inputModeTxt[inputMode],w,0,24);
  }
  catch(Exception e)
  {
   System.out.println("輸入法出錯"+e.toString());
  }
 }
 public void drawTextBox(Graphics g,int color1,int color2,int color3,int stx,int sty,int bw,int bh,int boardW,int type)
 {
  if(type==0)
  {
   g.setColor(color1);
   g.fillRect(stx-boardW,sty-boardW,bw+2*boardW,bh+2*boardW);  
   g.setColor(color2);
   g.fillRect(stx,sty,bw+boardW,bh+boardW);
   g.setColor(color3);
   g.fillRect(stx,sty,bw,bh);  
  }
  else
  {
   g.setColor(color2);
   g.fillRect(stx-boardW,sty-boardW,bw+2*boardW,bh+2*boardW);  
   g.setColor(color1);
   g.fillRect(stx,sty,bw+boardW,bh+boardW);
   g.setColor(color3);
   g.fillRect(stx,sty,bw,bh);  
  }   
 }
 public void keyPressed(int i)
 {
  time2=System.currentTimeMillis();
  if(i==MIDKEY)
  {
   if(inputMode==2)
   {
    if((inputChar=getChar())!=null)
    {
     cls();
     keyAvailable.removeAllElements();
     currentInputPad=null;
    }
   }
  }
  if(i==SOFTRIGHTKEY)
  {
   backWord();
//   cls();
//   keyAvailable=new Vector(0,1);
//   currentInputPad=null;
  }
  if(i>=48&&i<58)
  {
   if(inputMode==2&&i>=50)
   {
    if(checkWord(i-50))
    {
     inputKey[currentPos++]=i-50;
     currentInputPad=null;
    }
    select=0;
   }
   else if(inputMode==1)
    inputChar=""+(i-48);
   else if(inputMode==0)
   {
    if(i>=50)
    {
//nbsp;    System.out.println("按键时间"+time2+"."+time1);
     if((time2-time1)<500)
     {
//      System.out.println("连续按键");
      charKeyPos++;
      if(charKeyPos==charKey[i-50].length)
       charKeyPos=0;
//      System.out.println("内容长度"+content[0].length()+"光标位置"+charPos);
      if(charPos==content[0].length())
      {
       System.out.println("1");
       content[0]=content[0].substring(0,charPos-1);
       charPos--;
       System.out.println("2");
      }
      else
       content[0]=content[0].substring(0,charPos-1)+content[0].substring(charPos,content[0].length());
      refreshContent();
     }
     inputChar=charKey[i-50][charKeyPos];
    }
   }
  }
  if(i==UPKEY)
   doUp();
  if(i==DOWNKEY)
   doDown();
  if(i==LEFTKEY)
  {
   if(charSelect>0)
    charSelect--;
   if(charSelect%num_row==num_row-1)
    charPage--;
  }
  if(i==RIGHTKEY)
  {
   if(charSelect<currentInputPad.length-1)
    charSelect++;
   if(charSelect%num_row==0&&charSelect!=0)
    charPage++;
  }
  /*切换输入法*/
  if(i==POUNDKEY)
  {
   inputMode++;
   if(inputMode==inputModeTxt.length)
    inputMode=0;
  }
  /*删除*/
  if(i==CKEY)
  {
   if(charPos>=2&&PaintCanvas.checkFace(content[0].substring(charPos-2,charPos))>-1)
   {

    content[0]=content[0].substring(0, charPos-2)+content[0].substring(charPos,content[0].length());
    charPos-=2;
   }
   else if(charPos>0)
   {
    if(charPos==content[0].length())
     content[0]=content[0].substring(0,charPos-1);
    else
     content[0]=content[0].substring(0, charPos-1)+content[0].substring(charPos,content[0].length());
    charPos--;
   }
   refreshContent();
  }
  time1=time2;
 }
 /*回退*/
 public void backWord()
 {
  if(wordsBuffer.size()>0)
  {
   keyAvailable=(Vector)wordsBuffer.elementAt(wordsBuffer.size()-1);
   wordsBuffer.removeElementAt(wordsBuffer.size()-1);
   currentInputPad=null;
  }
 }
 public void checkWords(Vector temp,String key,int ik)
 {
  int p;
  for(p=0;p<charKey[ik].length;p++)
  {

   int m;
   for(m=0;m<wordKey.length;m++)
   {
    if(wordKey[m].indexOf(key+charKey[ik][p])==0)
    {
     temp.addElement(new String(key+charKey[ik][p]));
     break;
    }
   }
  }
 }
 /*检查是否有合适的拼音*/
 public boolean checkWord(int ik)
 {
  Vector temp=new Vector(0,1);
  String key="";
  if(keyAvailable.size()>0)
  {
   for(int i=0;i<keyAvailable.size();i++)
   {
    key=(String)keyAvailable.elementAt(i);
    checkWords(temp,key,ik);
   }
  }
  else
   checkWords(temp,key,ik); 
  if(temp.size()>0)
  {
   wordsBuffer.addElement(keyAvailable);
   keyAvailable=temp;
   return true;
  }
  return false;
 }
 /*从字库里读取文件*/
 public void readWords()
 {
  try
  {
   InputStream is;
   String[] words;
   int fontNum=0;
   is=getClass().getResourceAsStream("/input/chars.txt");
   StringBuffer sb=new StringBuffer();
   int c;
   int pos=0;
   while((c=is.read())!=-1)
   {
//    System.out.println(c);
    if(c=='\n')
    {
     if(pos==0&&fontNum==0)
     {
      fontNum=Integer.parseInt(sb.toString());
      wordKey=new String[fontNum];
//      System.out.println("拼音表长度:"+wordKey.length);
     }
     else
     {
      String key;
      byte[] data1=new byte[sb.toString().length()];
      for(int i=0;i<data1.length;i++)
       data1[i]=(byte)sb.charAt(i);
      String s=new String(data1,"UTF-8");
      key=s.substring(0, s.indexOf("*")).toLowerCase();
//      System.out.println(key);
      words=new String[s.length()-s.indexOf("*")-1];
      for(int j=0;j<words.length;j++)
      {
       words[j]=s.substring(s.indexOf("*")+1+j,s.indexOf("*")+2+j);
      }
      hashtable.put(key, words);
      wordKey[pos++]=key;  
     }
     sb=new StringBuffer();
    }
    else if(c!=0x0d)
    {
     sb.append((char)c);
    }
   }
   String key;
   byte[] data1=new byte[sb.toString().length()];
   for(int i=0;i<data1.length;i++)
    data1[i]=(byte)sb.charAt(i);
   String s=new String(data1,"UTF-8");
   key=s.substring(0, s.indexOf("*"));
   words=new String[s.length()-s.indexOf("*")-1];
   for(int j=0;j<word.length;j++)
   {
    words[j]=s.substring(s.indexOf("*")+1+j,s.indexOf("*")+2+j);
   }
   hashtable.put(key, words);
   wordKey[pos++]=key;
  }
  catch(Exception e)
  {
   System.out.println("读取字库出错"+e.toString());
  }
 }
 public String getChar()
 {
  if(currentInputPad!=null)
   return currentInputPad[charSelect];
  else
   return null;
 }
 public void setInputMode(int type)
 {
  inputMode=type;
 }
 public int getInputMode()
 {
  return inputMode;
 }
 public void refreshContent()
 {
  if(content[0].length()>0)
  {
   if(charPos==0)
   {
    content[1]=" "+content[0];
    content[2]="|"+content[0];
   }
   else if(charPos==content[0].length())
   {
    content[1]=content[0]+" ";
    content[2]=content[0]+"|";
   }
   else
   {
    content[1]=content[0].substring(0,charPos)+" "+content[0].substring(charPos,content[0].length());
    content[2]=content[0].substring(0,charPos)+"|"+content[0].substring(charPos,content[0].length());
   }
  }
  System.out.println(content[0]);
  System.out.println(content[1]);
  System.out.println(content[2]);
 }
 /*移动光标*/
 public void moveCharPos(int direct)
 {
  if(direct==0)
  {
   if(charPos>2)
   {
    System.out.println(content[0].substring(charPos-2,charPos));
    if(PaintCanvas.checkFace(content[0].substring(charPos-2,charPos))>-1)
     charPos-=2;
    else
     charPos--;
   }
   else if(charPos>0)
    charPos--;
  }
  else
  {
   if(charPos<content[0].length()-2)
   {
    if(PaintCanvas.checkFace(content[0].substring(charPos+1,charPos+3))>-1)
     charPos+=2;
    else
     charPos++;
   }
   else if(charPos<content[0].length())
    charPos++;
  }
  refreshContent();
 }
}

这个代码实现了用#号键切换英文,数字,拼音之间的输入法切换(不好意思,暂时没有加入标点输入),然后在自己的Canvas界面中通过如下按键控制

 /*输入法的按键*/
 public void keyPressedInput(int i)
 {
  if(!chooseFace&&down&&imt.keyAvailable.size()==0)
  {
   chooseFace=true;
   faceNo=7;
  }
  else if(!chooseFace&&left&&imt.keyAvailable.size()==0)
  {
   imt.moveCharPos(0);
  }
  else if(!chooseFace&&right&&imt.keyAvailable.size()==0)
  {
   imt.moveCharPos(1);
  }
  else if(chooseFace)
  {
   if(left)
   {
    if(faceNo==0)
     faceNo=face.rows*face.columns-1;
    else
     faceNo--;
   }
   else if(right)
   {
    if(faceNo==face.rows*face.columns-1)
     faceNo=0;
    else
     faceNo++;
   }
   else if(up)
    chooseFace=false;
   else if(fire||softLeft)
   {
    imt.content[0]+=faceSign[faceNo];
    imt.charPos+=2;
    imt.refreshContent();
   }
  }
  else if(softRight)
  {
   if(imt.keyAvailable==null||imt.keyAvailable.size()==0)
   {
    drawMessage=-1;
    imt.clsContent();
   }
   else
    imt.keyPressed(-7);
  }
  else if(softLeft)
  {
   if(imt.keyAvailable.size()==0)
   {

    if(imt.content[0]!=null&&imt.content[0].length()>0)
    {
     sendMessage(drawMessage);
    }
    else
     setNotice("对不起,你输入的信息为空");
    drawMessage=-1;
   }
  }
  else
  {
   imt.keyPressed(i);
   if(imt.inputChar!=null)
   {
    if(imt.content[0]==null||imt.content[0].length()==0)
    imt.content[0]=imt.inputChar;
    else
     imt.content[0]=imt.content[0].substring(0,imt.charPos)+imt.inputChar+imt.content[0].substring(imt.charPos, imt.content[0].length());
    imt.inputChar=null;
    imt.charPos++;
   }
  }
  imt.refreshContent();
 }

这里面有一些我自己的工程中要用到的类,大家看的时候注意区分一下,呵呵,比如chooseFace是为了我们这边需要插入表情头像用的,大家可以不用,绘制的时候,交替显示inputmethod里的content[1]和content[2],确定需要用到输入内容的时候,调用inputmethod里的content[0]就行了。

另外给一下字库文件的格式

392
A*啊阿腌
Ai*爱矮挨哎碍癌艾唉哀蔼隘埃皑呆嫒暧捱

字库文件是一个TXT文件,第一行的数字标明这个字库里有多少拼音,然后每一行是拼音和字库,这个文件可以自己随意定义。

OK,就说这么多吧,大家有看不明白的地方,可以找我交流一下,谢谢。

- 作者: 刀剑啸 2007年05月16日, 星期三 14:25  回复(6) |  引用(0) 加入博采

常用的排序算法(包括冒泡排序,选择排序,插入排序,希尔排序,快速排序)

排序算法在程序中会用到很多,这里介绍几种常见的排序方法以及比较

冒泡排序:对一个队列里的数据,挨个进行轮询和交换,每次轮询出一个当前最大或者最小的值放在队尾,然后继续下次轮询,轮询长度-1,就跟冒泡一样,所以称为冒泡排序,运算时间复杂度N平方

选择排序:对一个队列里的数据,选出当前最大或者最小的值,然后将他与队首的数据交换,然后从第二个开始,进行相同的操作,运算时间复杂度N平方,但由于他不像冒泡一样需要不停的交换位置,所以会比冒泡快一些

插入排序:对一个队列里的数据,从第二个开始,与此位置之前的数据进行比较,形成局部有序的队列,循环此操作,直到队尾,运算时间复杂度依然为N平方,但他由于保证了局部的有序性,所以比较的次数会更少一些,相对前两种会更快

希尔排序:其实就是用步长控制的插入排序,希尔排序通过加大插入排序中元素之间的间隔,并在这些有间隔的元素中进行插入排序,从而让数据项可以大幅度移动,这样的方式可以使每次移动之后的数据离他们在最终序列中的位置相差不大,保证数据的基本有序,大大提升了排序速度,运算时间复杂度N*logN

快速排序:对一个队列,以他队尾的数据为基准值,先划分成两块数据,一块都大于这个值,一块小于这个值,然后对这两块进行同样的操作,这是最快的排序方法,运算时间复杂度N*logN

下面是代码:

 public static void sort(int[] a)
 {
  long time1,time2;
  int c;
  time1=System.currentTimeMillis();
//  /*冒泡排序*/
//  for(int i=a.length-1;i>1;i--)
//  {
//   for(int j=0;j<i;j++)
//   {
//
//    if(a[j]<a[j+1])
//    {
//     c=a[j];
//     a[j]=a[j+1];
//     a[j+1]=c;
//    }
//   }
//  }
//  /*选择排序*/
//  int pos=0;
//  for(int i=0;i<a.length-2;i++)
//  {
//   for(int j=i;j<a.length-1;j++)
//   {
//    if(a[pos]<a[j+1])
//     pos=j+1;
//   }
//   c=a[i];
//   a[i]=a[pos];
//   a[pos]=c;
//   pos=i+1;
//  }
//  /*插入排序*/
//  for(int i=1;i<a.length;i++)
//  {
//   c=a[i];
//   int m=i-1;
//   while(m>=0&&a[m]<c)
//   {
//    a[m+1]=a[m];
//    m--;
//   }
//   a[m+1]=c;
//  }
//  /*希尔排序*/
//  int h=1;
//  int m=0;
//  while(3*h+1<a.length)
//   h=3*h+1;
//  while(h>0)
//  {
//   for(int i=h;i<a.length;i++)
//   {
//    c=a[i];
//    m=i-h;
//    while(m>=0&&a[m]<c)
//    {
//     a[m+h]=a[m];
//     m-=h;
//    }
//    a[m+h]=c;
//    
//   }
//   h=(h-1)/3;
//  }
  /*快速排序*/
  provide(a,0,a.length-1);
  time2=System.currentTimeMillis();
  System.out.println("time:"+(time2-time1));
 }
 /*递归调用划分*/
 public static void provide(int[] a,int left,int right)
 {
  try
  {
   if(right<=left)
    return;
   else
   {
    /*设置基准点*/
    int prov=a[right];
    /*取得划分中断点*/
    int par=partitionIt(a,left,right,prov);
    /*对划分后的两边再次划分*/
    provide(a,left,par-1);
    provide(a,par+1,right);
    
   }
  }
  catch(Exception e)
  {
   System.out.println("eer:"+left+"."+right);
  }
 }
 /*划分算法*/
 public static int partitionIt(int[] a,int left,int right,int prov)
 {
  /*设置左右端点的指针*/
  int leftP=left-1;
  int rightP=right;
  int c;//用于交换的中间变量
  /*当左右指针未相遇时继续操作*/
  while(leftP<rightP)
  {
   /*当左指针的数据小于基准值时跳出*/
   while(leftP<a.length-1&&a[++leftP]>prov)
    ;
   /*当右指针的数据大于基准值时跳出*/
   while(rightP>leftP&&a[--rightP]<prov)
    ; 
   /*左右指针都停下时交换数据*/
   c=a[leftP];
   a[leftP]=a[rightP];
   a[rightP]=c;
  } 
  /*划分结束,将基准点与指针的相遇点交换*/
  c=a[rightP];
  a[rightP]=a[right];
  a[right]=c; 
  return leftP;
 }

- 作者: 刀剑啸 2007年03月28日, 星期三 18:16  回复(1) |  引用(0) 加入博采

成功是等不来的

  成功是什么,鬼才知道,对不同的人来说,成功具有不同的含义,然而如何才能够获得成功应该是大家都关心的话题,包括我自己,但我自己都是迷茫的,我向往成功,却也不停的错过去争取成功的机会,回想再三,其实就是自己怎一个懒字了得。

   很多日子之前就曾经说过要学这样学那样,结果三年光阴已经逝去,我却依旧是一个除了J2me之外啥都不会的半残,而且根本没有一点想学习的念头,而身边的兄弟们却一个个都开始身杯十八般武艺,有时候听他们讨论技术问题,我基本上是云里雾里,感觉自己就跟被埋进了土堆里的死人一样,已经快被时代所抛弃。

    我曾说自己不愿意再技术,想往管理的路上发展,然而当机会真的来到我面前的时候,当某公司力邀我去做他们开发团队的Leader的时候,我却萎缩了,我当然会找种种理由来解释自己不能接受这个职位,然而我自己心里最清楚,我是害怕,我没有任何一点这方面的经验,我害怕自己做不了会对人不好交待,我怕自己丢人,然而为什么我做不到呢,还不是因为我没有好好充电么,经验原本就是在实践中积累的,而我却浪费了这么多时间,我这时候才知道,YY是开心的,然而当现实来到你跟前你却依旧只能YY而不敢接受的时候,你真的就是个天杀的贱人。

    成功是等不来的,2007年春节马上就到了,新的一年又该拉开大幕,人都在渐渐老去,再不花时间学习,那成功就永远只能成为你枕边的一个梦了,也许还带着些许的口水...

- 作者: 刀剑啸 2007年01月29日, 星期一 09:55  回复(4) |  引用(0) 加入博采

J2me如何播放声音

在手机应用或者手机游戏中都会用到音效,所以如何播放音效是程序应该解决的问题,现在的音效一般有四种,amr,mid,wav,mp3,对J2me来说,最适用的是mid音效,下面给出的代码是我的声音播放类,适用于四种音效格式,在创建播放器的时候提供了两种方式,一种是直接读取资源文件的创建方式,一种是先从本地或者网络获取到包含声音的流byte[]的创建方式

/*手机博客客户端.声音类
开发:李果
开发开始日期:2006年5月8日
*/
import javax.microedition.media.*;
import java.io.*;
public class soundPlayer

 public String pType;//手机型号 
 public final String[] mediaType=new String[]{"audio/x-wav","audio/midi","audio/mpeg","audio/amr"}; 
 public soundPlayer(String s)
 {
  pType=s;
 }
 
 /*从字节数组里获取输入流*/
 public InputStream getInputStream(byte[] data)
 {
  try
  {
   ByteArrayInputStream bis=new ByteArrayInputStream(data);
   return (InputStream)bis;
  }
  catch(Exception e)
  {
   return null;
  }
 }
 public Player createPlayer(InputStream is,String t,int loop)
 {
  Player player;
  if(is!=null)
  {
   try
   {
    if(t.equals("mid"))
    player=Manager.createPlayer(is,mediaType[1]);
    else
    if(t.equals("wav"))
    player=Manager.createPlayer(is,mediaType[0]);
    else
    if(t.equals("mp3"))
    player=Manager.createPlayer(is,mediaType[2]);
    else
    if(t.equals("amr"))
    player=Manager.createPlayer(is,mediaType[3]);
    else
    return null;
   }
   catch(Exception e)
   {
    return null;
   }
  }
  else
  return null;
  player.setLoopCount(loop);  
  return player;  
 }
 /*创建播放器*/
 public Player createPlayer(String s,int loop)
 {
  Player player;
  try
  {
   InputStream is=getClass().getResourceAsStream(s);
   String t=s.substring(s.indexOf('.')+1,s.length());
   if(t.equals("mid"))
   player=Manager.createPlayer(is,mediaType[1]);
   else
   if(t.equals("wav"))
   player=Manager.createPlayer(is,mediaType[0]);
   else
   if(t.equals("mp3"))
   player=Manager.createPlayer(is,mediaType[2]);
   else
   if(t.equals("amr"))
   player=Manager.createPlayer(is,mediaType[3]);
   else
   return null;
  }
  catch(Exception e)
  {
   return null;
  }
  player.setLoopCount(loop);  
  return player;
 }
 /*播放声音*/
 public void playSound(Player p)
 {
  try
  {
   //System.out.println(p.getState());
   if(p.getState()!=400)
   p.start();
  }
  catch(Exception e)
  {
  }
 }
 /*暂停声音*/
 public void pauseSound(Player p)
 {
  try
  {
   if(p.getState()==400)
   p.stop();
  }
  catch(Exception e)
  {
  }
 }
 /*停止声音*/
 public void stopSound(Player p)
 {
  try
  {
   if(p.getState()==400)
   p.stop();
   if(!pType.equals("NOKIA"))
   p.deallocate();
  }
  catch(Exception e)
  {
   System.out.println(e);
  }
 }
 /*关闭声音*/
 public void closeSound(Player p)
 {
  try
  {
   stopSound(p);
   p.close();
  }
  catch(Exception e)
  {
  }
 }
}

- 作者: 刀剑啸 2006年12月13日, 星期三 14:06  回复(1) |  引用(0) 加入博采

jsr75相关操作代码新版本

这个版本比之前那个代码多了如下内容:

1.增加了机型判断,增加了两个方法用以直接读取手机的图片文件和铃声文件

2.列表方法增加了根目录查看

3.完善了PIM读取方法,只读取电话本里的联系人姓名和电话

4.完善了写文件操作,在非强制写入的情况下做了异常判断

如下代码里的注释部分是我自己用来调试用的,可以不要

/*文件系统类
开发:李果
开发开始日期:2006年12月11日
*/
import javax.microedition.io.*;
import javax.microedition.io.file.*;
import java.io.*;
import java.util.*;
import javax.microedition.pim.*;
public class fileSystem
{
 int fileSize;//文件总大小
 int currentProgress;//读取进度
 String platform;
 String message;
 String imageFilePath;
 String soundFilePath;
 public static final String S40_DEVICE[]={"2610","2855","2865","3152","3155","5140","5200","5300","6020","6060","6080","6085","6101","6102","6103","6111","6125","6126","6131","6133","6136","6151","6152","6155","6155","6165","6170","6230","6233","6234","6235","6255","6265","6270","6280","6282","6288","6822","7260","7270","7360","7370","7373","7390","8800",}; 
 public fileSystem()
 {
  platform = System.getProperty("microedition.platform");
  if(platform.startsWith("SonyEricsson"))
  {
     imageFilePath="c:/pictures/";
     soundFilePath="c:/sounds/";
    }
  else
    if(platform.startsWith("Nokia"))
    {
    boolean isS40=false;
     for(int i=0;i<S40_DEVICE.length;i++)
     {
      if(platform.startsWith("Nokia".concat(S40_DEVICE[i])))
      {
      isS40=true;
      break;
     }
     }
     if(isS40)
     {
     imageFilePath="C:/predefgallery/predefphotos/";
     soundFilePath="C:/predefgallery/predefrecordings/";
    }
    else
    {
     imageFilePath="C:/Data/Images/";
     soundFilePath="C:/Data/Sounds/Digital/";
    }
   }
   else
   {
    imageFilePath="/";
    soundFilePath="/";
   }  
 }
 /**保存文件
 * @path:路径
 * @fileData:文件数据
 * @overrite:是否强制覆盖保存
 * @return: -1:文件已存在,0:出现异常,1:保存成功
 */
 public int saveFile(String path,byte[] fileData,boolean overrite)
 {
  try
  {
   FileConnection fc=(FileConnection)(Connector.open(path));
   if(fc.exists())
   {
    if(overrite)
    {
     fc.create();
     fc.setWritable(true);
     OutputStream os=fc.openOutputStream();
     os.write(fileData);
     os.close();  
     return 1;   
    }
    else
    return -1;
   }
   else
   {
    fc.create();
    fc.setWritable(true);
    OutputStream os=fc.openOutputStream();
    os.write(fileData);
    os.close();
    return 1;
   }
  }
  catch(Exception e)
  {
   System.out.println("saveFileErr:"+e.toString());
   return 0;
  }
 } 
 /*删除文件*/
 public void deleteFile(String path)
 {
  try
  {
   FileConnection fc=(FileConnection)(Connector.open(path));
   if(fc.exists())
   fc.delete();
  }
  catch(Exception e)
  {
   System.out.println("deleteFileErr:"+e.toString());
  }
 }
 
 /**获取目录文件列表
 * @path:路径
 * @type:列表类型(0:文件夹和文件都列;1:只列文件夹;2:只列文件)
 * @return:指定路径下的目录和文件的名称列表
 */
 public Vector getList(String path,int type)
 {
  try
  {
   Enumeration en=null;
   Vector listVec=new Vector(0,1);
   if(path.equals("root"))
   { 
    en=FileSystemRegistry.listRoots();
   }
   else
   {
     FileConnection fc=(FileConnection)(Connector.open(path));
     if(fc.exists())
    en=fc.list();
   }
   if(en!=null)
   {
    while(en.hasMoreElements())
    {
     String name=(String)(en.nextElement());
     switch(type)
     {
      case 0:
      listVec.addElement(name);
      break;
      case 1:
      if(name.indexOf("/")!=-1)
      listVec.addElement(name);
      break;
      case 2:
      if(name.indexOf("/")==-1)
      listVec.addElement(name);
      break;      
     }
    }
    return listVec;
   }
   else
   {
    System.out.println("pathErr");
    return null;
   }
  }
  catch(Exception e)
  {
   System.out.println("listErr:"+e.toString());   message=e.toString();
   return null;   
  }
 }
 /*图片文件列表*/
 public Vector getImageList()
 {
  Vector list=getList("file:///"+imageFilePath,0);
  return list;
 }
 /*声音文件列表*/
 public Vector getSoundList()
 {
  Vector list=getList("file:///"+soundFilePath,0);
  return list;
 }
 /*读取文件
 $path:文件路径
 $showProgress:是否显示读取进度,注意,如果选择显示进度会导致读取文件速度变慢
  $return:如果成功获取到文件则返回存储文件数据的数组,否则返回null
  */
 public byte[] readFile(String path,boolean showProgress)
 {
  try
  {
   FileConnection fc=(FileConnection)(Connector.open(path));
   if(fc.exists())
   {
    message="文件存在";
    InputStream is=fc.openInputStream();
    fileSize=is.available();
    byte[] temp=new byte[fileSize];
    /*如果需要显示进度*/
    if(showProgress)
    {
     int ch;
     int i=0;
     int step=fileSize/100;
     currentProgress=0;
     while((ch=is.read())!=-1)
     {
      temp[i++]=(byte)ch;
      if(i%step==0)
      currentProgress++;
     }
    }
    else
    is.read(temp);
    is.close();
    return temp;
   }
   else
   return null;
  }
  catch(Exception e)
  {
   System.out.println("readFileErr:"+path+e.toString());
   message=e.toString();
   return null;
  }
 }
 /**获取手机中的联系人信息
 * @return:包含联系人姓名和电话的Vector
 */
 public Vector readPIM()
 {
  try
  {
   Vector pim=new Vector(0,1);
   ContactList cl=(ContactList)(PIM.getInstance().openPIMList(PIM.CONTACT_LIST,PIM.READ_ONLY));
   Enumeration en=cl.items();
   Vector c=new Vector(0,1);
   while(en.hasMoreElements())
   {
    c.addElement((Contact)(en.nextElement()));
   }
   System.out.println(c.size());
   for(int i=0;i<c.size();i++)
   {
    Contact temp=(Contact)(c.elementAt(i));
    if(cl.isSupportedField(Contact.TEL))
    {
     String name="",phone="";
     if(cl.isSupportedField(Contact.FORMATTED_NAME))
     {
      for(int m=0;m<temp.countValues(Contact.FORMATTED_NAME);m++)
      name+="&"+temp.getString(Contact.FORMATTED_NAME,m);
     }
     name+="&";
     for(int m=0;m<temp.countValues(Contact.TEL);m++)
     phone+="&"+temp.getString(Contact.TEL,m);
     phone+="&";
      pim.addElement(new String[]{name,phone});
    }
       //pim.addElement((String)(temp.getString(Contact.FORMATTED_NAME,m)));
       //System.out.println(temp.getString(Contact.TEL,m));
//     message="数量:"+c.size()+
//     (cl.isSupportedField(Contact.NAME)?"Name:"+temp.countValues(Contact.NAME):"")
//     +(cl.isSupportedField(Contact.ADDR)?"addr:"+temp.countValues(Contact.ADDR):"")
//     +(cl.isSupportedField(Contact.EMAIL)?"Email:"+temp.countValues(Contact.EMAIL):"")
//     +(cl.isSupportedField(Contact.FORMATTED_NAME)?"FORMATTED_NAME:"+temp.countValues(Contact.FORMATTED_NAME):"")
//     +(cl.isSupportedField(Contact.NICKNAME)?"NICKNAME:"+temp.countValues(Contact.NICKNAME):"")
//     +(cl.isSupportedField(Contact.TEL)?"TEL:"+temp.countValues(Contact.TEL):"")
//     +(cl.isSupportedField(Contact.TITLE)?"Title:"+temp.countValues(Contact.TITLE):"");
   }
   return pim;
  }
  catch(Exception e)
  {
   System.out.println(e);
   message="读取PIM失败:"+e.toString();
   return null;
  }
 }
}

- 作者: 刀剑啸 2006年12月13日, 星期三 14:02  回复(1) |  引用(0) 加入博采

MD5算法J2me版本

是在猴哥和阿土的帮助下得到的,直接贴代码,原版只有一个入口是字符串入口,在实际使用中,此入口在计算文件的MD5时会有问题,所以我加了一个byte[]入口。

/*手机博客客户端.MD5码计算
开发:李果
开发开始日期:2006年5月8日
*/
public class MD5 {

    /* 下面这些S11-S44实际上是一个4*4的矩阵,在原始的C实现中是用#define 实现的,这里把它们

    /* 实现成为static final是表示了只读,切能在同一个进程空间内的多个Instance间共享*/

    static final int S11 = 7;

    static final int S12 = 12;

    static final int S13 = 17;

    static final int S14 = 22;


    static final int S21 = 5;

    static final int S2 = 9;

    static final int S23 = 14;

    static final int S24 = 20;


    static final int S31 = 4;

    static final int S32 = 11;

    static final int S33 = 16;

    static final int S34 = 23;


    static final int S41 = 6;

    static final int S42 = 10;

    static final int S43 = 15;

    static final int S44 = 21;

    static final byte[] PADDING = {-128, 0, 0, 0, 0, 0, 0, 0, 0,

                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

    /* 下面的三个成员是MD5计算过程中用到的3个核心数据,在原始的C实现中 */

    /*   被定义到MD5_CTX结构中 */

    private long[] state = new long[4];  // state (ABCD)

    private long[] count = new long[2];  // number of bits, modulo 2^64 (lsb first)

    private byte[] buffer = new byte[64]; // input buffer

    /* digestHexStr是MD5的唯一一个公共成员,是最新一次计算结果的16进制ASCII表示. */

    public String digestHexStr;

    /* digest,是最新一次计算结果的2进制内部表示,表示128bit的MD5值. */

    private byte[] digest = new byte[16];

    /*  getMD5ofStr是类MD5最主要的公共方法,入口参数是你想要进行MD5变换的字符串 */

    /*  返回的是变换完的结果,这个结果是从公共成员digestHexStr取得的.*/

    public String getMD5ofStr(String inbuf) {

        md5Init();

        md5Update(inbuf.getBytes(), inbuf.length());

        md5Final();

        digestHexStr = "";

        for (int i = 0; i < 16; i++) {
            digestHexStr += byteHEX(digest[i]);
        }

        return digestHexStr;
    }
   
    public String getMD5ofStr(byte[] inbuf)
    {

        md5Init();

        md5Update(inbuf, inbuf.length);

        md5Final();

        digestHexStr = "";

        for (int i = 0; i < 16; i++) {
            digestHexStr += byteHEX(digest[i]);
        }

        return digestHexStr;
    }     

    /* 这是MD5这个类的标准构造函数,JavaBean要求有一个public的并且没有参数的构造函数. */

    public MD5() {
        md5Init();
    }

    /* md5Init是一个初始化函数,初始化核心变量,装入标准的幻数 */
    private void md5Init() {

        count[0] = 0L;

        count[1] = 0L;

        ///* Load magic initialization constants.

        state[0] = 0x67452301L;

        state[1] = 0xefcdab89L;

        state[2] = 0x98badcfeL;

        state[3] = 0x10325476L;

        return;

    }

    /* F, G, H ,I 是4个基本的MD5函数,在原始的MD5的C实现中,由于它们是 */

    /* 简单的位运算,可能出于效率的考虑把它们实现成了宏,在java中,*/

    /* 我把它们实现成了private方法,名字保持了原来C中的。 */
    private long F(long x, long y, long z) {
        return (x & y) | ((~x) & z);
    }


    private long G(long x, long y, long z) {
        return (x & z) | (y & (~z));
    }


    private long H(long x, long y, long z) {
        return x ^ y ^ z;
    }


    private long I(long x, long y, long z) {
        return y ^ (x | (~z));
    }

    /* FF,GG,HH和II将调用F,G,H,I进行近一步变换 FF, GG, HH, and II transformations */

    /* for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */
    private long FF(long a, long b, long c, long d, long x, long s, long ac) {

        a += F(b, c, d) + x + ac;

        a = ((int) a << s) | ((int) a >>> (32 - s));

        a += b;

        return a;
    }


    private long GG(long a, long b, long c, long d, long x, long s, long ac) {

        a += G(b, c, d) + x + ac;

        a = ((int) a << s) | ((int) a >>> (32 - s));

        a += b;

        return a;
    }


    private long HH(long a, long b, long c, long d, long x, long s, long ac) {

        a += H(b, c, d) + x + ac;

        a = ((int) a << s) | ((int) a >>> (32 - s));

        a += b;

        return a;
    }


    private long II(long a, long b, long c, long d, long x, long s, long ac) {

        a += I(b, c, d) + x + ac;

        a = ((int) a << s) | ((int) a >>> (32 - s));

        a += b;

        return a;
    }

    /* md5Update是MD5的主计算过程,inbuf是要变换的字节串,inputlen是长度,这个 */

    /* 函数由getMD5ofStr调用,调用之前需要调用md5init,因此把它设计成private */
    private void md5Update(byte[] inbuf, int inputLen) {

        int i, index, partLen;

        byte[] block = new byte[64];

      &nbs; index = (int) (count[0] >>> 3) & 0x3F;

        // /* Update number of bits */

        if ((count[0] += (inputLen << 3)) < (inputLen << 3))

            count[1]++;

        count[1] += (inputLen >>> 29);

        partLen = 64 - index;

        // Transform as many times as possible.

        if (inputLen >= partLen) {

            md5Memcpy(buffer, inbuf, index, 0, partLen);

            md5Transform(buffer);

            for (i = partLen; i + 63 < inputLen; i += 64) {

                md5Memcpy(block, inbuf, 0, i, 64);

                md5Transform(block);

            }

            index = 0;

        } else

            i = 0;

        ///* Buffer remaining input */

        md5Memcpy(buffer, inbuf, index, i, inputLen - i);

    }


    /* md5Final整理和填写输出结果 */
    private void md5Final() {

        byte[] bits = new byte[8];

        int index, padLen;

        ///* Save number of bits */

        Encode(bits, count, 8);

        ///* Pad out to 56 mod 64.

        index = (int) (count[0] >>> 3) & 0x3f;

        padLen = (index < 56) ? (56 - index) : (120 - index);

        md5Update(PADDING, padLen);

        ///* Append length (before padding) */

        md5Update(bits, 8);

        ///* Store state in digest */

        Encode(digest, state, 16);

    }


    /* md5Memcpy是一个内部使用的byte数组的块拷贝函数,从input的inpos开始把 */

    /* len长度的字节拷贝到output的outpos位置开始. */
    private void md5Memcpy(byte[] output, byte[] input, int outpos, int inpos, int len) {
        int i;

        for (i = 0; i < len; i++)
            output[outpos + i] = input[inpos + i];
    }


    /* md5Transform是MD5核心变换程序,有md5Update调用,block是分块的原始字节. */
    private void md5Transform(byte block[]) {
        long a = state[0], b = state[1], c = state[2], d = state[3];

        long[] x = new long[16];


        Decode(x, block, 64);

        /* Round 1 */

        a = FF(a, b, c, d, x[0], S11, 0xd76aa478L); /* 1 */

        d = FF(d, a, b, c, x[1], S12, 0xe8c7b756L); /* 2 */

        c = FF(c, d, a, b, x[2], S13, 0x242070dbL); /* 3 */

        b = FF(b, c, d, a, x[3], S14, 0xc1bdceeeL); /* 4 */

        a = FF(a, b, c, d, x[4], S11, 0xf57c0fafL); /* 5 */

        d = FF(d, a, b, c, x[5], S12, 0x4787c62aL); /* 6 */

        c = FF(c, d, a, b, x[6], S13, 0xa8304613L); /* 7 */

        b = FF(b, c, d, a, x[7], S14, 0xfd469501L); /* 8 */

        a = FF(a, b, c, d, x[8], S11, 0x698098d8L); /* 9 */

        d = FF(d, a, b, c, x[9], S12, 0x8b44f7afL); /* 10 */

        c = FF(c, d, a, b, x[10], S13, 0xffff5bb1L); /* 11 */

        b = FF(b, c, d, a, x[11], S14, 0x895cd7beL); /* 12 */

        a = FF(a, b, c, d, x[12], S11, 0x6b901122L); /* 13 */

        d = FF(d, a, b, c, x[13], S12, 0xfd987193L); /* 14 */

        c = FF(c, d, a, b, x[14], S13, 0xa679438eL); /* 15 */

        b = FF(b, c, d, a, x[15], S14, 0x49b40821L); /* 16 */

        /* Round 2 */

        a = GG(a, b, c, d, x[1], S21, 0xf61e2562L); /* 17 */

        d = GG(d, a, b, c, x[6], S22, 0xc040b340L); /* 18 */

        c = GG(c, d, a, b, x[11], S23, 0x265e5a51L); /* 19 */

        b = GG(b, c, d, a, x[0], S24, 0xe9b6c7aaL); /* 20 */

        a = GG(a, b, c, d, x[5], S21, 0xd62f105dL); /* 21 */

        d = GG(d, a, b, c, x[10], S22, 0x2441453L); /* 22 */

        c = GG(c, d, a, b, x[15], S23, 0xd8a1e681L); /* 23 */

        b = GG(b, c, d, a, x[4], S24, 0xe7d3fbc8L); /* 24 */

        a = GG(a, b, c, d, x[9], S21, 0x21e1cde6L); /* 25 */

        d = GG(d, a, b, c, x[14], S22, 0xc33707d6L); /* 26 */

        c = GG(c, d, a, b, x[3], S23, 0xf4d50d87L); /* 27 */

        b = GG(b, c, d, a, x[8], S24, 0x455a14edL); /* 28 */

        a = GG(a, b, c, d, x[13], S21, 0xa9e3e905L); /* 29 */

        d = GG(d, a, b, c, x[2], S22, 0xfcefa3f8L); /* 30 */

        c = GG(c, d, a, b, x[7], S23, 0x676f02d9L); /* 31 */

        b = GG(b, c, d, a, x[12], S24, 0x8d2a4c8aL); /* 32 */

        /* Round 3 */

        a = HH(a, b, c, d, x[5], S31, 0xfffa3942L); /* 33 */

        d = HH(d, a, b, c, x[8], S32, 0x8771f681L); /* 34 */

        c = HH(c, d, a, b, x[11], S33, 0x6d9d6122L); /* 35 */

        b = HH(b, c, d, a, x[14], S34, 0xfde5380cL); /* 36 */

        a = HH(a, b, c, d, x[1], S31, 0xa4beea44L); /* 37 */

        d = HH(d, a, b, c, x[4], S32, 0x4bdecfa9L); /* 38 */

        c = HH(c, d, a, b, x[7], S33, 0xf6bb4b60L); /* 39 */

        b = HH(b, c, d, a, x[10], S34, 0xbebfbc70L); /* 40 */

        a = HH(a, b, c, d x[13], S31, 0x289b7ec6L); /* 41 */

        d = HH(d, a, b, c, x[0], S32, 0xeaa127faL); /* 42 */

        c = HH(c, d, a, b, x[3], S33, 0xd4ef3085L); /* 43 */

        b = HH(b, c, d, a, x[6], S34, 0x4881d05L); /* 44 */

        a = HH(a, b, c, d, x[9], S31, 0xd9d4d039L); /* 45 */

        d = HH(d, a, b, c, x[12], S32, 0xe6db99e5L); /* 46 */

        c = HH(c, d, a, b, x[15], S33, 0x1fa27cf8L); /* 47 */

        b = HH(b, c, d, a, x[2], S34, 0xc4ac5665L); /* 48 */

        /* Round 4 */

        a = II(a, b, c, d, x[0], S41, 0xf4292244L); /* 49 */

        d = II(d, a, b, c, x[7], S42, 0x432aff97L); /* 50 */

        c = II(c, d, a, b, x[14], S43, 0xab9423a7L); /* 51 */

        b = II(b, c, d, a, x[5], S44, 0xfc93a039L); /* 52 */

        a = II(a, b, c, d, x[12], S41, 0x655b59c3L); /* 53 */

        d = II(d, a, b, c, x[3], S42, 0x8f0ccc92L); /* 54 */

        c = II(c, d, a, b, x[10], S43, 0xffeff47dL); /* 55 */

        b = II(b, c, d, a, x[1], S44, 0x85845dd1L); /* 56 */

        a = II(a, b, c, d, x[8], S41, 0x6fa87e4fL); /* 57 */

        d = II(d, a, b, c, x[15], S42, 0xfe2ce6e0L); /* 58 */

        c = II(c, d, a, b, x[6], S43, 0xa3014314L); /* 59 */

        b = II(b, c, d, a, x[13], S44, 0x4e0811a1L); /* 60 */

        a = II(a, b, c, d, x[4], S41, 0xf7537e82L); /* 61 */

        d = II(d, a, b, c, x[11], S42, 0xbd3af235L); /* 62 */

        c = II(c, d, a, b, x[2], S43, 0x2ad7d2bbL); /* 63 */

        b = II(b, c, d, a, x[9], S44, 0xeb86d391L); /* 64 */


        state[0] += a;

        state[1] += b;

        state[2] += c;

        state[3] += d;

    }

    /* Encode把long数组按顺序拆成byte数组,因为java的long类型是64bit的,*/

    /* 只拆低32bit,以适应原始C实现的用途. */
    private void Encode(byte[] output, long[] input, int len) {

        int i, j;

        for (i = 0, j = 0; j < len; i++, j += 4) {

            output[j] = (byte) (input[i] & 0xffL);

            output[j + 1] = (byte) ((input[i] >>> 8) & 0xffL);

            output[j + 2] = (byte) ((input[i] >>> 16) & 0xffL);

            output[j + 3] = (byte) ((input[i] >>> 24) & 0xffL);

        }

    }

    /* Decode把byte数组按顺序合成成long数组,因为java的long类型是64bit的,*/

    /* 只合成低32bit,高32bit清零,以适应原始C实现的用途. */
    private void Decode(long[] output, byte[] input, int len) {

        int i, j;

        for (i = 0, j = 0; j < len; i++, j += 4)

            output[i] = b2iu(input[j]) |

                    (b2iu(input[j + 1]) << 8) |

                    (b2iu(input[j + 2]) << 16) |

                    (b2iu(input[j + 3]) << 24);

        return;

    }

    /* b2iu是一个把byte按照不考虑正负号的原则的"升位"程序,因为java没有unsigned运算 */
    public static long b2iu(byte b) {

        return b < 0 ? b & 0x7F + 128 : b;

    }

    /* byteHEX(),用来把一个byte类型的数转换成十六进制的ASCII表示,*/

    /* 因为java中的byte的toString无法实现这一点,我们又没有C语言中的sprintf(outbuf,"%02X",ib). */
    public static String byteHEX(byte ib) {

        /* if want to output normal letter please user DigitNormal */

        char[] DigitNormal = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',

                              'a', 'b', 'c', 'd', 'e', 'f'};

        /* if want to output capitalization letter please user DigitCap */

        /* char[] DigitCap = { '0','1','2','3','4','5','6','7','8','9',

        'A','B','C','D','E','F' }; */

        char[] ob = new char[2];

        ob[0] = DigitNormal[(ib >>> 4) & 0X0F];

        /* ob[0] = DigitCap[(ib >>> 4) & 0X0F]; */

        ob[1] = DigitNormal[ib & 0X0F];

        /* ob[1] = DigitCap[ib & 0X0F]; */

        String s = new String(ob);

        return s;
    }


    public byte[] getMD5(byte[] data1 , byte[] data2) {
        md5Init();

        md5Update(data1, data1.length);

        md5Update(data2, data2.length);

//        md5Update(Request.key , Request.key.length);

        md5Final();

        return digest;
    }

}


- 作者: 刀剑啸 2006年08月29日, 星期二 13:22  回复(2) |  引用(0) 加入博采

J2me中实现图片缩放

不多说了,直接贴代码

 /*图像变换*/
 public Image scaleImage(Image src,int scales1,int scales2)
 {
  return transImage(src,src.getWidth()*scales1/scales2,src.getHeight()*scales1/scales2);
 }
 public Image transImage(Image src, int w, int h)
 {
    int srcW = src.getWidth();
    int srcH = src.getHeight();
    int dstW=w,dstH=h;
    Image tmp = Image.createImage(dstW, srcH);
    Graphics g = tmp.getGraphics();
    int scale=16;   
  int delta = (srcW << scale) / dstW;//扫描长度
    int pos = delta / 2;//扫描位置
    for (int x = 0; x < dstW; x++)
    {
      g.setClip(x, 0, 1, srcH);
      g.drawImage(src, x - (pos >> scale), 0, Graphics.LEFT | Graphics.TOP);
      pos += delta;
    }
    Image dst = Image.createImage( dstW, dstH);
    g = dst.getGraphics();
    delta = (srcH << scale) / dstH;
    pos = delta / 2;
    for (int y = 0; y < dstH; y++)
    {
      g.setClip(0,y, dstW, 1);
      g.drawImage(tmp, 0, y - (pos >> scale), Graphics.LEFT | Graphics.TOP);
      pos += delta;
    }
    return dst;
 } 

用法举例:

1.将一张图片pic转换成176*208的图

pic=transImage(pic,176,208);

2.将一张图片pic转换成原来的两倍大

pic=scaleImage(pic,2,1);

3.将一张图片pic转换成原来的三分之二

pic=scaleImage(pic,2,3);

从上面的例子,大家应该知道怎么用了吧,呵呵

- 作者: 刀剑啸 2006年07月21日, 星期五 17:37  回复(6) |  引用(0) 加入博采

Jsr75学习笔记(一)

这段时间因为开发上要用到本地文件,因此开始接触Jsr75的包,Jsr75分两个部分,一部分是File,即本地文件系统,一部分是PIM,说白了就是电话本之类的信息,我先学习的是File部分,通过import javax.microedition.io.file.*里的包,可以实现自由访问本机的文件系统,就跟Windos里的资源管理器一样,在这里我介绍几个我写的方法

一.获取指定路径的目录和文件列表

 /*目录文件列表*/
 public Vector list(String path)
 {
  try
  {
   FileConnection fc=(FileConnection)(Connector.open(path));
   if(fc.exists())
   {
    Vector listVec=new Vector(0,1);
    Enumeration en=fc.list();
    while(en.hasMoreElements())
    {
     listVec.addElement((String)(en.nextElement()));
    }
    return listVec;
   }
   else
   return null;
  }
  catch(Exception e)
  {
   System.out.println("listErr:"+e.toString());
   return null;   
  }
 }

方法里的path参数就是要查找的路径,比如file:///c:/pictures/,切记,如果是目录Path,那么后面的/一定不能省,否则会查找不到内容。这个方法返回的是一个包含了指定Path下的所有目录名和文件名的向量。

二.建立或者保存一个文件到指定路径

 /*保存文件*/
 public void saveFile(String path,byte[] fileData)
 {
  try
  {
   FileConnection fc=(FileConnection)(Connector.open(path));
   fc.create();
   fc.setWritable(true);
   OutputStream os=fc.openOutputStream();
   os.write(fileData);
   os.close();
  }
  catch(Exception e)
  {
   System.out.println("saveFileErr:"+e.toString());
  }
 } 

fileData是需要保存的文件内容,可以是声音,也可以是图像,或者文字之类

三.删除指定文件

 /*删除文件*/
 public void deleteFile(String path)
 {
  try
  {
   FileConnection fc=(FileConnection)(Connector.open(path));
   if(fc.exists())
   fc.delete();
  }
  catch(Exception e)
  {
   System.out.println("deleteFileErr:"+e.toString());
  }
 }

这个方法就不用多解释了

四.读取指定文件

 /*读取文件*/
 public byte[] readFile(String path)
 {
  try
  {
   FileConnection fc=(FileConnection)(Connector.open(path));
   if(fc.exists())
   {
    InputStream is=fc.openInputStream();
    byte[] temp=new byte[is.available()];
    is.read(temp);
    is.close();
    return temp;
   }
   else
   return null;
  }
  catch(Exception e)
  {
   System.out.println("readFileErr:"+path+e.toString());
   return null;
  }
 }

此方法也不用多解释了。

以上是关于文件操作的最基本的一些功能,也是第一期的学习笔记研究到的内容,更多的内容,过几天继续研究继续写吧,呵呵。

- 作者: 刀剑啸 2006年07月21日, 星期五 12:24  回复(2) |  引用(0) 加入博采

摩托手机上的音效开发问题
有不少朋友问我为什么摩托的手机在音效方面会有问题,典型的表现是声音在模拟器上打开和关闭不会有问题,但在真机上就会出现关闭声音后无法再开启的问题,其原因很大可能是大家在关闭音效的时候只是调用了stop(),却没有调用deallocate()方法,摩托和NOKIA在这一点不同,NOKIA是不能用Deallocate,MOTO却是必须调用,否则下次打开声音会发生问题。

- 作者: 刀剑啸 2006年07月19日, 星期三 17:17  回复(0) |  引用(0) 加入博采

做应用,惬意的日子
      不知不觉,从游戏转到应用上已经快三个月了,这三个月来的工作,只能用一个词--惬意来形容,再也不用像过去那样成天担心移动的评审,上线,成天面对公司的催活,一个月出N个游戏了,现在一个项目要做好几个月,每一行代码都是自己的心血,都带着一种浓浓的成就感,而不像过去那样写来写去都是换皮之作,没有多少东西是属于自己的。这样的工作,才让人有进取心,有动力去写。

- 作者: 刀剑啸 2006年06月26日, 星期一 10:35  回复(3) |  引用(0) 加入博采

踢球,不能这么无耻

    昨天晚上的兰牙大战,赛前本来还期待是一场比较精彩的比赛,毕竟这是开赛以来第一次种子队在淘汰赛里对决,结果,96分钟下来,上演的是一场裁判的个人秀和火药味十足的群殴。不过这对于我们这些熬夜看球的真球迷或者伪球迷来说,倒也是一场“经典”的比赛。

    整场比赛从C罗被荷兰狂踹下场,荷兰球员却只领到一张黄牌开始就步入了野蛮,可以说这是裁判最大的失误,由此开始,裁判已经控制不住场上的局势,之后葡萄牙的6号积极申请红牌,菲哥一怒之下染黄,荷兰人肘击菲哥吃红,荷兰人在葡萄牙队员疗伤回场后不把球开回葡萄牙,被愤怒的
Deco狂铲倒地,双方各吃一黄,再以后。。。剪刀腿,铁头功,满天飞的黄红牌把这场比赛演变成了一场黑社会火拼大戏,但相对而言,荷兰人更为无耻,尤其是某队员在射门结束后并不收腿,硬生生踹在里卡多身上还装作啥事没有的镜头,让BBS全版愤怒了,声讨之文充斥版面,荷兰踢球之脏,从小组赛里跟大象对决开始就表现得越发的嚣张,那一场比赛里有裁判的偏袒,使荷兰人越发的不可收拾,有个网友说得好,荷兰人要技术没技术,要力量没力量,于是只有靠犯规了,这么肮脏的踢法,最终还是没有扭转他们被葡萄牙淘汰的命运,真是可叹,巴斯腾也该好好反省一下了。

- 作者: 刀剑啸 2006年06月26日, 星期一 10:28  回复(0) |  引用(0) 加入博采

莫名的郁闷
这两天心情不知道怎么回事,莫名的感到不爽,总感觉有什么东西压在心上,却又捉摸不清.按说刚换了工作,一切是个新的开始,应该会意气风发,但我却觉得自己的心里有一种很沧桑的滋味在涌动,为什么这么累呢,从早到晚都在听着伤感的歌,脑子里跟灌了铅似的,无法思考任何东西.

- 作者: 刀剑啸 2006年05月18日, 星期四 18:04  回复(0) |  引用(0) 加入博采

人生这么多曲折啊

     辞职两个周了,下星期该去新公司上班了,这两星期一直在家玩儿,也算是放松一下自己的心情,结果今天突然听风过说Move2008出事了,我一听头就大了,因为我一直很支持他们,对狼狼(亚俊兄)也是一直很佩服和支持的一个人,没想到这事是因他而起。当然,事情的真相以及内幕,我做为一个局外人,是无从得知的,只是从他的博客的文章还有别人的评议中能知道知言片语,看到这么多人攻击狼狼,我也很难受,人最郁闷的事情就是在自己辛苦拼搏的过程中却出现这么多不和谐甚至是让人悲伤的坎坷,很多事情确实不是自己所期望的,也不是自己意料得到的,一件不经意的小事,也许会酿成很大的风波。

     再联想到自己,虽然暂时还没有出现到类似的事情,但不能保证不会有这么一天也成为众矢之的,不过担心又有什么用呢,唯一可行的就是不断的修行,提高自己,不光是做事,也有做人,虽然人生是曲折的,但努力把这些曲折尽量减少便是一种成功吧。

- 作者: 刀剑啸 2006年04月16日, 星期日 13:50  回复(0) |  引用(0) 加入博采

2.0里半透明效果的实现

2.0提供了对Image更多的信息的操作,因此可以方便的实现半透明的效果,这里就给出一个创建半透明图的方法

 /*得到指定透明度的一张图的透明图*/
 public Image createARGBImage(Image src,int Alpha)
 {
  int[] rgb=new int[src.getWidth()*src.getHeight()];
  menuBg.getRGB(rgb,0,src.getWidth(),0,0,src.getWidth(),src.getHeight());
  for(int i=0;i  rgb[i]+=Alpha;
  return(Image.createRGBImage(rgb,src.getWidth(),src.getHeight(),true));  
 }

用这个方法可以方便的得到一张指定透明度的图,但相应的,这样得到的带透明度的图所占用的内存大概是直接创建一张普通图片的内存的2倍。

- 作者: 刀剑啸 2006年03月24日, 星期五 14:25  回复(0) |  引用(0) 加入博采

1。0里用标准API做图片翻转

在游戏中经常要用到一些图片翻转的效果,在1。0里可以用NOKIA的API,或者用2。0的标准API,但由于用2。0的API经常会被移动打回来,所以我写了一个1。0的标准Api实现图片翻转的方法,如下:

 /*图片翻转效果*/
 public void drawTransImage(Graphics g1,Image image,int x,int y,int type)
 {
  if(type==0)//左右翻转
  {
   for(int i=0;i   drawClipImage(g1,image,x+i,y,1,image.getHeight(),image.getWidth()-i,0);
  }
  else
  {
   for(int i=0;i   drawClipImage(g1,image,x,y+i,image.getWidth(),1,0,image.getHeight()-i);
  }
 }

 /*画小图*/
 public void drawClipImage(Graphics g,Image a,int clipx,int clipy,int clipw,int cliph,int offx,int offy)
 {
  int x,y,w,h;
  x=g.getClipX();
  y=g.getClipY();
  w=g.getClipWidth();
  h=g.getClipHeight();
  g.setClip(clipx,clipy,clipw,cliph);
  g.drawImage(a,clipx-offx,clipy-offy,0);
  g.setClip(x,y,w,h);
 } 

- 作者: 刀剑啸 2005年12月5日, 星期一 16:19  回复(1) |  引用(0) 加入博采

程序有时候莫名变快的原因
这些天有不少朋友问到我同一个Bug,就是游戏中经常会出现线程变快的情况,比如在游戏界面中退出到菜单再点击“继续游戏”后进入到游戏界面后,整个画面都变快了,其这个问题很简单,都是TimerTask惹的祸。不少人喜欢用TimerTask来做为线程实现方式,而一般在点击开始游戏或者继续游戏时都执行了线程的启动方法,其直接结果就是让同一个TimerTask对象被启动了多次,而他们都执行着同样的任务,这就使得整个游戏界面都变快了,解决的办法也很简单,方法一,在退出到主菜单的时候都调用一下该TimerTask的Cancel方法,方法二,退出到主菜单的时候让该线程空跑(即让该线程的Run方法不执行任何操作),而在点击开始游戏或继续游戏时要判断该线程是不是处于Cancel状态,如果不是,就不再启动该线程,这样一般就能够解决这个问题了。:)

- 作者: 刀剑啸 2005年12月4日, 星期日 21:08  回复(0) |  引用(0) 加入博采

寒秋

春花如梦去,

秋月踏云来,

把酒愁销尽,

独醉难释怀,

长袖何处舞,

短歌且当哭,

拔剑心戚戚,

千杯无人扶。

悲己空寂寞,

油尽灯欲枯,

聚时不知味,

散时方忆福

- 作者: 刀剑啸 2005年11月20日, 星期日 21:32  回复(2) |  引用(0) 加入博采

怒风

风舞九天叶飘零,

长夜当歌醉独行,

赤足未觉泥中刺,

醒时已是血淋淋。

怒时长剑啸向天,

狂沙乱草改容颜,

路人冷笑摇手去,

力尽衰倒大道边

- 作者: 刀剑啸 2005年11月16日, 星期三 15:42  回复(0) |  引用(0) 加入博采

凸多边形填充的算法补充

这个算法比先前的算法效率提高了10倍

import java.lang.*;
import javax.microedition.lcdui.*;
import java.util.*;
import javax.microedition.rms.*;
import java.io.*;
class MainPit extends Canvas implements Runnable
{
 
Graphics gb;
Image bufImg;

private int nWidth = getWidth();
private int nHeight = getHeight();
int[] x;
int[] y;
int[] id;
int top,bottom;
public MainPit()
{
try{
bufImg = Image.createImage(nWidth,nHeight);
}catch(Exception e){System.out.println(e+" createImage");}
gb = bufImg.getGraphics();
}


public void paint(Graphics g)
{
g.drawImage(bufImg,0,0,0);
}

int nodes[][] = {//8/
{20,100},//0
{100,40},//1
{150,80},//2
{60,50},
//{150,110},//3
{150,150},//4
//{160,150},//5
//{110,110},//6
{50,130},//7
{160,140},
{60,139},
{110,45}
};
public void sort(int nodes[][])
{
 int i=nodes.length;
 int temp1=0;
 int temp2=0;
 for(int m=0;m for(int n=0;n {
  if(nodes[n][0]>nodes[n+1][0]||(nodes[n][0]==nodes[n+1][0]&&nodes[n][1]>nodes[n+1][1]))
  {
   temp1=nodes[n][0];
   temp2=nodes[n][1];
   nodes[n][0]=nodes[n+1][0];
   nodes[n][1]=nodes[n+1][1];
   nodes[n+1][0]=temp1;
   nodes[n+1][1]=temp2;
  }
 }
}
public void sortTang(int nodes[][])
{
 id=new int[nodes.length-1];
 int[] high=new int[id.length];
 int[] low=new int[id.length];
 for(int i=0;i {
  id[i]=-1;//序号数组
  high[i]=-1;
  low[i]=-1;
 }
 int Htag,Ltag;
 Htag=0;
 Ltag=0;
 for(int i=1;i {
  if(nodes[i][1]<=nodes[0][1])
  high[Htag++]=i;
  else
  low[Ltag++]=i;
 }
 for(int i=0;i {
  if(high[i]>0)
  id[i]=high[i];
  else
  id[i]=low[Ltag-1-i+Htag];
 }
 top=0;
 bottom=id.length-1;
}
/*判断点x2,y2是不是在指定的线段上*/
public boolean cut(int x0,int y0,int x1,int y1,int x2,int y2)
{
 if(((y1-y0)*(x2-x0)<=(y2-y0)*(x1-x0))&&((y1-y0)*(x2-x0)>=(y2-1-y0)*(x1-x0)))
 return true;
 else
 return false;
}
public int findNextPoint(int[][] nodes,int a,boolean s)
{
 if(a==nodes.length-3)
 return a+2;
 else
 {    if(id[top]==a+1)
    {
     top++;
     return id[bottom];
    }
    else
    {
     bottom--;
     return id[top];
    }
 }
}
public void fillPolygon(int nodes[][])
{
 gb.setColor(0xff0000);
 int tempy1=nodes[0][1];
 int tempy2=0;
 int nextP=0;
 int p1=0;
 int p2=0;
 int p3=0;
 int p4=0;
 int scanp1=-1;
 int scanp2=-1;
 for(int i=0;i {
  nextP=0;
  if(nodes[i][0]  {
   if(tempy1!=nodes[i][1])
   nextP=findNextPoint(nodes,i,tempy1>=nodes[i][1]?true:false);
   else
   if((nodes[i+1][1]-nodes[i][1])*(nodes[i+2][0]-nodes[i][0])<(nodes[i+2][1]-nodes[i][1])*(nodes[i+1][0]-nodes[i][0]))
   nextP=findNextPoint(nodes,i,true);
   else
   nextP=findNextPoint(nodes,i,false);
   if((nodes[i+1][1]-nodes[nextP][1])*(nodes[i][1]-tempy1)>=0)
   p3=tempy1;
   else
   p3=nodes[i][1];
   for(int j=0;j   {
    if(cut(nodes[i][0],p3,nodes[nextP][0],nodes[nextP][1],nodes[i+1][0],j))
    {
     tempy2=j;
     break;
    }
   }
   p1=nodes[i][1]>tempy1?tempy1:nodes[i][1];
   p2=p1!=tempy1?tempy1:nodes[i][1];
   p3=nodes[i+1][1]>tempy2?tempy2:nodes[i+1][1];
   p4=p3!=tempy2?tempy2:nodes[i+1][1];
   scanp1=p1;
   scanp2=p2;
   for(int j=nodes[i][0];j<=nodes[i+1][0];j++)
   {
    for(int m=scanp1>p3?p3:scanp1;m<=(scanp1>p3?scanp1:p3);m++)
    {
     if(cut(nodes[i][0],p1,nodes[i+1][0],p3,j,m))
     {
      scanp1=m;
      break;
     }
    }
    for(int m=scanp2>p4?p4:scanp2;m<=(scanp2>p4?scanp2:p4);m++)
    {
     if(cut(nodes[i][0],p2,nodes[i+1][0],p4,j,m))
     {
      scanp2=m;
      break;
     }
    }   
    gb.drawLine(j,scanp1,j,scanp2);
   }
   tempy1=tempy2;
  }
  else
  {
   gb.drawLine(nodes[i][0],nodes[i][1],nodes[i+1][0],nodes[i+1][1]);
   tempy1=nodes[i][1];
   bottom--;
  }
 }
}
private void drawPolygon(int nodes[][])
{
gb.setColor(0x0000ff00);
for(int i = 0; i < nodes.length; i++){
gb.drawLine(nodes[i][0],nodes[i][1],nodes[i][0],nodes[i][1]);
gb.drawString(String.valueOf(nodes[i][0])+"."+String.valueOf(nodes[i][1]),nodes[i][0],nodes[i][1],0);
}
}
public void run()
{
x=new int[nodes.length];
y=new int[nodes.length];
for(int i=0;i{
 x[i]=nodes[i][0];
 y[i]=nodes[i][1];

gb.setColor(0x00ffffff);
gb.fillRect(0,0,nWidth,nHeight);
gb.setColor(0);
long time1=0;
long time2=0;
sort(nodes);
sortTang(nodes);
time1=System.currentTimeMillis();
//fillPolygon(gb,x,y);
fillPolygon(nodes);
time2=System.currentTimeMillis();
System.out.println(time2-time1);
drawPolygon(nodes);
System.out.println("done1");
repaint();
}

private void pause(long t)
{
try{Thread.sleep(t);}catch(Exception e){}
}
public void keyPressed(int keyCode)
  {


}

- 作者: 刀剑啸 2005年11月9日, 星期三 22:32  回复(0) |  引用(0) 加入博采

凸多边形填充的方法(扫描线法)

import java.lang.*;
import javax.microedition.lcdui.*;
import java.util.*;
import javax.microedition.rms.*;
import java.io.*;
class MainPit extends Canvas implements Runnable
{
Graphics gb;
Image bufImg;

private int nWidth = getWidth();
private int nHeight = getHeight();

public MainPit()
{
try{
bufImg = Image.createImage(nWidth,nHeight);
}catch(Exception e){System.out.println(e+" createImage");}
gb = bufImg.getGraphics();
}


public void paint(Graphics g)
{
g.drawImage(bufImg,0,0,0);
}

int nodes[][] = {//8/
{20,100},//0
{100,40},//1
{150,80},//2
{60,50},
//{150,110},//3
{150,150},//4
//{160,150},//5
//{110,110},//6
{50,130},//7
{160,140},
{60,139},
{110,45}
};
public void sort(int nodes[][])
{
 int i=nodes.length;
 int temp1=0;
 int temp2=0;
 for(int m=0;m for(int n=0;n {
  if(nodes[n][0]>nodes[n+1][0]||(nodes[n][0]==nodes[n+1][0]&&nodes[n][1]>nodes[n+1][1]))
  {
   temp1=nodes[n][0];
   temp2=nodes[n][1];
   nodes[n][0]=nodes[n+1][0];
   nodes[n][1]=nodes[n+1][1];
   nodes[n+1][0]=temp1;
   nodes[n+1][1]=temp2;
  }
 }
}
/*判断点x2,y2是不是在指定的线段上*/
public boolean cut(int x0,int y0,int x1,int y1,int x2,int y2)
{
 if(((y1-y0)*(x2-x0)<=(y2-y0)*(x1-x0))&&((y1-y0)*(x2-x0)>=(y2-1-y0)*(x1-x0)))
 return true;
 else
 return false;
}
public int findNextPoint(int[][] nodes,int a,boolean s)
{
 int min=0;
 int max=0; 
 if(a==nodes.length-3)
 return a+2;
 else
 {
  min=a+1;
  max=a+1;
  for(int j=a+2;j &nsp;{
   if((nodes[j][1]-nodes[a][1])*(nodes[min][0]-nodes[a][0])<(nodes[min][1]-nodes[a][1])*(nodes[j][0]-nodes[a][0]))
   {
    min=j;
   }
   if((nodes[j][1]-nodes[a][1])*(nodes[max][0]-nodes[a][0])>(nodes[max][1]-nodes[a][1])*(nodes[j][0]-nodes[a][0]))
   {
    max=j;
   }
  }
  if(nodes[min][0]-nodes[max][0]>0)
  return min;
  else
  if(nodes[min][0]-nodes[max][0]<0)
  return max;
  else
  if(min==a+1)
  return max;
  else
  return min;
 }
}
public void fillPolygon(int nodes[][])
{
 sort(nodes);
 gb.setColor(0xff0000);
 int tempy1=nodes[0][1];
 int tempy2=0;
 int nextP=0;
 int p1=0;
 int p2=0;
 int p3=0;
 int p4=0;
 for(int i=0;i {
  nextP=0;
  if(nodes[i][0]  {
   if(tempy1!=nodes[i][1])
   nextP=findNextPoint(nodes,i,tempy1>=nodes[i][1]?true:false);
   else
   if((nodes[i+1][1]-nodes[i][1])*(nodes[i+2][0]-nodes[i][0])<(nodes[i+2][1]-nodes[i][1])*(nodes[i+1][0]-nodes[i][0]))
   nextP=findNextPoint(nodes,i,true);
   else
   nextP=findNextPoint(nodes,i,false);
   if((nodes[i+1][1]-nodes[nextP][1])*(nodes[i][1]-tempy1)>=0)
   p3=tempy1;
   else
   p3=nodes[i][1];
   for(int j=0;j   {
    if(cut(nodes[i][0],p3,nodes[nextP][0],nodes[nextP][1],nodes[i+1][0],j))
    {
     tempy2=j;
     break;
    }
   }
    if((nodes[i][1]-tempy1)*(nodes[i+1][1]-tempy2)>=0)
    p3=nodes[i+1][1];
    else
    p3=tempy2;
    if(p3==nodes[i+1][1])
    p4=tempy2;
    else
    p4=nodes[i+1][1];
    
   for(int j=nodes[i][0];j<=nodes[i+1][0];j++)
   {

    for(int m=1;m<=nHeight;m++)
    {
     if(cut(nodes[i][0],nodes[i][1],nodes[i+1][0],p3,j,m))
     p1=m;
     if(cut(nodes[i][0],tempy1,nodes[i+1][0],p4,j,m))
     p2=m;
    }   
    gb.drawLine(j,p1,j,p2);
   }
   tempy1=tempy2;
  }
  else
  {
   gb.drawLine(nodes[i][0],nodes[i][1],nodes[i+1][0],nodes[i+1][1]);
   tempy1=nodes[i][1];
  }
 }
}
private void drawPolygon(int nodes[][])
{
gb.setColor(0x0000ff00);
for(int i = 0; i < nodes.length; i++){
gb.drawLine(nodes[i][0],nodes[i][1],nodes[i][0],nodes[i][1]);
gb.drawString(String.valueOf(nodes[i][0])+"."+String.valueOf(nodes[i][1]),nodes[i][0],nodes[i][1],0);
}
}
public void run()
{
gb.setColor(0x00ffffff);
gb.fillRect(0,0,nWidth,nHeight);
fillPolygon(nodes);
drawPolygon(nodes);
System.out.println("done1");
repaint();
}

private void pause(long t)
{
try{Thread.sleep(t);}catch(Exception e){}
}
public void keyPressed(int keyCode)
  {


}
 按此在新窗口浏览图片

- 作者: 刀剑啸 2005年11月9日, 星期三 10:34  回复(0) |  引用(0) 加入博采

血色浪漫

      血色浪漫,也只有鲜血的颜色和夕阳完美的融和在一起的时候,你才会从心底感动,虽然,你眼里早已是汪洋。

      这本来就是个弱肉强食的社会,不懂得生存,早晚就成了别人锅里的一盘菜。

     不要太多埋怨,埋怨只能证明你就是个弱者,只能眼巴巴看着别人的碗等着有口汤喝,那你除了渣味,还能尝到啥呢。

- 作者: 刀剑啸 2005年11月2日, 星期三 23:52  回复(4) |  引用(0) 加入博采

冬天的气息

    村子很穷,一到晚上,汉子们就拉着婆娘们在炕上折腾,很多孩子就是因为父母的无聊而来到这个世上,也不知道等待他们的是什么样的生活。

    这段经典的话让我呆了很久,我不知道我们自己的无聊催生了些什么东西,有什么产物或许会在某一天突然缠在自己身旁,让你目瞪口呆。

    冬天已经越走越近,这一年,又将结束了,天气倒还没有变冷,但我现在的心很冷,上面还有依稀的血迹。不知道有什么东西堵在胸口,是对自己的憎恨,还是对未来的茫然,我突然觉得自己有必要在一个无人的角落大哭一场,把所有抑郁的悲愤统统深埋进黑暗的阴影里,不让别人知晓。我的视野里出现了这么一出场景,无人的天空,空旷的原野,偶尔传来几声狼的声音,鸟也不知道去哪了,或者还会从哪里跳出几只兔子,还带着B4的神情同情的看着我,那模样像是说,小样的,新来的吧。周围除了石头还是石头,也不知道咋还能长出几根枯草,没有生气,但也没死掉,颤微微的在风里舞着,我心里不由跳出一句,活着,真他妈好。还有啥能比活着更幸福?贪婪,让人已经忽略了自己活着的这个事实。

    冬天好慢,还没飘雪,干涩的空气让人难以下咽,偶尔会有几片落叶,轻轻的打着转落下来,砸到一头熟睡的猪,猪没醒,口水哗哗的,估计在怀念自己的祖先,那个挥着九齿耙抱着女人四处Soho的八大爷,娘的,这种好事咋就不能代代相传呢。不过丫也够轻松的了,吃了睡睡了吃,虽然难免挨上一刀,其实。。这世间的万物,包括人,又能逃过一刀么?活一辈子,伤痕累累,行将入土的时候数着身上的刀口,倒还可以骂一句,老子TMD也还是个男人。

- 作者: 刀剑啸 2005年11月2日, 星期三 11:00  回复(0) |  引用(0) 加入博采

一个通用的游戏信息框架类

百宝箱的游戏都需要有游戏菜单,游戏关于和游戏帮助的信息,为了能够自适应不同的手机,方便作这些信息的显示,我写了如下的类

/*游戏中的一些常用的框架*/
import javax.microedition.lcdui.*;
import java.util.Vector;
class showContent
{
 int w,h;//屏幕的长和宽
 int cw;//字体的宽
 int page,maxPage;//帮助信息中的页码/最大页码
 int rn;//每行最大字数
 int maxR;//每屏最多显示的行数
 int cr;//字体行距
 Vector about;
 Vector help;
 public showContent(int wid,int hei,int charw,int charR,String[] aboutText,String[] helpText)
 {
  about=new Vector(0,1);
  help=new Vector(0,1);
  w=wid;h=hei;cw=charw;cr=charR;
  rn=w/cw;
  maxR=(h-20)/cr;
  page=0;
  for(int m=0;m  {
   int i=1+(aboutText[m].length()-1)/rn;
   for(int p=0;p   {
    if(p    about.addElement((String)(aboutText[m].substring(p*rn,(p+1)*rn)));
    else
    about.addElement((String)(aboutText[m].substring(p*rn)));
   }
  }
  for(int m=0;m  {
   int i=1+(helpText[m].length()-1)/rn;
   for(int p=0;p   {
    if(p    help.addElement((String)(helpText[m].substring(p*rn,(p+1)*rn)));
    else
    help.addElement((String)(helpText[m].substring(p*rn)));
   }
  }
  maxPage=(help.size()-1)/maxR;
 }
 public void showAbout(Graphics g1,int x,int y)//显示关于
 {
  g1.setColor(0);
  g1.fillRect(0,0,w,h);
  g1.setColor(0xffffff);
  for(int i=0;i  {
   g1.drawString((String)(about.elementAt(i)),x,y+i*cr,0);
  }
 }
 /*显示暂停*/
  public void drawPause(Graphics g1)
  {
   g1.setColor(0);
   g1.fillRect(w/2-30,h/2-6,60,30);
   g1.setColor(0xffffff);
   g1.drawRect(w/2-30,h/2-6,60,30);
   g1.drawString("暂停中",w/2-20,h/2,0);
  } 
 public void showHelp(Graphics g1,int x,int y)//显示帮助
 {
  g1.setColor(0);
  g1.fillRect(0,0,w,h);
  g1.setColor(0xffffff);  
  for(int i=0;i  {
   if(page*maxR+i   g1.drawString((String)(help.elementAt(page*maxR+i)),x,y+i*cr,0);
  }
  g1.setColor(0xffff00);
  g1.drawString("按上下方向键翻页",20,h-20,0);
 }
  public void drawMenu(Graphics g1,int x,int y,int row,int w,String[] arrayStr,int no)//显示菜单
  {
     g1.setColor(0xffff00);
     g1.fillRect(x,y,w,arrayStr.length*row);
     g1.setColor(0xffffff);
     g1.drawRect(x,y,w,arrayStr.length*row);
     for(int m=0;m     {
      if(no==m)
      g1.setColor(0x0000ff);
      else
      g1.setColor(0);
      g1.drawString(arrayStr[m],x+5,y+5+m*row,0);
     }  
 }   
}

呵呵,这个类的用法就不细说了,应该很容易看明白的。

- 作者: 刀剑啸 2005年10月10日,星期一 09:43  回复(0) |  引用(0) 加入博采

如何生成随机的自然数序列

在应用中有时候需要用到随机的自然数序列,比如拼图游戏的初始状态的图片顺序,将这个问题简单来说就是将0~n-1的n个数的排列顺序随机打乱,得到新的一个数字序列.下面给出我的做法.

设数组source,goal分别对应打乱前的源序列和最后要得到的新序列

for(int i=0;i{
int pos=rand(source.length-1-i);
goal[i]=source[pos];
source[pos]=source[source.length-1-i];
}  

这种做法只用了一次循环,效率应该比较高(我认为,呵呵),或者也可以用Vector来做.

- 作者: 刀剑啸 2005年09月29日, 星期四 13:13  回复(1) |  引用(1) 加入博采

NOKIA播放OTT的方法
发贴心情 NOKIA播放OTT的方法

/*创建播放器
S为音乐文件路径
type为类型,1为Tone,5为Wav
*/
public Sound createPlayer(String s,int type)
{  
  try
  {
   byte[] byte1,byte2;
   byte1=new byte[1000];    
   InputStream is=getClass().getResourceAsStream(s);
   int i =is.read(byte1);
   byte2 =new byte[i];
   System.arraycopy(byte1,0,byte2,0,byte2.length);
   is.close();
  return(new Sound(byte2,type));  
  }
  catch(Exception e)
  {
   return null;
  }
}

通过这个方法可以创建一个播放器,然后用play()方法就能播放了

- 作者: 刀剑啸 2005年09月26日, 星期一 14:10  回复(0) |  引用(0) 加入博采