import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import javax.bluetooth.BluetoothStateException; import javax.bluetooth.DataElement; import javax.bluetooth.DiscoveryAgent; import javax.bluetooth.LocalDevice; import javax.bluetooth.ServiceRecord; import javax.microedition.io.Connector; import javax.microedition.io.StreamConnection; import javax.microedition.io.StreamConnectionNotifier; 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; /** * GameServer 游戏服务器类 * 创建游戏等侍客户端的链接。 * 采用多线程技术,游戏主线程,接收数据线程,送收数据线程, * 三种线程维护游戏的运作。 * 同一时间段内游戏主线程只与一个接收或发送数据线程并行运行。 * 游戏中的坐标采用相对坐标,使得游戏的移植性相对好点。 */ public class GameServer 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 waitMessImage = 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 isRedAngleRunning ; /*等待时的动画帧*/ 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 Command cmdExit = new Command("退出游戏",Command.EXIT,1); private FlatMainMIDlet flatMainMidlet = null; private String userName = null; private int sI = 0; /*游戏结束类型 1 赢 2 输 3 平手*/ private int overStyle = 0; private int win = 0; private int loss = 0; private int deuce = 0; /*服务链接器*/ StreamConnectionNotifier server = null; //服务器服务记录 ServiceRecord record=null; //数据输入流 private DataInputStream dis = null; //数据输出流 private DataOutputStream dos = null; public GameServer(FlatMainMIDlet flatMainMidlet ,String name) { super(true); this.flatMainMidlet = flatMainMidlet; this.userName = name; 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; LocalDevice local = null; try { /*设置设备的发现模式,使设备处可发现*/ local = LocalDevice.getLocalDevice(); local.setDiscoverable(DiscoveryAgent.GIAC); } catch (BluetoothStateException e) { return; } try { /*开启服务*/ server = (StreamConnectionNotifier)Connector.open( "btspp://localhost:33333333333333333333333333333333"); /*服务器服务记录*/ ServiceRecord record = local.getRecord(server); /*自定义服务记录属性*/ DataElement elm = null; elm = new DataElement(DataElement.STRING, userName); record.setAttributeValue(0x1234, elm); elm = null; elm = new DataElement(DataElement.STRING, "SCHOLAR_II"); record.setAttributeValue(0x1235, elm); /*更新服务记录属性*/ local.updateRecord(record); } catch (IOException e) { return; } initWaitGameCanvas(); /*等待用户的链接*/ StreamConnection conn = null; try { /*等待客户端的链接*/ conn = server.acceptAndOpen(); /*客户端链接后,关闭发现模式*/ local.setDiscoverable(DiscoveryAgent.NOT_DISCOVERABLE); } catch (IOException e) { return; } /*获得输入输出流*/ try { dis = conn.openDataInputStream(); dos = conn.openDataOutputStream(); } catch (IOException e) { close(); return; } while(isRunning){ /*初使化游戏界面*/ initGameCanvas(); /*游戏循环主体*/ while(isGameOver!=true){ input(); updateSpriteFrame(); updateGameCanvas(); try { Thread.sleep(400); } catch (InterruptedException e) { close(); return; } } showGameResult(); /*游戏次数加1*/ 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(); } bgImage = Image.createImage(chessImage, 0, 0, 180, 208, Sprite.TRANS_NONE); waitMessImage = Image.createImage(chessImage, 0, 210, 150, 60, 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 initWaitGameCanvas(){ /*设计背景填充为白色*/ g.setColor(0xFFFFFF); g.fillRect(0, 0, getWidth(), getHeight()); g.drawImage(bgImage, halfWidth, halfHeight,Graphics.VCENTER|Graphics.HCENTER); showWaitMessage(); flushGraphics(); } private void initGameCanvas(){ isGameOver = false; position = 0; for(int i = 0 ; i <= 4; i++){ for(int j = 0; j <= 8; j++){ fruitList[i][j] = 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; /*设置红色天使可运动的状态*/ isRedAngleRunning = true; } else{ /*设置天使精灵的初使位置*/ redAngle.setPosition(waitPointX, waitPointY); whiteAngle.setPosition(runPointX, runPointY); /*设置精录的初使帧序列*/ redAngle.setFrameSequence(waitFrameSequence); whiteAngle.setFrameSequence(runFrameSequence); redAngleCurrentX = waitPointX; redAngleCurrentY = waitPointY; whiteAngleCurrentX = runPointX; whiteAngleCurrentY = runPointY; /*设置红色天使可运动的状态*/ isRedAngleRunning = false; /*接收线程*/ new AcceptThread().start(); } } /** * 处理用户输入 * */ private void input() { if(isRedAngleRunning){ int keyState = getKeyStates(); /*向左*/ if((keyState & GameCanvas.LEFT_PRESSED) != 0){ if((redAngleCurrentX - angleMoveOffsetX)-runPointX >= 0){ redAngleCurrentX = redAngleCurrentX - angleMoveOffsetX; position--; //发送数据,新建发送数据线程 new SendThread(redAngleCurrentX).start(); } } /*向右*/ if((keyState & GameCanvas.RIGHT_PRESSED) != 0){ if((redAngleCurrentX + angleMoveOffsetX)-(halfWidth + 70) < 0 ){ redAngleCurrentX = redAngleCurrentX + angleMoveOffsetX; position++; //发送数据,新建发送数据线程 new SendThread(redAngleCurrentX).start(); } } /*重新设置红色天使精灵的位置*/ redAngle.setPosition(redAngleCurrentX, redAngleCurrentY); /*向上*/ 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]=1; /*判断输或和局*/ 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 showWaitMessage(){ g.drawImage(waitMessImage, halfWidth - 2, halfHeight - 25 , Graphics.VCENTER|Graphics.HCENTER); } /** * 显示 平手的信息条 * */ 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(isRedAngleRunning){ whiteAngleCurrentX = runPointX; whiteAngleCurrentY = runPointY; redAngleCurrentX = waitPointX; redAngleCurrentY = waitPointY; whiteAngle.setPosition(whiteAngleCurrentX, whiteAngleCurrentY); redAngle.setPosition(redAngleCurrentX, redAngleCurrentY); whiteAngle.setFrameSequence(runFrameSequence); redAngle.setFrameSequence(waitFrameSequence); isRedAngleRunning = false; /*接收线程*/ new AcceptThread().start(); } else{ whiteAngleCurrentX = waitPointX; whiteAngleCurrentY = waitPointY; redAngleCurrentX = runPointX; redAngleCurrentY = runPointY; whiteAngle.setPosition(whiteAngleCurrentX, whiteAngleCurrentY); redAngle.setPosition(redAngleCurrentX, redAngleCurrentY); whiteAngle.setFrameSequence(waitFrameSequence); redAngle.setFrameSequence(runFrameSequence); isRedAngleRunning = 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]==1){ 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] == 1){ 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] == 1){ k++; } else{ break; } } if(k >= 3){ return 1; } } /*水平方向上的判断*/ k = 0; /*向左查找*/ for(i = colu - 1; i >= 0; i--){ if(fruitList[row][i] == 1){ k++; } else{ break; } } if(k>=3){ return 1; } /*向右查找*/ for(i = colu + 1; i <=8 ; i++){ if(fruitList[row][i] == 1){ 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] == 1){ 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] == 1){ k++; } else{ break; } } if(k >= 3) return 1; /*和棋的判断*/ for(i = 0;i <= 8;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) { close(); flatMainMidlet.showFlatMenu(); } } /** * 关闭连接 */ public void close() { try { /*关闭输入流*/ if (dis != null) { dis.close(); dis = null; } /*关闭输出流*/ if (dos != null) { dos.close(); dos = null; } /*关闭服务器*/ if (server != null) { server.close(); server = null; } } catch (Exception e) { flatMainMidlet.showFlatMenu(); } } /*内部类--发送数据的线程类*/ 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 { i = dis.readInt(); } catch (IOException e) { close(); return; } /*如果对手与放下水果,结束接收线程*/ if(i>=1000) break; whiteAngleCurrentX = i; whiteAngle.setPosition(whiteAngleCurrentX, whiteAngleCurrentY); } /*分解接收到的数据*/ 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] = 2; /*没有结束,互换角色*/ if(l == 0){ replaceRole(); } } } }//GameServer.java文件结束