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

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

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

笔者刚刚开始学习写游戏,并没有什么经验,因此选择了门槛比较低的猜数字游戏。花了一天的时间,基本能够在Nokia6108上运行了,界面比较简单,为学习之用。

下面介绍一下如何实现猜数字游戏,其实这是一个比较经典的游戏。游戏的原理是:游戏开始的时候会自动产生四个不重复的随机数字比如1234,用户输入四个数字,系统通过判断返回给用户xAyB的结果,其中A代表数字正确位置也正确,B代表数字正确但是位置不正确。如果用户猜对游戏就结束了,10次内没有猜对,游戏也结束。在这里我们重点介绍为游戏而实现的组件,简单的流程控制和游戏逻辑。

首先介绍组件,这里我们提供了两个组件,一个就是Button,他可以接收用户输入的数字,并且可以响应用户的按键事件。

首先我们构造一个基本的组件,这个组件需要包括左上角顶点的坐标(x,y),宽度w,高度h以及前景色、背景色。最重要的一点是我们需要给他提供一个容器来管理他,因此提供一个Manager类。
package com.j2medev.numbergame;

import javax.microedition.lcdui.*;
import com.nokia.mid.ui.*;

//A root class for Canvas-based components.
//Because Area extends Canvas, you can actually
//use a component directly as a Canvas, although
//it's recommended you place it on Manager.

public abstract class Area extends FullCanvas
{
protected int x;

protected int y;

protected int w;

protected int h;

protected Font font;

protected Manager parent;

protected int backcolor = -1;

protected int forecolor = -1;

protected Area(int x, int y, int w, int h)
{
this(x, y, w, h, null);
}

protected Area(int x, int y, int w, int h, Font f)
{
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.font = f;
}

// Erase the background using backcolor

protected void eraseBackground(Graphics g)
{
g.setColor(getBackColor());

if (parent == null)
{
g.fillRect(0, 0, getCanvasWidth(), getCanvasHeight());
} else
{
g.fillRect(0, 0, w, h);
}
}

public final int getBackColor()
{
if (backcolor == -1)
{
if (parent != null)
{
return parent.getBackColor();
}

backcolor = 0xFFFFFF;
}

return backcolor;
}

protected final int getCanvasHeight()
{
return super.getHeight();
}

protected final int getCanvasWidth()
{
return super.getWidth();
}

public final int getHeight()
{
return h;
}

public final int getWidth()
{
return w;
}

public final int getX()
{
return x;
}

public final int getY()
{
return y;
}

public final Font getFont()
{
if (font == null)
{
if (parent != null)
{
return parent.getFont();
}

font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
Font.SIZE_SMALL);
;

}

return font;
}

public final int getForeColor()
{
if (forecolor == -1)
{
if (parent != null)
{
return parent.getForeColor();
}

forecolor = 0;
}

return forecolor;
}

public Manager getParent()
{
return parent;
}

public void keyPressed(int keyCode)
{
}

public void keyReleased(int keyCode)
{
}

public void keyRepeated(int keyCode)
{
}

protected void moveFocus(boolean forward)
{
if (parent != null)
{
parent.moveFocus(forward);
}
}

// If the area is acting like a Canvas, call
// the real paint routine

protected void paint(Graphics g)
{

eraseBackground(g);
g.setColor(getForeColor());
g.setFont(getFont());
paintArea(g, true);
}

// The manager calls this paint routine on each of
// its children

public final void paint(Graphics g, boolean hasFocus)
{
int cx = g.getClipX();
int cy = g.getClipY();
int ch = g.getClipHeight();
int cw = g.getClipWidth();
Font f = g.getFont();
int col = g.getColor();

eraseBackground(g);

g.setClip(x, y, w, h);
g.setFont(getFont());
g.setColor(getForeColor());

paintArea(g, hasFocus);

g.setClip(cx, cy, cw, ch);
g.setFont(f);
g.setColor(col);
}

// Subclass implements to do actual painting

protected abstract void paintArea(Graphics g, boolean hasFocus);

// Repaint the area of the given child

public void repaintArea(Area child, boolean now)
{
if (parent != null)
{
parent.repaintArea(child, now);
} else
{
repaint(child.getX(), child.getY(), child.getWidth(), child
.getHeight());

if (now)
{
serviceRepaints();
}
}
}

public void setBackColor(int col)
{
backcolor = col;
}

public void setForeColor(int col)
{
forecolor = col;
}

protected void setParent(Manager parent)
{
this.parent = parent;
}

}
这是一个抽象类,他的抽象方法protected abstract void paintArea(Graphics g, boolean hasFocus);是留给他的子类实现的。因此我们在子类中重点需要关注的就是如何来绘制自己和根据用户的输入做出响应。下面我们来实现Button类,我们需要提供一个ButtonListener类,通过他我们可以实现回调的功能,即在按键按下的时候去做ButtonListener中规定的方法,非常类似于CommandListener的功能。

package com.j2medev.numbergame;

public interface ButtonListener
{
public void buttonPressed(Button pushed);

}
下面是Button类的代码

package com.j2medev.numbergame;
import javax.microedition.lcdui.*;

public class Button extends Area
{

private String label;

private boolean selected;

private ButtonListener listener;

private boolean modifiable = true;

private int marginx = 4;

private int marginy = 4;

public Button(String label, int x, int y)
{
this(label, x, y, 0, 0, null);
}

public Button(String label, int x, int y, Font f)
{
this(label, x, y, 0, 0, f);
}

public Button(String label, int x, int y, int w, int h)
{
this(label, x, y, w, h, null);
}

public Button(String label, int x, int y, int w, int h, Font f)
{
super(x, y, w, h, f);

if (label == null)
label = "";

int tw = calcMinWidth(label, getFont());
int th = calcMinHeight(label, getFont());

if (tw > w)
this.w = tw;
if (th > h)
this.h = th;

this.label = label;
}

public void setModifiable(boolean flag)
{
this.modifiable = flag;
}

public static int calcMinWidth(String text, Font f)
{
return f.stringWidth(text) + 8;
}

public static int calcMinHeight(String text, Font f)
{
return f.getHeight() + 8;
}

public String getLabel()
{
return label;
}

public void setMargin(int x,int y)
{
this.marginx = x;
this.marginy = y;
}
protected void paintArea(Graphics g, boolean hasFocus)
{
g.setStrokeStyle(Graphics.SOLID);
g.drawRect(x, y, w - 1, h - 1);



if (selected)
{
g.setColor(getForeColor());
g.fillRect(x, y, w - 1, h - 1);
g.setColor(getBackColor());
} else if (hasFocus)
{
g.setStrokeStyle(Graphics.DOTTED);
g.drawRect(x + 3, y + 3, w - 7, h - 7);
g.setStrokeStyle(Graphics.SOLID);
}

g.drawString(label, x + marginx, y + marginy, Graphics.TOP | Graphics.LEFT);
}

public void keyPressed(int keyCode)
{
int num = keyCode - 48;
if (num >= 0)
{
if (modifiable)
{
this.label = num + "";
}
repaintArea(this, true);
moveFocus(true);
return;
}

int action = getGameAction(keyCode);
switch (action)
{
case UP:
case LEFT:
moveFocus(false);
break;
case DOWN:
case RIGHT:
moveFocus(true);
break;
case FIRE:
if (listener != null)
{
listener.buttonPressed(this);
}
break;
}

}

public void setLabel(String s)
{
this.label = s;
}

public void keyReleased(int keyCode)
{

}

public void setListener(ButtonListener listener)
{
this.listener = listener;
}
}

我们应该重点关注一下paintArea()方法,以及keyPressed()方法。如果我们注册了一个ButtonListener给Button的话,那么当按键事件发生的时候,buttonPressed()方法就会触发并且把这个按键传递给他,这样我们应用程序就可以根据用户的事件来处理相关的逻辑了。

我们推荐制作一个容器类来管理我们的Button,他会知道什么时候应该移动焦点,什么时候该去绘制它的“孩子”们。我们把这个类叫Manager。

package com.j2medev.numbergame;
import java.util.*;
import javax.microedition.lcdui.*;

// A subclass of Area that can act as
// the parent for other components.

public class Manager extends Area
{
protected Vector children = new Vector();

protected Area focus = null;

public Manager()
{
super(0, 0, 0, 0, null);
w = getCanvasWidth();
h = getCanvasHeight();
}

public void add(Area child)
{
if (!children.contains(child))
{
children.addElement(child);
child.setParent(this);
repaintArea(child, false);
}
}

protected Area getFocus()
{
if (focus == null && children.size() > 0)
{
focus = (Area) children.elementAt(0);
}

return focus;
}

public void keyPressed(int keyCode)
{
Area focus = getFocus();
if (focus != null && focus != this)
{
focus.keyPressed(keyCode);
}
}

public void keyReleased(int keyCode)
{

}

public void keyRepeated(int keyCode)
{

}

// Called to move the focus to the next
// or previous component

protected void moveFocus(boolean forward)
{
Area oldFocus = getFocus();
if (oldFocus != null)
{
int i = children.indexOf(oldFocus);
int last = children.size() - 2;
if (forward)
{
if (++i > last)
i = 0;
} else
{
if (--i < 0)
i = last;
}

focus = (Area) children.elementAt(i);
repaintArea(oldFocus, false);
repaintArea(focus, true);
}
}

public void remove(Area child)
{
if (children.removeElement(child))
{
child.setParent(null);
repaintArea(child, false);
}
}

protected void paint(Graphics g)
{
if (focus == null)
getFocus();

eraseBackground(g);
g.setColor(getForeColor());

int n = children.size();
for (int i = n - 1; i >= 0; --i)
{
try
{
Area area = (Area) children.elementAt(i);
area.paint(g, (focus == area));
} catch (Exception e)
{
e.printStackTrace();
}
}
}

protected void paintArea(Graphics g, boolean hasFocus)
{
}
}

在猜数字游戏中,我们还需要一个用于显示用户输入和系统返回纪录的组件,他同样继承与Area,但是他不需要获得焦点。只是显示结果。

package com.j2medev.numbergame;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;


public class Mark extends Area
{
private int px;

private int py;

private int count = 0;

private int[][] ab = new int[10][2];

private int[][] input = new int[10][4];

private boolean first = true;

private boolean open = false;

public Mark(int x, int y, int w, int h)
{
super(x, y, w, h);
px = x;
py = y;

}

public Mark(int x, int y, int w, int h, Font f)
{
super(x, y, w, h, f);
px = x;
py = y;

}

public int getCount()
{
return count;
}

public void setCount(int count)
{
this.count = count;
}

public void reset()
{
setCount(0);
this.first = true;
}

public void setAB(int[] ab)
{
this.ab[count][0] = ab[0];
this.ab[count][1] = ab[1];
}

public void setInput(int[] input)
{
for(int i = 0;i<input.length;i++)
{
this.input[count][i] = input[i];
}
}

public void setOpen(boolean open)
{
this.open = open;
}

public int getLineHeight()
{
return this.getFont().getHeight();
}

private String getInput(int count)
{
return ""+input[count][0]+input[count][1]+input[count][2]+input[count][3];
}

protected void paintArea(Graphics g, boolean hasFocus)
{
if (first)
{
first = false;

return;
}
if (open)
{
count++;

if (count <= 5)
{
for (int i = 0; i < count; i++)
{
g.drawString(i + 1 + ":" + ab[i][0] + "A" + ab[i][1] + "B "+getInput(i),
px, py + i * getLineHeight(), Graphics.TOP
| Graphics.LEFT);

}
} else
{
for (int i = 0; i < 5; i++)
{
g.drawString(i + 1 + ":" + ab[i][0] + "A" + ab[i][1] + "B "+getInput(i),
px, py + i * getLineHeight(), Graphics.TOP
| Graphics.LEFT);

}
for (int j = 5; j < count; j++)
{
g.drawString(j + 1 + ":" + ab[j][0] + "A" + ab[j][1] + "B "+getInput(j),
px + this.getWidth()/2+1, py + (j - 5)
* getLineHeight(), Graphics.TOP
| Graphics.LEFT);
}
}

}
}
}

相关文章:

  • 深入学习之继承图总结
  • 基于Nokia S40的猜数字游戏之二
  • 深入学习之 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号
  • JavaScript 如何正确处理 Unicode 编码问题!
  • [nginx文档翻译系列] 控制nginx
  • JS+CSS实现数字滚动
  • js对象的深浅拷贝
  • js算法-归并排序(merge_sort)
  • LeetCode18.四数之和 JavaScript
  • LeetCode541. Reverse String II -- 按步长反转字符串
  • uva 10370 Above Average
  • yii2中session跨域名的问题
  • 不上全站https的网站你们就等着被恶心死吧
  • 将回调地狱按在地上摩擦的Promise
  • 树莓派 - 使用须知
  • 【云吞铺子】性能抖动剖析(二)
  • Android开发者必备:推荐一款助力开发的开源APP
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (07)Hive——窗口函数详解
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (论文阅读30/100)Convolutional Pose Machines
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • (转)EOS中账户、钱包和密钥的关系
  • (转)大道至简,职场上做人做事做管理
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .net core 6 集成和使用 mongodb
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • .NET下的多线程编程—1-线程机制概述
  • @ 代码随想录算法训练营第8周(C语言)|Day53(动态规划)
  • @autowired注解作用_Spring Boot进阶教程——注解大全(建议收藏!)
  • @RequestParam,@RequestBody和@PathVariable 区别
  • [ 常用工具篇 ] AntSword 蚁剑安装及使用详解
  • [BT]BUUCTF刷题第9天(3.27)
  • [BZOJ1178][Apio2009]CONVENTION会议中心
  • [C puzzle book] types