当前位置: 首页 > news >正文

基于Nokia S40的猜数字游戏之二

作者:mingjava 文章来源:http://www.j2medev.com/Article/ShowArticle.asp?ArticleID=143

现在我们已经有一能够接收用户输入事件的Button类了,下面我们应该考虑如何实现游戏中相关的逻辑,猜数字中的游戏逻辑都比较简单,主要是产生一个4位随机数字且不能重复,其次是根据输入返回给用户结果。我们提供一个Engine类来完成这个工作。
package com.j2medev.numbergame;

import java.util.Random;

public class Engine
{
private int[] answer = new int[4];

private Random random = new Random();

public void init()
{
int[] number = new int[10];
for (int i = 0; i < number.length; i++)
{
number[i] = i;
}

int n = 10;
for (int index = 0; index < answer.length; index++)
{
int r = Math.abs(random.nextInt() % n);
answer[index] = number[r];
number[r] = number[n - 1];
n--;
}
}

public int[] getAnswer()
{
return answer;
}

public int[] queryResult(int[] input)
{
int[] state = new int[2];
int a = 0;
int b = 0;
for (int i = 0; i < answer.length; i++)
{
for (int j = 0; j < answer.length; j++)
{

if ((input[j] ^ answer[i]) == 0)
{
if (i == j)
{
a++;
} else
{
b++;
}

}
}
}
state[0] = a;
state[1] = b;
return state;
}
}

在游戏的运行中,我们有时候需要提示用户它的操作有误,比如输入数字为空,或者显示给用户已经答对了,一个庆祝的界面。当然这些你可以通过MIDP中提供的Alert来完成,我在这里实现了一个简单的界面类,这是一个抽象类,扩展了FullCanvas但是并没有实现paint()方法,把这个方法留给他的字类来实现。
/*
* Created on 2004-12-21
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package com.j2medev.numbergame;

import java.util.Timer;
import java.util.TimerTask;

import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Font;

import com.nokia.mid.ui.FullCanvas;

public abstract class NumScreen extends FullCanvas
{
protected Timer timer = new Timer();
protected Display display;
protected Manager next;
protected int timeout;
protected Font font;

public NumScreen(Display display,Manager next)
{
this.display = display;
this.next = next;

setTimeout(3000);
}

public Font getFont()
{
if(font == null)
{
font = Font.getDefaultFont();
}
return font;
}

public void setFont(Font font)
{
this.font = font;
}

public void setTimeout(int time)
{
this.timeout = time;
}


public void dismiss()
{
timer.cancel();
display.setCurrent(next);
}

public void showNotify()
{
timer.schedule(new TimerTask()
{
public void run()
{
dismiss();
}
},3000);
}

}
基于这个类,我们实现一个SplashScreen用在程序启动的时候的欢迎界面上,还提供一个类CongScreen用于显示用户的成绩和提示。

package com.j2medev.numbergame;

import java.io.IOException;

import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

public class SplashScreen extends NumScreen
{

public SplashScreen(Display display,Manager next)
{
super(display, next);
}

protected void paint(Graphics arg0)
{
Image welcome = null;
try
{
welcome = Image.createImage("/welcome.png");
} catch (IOException e)
{
e.printStackTrace();
}

arg0.drawImage(welcome, 2, 2, Graphics.TOP | Graphics.LEFT);

}

}


package com.j2medev.numbergame;

import java.io.IOException;

import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

public class CongScreen extends NumScreen
{

private String title;

private Mark mark;

private Image image;

private Image star;

private Manager manager;

private int type = CONG;

public static final int CONG = 1;
public static final int WARNING = 2;

public CongScreen(Display display, Manager next)
{
super(display, next);

}

public CongScreen(Display display,Manager next, Mark mark)
{
this(display, next);
this.mark = mark;

}


protected void paint(Graphics g)
{
int width = this.getWidth();
int height = this.getHeight();
if (image == null)
{
try
{
image = Image.createImage("/cong.png");
star = Image.createImage("/star.png");
} catch (IOException e)
{
e.printStackTrace();
}
}
if (title != null)
{
g.drawString(title, width / 2, 5, Graphics.HCENTER | Graphics.TOP);
}
int offset = 10 + getFont().getHeight();
g.drawImage(image, 2, offset, Graphics.TOP | Graphics.LEFT);
offset = offset + image.getHeight();

if(type == CONG)
{
int number = 5 - mark.getCount()/2;
if(number ==0) number = 1;

g.drawString("成绩:",2,offset+3,Graphics.TOP|Graphics.LEFT);
for(int i = 0;i<number;i++)
{
g.drawImage(star,4+font.stringWidth("成绩:")+i*star.getWidth(),offset+3,Graphics.LEFT|Graphics.TOP);

}

}
}

public void setType(int type)
{
this.type = type;
}

public String getTitle()
{
return title;
}

public void setTitle(String title)
{
this.title = title;
}

public Mark getMark()
{
return mark;
}

public void setMark(Mark mark)
{
this.mark = mark;
}

}

至此我们程序需要的元素都有了,下面我们的任务是写游戏的MIDlet了。由于我是针对s40的手机写的游戏,因此在了解到他的屏幕为128*128之后,进行了界面布局的计算。并且用到了Nokia UI提供的FullCanvas类,但是没有使用它提供的DirectGraphics,因为没有太多需要图形和动作的处理。

package com.j2medev.numbergame;

import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class NumberGame extends MIDlet implements ButtonListener
{

private Display display;

private SplashScreen welcome;

private Manager manager;

private Button[] buttons = new Button[4];

private Button cmd;

private Mark mark;

private Engine engine;

protected void startApp() throws MIDletStateChangeException
{

initMIDlet();

}

private void initMIDlet()
{
display = Display.getDisplay(this);
manager = new Manager();
engine = new Engine();
engine.init();

int screenWidth = manager.getWidth();
int screenHeight = manager.getHeight();
int balance = screenWidth / 5;
int buttonWidth = balance - 1;
int buttonHeight = 15;
for (int i = 0; i < buttons.length; i++)
{
buttons[i] = new Button("", 1 + i * balance, 1, buttonWidth,
buttonHeight);
manager.add(buttons[i]);
buttons[i].setMargin(8, 4);
buttons[i].setListener(this);
}

cmd = new Button("OK", 1 + buttons.length * balance, 1, buttonWidth,
buttonHeight);
manager.add(cmd);
cmd.setListener(this);
cmd.setModifiable(false);

mark = new Mark(1, 1 + cmd.getHeight() + 2, screenWidth - 3,
screenHeight - 3 - cmd.getHeight());
manager.add(mark);

welcome = new SplashScreen(display, manager);
display.setCurrent(welcome);

}

protected void pauseApp()
{


}

protected void destroyApp(boolean arg0) throws MIDletStateChangeException
{

}

public void buttonPressed(Button button)
{
String label = button.getLabel();
if (label == "OK")
{
int[] res = getInput();
if (res.length == 1)
{
CongScreen cs = new CongScreen(display, manager);
cs.setTitle("数字不能为空");
cs.setType(CongScreen.WARNING);
display.setCurrent(cs);

return;
}
int[] feedback = engine.queryResult(res);

if (feedback[0] == 4)
{

CongScreen cs = new CongScreen(display, manager, mark);
cs.setTitle("恭喜您!");

display.setCurrent(cs);

resetGame();
return;
}
if (mark.getCount() == 9 & feedback[0] != 4)
{

CongScreen cs = new CongScreen(display, manager, mark);
cs.setTitle("重新开始吧");
cs.setType(CongScreen.WARNING);

display.setCurrent(cs);

resetGame();
return;
}
mark.setInput(res);
mark.setAB(feedback);
mark.setOpen(true);
manager.repaintArea(mark, true);
mark.setOpen(false);

}

}

public String input2String(int[] input)
{
String s = "";
for (int i = 0; i < input.length; i++)
{
s = s + input[i];
}
return s;
}

private int[] getInput()
{
String[] inputString = new String[4];
for (int i = 0; i < buttons.length; i++)
{
inputString[i] = buttons[i].getLabel();
}

for (int k = 0; k < inputString.length; k++)
{
if (inputString[k].equals(""))
{
return new int[] { 100 };
}
}

int[] number = new int[4];
for (int j = 0; j < inputString.length; j++)
{
number[j] = Integer.parseInt(inputString[j]);
}
return number;
}

private void resetButton()
{
for (int i = 0; i < buttons.length; i++)
{
buttons[i].setLabel("");
}
}

public void resetGame()
{
resetButton();
mark.reset();
engine.init();
}

}

总结:这个游戏比较简单,但是其中组件的实现比较重要。我们从中可以学到回调以及容器管理组件的技术。由于本人没有游戏开发经验,因此在美工方面比较欠缺,只是随便画了几个图形。猜数字的界面也很淡薄,缺乏吸引力。我们的目的在于学习。希望游戏开发的高手多多分享一下自己的经验,我也会开始自己的下一个动作类游戏。

相关文章:

  • 深入学习之 this 方法2
  • 应用Nokia UI API处理声音问题
  • 深入学习之css重点
  • Nokia UI学习范例FishTank研究
  • react 向事件处理程序传递参数
  • react 有状态组件 切换登陆和未登录状态以及UI展示
  • 整合SE J2ME SDK与eclipse开发环境
  • MP3在Sony Ericsson K700上的音响效果
  • K700之图像内存处理
  • react 隐藏组件 阻止渲染
  • react 数组map方法转化列表
  • 使用索爱V800开发流媒体应用程序
  • 读取索爱手机固件版本信息和IMEI号
  • react jsx中使用map
  • 在基于MIDP的应用程序上使用JDBC
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • 【mysql】环境安装、服务启动、密码设置
  • es6--symbol
  • IDEA 插件开发入门教程
  • Js基础知识(一) - 变量
  • Laravel Telescope:优雅的应用调试工具
  • PaddlePaddle-GitHub的正确打开姿势
  • 分享一份非常强势的Android面试题
  • 关于 Cirru Editor 存储格式
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 携程小程序初体验
  • Android开发者必备:推荐一款助力开发的开源APP
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • 我们雇佣了一只大猴子...
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • #Z0458. 树的中心2
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (力扣)1314.矩阵区域和
  • (十六)串口UART
  • (图)IntelliTrace Tools 跟踪云端程序
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (转)c++ std::pair 与 std::make
  • (转)Linux下编译安装log4cxx
  • (转)Oracle存储过程编写经验和优化措施
  • (转载)(官方)UE4--图像编程----着色器开发
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .bat批处理出现中文乱码的情况
  • .mysql secret在哪_MYSQL基本操作(上)
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • .NET构架之我见
  • @Conditional注解详解
  • @EnableWebMvc介绍和使用详细demo
  • @Transactional 详解
  • [ solr入门 ] - 利用solrJ进行检索