移动互联网应用开发技术思考

目前的状况可谓是百家争鸣,随着Android技术的兴起,各手机生产厂家越来越混乱,也越来越验证了Android商业模式的先天不足。了解Android的同学都会知道,做Android开发是一件相对(相对iOS或者WP)比较痛苦的事情,因为得考虑各种各样的设备(包括屏幕分辨率、传感器支持情况、高中低配置、等等),而且这样算下来成本也高了不少。

目前的wp平台还不支持C/C++语言开发,所以如果我们开发一个软件,希望它跨平台的话,那是不可能的(PhoneGap不在考虑范围内,因为它运行效率太低),必须在每一个平台上重新开发。这让我们开发者痛苦不堪,有些程序员甚至夜夜加班不能按期完成任务,这不是程序员的问题,而是各大公司心怀鬼胎(各平台互相不支持)所导致的后果。

聪明的公司会自己写一套C/C++运行库以在各种平台上运行(有能力的公司才能够做到,普通的公司只能忍受各平台的分歧),就算是这样,一些新兴的平台在最初可能也不是支持C/C++语言,比如Android平台最初只支持Java,WP平台目前只支持C#。

目前也许有一个平台相对于PhoneGap更有使用的价值,那就是Adobe AIR,Adobe公司一直在致力于创造一个跨平台的运行,只是由于Adobe公司缺乏远见、反应迟钝、动作缓慢才导致它从2009年至今一直停滞不前,据我个人经验,Adobe AIR目前所拥有的功能实际上在2009年以前就应该拥有。不管是早是晚,反正它已经有了,现在如果你的软件对于性能的要求不是太高的话,Adobe AIR不失为一个不错的选择。

从Java到C++转型需知

很多同学是从Java语言进入编程世界的,但随着知识的增加与深入,逐渐认识到C/C++语言的重要性,所以很多比较有远见的程序员开始学习C/C++语言的开发。

从Java到C++,最重要的区别是面向对象的区别,C++的类可以多重继承,而Java只能有单一的父类,看起来Java像是个女儿国,而C++才是个真正的国度。当然Java也有Java的好处,那就是生活简单,像处女一样。

区别如下:

1.定义类

如下一个简单的Java类:
[code]

public class Array{

	private int length=0;

	public int getLength() {
		return length;
	}
}

[/code]

在C++语言中的定义应该如下所示:
[code]

class Array{

private:
	int length;

public:
	Array(){
		length=0;
	}

	int getLength() const {
		return length;
	}
};

[/code]

2.类的继承
我们执行一个操作,定义一个类A和一个类B,而类B继承自类A,在Java语言中应该这样写:
[code]

public class A{
}

public class B extends A{
}

[/code]

在C++语言中应该这样写:
[code]

class A{
};

class B:public A{
};

[/code]

3.方法重写
下面展示一个Java语言的方法重写过程:

[code]

public class A{
	public void sayHello(){
		System.out.println("A say : Hello World");
	}
}

public class B extends A{
	public void sayHello() {
		System.out.println("B say : Hello World");
	}
}

[/code]

那么这个功能在C++语言中又该如何去写呢?我们先写一段程序,再分析,如下:
[code]

class A{
public:
	void sayHello(){
		printf("A say : Hello World");
	}
};

class B:public A{
public:
	void sayHello(){
		printf("B say : Hello World");
	}
};

[/code]

这样去写看上去好像没有问题,这也是Java开发人员爱犯的一个错误,如果说她没有问题的话,我们写一段调用她的程序,就立即能够看出问题了,调用程序如下所示:
[code]

int main() {
	A* a = new B;
	a->sayHello();
	return 0;
}

[/code]

运行一下,我们看看输出结果:

A say : Hello World

我们使用的对象明明就是B实例,为什么输出的仍然是A的输出信息呢,这是因为我们的sayHello方法是实函数,这种方法一旦定义,那么它就属于定义它的那个类,不会再改变了,是不能被重写的。如果想让程序在运行过程中自动查找sayHello方法的所属类,应该把这个方法定义为虚函数,则上述类的正确写法应该如下所示:
[code]

class A{
public:
	virtual void sayHello(){
		printf("A say : Hello World");
	}

	virtual ~ A(){
	}
};

class B:public A{
public:
	virtual void sayHello(){
		printf("B say : Hello World");
	}

	virtual ~B(){
	}
};

[/code]

4.接口
在C++语言中没有接口的概念,但是可以用纯虚类来代替。如下所示:
[code]

class IPeople{
public:
	virtual int getAge()=0;
	virtual string getName()=0;
	virtual ~IPeople(){
	}
};

class Man:public IPeople{
public:
	Man(int age,string name){
		this->age=age;
		this->name=name;
	}

	virtual string getName(){
		return this->name;
	}

	virtual int getAge(){
		return this->age;
	}

	virtual ~Man(){
	}

private:
	int age;
	string name;
};

int main() {
	Man* m= new Man(8,"xiao ming");
	cout<<m->getName()<<endl;
	return 0;
}

[/code]

其中的IPeople类是一个纯虚类,其中只有纯虚函数,这样的类和接口的概念是一样的,继承者必须实现所有的纯虚函数。

Android版连连看游戏源码

本源码可以很方便的扩展成多关、多游戏资源包、多模式的连连看游戏,自认为写得非常专业(呵呵,得瑟一下)。

截图如下:

源码下载:LinkGame

连连看游戏主要算法文件源码如下:
[code]

package com.plter.linkgame.game;

import java.util.ArrayList;
import java.util.List;

import android.graphics.PointF;
import android.graphics.RectF;

public class GameUtil {

	public static float getXByIndexi(int indexI){
		return indexI*(Config.cardWidth+1)+Config.cardsOffsetX;
	}

	public static float getYByIndexJ(int indexJ){
		return indexJ*(Config.cardHeight+1)+Config.cardsOffsetY;
	}

	public static float getCenterXByIndexI(int indexI){
		return getXByIndexi(indexI)+Config.cardWidth/2;
	}

	public static float getCenterYByIndexJ(int indexJ){
		return getYByIndexJ(indexJ)+Config.cardHeight/2;
	}

	public static PointF getCenterByIndexIJ(int indexI,int indexJ){
		return new PointF(getCenterXByIndexI(indexI), getCenterYByIndexJ(indexJ));
	}

	/**
	 * 根据中心点取得卡片区域
	 * @return
	 */
	public static RectF getRectFByCenter(PointF p){
		return new RectF(p.x-Config.cardWidth/2, p.y-Config.cardHeight/2, p.x+Config.cardWidth/2, p.y+Config.cardHeight/2);
	}

	/**
	 * 对卡片执行一级测试
	 * @param	genLines 是否生成连线
	 * @return
	 */
	public static boolean testCards1(int i1,int j1,int i2,int j2,boolean genLines){

		boolean conn=true;

		if (i1==i2) {
			int min,max;
			if (j1>j2) {
				min=j2;
				max=j1;
			}else{
				min=j1;
				max=j2;
			}

			//纵向测试
			conn=true;
			for (int j = min+1; j < max; j++) {
				if (currentGameCardsMap[i1][j]!=null) {
					conn=false;
					break;
				}
			}
			if (conn) {
				if (genLines) {
					lastLinkedLinePoints.clear();
					lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j1));
					lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j2));
				}
				return true;
			}
		}else if (j1==j2) {

			int min,max;
			if (i1>i2) {
				min=i2;
				max=i1;
			}else{
				min=i1;
				max=i2;
			}

			//横向测试
			conn=true;
			for (int i = min+1; i < max; i++) {
				if (currentGameCardsMap[i][j1]!=null) {
					conn=false;
					break;
				}
			}
			if (conn) {
				if (genLines) {
					lastLinkedLinePoints.clear();
					lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j1));
					lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j2));
				}
				return true;
			}
		}

		return false;
	}

	/**
	 * 对卡片执行二级测试
	 * @param genLines 是否生成连线
	 * @return
	 */
	public static boolean testCards2(int i1,int j1,int i2,int j2,boolean genLines){

		int middleI1=i1,middleJ1=j2,middleI2=i2,middleJ2=j1;
		PointF middle1Center=new PointF(GameUtil.getCenterXByIndexI(middleI1), GameUtil.getCenterYByIndexJ(middleJ1)),
				middle2Center=new PointF(GameUtil.getCenterXByIndexI(middleI2), GameUtil.getCenterYByIndexJ(middleJ2));

		if (currentGameCardsMap[middleI1][middleJ1]==null&&
				testCards1(middleI1, middleJ1, i1, j1, false)&&
				testCards1(middleI1, middleJ1, i2, j2, false)) {

			if (genLines) {
				lastLinkedLinePoints.clear();
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j1));
				lastLinkedLinePoints.add(middle1Center);
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j2));
			}
			return true;
		}

		if (currentGameCardsMap[middleI2][middleJ2]==null&&
				testCards1(middleI2, middleJ2, i1, j1, false)&&
				testCards1(middleI2, middleJ2, i2, j2, false)) {

			if (genLines) {
				lastLinkedLinePoints.clear();
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j1));
				lastLinkedLinePoints.add(middle2Center);
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j2));
			}
			return true;
		}

		return false;
	}

	/**
	 * 对卡片执行三级横向测试
	 * @return
	 */
	public static boolean testCards3H(int i1,int j1,int i2,int j2,boolean genLines){
		int i=0;
		for (i = i1+1; i < currentLevel.getH_cards_count(); i++) {
			if (i!=i2&&currentGameCardsMap[i][j1]==null) {
				if (testCards1(i, j1, i1, j1, false)&&testCards2(i, j1, i2, j2, false)) {
					if (genLines) {
						lastLinkedLinePoints.clear();
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j1));
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i, j1));
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i, j2));
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j2));
					}

					return true;
				}
			}
		}
		i=currentLevel.getH_cards_count();
		if (testCards1(i, j1, i1, j1, false)&&testCards1(i, j2, i2, j2, false)) {
			if (genLines) {
				lastLinkedLinePoints.clear();
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j1));
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i, j1));
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i, j2));
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j2));
			}

			return true;
		}

		for (i = i1-1; i >0; i--) {
			if (i!=i2&&currentGameCardsMap[i][j1]==null) {
				if (testCards1(i, j1, i1, j1, false)&&testCards2(i, j1, i2, j2, false)) {

					if (genLines) {
						lastLinkedLinePoints.clear();
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j1));
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i, j1));
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i, j2));
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j2));
					}

					return true;
				}
			}
		}

		i=-1;
		if (testCards1(i, j1, i1, j1, false)&&testCards1(i, j2, i2, j2, false)) {
			if (genLines) {
				lastLinkedLinePoints.clear();
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j1));
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i, j1));
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i, j2));
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j2));
			}

			return true;
		}

		return false;
	}

	/**
	 * 对卡片执行三级纵向测试
	 * @return
	 */
	public static boolean testCards3V(int i1,int j1,int i2,int j2,boolean genLines){
		int j=0;
		for (j = j1+1; j < currentLevel.getV_cards_count(); j++) {
			if (j!=j2&&currentGameCardsMap[i1][j]==null) {
				if (testCards1(i1, j, i1, j1, false)&&testCards2(i1, j, i2, j2, false)) {
					if (genLines) {
						lastLinkedLinePoints.clear();
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j1));
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j));
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j));
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j2));
					}
					return true;
				}
			}
		}
		j=currentLevel.getV_cards_count();
		if (testCards1(i1, j, i1, j1, false)&&testCards1(i2, j, i2, j2, false)) {

			if (genLines) {
				lastLinkedLinePoints.clear();
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j1));
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j));
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j));
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j2));
			}
			return true;
		}

		for (j = j1-1; j >0; j--) {
			if (j!=j2&&currentGameCardsMap[i1][j]==null) {
				if (testCards1(i1, j, i1, j1, false)&&testCards2(i1, j, i2, j2, false)) {

					if (genLines) {
						lastLinkedLinePoints.clear();
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j1));
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j));
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j));
						lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j2));
					}
					return true;
				}
			}
		}

		j=-1;
		if (testCards1(i1, j, i1, j1, false)&&testCards1(i2, j, i2, j2, false)) {

			if (genLines) {
				lastLinkedLinePoints.clear();
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j1));
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i1, j));
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j));
				lastLinkedLinePoints.add(GameUtil.getCenterByIndexIJ(i2, j2));
			}
			return true;
		}
		return false;
	}

	/**
	 * 对卡片执行三级测试
	 * @return
	 */
	public static boolean testCards3(int i1,int j1,int i2,int j2,boolean genLines){

		if (i1==i2) {
			if (testCards3H(i1, j1, i2, j2, genLines)) {
				return true;
			}
		}else if (j1==j2) {
			if (testCards3V(i1, j1, i2, j2, genLines)) {
				return true;
			}
		}else{
			if (testCards3H(i1, j1, i2, j2, genLines)) {
				return true;
			}
			if (testCards3V(i1, j1, i2, j2, genLines)) {
				return true;
			}
		}

		return false;
	}

	public static boolean testCards(Level currentLevel,Card[][] currentGameCardsMap,int i1,int j1,int i2,int j2,boolean genLines){
		GameUtil.currentLevel=currentLevel;
		GameUtil.currentGameCardsMap=currentGameCardsMap;

		if (i1==i2||j1==j2) {
			//一级测试
			if (testCards1(i1,j1,i2,j2,genLines)) {
				return true;
			}else if (testCards3(i1,j1,i2,j2,genLines)) {//三级测试
				return true;
			}
		}else{
			//二级测试
			if (testCards2(i1,j1,i2,j2,genLines)) {
				return true;
			}else if(testCards3(i1,j1,i2,j2,genLines)){//三级测试
				return true;
			}
		}	

		return false;
	}

	public static final List<PointF> lastLinkedLinePoints = new ArrayList<PointF>();

	private static Level currentLevel=null;
	private static Card[][] currentGameCardsMap=null;
}

[/code]