JAVA CARD实现扫雷AI程序
程序员文章站
2024-03-23 22:11:04
...
beginning
这学期的JAVA智能卡课期末作业居然是叫我们自己做一个能自动扫雷的AI程序,OMG,上网搜了一下,其实网上java的智能卡代码挺多的,但是我们毕竟是智能卡,还是有一点点不一样的,所以把代码在这里码出来。
设计需求分析
老师给的棋盘还是非常简单的,大概相当于系统游戏中的初级难度,所以也不需要网上的那些高级策略,所以只采用了最基本的两条策略。
APDU指令表
完整代码
/**
*
*/
package minesweep;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.APDU;
import javacard.framework.Util;
/**
* @author Administrator
*
*/
public class SweepAI extends Applet {
byte [] checkerboard=new byte[128];
byte [] out=new byte[4];
byte [] studentID={32,30,31,36,32,31,31,30,30,32};
byte [] name={0x06,(byte) 0xD5,(byte) 0xC5,(byte) 0xD0,(byte) 0xA3,(byte) 0xD3,(byte) 0xEF};
short Sidelength,bufr,mineset;
short location=0,dark=0,flag=0,allflag=0,CF=1;
short locationX=1,locationY=1;
short maxsize;
public class Stack {
protected short MAX_DEPTH = 8;
protected short depth = 0;
protected byte[] stack = new byte[MAX_DEPTH];
protected void push(short n) {stack[depth++] = (byte) n;}
protected short pop() {return stack[--depth];}
}
Stack fstack=new Stack();
Stack ostack=new Stack();
Stack rstack=new Stack();
public static void install(byte[] bArray, short bOffset, byte bLength) {
// GP-compliant JavaCard applet registration
new SweepAI().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
}
final static byte MS_CLA =(byte)0x00;
//INS
public void process(APDU apdu) {
// Good practice: Return 9000 on SELECT
if (selectingApplet()) {
return;
}
apdu.setIncomingAndReceive();
byte[] buf = apdu.getBuffer();
if(buf[ISO7816.OFFSET_CLA]!=MS_CLA)
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
switch (buf[ISO7816.OFFSET_INS]) {
case (byte) 0x00:
break;
case (byte) 0x81:
Util.arrayCopyNonAtomic(studentID, (short)0, buf, (short)0, (short)10);
apdu.setOutgoingAndSend((short)0,(short)10);
return;
case (byte) 0x82:
Util.arrayCopyNonAtomic(name, (short)0, buf, (short)0, (short)7);
apdu.setOutgoingAndSend((short)0,(short)7);
return;
case (byte) 0x51:
Sidelength=buf[ISO7816.OFFSET_P1];
mineset=buf[ISO7816.OFFSET_P2];
maxsize=(short)(Sidelength*Sidelength);
Util.arrayCopyNonAtomic(buf,ISO7816.OFFSET_CDATA, checkerboard, (short)0, buf[ISO7816.OFFSET_LC]);
if(checkerboard[location]==0x11){
out[0]=03;
out[1]=00;
CF=1;
Util.arrayCopyNonAtomic(out, (short)0, buf, (short)0, (short)2);
apdu.setOutgoingAndSend((short)0,(short)2);
return;
}
else if(CF==1){CF=0;openrandom(apdu);}
else if(fstack.depth>0){doflag(apdu);} //待插旗栈不为空则继续插旗操作
else if(ostack.depth>0){doopen(apdu);} //待翻开栈不为空则继续翻开操作
else if(allflag==mineset){ //判断是否胜利
for(location=0;location<maxsize;location++){
if(checkerboard[location]==0x09){
out[0]=01;
out[1]=(byte) location;
Util.arrayCopyNonAtomic(out, (short)0, buf, (short)0, (short)2);
apdu.setOutgoingAndSend((short)0,(short)2);
return;}
}
out[0]=04;
out[1]=00;
CF=1;
Util.arrayCopyNonAtomic(out, (short)0, buf, (short)0, (short)2);
apdu.setOutgoingAndSend((short)0,(short)2);
}
else zhixing(Sidelength,checkerboard,apdu); //执行遍历棋盘操作
return;
default:
// good practice: If you don't know the INStruction, say so:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
private void zhixing(short Slength,byte [] boardinfo,APDU apdu){
for(location=0;location<maxsize;location++){
if(boardinfo[location]<=8 && boardinfo[location]>0){
setlocationXY(location);
if(boardinfo[location]!=0x00 |boardinfo[location]!=0x10)
{judge(location,boardinfo,Slength);
if(dark!=0){
if(boardinfo[location]==dark+flag)
{flagA();doflag(apdu);clrrstate();;break;}
if(boardinfo[location]==flag)
{openA();doopen(apdu);clrrstate();;break;}
clrrstate();
}
}
}
if(location==maxsize-1){
openrandom(apdu);return;
}
}
}
private void clrrstate() {
// TODO Auto-generated method stub
for(;rstack.depth>0;){rstack.pop();}
dark=0;
flag=0;
}
private void setlocationXY(short n){
locationX=(short) (n/Sidelength+1);
locationY=(short) (n%Sidelength+1);
}
private void judge(short locat,byte [] info,short size){
//判断周围的格子情况
if(locationX-1>0 && locationY-1>0 && locationX-1<=size && locationY-1<=size){
if(info[locat-size-1]==0x09)
{dark=(short) (dark+1);rstack.push((short)(locat-size-1));}
else if(info[locat-size-1]==0x10){flag=(short) (flag+1);}
}
if(locationX-1>0 && locationY>0 && locationX-1<=size && locationY<=size ){
if(info[locat-size]==0x09)
{dark=(short) (dark+1);rstack.push((short)(locat-size));}
else if(info[locat-size]==0x10){flag=(short) (flag+1);}
}
if(locationX-1>0 && locationY+1>0&& locationX-1<=size && locationY+1<=size){
if(info[locat-size+1]==0x09)
{dark=(short) (dark+1);rstack.push((short)(locat-size+1));}
else if(info[locat-size+1]==0x10){flag=(short) (flag+1);}
}
if(locationX>0 && locationY-1>0 && locationX<=size && locationY-1<=size){
if(info[locat-1]==0x09)
{dark=(short) (dark+1);rstack.push((short)(locat-1));}
else if(info[locat-1]==0x10){flag=(short) (flag+1);}
}
if(locationX>0 && locationY+1>0 && locationX<=size && locationY+1<=size){
if(info[locat+1]==0x09)
{dark=(short) (dark+1);rstack.push((short)(locat+1));}
else if(info[locat+1]==0x10){flag=(short) (flag+1);}
}
if(locationX+1>0 && locationY-1>0&& locationX+1<=size && locationY-1<=size){
if(info[locat+size-1]==0x09)
{dark=(short) (dark+1);rstack.push((short)(locat+size-1));}
else if(info[locat+size-1]==0x10){flag=(short) (flag+1);}
}
if(locationX+1>0 && locationY>0 && locationX+1<=size && locationY<=size ){
if(info[locat+size]==0x09)
{dark=(short) (dark+1);rstack.push((short)(locat+size));}
else if(info[locat+size]==0x10){flag=(short) (flag+1);}
}
if(locationX+1>0 && locationY+1>0&& locationX+1<=size && locationY+1<=size){
if(info[locat+size+1]==0x09)
{dark=(short) (dark+1);rstack.push((short)(locat+size+1));}
else if(info[locat+size+1]==0x10){flag=(short) (flag+1);}
}
}
private void openA(){
//为m位置周围所有的09做待翻开标记
for(;rstack.depth>0;){bufr=rstack.pop();ostack.push(bufr);}
}
private void flagA(){
//为m位置周围所有的09做待插旗标记
for(;rstack.depth>0;){bufr=rstack.pop();fstack.push(bufr);}
}
private void doopen(APDU apdu){
byte[]buffer=apdu.getBuffer();
out[0]=01;
out[1]= (byte) ostack.pop();
Util.arrayCopyNonAtomic(out, (short)0, buffer, (short)0, (short)2);
apdu.setOutgoingAndSend((short)0,(short)2);
}
private void doflag(APDU apdu){
allflag=(short) (allflag+1);
byte[]buffer=apdu.getBuffer();
out[0]=02;
out[1]= (byte) fstack.pop();
Util.arrayCopyNonAtomic(out, (short)0, buffer, (short)0, (short)2);
apdu.setOutgoingAndSend((short)0,(short)2);
return;
}
private void openrandom(APDU apdu){
//翻开一个未翻开的
short m=0;
location=0;
for(m=0;m<maxsize;m++){
if(checkerboard[m]==0x09){
byte[]buffer=apdu.getBuffer();
out[0]=01;
out[1]= (byte)m;
Util.arrayCopyNonAtomic(out, (short)0, buffer, (short)0, (short)2);
apdu.setOutgoingAndSend((short)0,(short)2);
break;}
}
}
}
总结
使用卡模拟器的时候运行的速度非常快,使用读卡器的时候运行速度大幅度下降,开始在遍历棋盘的时候没有加入判断是否为非暗格,结果第一步执行了足足41秒,加入判断后直接缩短到2秒,还是可以的。
在较大棋盘较少雷数下的表现还是不错的。
上一篇: 用ABAP代码实现从1累加到100
下一篇: 互联网安全架构--安全接口安全设计