最近闲来无事,突然怀念起小时候和堂兄表姐们经常玩24点游戏,于是就琢磨着是不是开发一个Android/ target=_blank class=infotextkey>安卓手机版本。然后上网上一搜,发现已经被别人给开发烂了啊。不过这只能说明这个小游戏要想赚广告费很难了,但是拿来锻炼和在妹纸面前装逼还是很有价值的,嘿嘿,想到这里,我最终还是花了3天时间开发了一个小游戏出来。
算法实现
在网上试玩了一个flash的版本,发现还需要实现计算所有正确的结果,然后网上稍微百度了下思路,就开始自己实现了。我开始时大概的思路就是穷举出所有的数字和算式的排列组合,然后一一进行验算,中间碰到两个问题,
然后,具体怎样进行遍历才能做到既不重复又无遗漏呢? 我的思路是这样的,还是得利用递归来简化实现,虽然递归很耗资源,但是作为非acm大神,算法水平一般般的我来说,还是先从简单的角度考虑。一个算式,不管包不包括括号,都可以抽象成两个数的计算的叠加,因为每次单个运算都是拿两个数运算的。然后再通过递归,将计算的结果和其他的数重新做两个数的运算,一直递归到只剩下一个结果时,那么这个数就是这种计算方法得到的答案了,和24比较就可以了。
至于每一个运算轨迹得到的表达式该怎么保存呢?我的做法是用一个类封装起来,然后维护两个数组,一个是数字(这个数字既是用户输入的,也可以是两个或多个数运算得到的结果),另一个就是这个数对应的表达式(当这个数是用户输入的时候就是一个数字而已,当这个数字是运算的结果时就是算式)的字符串。
实现代码:
package net.yunstudio.p24.util; import JAVA.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Random; import java.util.Set; import com.umeng.a.a.a.b.n; public class Count24 { private List<String> answerList=new ArrayList<String>(); public List<String> getAnswerList() { return answerList; } public static class Data{ public float[] arr; public String expStr=""; public String[] strs; public Data(){} public Data(int a,int b,int c,int d) { arr=new float[]{a,b,c,d}; strs=new String[]{a+"",b+"",c+"",d+""}; expStr=a+""; } public Data(int arr[]) { this.arr=new float[]{arr[0],arr[1],arr[2],arr[3]}; this.strs=new String[]{arr[0]+"",arr[1]+"",arr[2]+"",arr[3]+""}; } } public void count(Data data){ float[] arr=data.arr; if(arr.length<=1){ if(arr.length==1&&arr[0]==24){ answerList.add(data.expStr.substring(1, data.expStr.length()-1)); } return ; } for(int i=0,len=arr.length;i<len-1; i++){ for(int j=i+1;j<len;j++){ float x=arr[i]; float y=arr[j]; String xs=data.strs[i]; String ys=data.strs[j]; for(int k=0;k<6;k++){ Data newData=getNewArr(data,i); switch(k){ case 0: newData.arr[j-1]=x+y; newData.expStr=xs+"+"+ys; break; case 1: newData.arr[j-1]=x-y; newData.expStr=xs+"-"+ys; break; case 2: newData.arr[j-1]=y-x; newData.expStr=ys+"-"+xs; break; case 3: newData.arr[j-1]=x*y; newData.expStr=xs+"*"+ys; break; case 4: if(y!=0){ newData.arr[j-1]=x/y; newData.expStr=xs+"/"+ys; }else { continue; } break; case 5: if(x!=0){ newData.arr[j-1]=y/x; newData.expStr=ys+"/"+xs; }else { continue; } break; } newData.expStr="("+newData.expStr+")"; newData.strs[j-1]=newData.expStr; count(newData); } } } } private static Data getNewArr(Data data, int i) { Data newData=new Data(); newData.expStr=data.expStr; newData.arr=new float[data.arr.length-1]; newData.strs=new String[data.arr.length-1]; for(int m=0,len=data.arr.length,n=0;m<len;m++){ if(m!=i){ newData.arr[n]=data.arr[m]; newData.strs[n]=data.strs[m]; n++; } } return newData; } public static final List<String> easyCount(int[] curRandNums){ Count24 count24=new Count24(); count24.count(new Data(curRandNums)); Set<String> set=new HashSet<String>(count24.getAnswerList());//去重 return new ArrayList<String>(set); } public static void main(String[] args) throws InterruptedException { long start=System.currentTimeMillis(); List<String> answerStris=easyCount(new int[]{1,2,3,4}); System.out.println(System.currentTimeMillis()-start); for (String string : answerStris) { System.out.println(string); } } }
在电脑上面(神舟i7)大概需要60ms,这个速度初看还是可以接受的,但是到了手机上,居然需要6秒以上!!不过无意中发现,在android系统中对大量运算有优化,貌似计算了一定次数之后系统会缓存编译后的本地代码,然后手机上也可以像电脑上一样秒算了。
之后又花了一天做了个丑陋无比的简单界面,再花了一天时间加上积分功能,修复各种bug,添加广告和统计sdk,上传应用市场。。