当前位置:七道奇文章资讯编程技术Java编程
日期:2011-03-22 16:13:00  来源:本站整理

<b>J2ME连连看底子功效源代码(含具体注释)</b>[Java编程]

赞助商链接



  本文“<b>J2ME连连看底子功效源代码(含具体注释)</b>[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:

//界面类代码
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
/**
* 连连看游戏界面
*/
public class LinkCanvas extends Canvas implements Runnable{
   /**游戏逻辑类*/
   GameEngine engine;  
   /**屏幕宽度*/
   int width;
   /**屏幕高度*/
   int height;
   public LinkCanvas(){
     //成立对象
     engine = new GameEngine();
     //得到屏幕的高度和宽度
     width = getWidth();
     height = getHeight();
     //启动线程
     Thread t = new Thread(this);
     t.start();
   }
   /**
   * 绘制办法
   */
   protected void paint(Graphics g) {
     //清屏
     clearScreen(g);
     //绘制地图
     engine.paintMap(g);
     //绘制挑选框
     engine.paintSelectArea(g);
     //绘制连线
     engine.paintLinkLine(g);
   }
   /**
   * 清屏办法
   * @param g 画笔
   */
   private void clearScreen(Graphics g){
     g.setColor(0xffffff);
     g.fillRect(0, 0, width, height);
     g.setColor(0);
   }
   public void keyPressed(int keyCode){
     int action = getGameAction(keyCode);
     switch(action){
     case UP:
       engine.moveUP();
       break;
     case DOWN:
       engine.moveDown();
       break;
     case LEFT:
       engine.moveLeft();
       break;
     case RIGHT:
       engine.moveRight();
       break;
     case FIRE:
       engine.fire();//挑选块
       break;
     }
   }
   public void run() {
     try{
       while(true){
         //延时
         Thread.sleep(100);
         //每次判断逻辑
         engine.action();
         repaint();
       }
     }catch(Exception e){
       e.printStackTrace();
     }
   }
}
//逻辑类源代码
import java.util.*;
import javax.microedition.lcdui.*;
/**
* 游戏数据和逻辑类
*/
public class GameEngine {
   /**选中块的个数*/
   private int selectTileNum = 0;
   //第一个挑选块的行号和列号
   /**行号*/
   private int firstRow;
   /**列号*/
   private int firstCol;
   //第二个挑选块的行号和列号
   /**行号*/
   private int secondRow;
   /**列号*/
   private int secondCol;
   //当前挑选框,默许在左上角
   /**当前挑选框的行号*/
   private int cRow;
   /**当前挑选框的列号*/
   private int cCol;
   /**最大行数*/
   private final int MAX_ROW = 10;
   /**最大列数*/
   private final int MAX_COL = 10;
   /**地图数据,0代表空,数据1-10辨别代表十种差别的构造*/
   private int[][] map = new int[MAX_ROW][MAX_COL];
   /**随机数对象*/
   private Random ran = new Random();
   //地图区域左上角的坐标
   private final int LEFTX = 20;
   private final int LEFTY = 50;
   /**每个单元格的宽度*/
   private final int TILE_WIDTH = 20;
   /**每个单元格的高度*/
   private final int TILE_HEIGHT = 20;
   /**连线范例*/
   private int linkType;
   /**无法连线*/
   private final int NO_LINK = 0;
   /**水平连线*/
   private final int H_LINK = 1;
   /**垂直接洽*/
   private final int V_LINK = 2;
   /**一个拐点,先移动x*/
   private final int ONE_CORNER_FIRSTX = 3;
   /**一个拐点,先移动y*/
   private final int ONE_CORNER_FIRSTY = 4;
   /**两个拐点,待完善*/
   private final int TWO_CORNER = 5;
   /**
   * 两次拐弯的行号和列号
   * 数据格局为:
   *  第一个拐点的行号,第一个拐点的列号,第二个拐点的行号,第二个拐点的列号
   */
   int[] p = new int[4];
   public GameEngine(){
     //初始化地图数据
     initMap();
   }
   /**
   * 初始化地图数据
   */
   private void initMap(){
     for(int row = 0;row < map.length;row++){
       for(int col = 0;col < map[row].length;col++){
         map[row][col] = row + 1;
       }
     }
     //循环打乱10次
     int tempRow;
     int tempCol;
     int temp;
     for(int i = 0;i < 10;i++){
       for(int row = 0;row < map.length;row++){
         for(int col = 0;col < map[row].length;col++){
           //随机行号
           tempRow = Math.abs(ran.nextInt() % 10);
           //随机列号
           tempCol = Math.abs(ran.nextInt() % 10);
           //假如不是同一个单元格,则交换数据
           if(!((tempRow == row) && (tempCol == col))){
             temp = map[row][col];
             map[row][col] = map[tempRow][tempCol];
             map[tempRow][tempCol] = temp;
           }
         }
       }
     }
   }
   /**
   * 绘制地图数据
   * @param g 画笔
   */
   public void paintMap(Graphics g){
     for(int row = 0;row < map.length;row++){
       for(int col = 0;col < map[row].length;col++){
         //假如没有数据,则跳过
         if(map[row][col] == 0){
           continue;
         }else{//绘制方块
           //绘制方框
           g.drawRect(LEFTX + col * TILE_WIDTH, LEFTY + row * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
           //绘制数字
           g.drawString(String.valueOf(map[row][col]), LEFTX + col * TILE_WIDTH + 5,
               LEFTY + row * TILE_HEIGHT + 4,
               Graphics.TOP | Graphics.LEFT);
         }
       }
     }
   }
   /**
   * 绘制挑选框
   * @param g 画笔
   */
   public void paintSelectArea(Graphics g){
     //绘制当前挑选框
     g.setColor(0xff00);
     g.drawRect(LEFTX + cCol * TILE_WIDTH, LEFTY + cRow * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
     g.setColor(0);
     //绘制选中项
     switch(selectTileNum){
     case 1: //挑选一个
       g.setColor(0xff0000);
       g.drawRect(LEFTX + firstCol * TILE_WIDTH, LEFTY + firstRow * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
       g.setColor(0);
       break;
     case 2: //选中两个
       g.setColor(0xff0000);
       g.drawRect(LEFTX + firstCol * TILE_WIDTH, LEFTY + firstRow * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
       g.drawRect(LEFTX + secondCol * TILE_WIDTH, LEFTY + secondRow * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
       g.setColor(0);
       break;
     }
   }
   /**
   * 绘制方块连线
   * @param g 画笔
   */
   public void paintLinkLine(Graphics g){
     //假如无连线,则直接返回
     if(linkType == NO_LINK){
       return;
     }
     //按照连线范例实现绘制
     //绘制到方块的中央点
     switch(linkType){
     case H_LINK://水平
     case V_LINK://垂直
       paintLine(g,firstRow,firstCol,secondRow,secondCol);
       break;
     case ONE_CORNER_FIRSTX://一个拐弯,先移动X
       //水平线
       paintLine(g,firstRow,firstCol,firstRow,secondCol);
       //垂直线
       paintLine(g,firstRow,secondCol,secondRow,secondCol);
       break;
     case ONE_CORNER_FIRSTY://一个拐弯,先移动Y
       //水平线
       paintLine(g,firstRow,firstCol,secondRow,firstCol);
       //垂直线
       paintLine(g,secondRow,firstCol,secondRow,secondCol);
       break;
     case TWO_CORNER:
       //块1到第一个拐点的连线
       paintLine(g,firstRow,firstCol,p[0],p[1]);
       //两个拐点之间的连线
       paintLine(g,p[0],p[1],p[2],p[3]);
       //第二个拐点到块2的连线
       paintLine(g,p[2],p[3],secondRow,secondCol);
       break;
     }
     //逻辑代码,排除衔接范例
     linkType = NO_LINK;
   }
   /**
   * 绘制两个方块中央点的连线
   * @param g 画笔
   * @param r1 方块1的行号
   * @param c1 方块1的列号
   * @param r2 方块2的行号
   * @param c2 方块2的列号
   */
   private void paintLine(Graphics g,int r1,int c1,int r2,int c2){
     g.drawLine(LEFTX + c1 * TILE_WIDTH + TILE_WIDTH/2,
         LEFTY + r1 * TILE_HEIGHT + TILE_HEIGHT/2,
         LEFTX + c2 * TILE_WIDTH + TILE_WIDTH/2,
         LEFTY + r2 * TILE_HEIGHT + TILE_HEIGHT/2);
   }
   /**
   * 向左移动挑选框
   */
   public void moveLeft(){
     if(cCol > 0){
       cCol--;
     }
   }
   /**
   * 向右移动挑选框
   */
   public void moveRight(){
     if(cCol < MAX_COL -1){
       cCol++;
     }
   }
   /**
   * 向上移动挑选框
   */
   public void moveUP(){
     if(cRow > 0){
       cRow--;
     }
   }
   /**
   * 向下移动挑选框
   */
   public void moveDown(){
     if(cRow < MAX_ROW - 1){
       cRow++;
     }
   }
   /**
   * 肯定键逻辑处理
   */
   public void fire(){
     //假如挑选的块为空,则直接返回
     if(map[cRow][cCol] == 0){
       return;
     }
     //选中的块的数目增添1
     selectTileNum++;
     //辨别存储位置
     switch(selectTileNum){
     case 1: //第一次挑选
       firstRow = cRow;
       firstCol = cCol;
       break;
     case 2: //第二次挑选
       //挑选同一个块,2个挑选块都失去选中
       if((firstRow == cRow) && (firstCol == cCol)){
         selectTileNum = 0;
         return;
       }
       secondRow = cRow;
       secondCol = cCol;
       break;
     }
   }
   /**
   * 判断(r1,c1)块和(r2,c2)块中间能否为空行
   * 不包含这两个块
   * @param r1 块1的行号
   * @param c1 块1的列号
   * @param r2 块2的行号
   * @param c2 块2的列号
   * @return true代表为空,false代表不为空
   */  
   private boolean isEmptyRow(int r1,int c1,int r2,int c2){
     //判断能否位于同一行
     if(r1 != r2){
       return false;
     }
     //判断两个块的相对位置
     if(c1 > c2){ //第一块位于右侧
       for(int col = c1 - 1;col > c2;col--){
         //假若有非空块
         if(map[r1][col] != 0){
           return false;
         }
       }
     }else{ //第一块位于左侧
       for(int col = c2 - 1;col > c1;col--){
         //假若有非空块
         if(map[r1][col] != 0){
           return false;
         }
       }
     }
     return true;
   }
   /**
   * 判断块(r1,c1)和块(r2,c2)之间能否是空列
   * 不包含这两个块
   * @param r1 块1的行号
   * @param c1 块1的列号
   * @param r2 块2的行号
   * @param c2 块2的列号
   * @return true代表为空,false代表不为空
   */
   private boolean isEmptyCol(int r1,int c1,int r2,int c2){
     //判断能否位于同一列
     if(c1 != c2){
       return false;
     }
     //判断两个块的相对位置
     if(r2 > r1){//第一个块在上方
       for(int row = r1 + 1;row < r2;row++){
         //假若有非空块
         if(map[row][c1] != 0){
           return false;
         }
       }
     }else{//第二个块在上方
       for(int row = r2 + 1;row < r1;row++){
         //假若有非空块
         if(map[row][c1] != 0){
           return false;
         }
       }
     }
     return true;
   }
   /**
   * 判断一个块能否为空
   * @param r 块的行号
   * @param c 块的列号
   * @return true代表为空,false代表不空
   */
   private boolean isEmptyCell(int r,int c){
     return map[r][c] == 0;
   }  
   /**
   * 能否是一次转弯实现连线
   * @return NO_LINK代表没有连线,其他值代表对应的连线范例
   */
   private int isOneCornerLink(int r1,int c1,int r2,int c2){
     //先移动行,再移动列
     if(isEmptyCell(r1,c2)){ //转折点为空
       if(isEmptyRow(r1,c1,r1,c2) & isEmptyCol(r1,c2,r2,c2)){
         return ONE_CORNER_FIRSTX;
       }
     }
     //先移动列,再移动行
     if(isEmptyCell(r2,c1)){//转折点为空
       if(isEmptyCol(r1,c1,r2,c1) & isEmptyRow(r2,c1,r2,c2)) {
         return ONE_CORNER_FIRSTY;
       }
     }
     //无衔接
     return NO_LINK;
   }
   /**
   * 能否经过2次转折实现衔接
   * @param r1 块1的行号
   * @param c1 块1的列号
   * @param r2 块2的行号
   * @param c2 块2的列号
   * @return true代表可以衔接,false代表不能
   */
   private boolean isTwoCornerLink(int r1,int c1,int r2,int c2){
     int result;
     //正常情形,划分成4个方向
     //块1向上
     for(int row = r1 -1;row >= 0;row--){
       //假若有数据不为空,则直接完毕该方向的尝试
       if(map[row][c1] != 0){
         break;
       }
       //存储第一个拐点的坐标
       p[0] = row;
       p[1] = c1;
       //每次都尝试转折,则变成一个转点的操作
       result = isOneCornerLink(row,c1,r2,c2);
       //假如可以衔接
       if(result != NO_LINK){
         //存储第二个拐点的位置
         switch(result){
         case ONE_CORNER_FIRSTX:
           p[2] = row;
           p[3] = c2;
           break;
         case ONE_CORNER_FIRSTY:
           p[2] = r2;
           p[3] = c1;
           break;
         }
         return true;
       }
     }
     //块1向下
     for(int row = r1 + 1;row < MAX_ROW;row++){
       //假若有数据不为空,则直接完毕该方向的尝试
       if(map[row][c1] != 0){
         break;
       }
       //存储第一个拐点的坐标
       p[0] = row;
       p[1] = c1;
       //每次都尝试转折,则变成一个转点的操作
       result = isOneCornerLink(row,c1,r2,c2);
       //假如可以衔接
       if(result != NO_LINK){
         //存储第二个拐点的位置
         switch(result){
         case ONE_CORNER_FIRSTX:
           p[2] = row;
           p[3] = c2;
           break;
         case ONE_CORNER_FIRSTY:
           p[2] = r2;
           p[3] = c1;
           break;
         }
         return true;
       }
     }
     //块1向左
     for(int col = c1 -1;col >= 0;col--){
       //假若有数据不为空,则直接完毕该方向的尝试
       if(map[r1][col] != 0){
         break;
       }
       //存储第一个拐点的坐标
       p[0] = r1;
       p[1] = col;
       //每次都尝试转折,则变成一个转点的操作
       result = isOneCornerLink(r1,col,r2,c2);
       //假如可以衔接
       if(result != NO_LINK){
         //存储第二个拐点的位置
         switch(result){
         case ONE_CORNER_FIRSTX:
           p[2] = r1;
           p[3] = c2;
           break;
         case ONE_CORNER_FIRSTY:
           p[2] = r2;
           p[3] = col;
           break;
         }
         return true;
       }
     }
     //块1向右
     for(int col = c1 + 1;col < MAX_COL;col++){
       //假若有数据不为空,则直接完毕该方向的尝试
       if(map[r1][col] != 0){
         break;
       }
       //存储第一个拐点的坐标
       p[0] = r1;
       p[1] = col;
       //每次都尝试转折,则变成一个转点的操作
       result = isOneCornerLink(r1,col,r2,c2);
       //假如可以衔接
       if(result != NO_LINK){
         //存储第二个拐点的位置
         switch(result){
         case ONE_CORNER_FIRSTX:
           p[2] = r1;
           p[3] = c2;
           break;
         case ONE_CORNER_FIRSTY:
           p[2] = r2;
           p[3] = col;
           break;
         }
         return true;
       }
     }
     //四个特例,也就是超越地图区域的衔接
     //实现地图区域上侧的衔接,也就是到上侧是一个空列
     if((isEmptyCol(r1,c1,-1,c1)) & (isEmptyCol(r2,c2,-1,c2))){
       p[0] = -1;
       p[1] = c1;
       p[2] = -1;
       p[3] = c2;
       return true;
     }
     //左侧
     if((isEmptyRow(r1,c1,r1,-1)) & (isEmptyRow(r2,c2,r2,-1))){
       p[0] = r1;
       p[1] = -1;
       p[2] = r2;
       p[3] = -1;
       return true;
     }
     //下侧
     if((isEmptyCol(r1,c1,MAX_ROW,c1)) & (isEmptyCol(r2,c2,MAX_ROW,c2))){
       p[0] = MAX_ROW;
       p[1] = c1;
       p[2] = MAX_ROW;
       p[3] = c2;
       return true;
     }
     //右侧
     if((isEmptyRow(r1,c1,r1,MAX_COL)) & (isEmptyRow(r2,c2,r2,MAX_COL))){
       p[0] = r1;
       p[1] = MAX_COL;
       p[2] = r2;
       p[3] = MAX_COL;
       return true;
     }    
     return false;
   }
   /**
   * 逻辑判断能否有连线
   * @return NO_LINK代表无连线,别的数据代表有连线
   */
   private int logic(){
     //假如数值差别
     if(map[firstRow][firstCol] != map[secondRow][secondCol]){
       return NO_LINK;
     }
     //判断衔接方法
     if(isEmptyRow(firstRow,firstCol,secondRow,secondCol)){ //水平连线
       return H_LINK;
     }
     if(isEmptyCol(firstRow,firstCol,secondRow,secondCol)){//垂直连线
       return V_LINK;
     }
     //一个转点的衔接
     int result = isOneCornerLink(firstRow,firstCol,secondRow,secondCol);
     if(result != NO_LINK){
       return result;
     }
     //两个转点的衔接
     if(isTwoCornerLink(firstRow,firstCol,secondRow,secondCol)){
       return TWO_CORNER;
     }    
     //返回无衔接
     return NO_LINK;
   }
   /**
   * 逻辑辨别和逻辑处理
   */
   public boolean action(){
     //判断能否挑选两个方块
     if(selectTileNum != 2){
       return false;
     }
     boolean b = false;
     //判断能否有连线
     linkType = logic();
     //假若有连线,则消逝
     if(linkType != NO_LINK){
       map[firstRow][firstCol] = 0;
       map[secondRow][secondCol] = 0;
       b = true;
     }
     //挑选的块数初始化
     selectTileNum = 0;
     return b;
   }
}

文章根源:http://blog.csdn.net/Mailbomb/archive/2008/04/25/2328133.aspx


  以上是“<b>J2ME连连看底子功效源代码(含具体注释)</b>[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • <b>hosts是什么 hosts文件在什么位置 若何改正hosts</b>
  • <b>在 Windows 8 中手动安装语言包</b>
  • <b>五个常见 PHP数据库问题</b>
  • Windows中Alt键的12个高效快速的利用本领介绍
  • <b>MySQL ORDER BY 的实现解析</b>
  • <b>详解MySQL存储历程参数有三种范例(in、out、inout)</b>
  • <b>Win8系统恢复出来经典的开始菜单的办法</b>
  • <b>Win8系统花屏怎么办 Win8系统花屏的办理办法</b>
  • <b>Windows 7系统下无线网卡安装</b>
  • <b>为什么 Linux不需求碎片整理</b>
  • <b>Windows 8中删除账户的几种办法(图)</b>
  • <b>教你如安在win7下配置路由器</b>
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .