由 北大青鸟(骑士飞行棋)Demo 联想到了地图中的河流、路线绘制

来源:互联网 发布:德拉蒙德格林数据 编辑:程序博客网 时间:2024/04/30 15:18
 

--startGame类

public class StartGame {

    /**

     * 启动游戏

     * @param args

     */

    public static void main(String[] args) {

       Game game = new Game();   //创建游戏类

        game.start();             //开始游戏

    }

}

 

--Game类

import java.util.*;

public class Game {

      Map map;  //地图

      int playerPos1; //对战中玩家1的当前位置

      int playerPos2; //对战中玩家2的当前位置

      String[] goAndStop = new String[2];   //走或停标识设置

      String[] playerName = new String[2];  //对战角色

     

      /**

       * 初始化游戏的一局

       */

      public void init(){  

          map = new Map();

          map.createMap();  //生成地图

           playerPos1 = 0;   //设置玩家1起始位置

           playerPos2 = 0;   //设置玩家2起始位置

           goAndStop[0] = "on";  //记录玩家1下一次走或停

           goAndStop[1] = "on";  //设置玩家2下一次走或停

      }

     

     

      /**

       * 开始游戏

       */

      public void start(){

          //初始化

          init(); 

      System.out.println("※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※");

      System.out.println("//                                                //");

      System.out.println("//                                                //");

      System.out.println("//             骑    士    飞    行    棋               //");

      System.out.println("//                                                //");

      System.out.println("//                                                //");

      System.out.println("※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※\n\n\n");

      

      

      System.out.println("\n~~~~~~~~~~~~~~~~~~~两  人  对  战~~~~~~~~~~~~~~~~~~~");

      System.out.println("\n请选择角色: 1. 戴高乐 2. 艾森豪威尔 3. 麦克阿瑟 4. 巴顿");

      Scanner input = new Scanner(System.in);

      System.out.print("请玩家1选择角色:  ");

      int role1 = input.nextInt();

          int role2;

          do{

          System.out.print("请玩家2选择角色: ");

              role2 = input.nextInt();  //双方选择角色代号

          }while(role2==role1);  //不允许角色重复

          setRole(1, role1);   //设置玩家1代表的角色

          setRole(2, role2);   //设置玩家2代表的角色    

          play();   //开始两人对战

      }

     

      /**

       * 设置对战角色

       * @param no 玩家次序 1:玩家1 2:玩家2

       * @param role 角色代号

       */

      public void setRole(int no,int role){

      switch(role){

          case 1:

              playerName[no-1] = "戴高乐";

              break;

          case 2:

              playerName[no-1] = "艾森豪威尔";

              break;

          case 3:

              playerName[no-1] = "麦克阿瑟";

              break;

          case 4:

              playerName[no-1] = "巴顿";

              break;

          default:

              break;

      }

      }

     

     

      /**

       * 两人对战玩法

       */

      public void play(){  

          System.out.println("\n\n\n\n");

         

      System.out.print("\n\n****************************************************\n");

      System.out.print("                     Game  Start                    \n");

      System.out.print("****************************************************\n\n");

      

      //显示对战双方士兵样式

      System.out.println("^_^" + playerName[0] + "的士兵: A");

      System.out.println("^_^" + playerName[1] + "的士兵:  B\n");

         

      //显示对战地图

      System.out.println("\n图例: " + "■ 暂停  ¡è 幸运轮盘   ★ 地雷   〓 时空隧道   ∷ 普通\n");

         

          map.showMap(playerPos1, playerPos2);

         

         

      //游戏开始

      int step;  //存储骰子数目

          while(playerPos1 < 99 && playerPos2 < 99){   //有任何一方走到终点,跳出循环

          

          //轮流掷骰子

          if(goAndStop[0].equals("on")){   

                  //玩家1掷骰子

                step = throwShifter(1);   //掷骰子

                System.out.println("\n-----------------");  //显示结果信息

               System.out.println("骰子数: "+ step);

               playerPos1 = getCurPos(1, playerPos1, step);   //计算这一次移动后的当前位置

               System.out.println("\n您当前位置:  "+ playerPos1);

               System.out.println("对方当前位置:"+ playerPos2);

               System.out.println("-----------------\n");

               map.showMap(playerPos1, playerPos2); //显示当前地图

               if(playerPos1 == 99){  //如果走到终点

                   break;   //退出

                }

          }else{

              System.out.println("\n" + playerName[0] +"停掷一次!\n");   //显示此次暂停信息

              goAndStop[0] = "on";   //设置下次可掷状态

          }

 

          

              System.out.println("\n\n\n\n");

          

          if(goAndStop[1].equals("on")){

                  //玩家2掷骰子

               step = throwShifter(2); //掷骰子

               System.out.println("\n-----------------"); //显示结果信息

               System.out.println("骰子数: "+ step);

               playerPos2 = getCurPos(2, playerPos2, step);   //计算这一次移动后的当前位置

               System.out.println("\n您当前位置:  "+ playerPos2);

               System.out.println("对方当前位置:"+ playerPos1);

               System.out.println("-----------------\n");

               map.showMap(playerPos1, playerPos2);

               if(playerPos2 == 99){  //如果走到终点

                   break;   //退出

                }

          }else{

              System.out.println("\n" + playerName[1] + "停掷一次!\n");  //显示此次暂停信息

              goAndStop[1] = "on";  //设置下次可掷状态

          }

 

          System.out.println("\n\n\n\n");

      }

         

          //游戏结束

          System.out.println("\n\n\n\n");

          System.out.print("****************************************************\n");

      System.out.print("                      Game  Over                    \n");

      System.out.print("****************************************************\n\n");

          judge();

      }

     

     

      /**

       * 掷骰子

       * @param no 玩家次序

       * @return step 掷出的骰子数目

       */

      public int throwShifter(int no){

      int step = 0; 

      System.out.print("\n\n" + playerName[no-1] + ", 请您按任意字母键后回车启动掷骰子: ");

      Scanner input = new Scanner(System.in);

      String answer = input.next();

          step = (int)(Math.random()*10) % 6 + 1;   //产生一个1~6的数字,即掷的骰子数目

      return step;

      }

     

 

     

      /**

       * 计算玩家此次移动后的当前位置

       * @param no 玩家次序

       * @param position 移动前位置

       * @param step 掷的骰子数目

       * @return position 移动后的位置

       */

      public int getCurPos(int no,int position,int step){

      position = position + step;  //第一次移动后的位置

      if(position >= 99){

          return 99;

      }

      Scanner input = new Scanner(System.in);

      switch(map.map[position]){   //根据地图中的关卡代号进行判断

         case 0:    //走到普通格

          if(no ==1 && playerPos2 == position){   //玩家1与对方骑兵相遇

             playerPos2 = 0;    //踩到对方,对方回到起点

             System.out.println(":-D  哈哈哈哈...踩到了!");

          }

          if (no == 2 && playerPos1 == position){ //玩家2与对方骑兵相遇

             playerPos1 = 0;    //踩到对方,对方回到起点

             System.out.println(":-D  哈哈哈哈...踩到了!");

          }

             break;

             case 1:   //幸运轮盘

             System.out.println("\n◆◇◆◇◆欢迎进入幸运轮盘◆◇◆◇◆");

             System.out.println("   请选择一种运气:");

             System.out.println("   1. 交换位置  2. 轰炸");

             System.out.println("=============================\n");

             int choice  = input.nextInt();

             int temp;

             switch(choice){

                 case 1:

                  if(no == 1){

                      temp = position;

                         position = playerPos2;

                         playerPos2 = temp;

                  }else if(no == 2){

                      temp = position;

                         position = playerPos1;

                         playerPos1 = temp;

                  }

                  break;

                 case 2:

                  if(no == 1 && playerPos2 < 6){

                      playerPos2 = 0;

                  }else{

                      playerPos2 = playerPos2 - 6;

                  }

                  if(no == 2 && playerPos2 < 6){

                      playerPos1 = 0;

                  }else{

                      playerPos1 = playerPos1 - 6;

                  }

                  break;

             }

             //System.out.println(":~)  " + "幸福的我都要哭了...");

             break;

            case 2:   //踩到地雷

            position = position -6; //踩到地雷退6步

            System.out.println("~:-(  " + "踩到地雷,气死了...");

            break;

            case 3:  //下一次暂停一次

            goAndStop[no-1] = "off";  //设置下次暂停掷骰子

            System.out.println("~~>_<~~  要停战一局了。");

            break;

            case 4:   //时空隧道

                position = position + 10;  //进入时空隧道,加走10步

                System.out.println("|-P  " + "进入时空隧道, 真爽!");

                break;

      }

      

      //返回此次掷骰子后玩家的位置坐标   

      if(position < 0){

          return 0;

      }else if(position > 99){

          return 99;

      }else{

          return position;

      }

      }

     

      /**

       * 显示对战结果

       */

      public void judge(){

      if(playerPos1 > playerPos2){

          System.out.println("\n恭喜" + playerName[0] + "将军! 您获胜了!");

      }else{

          System.out.println("\n恭喜" + playerName[1] + "将军! 您获胜了!");

      }

      }

}

 

 

--Map类

public class Map {

    int[] map = new int[100];   //对战地图

    int[] luckyTurn = {6, 23, 40, 55, 69, 83}; //幸运轮盘

    int[] landMine = {5, 13, 17, 33, 38, 50, 64, 80, 94};   //地雷位置

    int[] pause = {9, 27, 60, 93};         //暂停

    int[] timeTunnel = {20, 25, 45, 63, 72, 88, 90};   //时空隧道

 

   

     /**

       * 生成地图:

       * 关卡代号为:1:幸运轮盘 2:地雷  3: 暂停 4:时空隧道 0:普通

       */

    public void createMap(){

        int i = 0;

        

        //在对战地图上设置幸运轮盘

        for(i = 0; i < luckyTurn.length; i++){

         map[luckyTurn[i]] = 1;

        }

        

        //在对战地图上设置地雷

        for(i = 0; i < landMine.length; i++){

        map[landMine[i]] = 2;

        }

        

        //在对战地图上设置暂停

        for(i = 0; i < pause.length; i++){

        map[pause[i]] = 3;

        }

        

        //在对战地图上设置时空隧道

        for(i = 0; i < timeTunnel.length; i++){

        map[timeTunnel[i]] = 4;

        }

    }

   

    /**

     * 显示地图关卡对应的图形

     * @param i 地图当前位置的关卡代号

     * @param index 当前地图位置编号

     * @param playerPos1 玩家1的当前位置

     * @param playerPos2 玩家2的当前位置

     * @return 地图当前位置的对应图片

     */

    public String getGraph(int i,int index,int playerPos1,int playerPos2){

    String graph = "";

    if(index == playerPos1 && index== playerPos2){

        graph = "@@";

    }else if(index == playerPos1){ 

        //graph = "♀";

        graph = "A";

        }else if(index == playerPos2){

        //graph = "♂";

        graph = "B";

        }else{

          switch(i){

       case 1:   //幸运轮盘

           graph = "¡è";

           break;

       case 2:   //地雷

           graph = "★";

           break;

       case 3:   //暂停

           graph = "■";

           break;

       case 4:   //时光隧道

           graph = "〓";

           break;

       default:

           graph = "∷";

           break;

        }

        }

    return graph;

    }

   

    /**

     * 输出地图的奇数行(第1、3行)

     * @param start 输出的起始点在地图上的位置

     * @param end  输出的结束点在地图上的位置

     * @param playerPos1 玩家1的当前位置

     * @param playerPos2 玩家2的当前位置

     */

    public void showLine1(int start,int end,int playerPos1,int playerPos2){    

    for(int i = start; i < end; i++){

        System.out.print(getGraph(map[i], i, playerPos1, playerPos2));

    }

    }

   

    /**

     * 输出地图的偶数行(第2行)

     * @param start 输出的起始点在地图上的位置

     * @param end  输出的结束点在地图上的位置

     * @param playerPos1 玩家1的当前位置

     * @param playerPos2 玩家2的当前位置

     */

    public void showLine2(int start,int end,int playerPos1,int playerPos2){   

    for(int i = end-1; i >= start; i-- ){ 

        System.out.print(getGraph(map[i], i,playerPos1, playerPos2));

    }

    }

   

    /**

     * 输出地图的右竖列

     * @param start 输出的起始点在地图上的位置

     * @param end  输出的结束点在地图上的位置

     * @param playerPos1 玩家1的当前位置

     * @param playerPos2 玩家2的当前位置

     */

    public void showRLine(int start,int end,int playerPos1,int playerPos2){

    for(int i = start; i< end; i++){

       for(int j = 28; j > 0; j--){  //输出29个空格

           System.out.print("  ");

       }

       System.out.print(getGraph(map[i], i,playerPos1, playerPos2));

       System.out.println();

    }

    }

   

    /**

     * 输出地图的左竖列

     * @param start 输出的起始点在地图上的位置

     * @param end  输出的结束点在地图上的位置

     * @param playerPos1 玩家1的当前位置

     * @param playerPos2 玩家2的当前位置

     */

    public void showLLine(int start,int end,int playerPos1,int playerPos2){

    for(int i = start; i < end; i++){

        System.out.println(getGraph(map[i], i,playerPos1, playerPos2));

    }

    }

 

    /**

     * 显示对战地图

     * @param playerPos1 玩家1的当前位置

     * @param playerPos2 玩家2的当前位置

     */

    public void showMap(int playerPos1,int playerPos2){

    showLine1(0, 31, playerPos1, playerPos2);   //显示地图第一行

    System.out.println();                     //换行

    showRLine(31,35, playerPos1, playerPos2);  //显示地图右竖行

    showLine2(35, 66, playerPos1, playerPos2); //显示地图第二行

    System.out.println();                     //换行

    showLLine(66, 69, playerPos1, playerPos2); //显示地图左竖行

        showLine2(69, 100, playerPos1, playerPos2); //显示地图第3行

    } 

}

 

从北大青鸟课件中得到的启发,今天无意中看到了这个小示例,虽然简单,但感觉代码逻辑值得借鉴。

图例: ■ 暂停  ¡è 幸运轮盘   ★ 地雷   〓 时空隧道   ∷ 普通

 

@@∷∷∷∷★¡è∷∷■∷∷∷★∷∷∷★∷∷〓∷∷¡è∷〓∷■∷∷∷

                                                                                                                      ∷

                                                                                                                      ∷

                                                                                                                      ★

                                                                                                                      ∷

∷★〓∷∷■∷∷∷∷¡è∷∷∷∷★∷∷∷∷〓∷∷∷∷¡è∷★∷∷∷

∷∷∷∷∷★■∷∷〓∷〓∷∷∷∷¡è∷∷★∷∷∷∷∷∷∷〓∷∷¡è

要是自己的话可以先想想,自己如何绘制该图形。

 

同时,通过该示例得到了一个启发: 就是在做射击类的游戏时,可以先定义好精灵行走的路线,然后根据路线来改变精灵的当前坐标,这样就看起来精灵像是在道路(河流)中行走而不会出来。以下是自己写的一个小示例:


package riverRun;

 

import java.awt.Color;

import java.awt.Frame;

import java.awt.Graphics;

import java.awt.Image;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

 

public class RiverRunApp extends Frame {

    public static final int MAP_WIDTH = 800;

    public static final int MAP_HEIGHT = 600;

    private Image offScreenImage = null;

    private Map map = null; // 绘制地图

 

    public RiverRunApp() {

       map = new Map();

    }

 

    public static void main(String[] args) {

       RiverRunApp app = new RiverRunApp();

       app.lauchFrame();

    }

 

    /** 初始化窗体信息 */

    private void lauchFrame() {

       this.setTitle("精灵沿指定路线行走");

       this.setSize(MAP_WIDTH, MAP_HEIGHT);

       this.setResizable(false); // 是否可以调整大小

       this.setBackground(new Color(187, 201, 229));

       this.setVisible(true);

       this.setLocation(800, 500);

       new Thread(new ThreadPaint()).start();

       this.addWindowListener(new WindowAdapter() {

           public void windowClosing(WindowEvent e) {

              System.exit(0);

           }

       });

    }

 

    /** 重绘屏幕 */

 

    class ThreadPaint implements Runnable {

       @Override

       public void run() {

           while (true) {

              try {

                  Thread.sleep(41);

                  repaint();

              } catch (InterruptedException e) {

                  e.printStackTrace();

              }

           }

       }

    }

 

    public void paint(Graphics g) {

       map.draw(g);

    }

 

    /** 加入缓冲区 */

 

    public void update(Graphics g) {

       if (offScreenImage == null) {

           offScreenImage = this.createImage(MAP_WIDTH,MAP_HEIGHT);

       }

       Graphics gOffScreen = offScreenImage.getGraphics();

       Color c = gOffScreen.getColor();

       gOffScreen.setColor(new Color(187, 201, 229));

       gOffScreen.fillRect(0, 0, MAP_WIDTH, MAP_HEIGHT);

       gOffScreen.setColor(c);

       this.paint(gOffScreen);

       g.drawImage(offScreenImage, 0, 0, null);

    }

}


==========================

package riverRun;


import java.awt.Graphics;
/**
 * 显示抽象类
 */
public abstract class ShowEntity {
/**绘制抽象方法*/
protected abstract void draw(Graphics g);
}


===================================

package riverRun;

 

import java.awt.Color;

import java.awt.Graphics;

/**

 * 地图类

 */

public class Map {

    public static final int row = RiverRunApp.MAP_HEIGHT / Grid.GRID_HEIGHT;

    public static final int cell =  RiverRunApp.MAP_WIDTH / Grid.GRID_WIDTH;

    private ShowEntity hero = null;

    private ShowEntity grid = null;

    private int[][] maps = new int[row][cell];           //地图网格

    //河流行走的路线

    private int[][] riverRoadLine = new int[][]{{3,0},{3,1},{3,2}, {3,3},{3,4},{3,5},   //第一横行

                                          {4,5},{5,5},{6,5},                     //右边竖行

                                          {6,4},{6,3},{6,2},                     //第二横行

                                          {7,2},{8,2},{9,2},{10,2},              //左边竖行

                                          {11,2},{11,3},{11,4},{11,5},{11,6},{11,7},{11,8},{11,9},{11,10}};     //第三横行

   

    public Map(){

       initMapInfo();

       hero = new Hero(riverRoadLine);

       grid = new Grid();

      

       System.out.println("初始化地图信息");

    }

 

    /**初始化地图信息*/

    private void initMapInfo() {

       for(int i = 0; i < riverRoadLine.length; i++){

           for(int j = 0; j < riverRoadLine[0].length; j++){

              int m = riverRoadLine[i][0];

              int n = riverRoadLine[i][1];

              maps[m][n] = 1;

           }

       }

    }

 

    public void draw(Graphics g){

       System.out.println("绘制地图");

       for(int i = 0; i < row; i++){

           for(int j = 0; j < cell; j++){

              switch(maps[i][j]){

                  case 0:    //土地

                     g.setColor(Color.RED);

                     break;

                  case 1:    //河流

                     g.setColor(Color.GREEN);

                     break;

              }

              g.fill3DRect(j * Grid.GRID_WIDTH, i * Grid.GRID_HEIGHT, Grid.GRID_WIDTH, Grid.GRID_HEIGHT,false);

           }

       }

       grid.draw(g);

       hero.draw(g);

    }

}


==========================================

package riverRun;

import java.awt.Graphics;

/**

 * 格子

 */

public class Grid extends ShowEntity{

 

    public static final int GRID_WIDTH = 40;  //宽度

    public static final int GRID_HEIGHT = 40; //高度

   

    public Grid(){

       System.out.println("初始化格子构造方法");

    }

   

    @Override

    protected void draw(Graphics g) {

       System.out.println("绘制格子");

    }

 

}


============================================


package riverRun;

 

import java.awt.Color;

import java.awt.Graphics;

/**

 * 行走的精灵

 */

public class Hero extends ShowEntity{

    private int[][] roadline;          //行走的路线

    private int x;                     //当前X坐标

    private int y;                     //当前Y坐标

    private int aimX;               //目标点X

    private int aimY;               //目标点Y

    private int width;                 //宽度

    private int height;                //高度

    private int speed;                 //速度

    private int curGrid = 0;        //行走到的当前格子

   

    public Hero(int[][] riverRoadLine){

       System.out.println("初始化精灵构造方法");

       this.roadline = riverRoadLine;

      

       x = roadline[curGrid][1] * Grid.GRID_WIDTH + (Grid.GRID_WIDTH >> 1) - (width >> 1);

       y = roadline[curGrid][0] * Grid.GRID_HEIGHT + (Grid.GRID_HEIGHT >> 1) - (height >> 1);

       ++curGrid;

       aimX = roadline[curGrid][1] * Grid.GRID_WIDTH + (Grid.GRID_WIDTH >> 1);

       aimY = roadline[curGrid][0] * Grid.GRID_HEIGHT + (Grid.GRID_HEIGHT >> 1);

       width = 20;

       height = 20;

       speed = 4;

    }

   

    @Override

    protected void draw(Graphics g) {

       System.out.println("绘制精灵");

       g.setColor(Color.BLUE);

       g.fillOval(x, y, width, height);

       move();

    }

 

    /**

     * 精灵行走

     */

    public void move(){

       if(curGrid >= roadline.length){

           System.out.println("精灵到达了目的地");

           return;

       }else{

           System.out.println("精灵的行走");

       }

       double spaceX = aimX - x;

       double spaceY = aimY - y;

       double angle = Math.atan2(spaceY, spaceX);

       double fx = Math.cos(angle) * speed;

       double fy = Math.sin(angle) * speed;

       if((aimX - x) * (aimX - x) + (aimY - y) * (aimY - y) < speed * speed){

           //取下一个目标点

           ++curGrid;

           aimX = roadline[curGrid][1] * Grid.GRID_WIDTH + (Grid.GRID_WIDTH >> 1);

           aimY = roadline[curGrid][0] * Grid.GRID_HEIGHT + (Grid.GRID_HEIGHT >> 1);

       }else{

           x += fx;

           y += fy;

       }

    }

}