import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import javax.microedition.io.Connector; import javax.microedition.io.StreamConnection; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Font; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Image; import javax.microedition.lcdui.game.GameCanvas; import javax.microedition.lcdui.game.Sprite; /** * GameClient 游戏客户端类 * 链接游戏服务器。 * 采用多线程技术,游戏主线,接收数据线程,送收数据线程, * 三种线程维护游戏的运作。 * 同一时间段内游戏主线程只与一个接收或发送数据线程并行运行 * 游戏中的坐标采用相对坐标,使得游戏的移植性相对好点。 */ public class GameClient extends GameCanvas implements Runnable, CommandListener { private Image chessImage = null; private Image bgImage = null; private Image redFruit = null; private Image whiteFruit = null; private Image redAngleImage = null; private Image whiteAngleImage = null; private Image winMessImage = null; private Image lossMessImage = null; private Image deuceMessImage = null; private Sprite redAngle = null; private Sprite whiteAngle = null; private Graphics g = null; /*游戏逻棋盘-游戏的水果架*/ private int fruitList[][] = new int[5][9]; private int halfWidth = 0; private int halfHeight = 0; private int basePointX = 0; private int basePointY = 0; /*玩家等候时的坐标*/ private int waitPointX = 0; private int waitPointY = 0; /*玩家运动时的坐标-下棋的状态*/ private int runPointX = 0; private int runPointY = 0; /*红色天使的当前坐标-对应玩家对手*/ private int redAngleCurrentX = 0; private int redAngleCurrentY = 0; /*白色天使的当前坐标-对应玩家*/ private int whiteAngleCurrentX = 0; private int whiteAngleCurrentY = 0; private int angleMoveOffsetX = 18; /*客户端是否停止链接*/ private boolean isRunning = true; /*游戏是否束结束*/ private boolean isGameOver = false; /*是否玩家在运动-下棋状态*/ private boolean isWhiteAngleRunning ; private static final int waitFrameSequence[] = {0,1,2,3,4,5,6,7,8,9,10,11}; private static final int runFrameSequence[] = {0,1,2}; private int position = 0;//--- private int count = 0; private int overStyle = 0; private Command cmdExit = new Command("退出游戏",Command.EXIT,1); private FlatMainMIDlet flatMainMidlet = null; /*链接字符串*/ private String connectURL = null; /*链接流*/ private StreamConnection client = null; /*数据输入流*/ private DataInputStream dis = null; /*数据输出流*/ private DataOutputStream dos = null; private int sI = 0; private int win = 0; private int loss = 0; private int deuce = 0; public GameClient(String connectURL, FlatMainMIDlet flatMainMidlet) { super(true); this.connectURL = connectURL; this.flatMainMidlet = flatMainMidlet; g = this.getGraphics(); addCommand(cmdExit); setCommandListener(this); halfWidth = this.getWidth()/2; halfHeight = this.getHeight()/2; basePointX = halfWidth-87; basePointY = halfHeight-83; waitPointX = halfWidth + 10; waitPointY = halfHeight + 60; runPointX = halfWidth - 90; runPointY = halfHeight+15; loadImage(); new Thread(this).start(); } public void run() { /*链接服务器*/ isRunning = true; try { /*链接服务器*/ client = (StreamConnection)Connector.open(connectURL); /*获得输入输出流*/ dis = client.openDataInputStream(); dos = client.openDataOutputStream(); } catch (Exception e) { return; } while(isRunning){ /*初使化游戏界面*/ initGameCanvas(); /*游戏循环主体*/ while(isGameOver!=true){ input(); updateSpriteFrame(); updateGameCanvas(); try { Thread.sleep(250); } catch (InterruptedException e) { e.printStackTrace(); } } showGameResult(); /*游戏次数自加*/ count++; } } public void commandAction(Command command, Displayable displayable) { /*退出游戏*/ if(command==cmdExit){ /*线程暂停*/ try { Thread.sleep(1000); } catch (InterruptedException e) { close(); return; } close(); flatMainMidlet.showFlatMenu(); } } public void loadImage() { try { chessImage = Image.createImage("/clessImage.png"); redAngleImage = Image.createImage("/red_angle.png"); whiteAngleImage = Image.createImage("/white_angle.png"); } catch (IOException e) { flatMainMidlet.showFlatMenu(); //System.out.println("图片加载出错"); } bgImage = Image.createImage(chessImage, 0, 0, 180, 208, Sprite.TRANS_NONE); winMessImage = Image.createImage(chessImage,0,270,150,60, Sprite.TRANS_NONE); lossMessImage = Image.createImage(chessImage,0,328,150,60, Sprite.TRANS_NONE) ; deuceMessImage = Image.createImage(chessImage,0,390,117,60, Sprite.TRANS_NONE); redFruit = Image.createImage(chessImage,164, 209, 16, 19, Sprite.TRANS_NONE); whiteFruit = Image.createImage(chessImage,164, 231, 16, 19, Sprite.TRANS_NONE); redAngle = new Sprite(redAngleImage,24,32); whiteAngle = new Sprite(whiteAngleImage,24,32); } private void initGameCanvas(){ isGameOver = false; for(int i = 0 ; i <= 4; i++){ for(int j = 0; j <= 8; j++){ fruitList[i][j] = 0; } } position = 0 ; /*设置精灵的初使位置*/ if(count%2==0){ /*设置天使精灵的初使位置*/ redAngle.setPosition(runPointX, runPointY); whiteAngle.setPosition(waitPointX, waitPointY); /*设置精录的初使帧序列*/ redAngle.setFrameSequence(runFrameSequence); whiteAngle.setFrameSequence(waitFrameSequence); redAngleCurrentX = runPointX; redAngleCurrentY = runPointY; whiteAngleCurrentX = waitPointX; whiteAngleCurrentY = waitPointY; /*设置红色天使可运动的状态*/ isWhiteAngleRunning = false; /*接收线程*/ new AcceptThread() .start(); } else{ /*设置天使精灵的初使位置*/ redAngle.setPosition(waitPointX, waitPointY); whiteAngle.setPosition(runPointX, runPointY); /*设置精录的初使帧序列*/ redAngle.setFrameSequence(waitFrameSequence); whiteAngle.setFrameSequence(runFrameSequence); redAngleCurrentX = waitPointX; redAngleCurrentY = waitPointY; whiteAngleCurrentX = runPointX; whiteAngleCurrentY = runPointY; /*设置红色天使可运动的状态*/ isWhiteAngleRunning = true; } } /** * 处理用户输入 * */ private void input() { if(isWhiteAngleRunning){ int keyState = getKeyStates(); /*向左*/ if((keyState & GameCanvas.LEFT_PRESSED) != 0){ if((whiteAngleCurrentX - angleMoveOffsetX)>=runPointX){ whiteAngleCurrentX = whiteAngleCurrentX - angleMoveOffsetX; position--; /*发送数据,新建发送数据线程*/ new SendThread(whiteAngleCurrentX).start(); } } /*向右*/ if((keyState & GameCanvas.RIGHT_PRESSED) != 0){ if((whiteAngleCurrentX + angleMoveOffsetX)<180){ whiteAngleCurrentX = whiteAngleCurrentX + angleMoveOffsetX; position++; //发送数据,新建发送数据线程 new SendThread(whiteAngleCurrentX).start(); } } /*重新设置红色天使精灵的位置*/ whiteAngle.setPosition(whiteAngleCurrentX, whiteAngleCurrentY); /*向上*/ if((keyState & GameCanvas.UP_PRESSED) != 0){ if(fruitList[4][position] ==0){ for(int i=0;i<5;i++) { if(fruitList[i][position]==0){ /*向水果架放置水果,白萝卜*/ fruitList[i][position]=2; /*判断输或和局*/ int flag = 0; sI = checkGameOver(i,position); flag = sI; if(sI == 1){ isGameOver = true; overStyle = 1; win++; }else if(sI == 3){ isGameOver = true; overStyle = 3; deuce++; } /*发送数据,新建发送数据线程*/ sI = sI*10000+ 1000 + i*10 + position; new SendThread(sI).start(); if(flag == 0) replaceRole(); break; } } } } } } /** * 更新游戏画面 * */ private void updateGameCanvas(){ /*设计背景填充为白色*/ g.setColor(0xFFFFFF); g.fillRect(0, 0, getWidth(), getHeight()); g.drawImage(bgImage, halfWidth, halfHeight,Graphics.VCENTER|Graphics.HCENTER); showfruits(); showSprites(); flushGraphics(); } /** * 更新精灵功画帧 * */ private void updateSpriteFrame(){ redAngle.nextFrame(); whiteAngle.nextFrame(); } /** * 显示平手的信息条 * */ private void showDeuceMessage(){ g.drawImage(deuceMessImage, halfWidth - 90, halfHeight + 104, Graphics.BOTTOM|Graphics.LEFT); } /** * 显示输的信息条 * */ private void showWinMessage(){ g.drawImage(winMessImage, halfWidth - 90, halfHeight + 104, Graphics.BOTTOM|Graphics.LEFT); } /** * 显示误蠃的信息条 * */ private void showLossMessage(){ g.drawImage(lossMessImage, halfWidth - 90, halfHeight + 104, Graphics.BOTTOM|Graphics.LEFT); } /** * 显示水果 * */ private void showfruits(){ for(int i=0;i<5;i++){ for(int j=0;j<9;j++) { if(fruitList[i][j]!=0) { if(fruitList[i][j]==1) { /*绘置红萝卜*/ g.drawImage(redFruit, basePointX + j*18, basePointY + i*20, Graphics.TOP|Graphics.LEFT); } else { /*绘置白萝卜*/ g.drawImage(whiteFruit, basePointX + j*18, basePointY + i*20, Graphics.TOP|Graphics.LEFT); } } } } } /** * 显示精灵 * */ private void showSprites(){ redAngle.paint(g); whiteAngle.paint(g); } /** * 置换角色 */ private void replaceRole(){ if(isWhiteAngleRunning){ whiteAngleCurrentX = waitPointX; whiteAngleCurrentY = waitPointY; redAngleCurrentX = runPointX; redAngleCurrentY = runPointY; whiteAngle.setPosition(whiteAngleCurrentX, whiteAngleCurrentY); redAngle.setPosition(redAngleCurrentX, redAngleCurrentY); whiteAngle.setFrameSequence(waitFrameSequence); redAngle.setFrameSequence(runFrameSequence); isWhiteAngleRunning = false; /*接收线程*/ new AcceptThread() .start(); } else{ whiteAngleCurrentX = runPointX; whiteAngleCurrentY = runPointY; redAngleCurrentX = waitPointX; redAngleCurrentY = waitPointY; whiteAngle.setPosition(whiteAngleCurrentX, whiteAngleCurrentY); redAngle.setPosition(redAngleCurrentX, redAngleCurrentY); whiteAngle.setFrameSequence(runFrameSequence); redAngle.setFrameSequence(waitFrameSequence); isWhiteAngleRunning = true; } position=0; getKeyStates(); getKeyStates(); /*线程暂停*/ try { Thread.sleep(200); } catch (InterruptedException e) { } } /** * 检测游戏结果/判断放下一个水果后的游戏结果 * @param row 水果架的行号 * @param colu 水果架的列号 * @return 1-赢 3-平手 0-没有结束 */ private int checkGameOver(int row,int colu){ /*赢棋的判断*/ int i = 0; int j = 0; int k = 0; /*垂直方向上的判断*/ if(row >= 3){ for(i=row-1;i >= 0;i--){ if(fruitList[i][colu]==2){ k++; } else{ break; } } } if(k >= 3){ return 1; } /*45角度方向上的判断*/ if((row+colu >= 3)&&(row + colu <= 9 )){ /*45向上查找*/ k = 0; for(i = row - 1, j = colu + 1;(i>=0)&&(j<=8);i--,j++ ){ if(fruitList[i][j] == 2){ k++; } else{ break; } } if(k >= 3){ return 1; } /*45向下查找*/ for(i = row + 1, j = colu - 1; (i <= 4)&&(j >= 0); i++, j--){ if(fruitList[i][j] == 2){ k++; } else{ break; } } if(k >= 3){ return 1; } } /*水平方向上的判断*/ k = 0; /*向左查找*/ for(i = colu - 1; i >= 0; i--){ if(fruitList[row][i] == 2){ k++; } else{ break; } } if(k>=3){ return 1; } /*向右查找*/ for(i = colu + 1; i <=8 ; i++){ if(fruitList[row][i] == 2){ k++; } else{ break; } } if(k >= 3){ return 1; } /*135度方向的判断*/ k = 0; /*135度向上查找*/ for(i = row - 1, j = colu - 1; (i >= 0)&&(j >= 0); i--,j--){ if(fruitList[i][j] == 2){ k++; } else{ break; } } if(k >= 3) return 1; /*135度向下查找*/ for(i = row + 1, j = colu + 1; (i <= 4)&&(j <= 8); i++, j++){ if(fruitList[i][j] == 2){ k++; } else{ break; } } if(k >= 3) return 1; /*和棋的判断*/ for(i = 0;i < 9;i++){ if(fruitList[4][i] == 0){ break; } } if(i==8){ return 3; } return 0; } /** * 显示游戏结果 * */ private void showGameResult(){ /*设计背景填充为白色*/ g.setColor(0xFFFFFF); g.fillRect(0, 0, getWidth(), getHeight()); g.drawImage(bgImage, halfWidth, halfHeight,Graphics.VCENTER|Graphics.HCENTER); showfruits(); showSprites(); g.setColor(0x000000); g.setFont(Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD,Font.SIZE_LARGE)); g.drawString("赢 " + win, halfWidth - 20, halfHeight -60, Graphics.TOP|Graphics.LEFT); g.drawString("输 " + loss, halfWidth - 20, halfHeight - 30, Graphics.TOP|Graphics.LEFT); g.drawString("平 " + deuce, halfWidth - 20, halfHeight , Graphics.TOP|Graphics.LEFT); switch(overStyle){ /*赢*/ case 1: showWinMessage(); break; /*输*/ case 2: showLossMessage(); break; /*和*/ case 3: showDeuceMessage(); break; } flushGraphics(); /*暂停3秒后在重新开始游戏*/ try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 关闭连接 */ public void close() { try { /*关闭输入流*/ if (dis != null) { dis.close(); dis = null; } /*关闭输出流*/ if (dos != null) { dos.close(); dos = null; } /*关闭客户端链接流*/ if (client != null) { client.close(); client = null; } } catch (Exception e) { } } /*内部类--发送数据的线程类*/ class SendThread extends Thread{ /*要发送的数据*/ private int data; public SendThread(int data){ this.data = data; } public void run(){ if (dos == null) { return; } try { dos.writeInt(data); dos.flush(); } catch (IOException e) { close(); return; } } } /*内部类--接收数据线程类*/ class AcceptThread extends Thread{ public void run(){ int i=10; while(i<1000){ try { if(dis == null){ return; } i = dis.readInt(); } catch (IOException e) { close(); return; } /*如果对手与放下水果,结束接收线程*/ if(i>=1000) break; redAngleCurrentX = i; redAngle.setPosition(redAngleCurrentX, redAngleCurrentY); } /*分解接收到的数据*/ int j = 0; int k = 0; int l = 0; l = i / 10000; /*最高位为1,对手赢*/ if(l == 1){ isGameOver = true; /*故自己输*/ overStyle = 2; loss++; /*分离出对手放的水果的坐标*/ j = (i -11000)/10; k = (i - 11000)%10; /*最高位为3,平手*/ }else if(l == 3){ isGameOver = true; overStyle = 3; deuce++; j = (i - 31000)/10; k = (i - 31000)%10; }else{ j = (i -1000)/10; k = (i - 1000)%10; } fruitList[j][k] = 1; /*没有结束,互换角色*/ if(l == 0){ replaceRole(); } } } }//