精华内容
下载资源
问答
  • 包括测试代码 二叉树的输出 先找到最左边的叶子并把路上遇到的节点依次压栈,然后弹 出栈顶的元素(该元素为最左边的叶子),并判断(1)它 有没有右节点;(2)右节点是否被访问过。如果(1)为 有右节点同时(2)...
  • 但是由于涉及到 native 库,社区提供的安装包中不包括 native 库,比如压缩算法的zstd、snappy 以及纠删码的ISA-L,所以会比较麻烦。本文将介绍如何编译并绑定native库,记录一下,或许会对其他人有些帮助。需要加入...

    编译 hadoop3 并绑定 native 库

    最近由于工作需要,需要编译hadoop3,hadoop 3本身编译比较简单;但是由于涉及到 native 库,社区提供的安装包中不包括 native 库,比如压缩算法的zstd、snappy 以及纠删码的ISA-L,所以会比较麻烦。 本文将介绍如何编译并绑定native库,记录一下,或许会对其他人有些帮助。

    需要加入的native

    1、isa-l

    用于纠删码

    2、snappy

    谷歌出品的 snappy 压缩算法,hadoop生态很常用的压缩算法。

    3、zstd

    Facebook 出品的 zstd 压缩算法,也是近年来 Hadoop 态常用压缩库,强烈推荐。

    当然也可以根据需要添加一些其他的,比如 lzo 等等。

    编译isa-l

    git clone https://github.com/intel/isa-l.git
    cd isa-l/
    git tag

    git checkout v2.29.0 -b v2.29

    yum install -y yasm(已经安装则不需要)
    yum install -y nasm(已经安装则不需要)
    yum install -y help2man(已经安装则不需要)

    ./autogen.sh
    ./configure --prefix=/usr --libdir=/usr/lib64
    make
    make install

    查看编译后的 lib :

    042b23f3ce7f7b341dbb1792f30d944d.png

    编译zstd

    https://github.com/facebook/zstd/tags

    下载源代码 这里是1.4.5

    tar -zxvf zstd-1.4.5.tar.gz

    cd zstd-1.4.5/

    make && make install注意 zstd 默认 在 /usr/local/lib 下面

    33bd484308f6cd3b2213fa3e4ee08b67.png

    编译snappy

    笔者的环境中 snappy 已经有了,这里就不编译了

    602349968d74e244e90c70b33e5594a6.png

    编译hadoop3

    上面的库都编译好以后,我们开始编译 hadoop3,并且支持 ISA-L,zstd,snappy

    编译 hadoop3 同时绑定 zstd,snappy,isa-l

    注意zstdisal 和snappy 目录

    mvn clean install -DskipTests -Pdist,native  -Dtar -Dbundle.snappy=true -Drequire.snappy=true  -Dsnappy.prefix=/usr/lib64  -Dsnappy.lib=/usr/lib64  -Drequire.zstd=true -Dbundle.zstd=true -Dzstd.lib=/usr/local/lib -Dbundle.isal=true -Drequire.isal=true -Disal.prefix=/usr/lib64 -Disal.lib=/usr/lib64

    编译完成后,会在 hadoop-dist/target 目录下产生 hadoop-${version}.tar.gz 的包,如下图

    efbc258be91f14f18e9b20d9c282c84a.png

    查看 native 包是否存在:

    b04d005106213d731668a81a85b31385.png

    验证 native

    export HADOOP_HOME=/root/cyc/hadoop/hadoop-dist/target/hadoop-3.2.1/

    然后切换到 bin 目录 cd bin

    执行 hadoop checknative

    dd3009e62aedc0b39bb6cff5727107ee.png

    错误处理:

    可能出现如下错误的解决办法:

    yum install -y cyrus-sasl*(已经安装了cyrus 则不需要)

    [WARNING] -- valgrind location: MEMORYCHECK_COMMAND-NOTFOUND
    [WARNING] CMake Error at main/native/libhdfspp/CMakeLists.txt:135 (message):
    [WARNING] Cound not find a SASL library (GSASL (gsasl) or Cyrus SASL (libsasl2).
    [WARNING] Install/configure one of them or define NO_SASL=1 in your cmake call
    [WARNING]
    [WARNING]
    [WARNING] -- Configuring incomplete, errors occurred!
    [WARNING] See also "/root/cyc/hadoop/hadoop-hdfs-project/hadoop-hdfs-native-client/target/CMakeFiles/CMakeOutput.log".
    [WARNING] See also "/root/cyc/hadoop/hadoop-hdfs-project/hadoop-hdfs-native-client/target/CMakeFiles/CMakeError.log".

    编译好的地址

    编译 native 还是比较麻烦的,为了方便大家编译,我把在CentOS 7 中编译好的 native 放到了GitHub 上面,理论上centos/readhat 7 应该可以直接用。

    仓库地址如下:

    https://github.com/utf7/hadoop-native/tree/master/native

    参考链接:

    1. https://github.com/facebook/zstd

    2. https://github.com/google/snappy

    3. https://github.com/intel/isa-l

    4. https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/NativeLibraries.html

    5. https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HDFSErasureCoding.html

    6. https://github.com/apache/hadoop/blob/rel/release-3.2.1/BUILDING.txt

    展开全文
  • Java实现经典坦克大战及源代码下载

    万次阅读 多人点赞 2017-01-08 11:22:45
    这是一个功能相对全的JAVA版坦克大战,界面绘制是通过JAVA的图形化用户界面完成的,包括了菜单界面和游戏界面。其中菜单界面可以供玩家选择重新开始游戏、暂停、继续、是否播放背景音乐、帮助等操作;游戏界面绘制了...

    目录

     

    一、简单介绍

    二、工程目录

    三、具体代码

    四、运行截图

    五、总结

    六、说明与下载


    一、简单介绍

            这是一个功能相对全的Java版坦克大战,界面绘制是通过Java的图形化用户界面完成的,包括了菜单界面和游戏界面。其中菜单界面可以供玩家选择重新开始游戏、暂停、继续、是否播放背景音乐、帮助等操作;游戏界面绘制了坦克、河流、草地、鹰碉堡等经典坦克场景,玩家在游戏界面操作坦克开始对战。

             本游戏使用的主要技术有Swing编程、面向对象编程、多线程编程。本想用I/O编程实现保存游戏数据,感觉单机版的没必要就没弄。

    游戏实现的主要功能有:

    1.坦克可以上下左右、以及左上左下右上右下八个方向移动,移动时添加音效

    2.坦克可以发子弹(可以连发),发射时添加音效

    3.击中对方坦克时,坦克消失,显示爆炸效果;子弹击中鹰碉堡时,游戏结束;子弹击中墙壁时,子弹消失

    4.我方坦克吃到血块时,生命值加满

    5.移动过程中检测碰撞,包括坦克与坦克,坦克与草地、河流、墙壁等

    6.声音处理(开始音乐、背景音乐等)

    7.菜单处理(开始游戏、暂停游戏、继续游戏、帮助等)

    8.计分(分关、记录成绩)

    二、工程目录

    三、具体代码

    每个文件都有详细的注释,不理解的可以联系作者,这里只贴出Tank.java和TankClient.java的代码,源代码将会在文章最后面贴出来,话不多说,先上代码

     

    Tank.java代码

     

    package com.xiaoli.tank;
    
    
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Rectangle;
    import java.awt.event.KeyEvent;
    import java.util.List;
    import java.util.Random;
    /**
     * 
     *Title:Tank
     *Description:坦克类,包括坦克移动、坦克发射炮弹等 
     *@author xiaoli
     *@date2017年1月4日
     */
    public class Tank {
    //坦克X方向速度,设置游戏难度时可拓展
        public static int XSPEED = 5;
        //坦克Y方向速度,设置游戏难度时可拓展
    public static int YSPEED = 5;
    //坦克宽度
    public static final int WIDTH = 30;
    //坦克高度
    public static final int HEIGHT = 30;
    //坦克是否活着
    private boolean live = true;
    //坦克的生命值
    private int life = 100;
    //持有对TankClient大管家的引用
    TankClient tc;
    //判断是否是我方坦克,默认true
    private boolean good=true;
    //用于记录坦克原来的坐标,碰到墙、坦克时方便退一步
    private int oldX,oldY;
    //绘制坦克的左上角坐标
    private int x, y;
    //用于产生随机数
    private static Random r = new Random();
    //用于控制敌人随机发出子弹
    private int step = r.nextInt(30)+10;
    //判断是否按下方向键
    private boolean bL=false, bU=false, bR=false, bD = false;
    //枚举类型定义了坦克的八个方向,和静止时的方向
    enum Direction {L, LU, U, RU, R, RD, D, LD, STOP};
    //坦克的方向
    private Direction dir = Direction.STOP;
    //炮筒的方向
    private Direction ptDir = Direction.D;
        //血条
    private BloodBar bar = new BloodBar();
    //构造方法
    public Tank(int x, int y, boolean good) {
    this.x = x;
    this.y = y;
    this.good = good;
    }
    //构造方法
    public Tank(int x, int y, boolean good, Direction dir,TankClient tc) {
    this(x, y, good);
    this.tc = tc;
    this.oldX=x;
    this.oldY=y;
    this.dir=dir;
    }
    /**
    * 
    *@Description:画出坦克
    * @param g
    */
    public void draw(Graphics g) {
    if(!live) {
    if(!good) {
    tc.tanks.remove(this);
    }
    return;
    }
    Color c = g.getColor();
    if(good) g.setColor(Color.RED);
    else g.setColor(Color.BLUE);
    g.fillOval(x, y, WIDTH, HEIGHT);
    g.setColor(c);
    //血条
       if(good) bar.draw(g); 
    switch(ptDir) {
    case L:
    g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x, y + Tank.HEIGHT/2);
    break;
    case LU:
    g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x, y);
    break;
    case U:
    g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH/2, y);
    break;
    case RU:
    g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH, y);
    break;
    case R:
    g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH, y + Tank.HEIGHT/2);
    break;
    case RD:
    g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH, y + Tank.HEIGHT);
    break;
    case D:
    g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH/2, y + Tank.HEIGHT);
    break;
    case LD:
    g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x, y + Tank.HEIGHT);
    break;
    }
    
    move();
    }
    /*
    * 坦克移动
    */
    void move() {
    this.oldX=x;
    this.oldY=y;
    switch(dir) {
    case L:
    x -= XSPEED;
    break;
    case LU:
    x -= XSPEED;
    y -= YSPEED;
    break;
    case U:
    y -= YSPEED;
    break;
    case RU:
    x += XSPEED;
    y -= YSPEED;
    break;
    case R:
    x += XSPEED;
    break;
    case RD:
    x += XSPEED;
    y += YSPEED;
    break;
    case D:
    y += YSPEED;
    break;
    case LD:
    x -= XSPEED;
    y += YSPEED;
    break;
    case STOP:
    break;
    }
    if(this.dir != Direction.STOP) {
    this.ptDir = this.dir;
    }
    if(!good){
    Direction[] dirs = Direction.values();
    if(step==0){
    step=r.nextInt(30)+10;
    int rn = r.nextInt(9);
    this.dir=dirs[rn];
    }
    step--;
    //敌人发子弹
    if(r.nextInt(40)>36){
      this.fire();
    }
    }
    if(x < 0) x = 0;
    if(y < 55) y = 55;
    if(x + Tank.WIDTH > TankClient.GAME_WIDTH) x = TankClient.GAME_WIDTH - Tank.WIDTH;
    if(y + Tank.HEIGHT > TankClient.GAME_HEIGHT) y = TankClient.GAME_HEIGHT - Tank.HEIGHT;
    }
    /**
    * 
    *@Description:用于撞到墙、坦克时返回上一步
    */
    private void stay(){
    x=oldX;
    y=oldY;
    }
    /**
    * 
    *@Description:按下键时监听
    * @param e
    */
    public void keyPressed(KeyEvent e) {
    int key = e.getKeyCode();
    switch(key) {
    case KeyEvent.VK_R:
    tc.bloods.clear();
        tc.grasses.clear();
        tc.rivers.clear();
        tc.walls.clear();
        tc.missiles.clear();
        tc.tanks.clear();
        tc.explodes.clear();
        
        //关卡、分数重置
        tc.score=0;
        tc.level=1;
        //草地
        tc.newGrass();
        //河流
        tc.newRiver();
        //墙
        tc.newWall();
        //当在区域中没有坦克时,就出来坦克      
        if (tc.tanks.size() == 0) {   
        tc.newTank();
    }
    tc.myTank = new Tank(220, 560, true, Direction.STOP, tc);//设置自己出现的位置
    if(!tc.home.isLive()){
    tc.home.setLive(true);
    }
    tc.dispose();
    new TankClient().lauchFrame();
    break;
    case KeyEvent.VK_LEFT :
    bL = true;
    break;
    case KeyEvent.VK_UP :
    bU = true;
    break;
    case KeyEvent.VK_RIGHT :
    bR = true;
    break;
    case KeyEvent.VK_DOWN :
    bD = true;
    break;
    }
    locateDirection();
    }
    /**
    * 
    *@Description:定位坦克的方向
    */
    void locateDirection() {
    if(bL && !bU && !bR && !bD) dir = Direction.L;
    else if(bL && bU && !bR && !bD) dir = Direction.LU;
    else if(!bL && bU && !bR && !bD) dir = Direction.U;
    else if(!bL && bU && bR && !bD) dir = Direction.RU;
    else if(!bL && !bU && bR && !bD) dir = Direction.R;
    else if(!bL && !bU && bR && bD) dir = Direction.RD;
    else if(!bL && !bU && !bR && bD) dir = Direction.D;
    else if(bL && !bU && !bR && bD) dir = Direction.LD;
    else if(!bL && !bU && !bR && !bD) dir = Direction.STOP;
    }
        /**
         * 
         *@Description:松开键时监听
         * @param e
         */
    public void keyReleased(KeyEvent e) {
    int key = e.getKeyCode();
    switch(key) {
    case KeyEvent.VK_K:
    if(this.good){
    if(!this.live){
    this.live=true;
    this.life=100;
    //复活次数加1
    tc.count++;
    }
    }
    break;
    case KeyEvent.VK_J:
    superFire();
    break;
    case KeyEvent.VK_CONTROL:
    fire();
    //发射炮弹音效
    new Audio(2);
    break;
    case KeyEvent.VK_LEFT :
    bL = false;
    new Audio(1);
    break;
    case KeyEvent.VK_UP :
    bU = false;
    new Audio(1);
    break;
    case KeyEvent.VK_RIGHT :
    bR = false;
    new Audio(1);
    break;
    case KeyEvent.VK_DOWN :
    bD = false;
    new Audio(1);
    break;
    }
    locateDirection();
    }
    /**
    * 
    *@Description:坦克开火
    * @return 炮弹对象
    */
    public Missile fire() {
    if(!live)return null;
    int x = this.x + Tank.WIDTH/2 - Missile.WIDTH/2;
    int y = this.y + Tank.HEIGHT/2 - Missile.HEIGHT/2;
    Missile m = new Missile(x, y, ptDir,this.good, this.tc);
    tc.missiles.add(m);
    return m;
    }
    /**
    * 
    *@Description:坦克根据方向开火
    * @return 炮弹对象
    */
    public Missile fire(Direction dir) {
    if(!live)return null;
    int x = this.x + Tank.WIDTH/2 - Missile.WIDTH/2;
    int y = this.y + Tank.HEIGHT/2 - Missile.HEIGHT/2;
    Missile m = new Missile(x, y, dir,this.good, this.tc);
    tc.missiles.add(m);
    return m;
    }
    /**
    * 
    *@Description:超级炮弹,可以向八个方向开火
    */
    public void superFire(){
    Direction[] dirs = Direction.values();
    for(int i=0;i<8;i++){
    fire(dirs[i]);
    }
    }
    /**
    * 
    *@Description:判断坦克是否撞墙
    * @param 墙对象
    * @return 是否撞墙了
    */
    public boolean CollidesWithWall(Wall w){
    if(this.live&&this.getRect().intersects(w.getRect())){
    this.stay();
    return true;
    }
    return false;
    }
    public boolean CollidesWithWalls(List<Wall> walls){
            for(int i=0;i<walls.size();i++){
            Wall w = walls.get(i);
            if(this.live&&this.getRect().intersects(w.getRect())){
               this.stay();
            return true;
            }
            }
    return false;
    }
    /**
    * 
    *@Description:判断坦克是否相撞
    * @param 多辆坦克
    * @return 是否和坦克相撞了
    */
    public boolean collidesWithTanks(List<Tank> tanks){
    for(int i=0;i<tanks.size();i++){
    Tank t = tanks.get(i);
    if(this!=t){
    if(this.live&&t.isLive()&&this.getRect().intersects(t.getRect())){
    this.stay();
    t.stay();
    return true;
    }
    }
    }
    return false;
    }
    /**
    * 
    *@Description:坦克是否碰到了鹰碉堡
    * @param 鹰碉堡对象
    * @return 是否碰到了鹰碉堡
    */
    public boolean CollidesWithHome(Home h){
    if(this.live&&h.isLive()&&this.getRect().intersects(h.getRect())){
    this.stay();
    return true;
    }
    return false;
    }
    /**
    * 
    *@Description:坦克是否碰到了河流,主要是地方坦克调用,我方坦克能直接渡河
    * @param 河流对象
    * @return 是否碰到了河流
    */
    public boolean CollidesWithRiver(River r){
    if(this.live&&this.getRect().intersects(r.getRect())){
    this.stay();
    return true;
    }
    return false;
    }
    /**
    * 
    *@Description:坦克是否碰到了河流,主要是地方坦克调用,我方坦克能直接渡河
    * @param 河流集合
    * @return 是否碰到了河流
    */
    public boolean CollidesWithRivers(List<River> rivers){
    for(int i=0;i<rivers.size();i++){
    River t = rivers.get(i);
    if(this.live&&this.getRect().intersects(t.getRect())){
    this.stay();
    return true;
    }
    }
    return false;
    }
    public Rectangle getRect() {
    return new Rectangle(x, y, WIDTH, HEIGHT);
    }
        /**
         * 
         *Title:BloodBar
         *Description:我方坦克的血条,用于显示我方坦克的生命值 
         *@author xiaoli
         *@date2017年1月4日
         */
    private class BloodBar{
    public void draw(Graphics g){
    Color c = g.getColor();
    g.setColor(Color.PINK);
    g.drawRect(x,y-10,WIDTH,8);
    //里面的
    g.setColor(Color.PINK);
    int w =WIDTH*life/100;
    g.fillRect(x, y-10, w, 8);
    g.setColor(c);
    }
    }
    /**
    * 
    *@Description:吃血块,主要是我方坦克调用
    * @param 血块对象
    * @return 是否吃到了血块
    */
    public boolean eat(Blood b){
    if(this.live&&b.isLive()&&this.getRect().intersects(b.getRect())){
    this.life=100;
    b.setLive(false);
    tc.bloods.remove(b);
    //吃血块音效
    new Audio(4);
    return true;
    }
    return false;
    }
    public boolean isLive() {
    return live;
    }
    
    
    public void setLive(boolean live) {
    this.live = live;
    }
    public int getLife() {
    return life;
    }
    
    
    public void setLife(int life) {
    this.life = life;
    }
    public boolean isGood() {
    return good;
    }
    }
    

     

    TankClient.java代码

    package com.xiaoli.tank;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.Frame;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.Menu;
    import java.awt.MenuBar;
    import java.awt.MenuItem;
    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    
    import javax.swing.JOptionPane;
    /**
     * 
     *Title:TankClient
     *Description:这个类是大管家,控制着其他类,也是程序入口 
     *@author xiaoli
     *@date2017年1月4日
     */
    public class TankClient extends Frame implements ActionListener {
    //游戏宽度
    public static final int GAME_WIDTH = 800;
    //游戏高度
    public static final int GAME_HEIGHT = 600;
        //是否开启重绘线程
    public static boolean printable=true;
    //用于产生随机数
    Random r = new Random();
    //记录复活次数
    public static int count=0;
    //关卡
    public static int level=1;
    //分数
    public static int score=0;
    //菜单条
    MenuBar jmb = null;
    //菜单
    Menu jm1 = null, jm2 = null, jm3 = null, jm4 = null;
    //菜单项
    MenuItem jmi1 = null, jmi2 = null, jmi3 = null, jmi4 = null, jmi5 = null,
    jmi6 = null, jmi7 = null, jmi8 = null, jmi9 = null,jmi10=null,jmi11=null;
    //从上到下从左到右画墙
    Wall w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12;
    //创建我的坦克
    Tank myTank = new Tank(220, 560, true,Tank.Direction.STOP, this);
    //创建鹰碉堡
    Home home = new Home(379,556,this);
        //墙集合,用于存放墙
    List<Wall> walls = new ArrayList<Wall>();
    //河流集合,用于存放河流
    List<River> rivers = new ArrayList<River>();
    //定义一个血块
    Blood b=null;
    //血块集合,用于存放血块。用集合的原因是方便删除
    List<Blood> bloods = new ArrayList<Blood>();
    //草集合,用于存放草
    List<Grass> grasses = new ArrayList<Grass>();
    //炸弹集合,用于存放炸弹
    List<Explode> explodes = new ArrayList<Explode>();
    //炮弹集合,用于存放炮弹
    List<Missile> missiles = new ArrayList<Missile>();
    //坦克集合,用于存放坦克
    List<Tank> tanks = new ArrayList<Tank>();
    //用于解决双缓冲闪烁现象
    Image offScreenImage = null;
    /**
    * 绘制场景
    */
    public void paint(Graphics g) {
    //分关
    if (score >= 1000 * level ) {
    setLevel(level + 1); // 进入下一关
    new Audio(5);
    grasses.clear();
        rivers.clear();
        missiles.clear();
        tanks.clear();
           explodes.clear();
        walls.clear();
        this.dispose();
    new TankClient().lauchFrame();
    }
    //家
    home.draw(g);
    //只能复活一次
    if(myTank.getLife()<=0&&count==1){
    myTank.setLive(false);
    home.gameOver(g);
    }
    if(r.nextInt(50)>48){
    newBlood();
    }
    //敌人死光
    if(tanks.size()<=0){
    for(int i=0; i<6; i++) {
    if(i<3){
       tanks.add(new Tank(50 + 40*(i+1), 50, false,Tank.Direction.D, this));
    }else{
    tanks.add(new Tank(50 + 40*(i+1), 50, false,Tank.Direction.R, this));
    }
    }
    }
    //g.drawString("血块数量:" + bloods.size(), 10, 50);
    //g.drawString("子弹数量:" + missiles.size(), 10, 70);
    //g.drawString("炸弹数量:" + explodes.size(), 10, 90);
    //g.drawString("坦克数量:" + tanks.size(), 10, 110);
    g.drawString("关卡:" + level, 10, 90);
    g.drawString("分数:" + score, 10, 110);
    g.drawString("生命值:" + myTank.getLife(), 10, 130);
    g.drawString("复活次数:" + count, 10, 150);
    //画墙
    for(int i=0;i<walls.size();i++){
    walls.get(i).draw(g);
    }
    for(int i=0; i<missiles.size(); i++) {
    Missile m = missiles.get(i);
    m.hitWalls(walls);
    m.hitTanks(tanks);
    m.hitTank(myTank);
    m.hitHome(home);
    m.draw(g);
    //if(!m.isLive()) missiles.remove(m);
    //else m.draw(g);
    }
    
    for(int i=0; i<explodes.size(); i++) {
    Explode e = explodes.get(i);
    e.draw(g);
    }
    
    for(int i=0; i<tanks.size(); i++) {
    Tank t = tanks.get(i);
    t.CollidesWithWalls(walls);
    myTank.collidesWithTanks(tanks);
    t.collidesWithTanks(tanks);
    t.CollidesWithHome(home);
    t.CollidesWithRivers(rivers);
    t.draw(g);
    }
    myTank.CollidesWithWalls(walls);
    myTank.CollidesWithHome(home);
    //画河流
    for(int i=0;i<rivers.size();i++){
    rivers.get(i).draw(g);
    }
    myTank.draw(g);
    // 画草地
    for (int i = 0; i < grasses.size(); i++) {
    grasses.get(i).draw(g);
    }
    // 画血块
    for (int i = 0; i < bloods.size(); i++) {
    Blood b = bloods.get(i);
    b.draw(g);
    myTank.eat(b);
    }
    }
    /**
    * repaint先调用update再调用paint,用于解决双缓冲闪烁现象
    */
    public void update(Graphics g) {
    if(offScreenImage == null) {
    offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);
    }
    Graphics gOffScreen = offScreenImage.getGraphics();
    Color c = gOffScreen.getColor();
    gOffScreen.setColor(new Color(0xcce8cf));
    gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
    gOffScreen.setColor(c);
    paint(gOffScreen);
    g.drawImage(offScreenImage, 0, 0, null);
    }
        /**
         * 本方法显示程序主窗口
         */
    public void lauchFrame() {
    //菜单项
    newMenu();
    //墙
    newWall();
    //河流
    newRiver();
    //草地
    newGrass();
    //坦克
    newTank();
    this.setTitle("经典坦克大战游戏 作者:小李");
    //this.setLocation(600,300);
    this.setSize(GAME_WIDTH, GAME_HEIGHT);
    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
    setLocation((dim.width - getSize().width) / 2,
    (dim.height - getSize().height) / 2);
    this.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent e) {
    System.exit(0);
    }
    });
    this.setResizable(false);
    this.addKeyListener(new KeyMonitor());
    
    setVisible(true);
    
    new Thread(new PaintThread()).start();
    //声音
    if(this.level==1){
     StartAudio startAudio = new StartAudio("audio/7301.wav");
     startAudio.start();
    }
    }
    /**
    * 
    *@Description:菜单项
    */
    public void newMenu(){
    // 创建菜单及菜单选项
    jmb = new MenuBar();
    jm1 = new Menu("游戏");
    jm2 = new Menu("暂停/继续");
    jm3 = new Menu("帮助");
    jm4 = new Menu("游戏难度");
    jm1.setFont(new Font("宋体", Font.BOLD, 15));// 设置菜单显示的字体
    jm2.setFont(new Font("宋体", Font.BOLD, 15));// 设置菜单显示的字体
    jm3.setFont(new Font("TimesRoman", Font.BOLD, 15));// 设置菜单显示的字体
    jm4.setFont(new Font("TimesRoman", Font.BOLD, 15));// 设置菜单显示的字体
    
    
    jmi1 = new MenuItem("重新开始");
    jmi2 = new MenuItem("退出");
    jmi11= new MenuItem("开启背景音乐");
    
    jmi3 = new MenuItem("暂停");
    jmi4 = new MenuItem("继续");
    jmi5 = new MenuItem("游戏说明");
    jmi6 = new MenuItem("难度1");
    jmi7 = new MenuItem("难度2");
    jmi8 = new MenuItem("难度3");
    jmi9 = new MenuItem("难度4");
    jmi10 = new MenuItem("操作说明");
    
    jmi1.setFont(new Font("TimesRoman", Font.BOLD, 15));
    jmi2.setFont(new Font("TimesRoman", Font.BOLD, 15));
    jmi3.setFont(new Font("TimesRoman", Font.BOLD, 15));
    jmi4.setFont(new Font("TimesRoman", Font.BOLD, 15));
    jmi5.setFont(new Font("TimesRoman", Font.BOLD, 15));
    
    
    jm1.add(jmi1);
    jm1.add(jmi2);
    jm1.add(jmi11);
    
    jm2.add(jmi3);
    jm2.add(jmi4);
    jm3.add(jmi5);
    jm3.add(jmi10);
    
    jm4.add(jmi6);
    jm4.add(jmi7);
    jm4.add(jmi8);
    jm4.add(jmi9);
    
    
    jmb.add(jm1);
    jmb.add(jm2);
    jmb.add(jm4);
    jmb.add(jm3);
    jmi1.addActionListener(this);
    jmi1.setActionCommand("NewGame");
    jmi2.addActionListener(this);
    jmi2.setActionCommand("Exit");
    jmi11.addActionListener(this);
    jmi11.setActionCommand("startMain");
    
    jmi3.addActionListener(this);
    jmi3.setActionCommand("Stop");
    jmi4.addActionListener(this);
    jmi4.setActionCommand("Continue");
    jmi5.addActionListener(this);
    jmi5.setActionCommand("help1");
    jmi10.addActionListener(this);
    jmi10.setActionCommand("help2");
    
    jmi6.addActionListener(this);
    jmi6.setActionCommand("level1");
    jmi7.addActionListener(this);
    jmi7.setActionCommand("level2");
    jmi8.addActionListener(this);
    jmi8.setActionCommand("level3");
    jmi9.addActionListener(this);
    jmi9.setActionCommand("level4");
    
    
    this.setMenuBar(jmb);// 菜单Bar放到JFrame上
    }
    /**
    * 
    *@Description:生成墙
    */
    public void newWall() {
    if(this.level==1){
    w1 = new Wall(210, 200, 100, 30, this);
    w2 = new Wall(210, 200, 30, 190, this);
    w3 = new Wall(280, 200, 30, 190, this);
    w4 = new Wall(210, 370, 100, 30, this);
    w5 = new Wall(440, 200, 100, 30, this);
    w6 = new Wall(440, 200, 30, 95, this);
    w7 = new Wall(470, 265, 70, 30, this);
    w8 = new Wall(510, 200, 30, 190, this);
    w9 = new Wall(440, 370, 100, 30, this);
    w10 = new Wall(379, 530, 43, 20, this);
    w11 = new Wall(280, 530, 30, 70, this);
    w12 = new Wall(510, 530, 30, 70, this);
    walls.add(w1);
    walls.add(w2);
    walls.add(w3);
    walls.add(w4);
    walls.add(w5);
    walls.add(w6);
    walls.add(w7);
    walls.add(w8);
    walls.add(w9);
    walls.add(w10);
    walls.add(w11);
    walls.add(w12);
    }else if(this.level==2){
    w1 = new Wall(210, 200, 100, 30, this);
    w2 = new Wall(210, 200, 30, 190, this);
    w3 = new Wall(280, 200, 30, 190, this);
    w4 = new Wall(210, 370, 100, 30, this);
    
    w5 = new Wall(410, 200, 30, 70, this);
    w6 = new Wall(410, 200, 90, 30, this);
    w7 = new Wall(470, 200, 30, 190, this);
    w8 = new Wall(470, 370, 90, 30, this);
    w9 = new Wall(530, 320, 30, 65, this);
    
    w10 = new Wall(379, 530, 43, 20, this);
    w11 = new Wall(280, 530, 30, 70, this);
    w12 = new Wall(510, 530, 30, 70, this);
    walls.add(w1);
    walls.add(w2);
    walls.add(w3);
    walls.add(w4);
    walls.add(w5);
    walls.add(w6);
    walls.add(w7);
    walls.add(w8);
    walls.add(w9);
    walls.add(w10);
    walls.add(w11);
    walls.add(w12);
    }else if(this.level>=3){
    w1 = new Wall(210, 200, 100, 30, this);
    w2 = new Wall(210, 200, 30, 190, this);
    w3 = new Wall(280, 200, 30, 190, this);
    w4 = new Wall(210, 370, 100, 30, this);
    
    w5 = new Wall(430, 200, 90, 30, this);
    w6 = new Wall(430, 285, 90, 30, this);
    w7 = new Wall(430, 370, 90, 30, this);
    w8 = new Wall(500, 200, 30, 200, this);
    
    w10 = new Wall(379, 530, 43, 20, this);
    w11 = new Wall(280, 530, 30, 70, this);
    w12 = new Wall(510, 530, 30, 70, this);
    walls.add(w1);
    walls.add(w2);
    walls.add(w3);
    walls.add(w4);
    walls.add(w5);
    walls.add(w6);
    walls.add(w7);
    walls.add(w8);
    
    walls.add(w10);
    walls.add(w11);
    walls.add(w12);
    }
    }
    /**
    * 
    *@Description:生成血块
    */
    public void newBlood(){
    //血块
    b = new Blood();
    //if(b.CollidesWithWalls(walls)){//血块不能画在墙里面
    //return;
    //}
    if(bloods.size()==0){
     bloods.add(b);
    }
    }
    /**
    * 
    *@Description:生成河流
    */
    public void newRiver(){
    for(int i=0;i<6;i++){
    River river = new River(18+i*30,340);
    rivers.add(river);
    river = new River(18+i*30,340+30);
    rivers.add(river);
    }
    for(int i=0;i<6;i++){
    River river = new River(568+i*30,340);
    rivers.add(river);
    river = new River(568+i*30,340+30);
    rivers.add(river);
    }
    }
    /**
    * 
    *@Description:生成草地
    */
    public void newGrass() {
    // 草地
    for (int i = 0; i < 10; i++) {
    Grass grass = new Grass((i + 1) * 18, 200);
    grasses.add(grass);
    grass = new Grass((i + 1) * 18, 200 + 1 * 18);
    grasses.add(grass);
    grass = new Grass((i + 1) * 18, 200 + 2 * 18);
    grasses.add(grass);
    grass = new Grass((i + 1) * 18, 200 + 3 * 18);
    grasses.add(grass);
    grass = new Grass((i + 1) * 18, 200 + 4 * 18);
    grasses.add(grass);
    grass = new Grass((i + 1) * 18, 200 + 5 * 18);
    grasses.add(grass);
    grass = new Grass((i + 1) * 18, 200 + 6 * 18);
    grasses.add(grass);
    grass = new Grass((i + 1) * 18, 200 + 7 * 18);
    grasses.add(grass);
    }
    for (int i = 1; i <= 11; i++) {
    Grass grass = new Grass(250 + 18 * 7, 182 + i * 18);
    grasses.add(grass);
    grass = new Grass(250 + 18 * 8, 182 + i * 18);
    grasses.add(grass);
    grass = new Grass(250 + 18 * 5, 182 + i * 18);
    grasses.add(grass);
    grass = new Grass(250 + 18 * 6, 182 + i * 18);
    grasses.add(grass);
    }
    for(int i=0;i<10;i++){
    Grass grass = new Grass(550+(i + 1) * 18, 200);
    grasses.add(grass);
    grass = new Grass(550+(i + 1) * 18, 200 + 1 * 18);
    grasses.add(grass);
    grass = new Grass(550+(i + 1) * 18, 200 + 2 * 18);
    grasses.add(grass);
    grass = new Grass(550+(i + 1) * 18, 200 + 3 * 18);
    grasses.add(grass);
    grass = new Grass(550+(i + 1) * 18, 200 + 4 * 18);
    grasses.add(grass);
    grass = new Grass(550+(i + 1) * 18, 200 + 5 * 18);
    grasses.add(grass);
    grass = new Grass(550+(i + 1) * 18, 200 + 6 * 18);
    grasses.add(grass);
    grass = new Grass(550+(i + 1) * 18, 200 + 7 * 18);
    grasses.add(grass);
    }
    }
    /**
    * 
    *@Description:生成坦克
    */
    public void newTank(){
    for (int i = 0; i < 10; i++) {
    if (i < 5) {
    tanks.add(new Tank(50 + 40 * (i + 1), 55, false,
    Tank.Direction.D, this));
    } else {
    tanks.add(new Tank(50 + 40 * (i + 1), 55, false,
    Tank.Direction.R, this));
    }
    }
    }
    /**
    * 
    *@Description:主函数、程序入口
    * @param args
    */
    public static void main(String[] args) {
    TankClient tc = new TankClient();
    tc.lauchFrame();
    
    }
    /**
    * 
    *Title:PaintThread
    *Description:重绘线程,模拟动态效果 
    *@author xiaoli
    *@date2017年1月4日
    */
    private class PaintThread implements Runnable {
    
    
    public void run() {
    while(printable) {
    repaint();
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    }
    /**
    * 
    *@Description:按键监听,对坦克、炮弹等进行人机交互
    * @param e
    */
    private class KeyMonitor extends KeyAdapter {
    public void keyReleased(KeyEvent e) {
    myTank.keyReleased(e);
    }
    
    
    public void keyPressed(KeyEvent e) {
    myTank.keyPressed(e);
    }
    
    }
        /**
         * 对菜单项操作
         */
    @Override
    public void actionPerformed(ActionEvent e) {
    // TODO Auto-generated method stub
    if (e.getActionCommand().equals("NewGame")) {
    printable = false;
    Object[] options = { "确定", "取消" };
    int response = JOptionPane.showOptionDialog(this, "您确认要重新开始!", "",
    JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null,
    options, options[0]);
    if (response == 0) {
                    this.score=0;
                    this.setLevel(1);
    printable = true;
    this.dispose();
    new TankClient().lauchFrame();
    } else {
    printable = true;
    new Thread(new PaintThread()).start(); // 线程启动
    }
    
    
    } else if (e.getActionCommand().endsWith("Stop")) {
    printable = false;
    // try {
    // Thread.sleep(10000);
    //
    // } catch (InterruptedException e1) {
    // // TODO Auto-generated catch block
    // e1.printStackTrace();
    // }
    } else if (e.getActionCommand().equals("Continue")) {
    
    
    if (!printable) {
    printable = true;
    new Thread(new PaintThread()).start(); // 线程启动
    }
    // System.out.println("继续");
    } else if (e.getActionCommand().equals("Exit")) {
    printable = false;
    Object[] options = { "确定", "取消" };
    int response = JOptionPane.showOptionDialog(this, "您确认要退出吗", "",
    JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null,
    options, options[0]);
    if (response == 0) {
    System.out.println("退出");
    System.exit(0);
    } else {
    printable = true;
    new Thread(new PaintThread()).start(); // 线程启动
    
    
    }
    
    
    } else if (e.getActionCommand().equals("help1")) {
    printable = false;
    JOptionPane.showMessageDialog(null, "随着人们精神文化生活的日益丰富,游戏成为了人们生活中必不可少的一部分\n90《坦克大战》更是90后一代人童年的回忆,也是一款经典游戏。\n"
    + "开发java版坦克大战有利用更深入理解java面向对象编程、swing界面编程、多线程编程"+"\n"+"参考:马士兵坦克大战视频教程、以及互联网资源"+"\n"+"作者邮箱:1275302036@qq.com"+"\n"
    +"若有关内容侵犯了您的权益,请及时联系作者删除,谢谢!",
    "提示!", JOptionPane.INFORMATION_MESSAGE);
    this.setVisible(true);
    printable = true;
    new Thread(new PaintThread()).start(); // 线程启动
    } else if(e.getActionCommand().equals("help2")){
    printable = false;
    JOptionPane.showMessageDialog(null, "用→ ← ↑ ↓控制方向,CTRL键盘发射,J超级炮弹,K复活(只能复活一次),R重新开始!\n"+"作者邮箱:1275302036@qq.com"+"\n"
    +"若有关内容侵犯了您的权益,请及时联系作者删除,谢谢!",
    "提示!", JOptionPane.INFORMATION_MESSAGE);
    this.setVisible(true);
    printable = true;
    new Thread(new PaintThread()).start(); // 线程启动
    }
    
    else if (e.getActionCommand().equals("level1")) {
    //Tank.count = 12;
    Tank.XSPEED = 5;
    Tank.YSPEED = 5;
    Missile.XSPEED = 10;
    Missile.YSPEED = 10;
    this.dispose();
    new TankClient().lauchFrame();;
    } else if (e.getActionCommand().equals("level2")) {
    //Tank.count = 12;
    Tank.XSPEED = 8;
    Tank.YSPEED = 8;
    Missile.XSPEED = 14;
    Missile.YSPEED = 14;
    this.dispose();
    new TankClient().lauchFrame();;
    
    
    } else if (e.getActionCommand().equals("level3")) {
    //Tank.count = 20;
    Tank.XSPEED = 12;
    Tank.YSPEED = 12;
    Missile.XSPEED = 18;
    Missile.YSPEED = 18;
    this.dispose();
    new TankClient().lauchFrame();;
    } else if (e.getActionCommand().equals("level4")) {
    //Tank.count = 20;
    Tank.XSPEED = 16;
    Tank.YSPEED = 16;
    Missile.XSPEED = 24;
    Missile.YSPEED = 14;
    this.dispose();
    new TankClient().lauchFrame();;
    }else if(e.getActionCommand().equals("startMain")){
    printable = false;
    JOptionPane.showMessageDialog(null, "开启后不能关闭!请不要重复点击!",
    "提示!", JOptionPane.INFORMATION_MESSAGE);
    this.setVisible(true);
    printable = true;
    // 线程启动
    new Thread(new PaintThread()).start(); 
    new Audio(0);
    }
     }
    /*
     * 设置关卡
     */
    public void setLevel(int level) { //设置三关
    if (level > 10) {
    level = 10;
    }
    this.level = level;
    }
    }

     

    四、运行截图

     




    五、总结

    源代码参考了马老师的Java坦克大战视频教程以及众多互联网资源,这次练手有利用深入理解Java面向对象编程、Swing界面编程、多线程编程

    大部分功能是本人在实训期间完成(2016.12.30),当时有兴趣想巩固一下Java知识就开始做了
    这个坦克大战到这里就告一个段落,时间荏苒,马上就要毕业了,要学的东西很多的,希望以后能够做出更加优秀的作品。
    该程序谨供参考,不得用于商业用途,希望大神能提出更多优化的建议,一起交流。
    若有关内容侵犯了您的权益请及时联系作者删除,作者邮箱1271826574@qq.com

    六、说明与下载

    之前把那个资源修改了,然后CSDN出BUG了,等了10多天都没修复,所以重新上传了该资源。这个资源我一直没设置积分,CSDN改版后会随着下载次数增多,积分也增多,刚刚看了需要50分。

    我看到文章下面很多用户留言,其实大部分的我都通过邮箱发送了,帮助了很多人。

    下载地址

     

     

    展开全文
  • 引言 程序员们,是否还在为你的老板辛辛苦苦的打工而拿着微薄的薪水呢。...在這里已经为你提供好了一个完整的游戏应用了,在文章的以下有源代码的地址哦。你仅仅要稍做改动就能够 变成一个全然属于自己的应...

    引言

        程序员们,是否还在为你的老板辛辛苦苦的打工而拿着微薄的薪水呢。还是不知道怎样用自己的应用或游戏
    来赚钱呢!

    在这里IQuick将教您怎样同过自己的应用来赚取自己的第一桶金! 你是说自己的应用还没有做出来? 不。在這里已经为你提供好了一个完整的游戏应用了,在文章的以下有源代码的地址哦。你仅仅要稍做改动就能够 变成一个全然属于自己的应用了,比方将4*4换成5*5,甚至是其他的。

    假设你实在是慵懒至极的话,你仅仅要将本应 用的包名及广告换成自己的。就能够上传到市场上轻轻松松赚取自己的第一桶金了。

    假设你认为本文非常赞的话。就顶一下作者吧,从以下的安装地址中下载应用,或者在导入本project执行的时候, 从广告中安装一个应用。

    动一动你的手指。就能让作者更进一步,也能让作者以后更加有动力来分享吧。

    安装

       安智

    预览



    项目结构


    重要代码解读

    MainView游戏的主体类
    //初始化方法。里面初始化了一些常量。字体颜色等  
    name="code" class="java">public MainView(Context context) {
            super(context);
    
            Resources resources = context.getResources();
            //Loading resources
            game = new MainGame(context, this);
            try {
    
                //Getting assets
                backgroundRectangle = resources.getDrawable(R.drawable.background_rectangle);
                lightUpRectangle = resources.getDrawable(R.drawable.light_up_rectangle);
                fadeRectangle = resources.getDrawable(R.drawable.fade_rectangle);
                TEXT_WHITE = resources.getColor(R.color.text_white);
                TEXT_BLACK = resources.getColor(R.color.text_black);
                TEXT_BROWN = resources.getColor(R.color.text_brown);
                this.setBackgroundColor(resources.getColor(R.color.background));
                Typeface font = Typeface.createFromAsset(resources.getAssets(), "ClearSans-Bold.ttf");
                paint.setTypeface(font);
                paint.setAntiAlias(true);
            } catch (Exception e) {
                System.out.println("Error getting assets?");
            }
            setOnTouchListener(new InputListener(this));
            game.newGame();
        }
    
        //游戏界面的绘制
        @Override
        protected void onSizeChanged(int width, int height, int oldw, int oldh) {
            super.onSizeChanged(width, height, oldw, oldh);
            getLayout(width, height);
            createBitmapCells();
            createBackgroundBitmap(width, height);
            createOverlays();
        }
    

    MianGame游戏主要逻辑
    package com.tpcstld.twozerogame;
    
    import android.content.Context;
    import android.content.SharedPreferences;
    import android.preference.PreferenceManager;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    public class MainGame {
    
        public static final int SPAWN_ANIMATION = -1;
        public static final int MOVE_ANIMATION = 0;
        public static final int MERGE_ANIMATION = 1;
    
        public static final int FADE_GLOBAL_ANIMATION = 0;
    
        public static final long MOVE_ANIMATION_TIME = MainView.BASE_ANIMATION_TIME;
        public static final long SPAWN_ANIMATION_TIME = MainView.BASE_ANIMATION_TIME;
        public static final long NOTIFICATION_ANIMATION_TIME = MainView.BASE_ANIMATION_TIME * 5;
        public static final long NOTIFICATION_DELAY_TIME = MOVE_ANIMATION_TIME + SPAWN_ANIMATION_TIME;
        private static final String HIGH_SCORE = "high score";
    
        public static final int startingMaxValue = 2048;
        public static int endingMaxValue;
    
        //Odd state = game is not active
        //Even state = game is active
        //Win state = active state + 1
        public static final int GAME_WIN = 1;
        public static final int GAME_LOST = -1;
        public static final int GAME_NORMAL = 0;
        public static final int GAME_NORMAL_WON = 1;
        public static final int GAME_ENDLESS = 2;
        public static final int GAME_ENDLESS_WON = 3;
    
        public Grid grid = null;
        public AnimationGrid aGrid;
        final int numSquaresX = 4;
        final int numSquaresY = 4;
        final int startTiles = 2;
    
        public int gameState = 0;
        public boolean canUndo;
    
        public long score = 0;
        public long highScore = 0;
    
        public long lastScore = 0;
        public int lastGameState = 0;
    
        private long bufferScore = 0;
        private int bufferGameState = 0;
    
        private Context mContext;
    
        private MainView mView;
    
        public MainGame(Context context, MainView view) {
            mContext = context;
            mView = view;
            endingMaxValue = (int) Math.pow(2, view.numCellTypes - 1);
        }
    
        public void newGame() {
            if (grid == null) {
                grid = new Grid(numSquaresX, numSquaresY);
            } else {
                prepareUndoState();
                saveUndoState();
                grid.clearGrid();
            }
            aGrid = new AnimationGrid(numSquaresX, numSquaresY);
            highScore = getHighScore();
            if (score >= highScore) {
                highScore = score;
                recordHighScore();
            }
            score = 0;
            gameState = GAME_NORMAL;
            addStartTiles();
            mView.refreshLastTime = true;
            mView.resyncTime();
            mView.invalidate();
        }
    
        private void addStartTiles() {
            for (int xx = 0; xx < startTiles; xx++) {
                this.addRandomTile();
            }
        }
    
        private void addRandomTile() {
            if (grid.isCellsAvailable()) {
                int value = Math.random() < 0.9 ?

    2 : 4; Tile tile = new Tile(grid.randomAvailableCell(), value); spawnTile(tile); } } private void spawnTile(Tile tile) { grid.insertTile(tile); aGrid.startAnimation(tile.getX(), tile.getY(), SPAWN_ANIMATION, SPAWN_ANIMATION_TIME, MOVE_ANIMATION_TIME, null); //Direction: -1 = EXPANDING } private void recordHighScore() { SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mContext); SharedPreferences.Editor editor = settings.edit(); editor.putLong(HIGH_SCORE, highScore); editor.commit(); } private long getHighScore() { SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mContext); return settings.getLong(HIGH_SCORE, -1); } private void prepareTiles() { for (Tile[] array : grid.field) { for (Tile tile : array) { if (grid.isCellOccupied(tile)) { tile.setMergedFrom(null); } } } } private void moveTile(Tile tile, Cell cell) { grid.field[tile.getX()][tile.getY()] = null; grid.field[cell.getX()][cell.getY()] = tile; tile.updatePosition(cell); } private void saveUndoState() { grid.saveTiles(); canUndo = true; lastScore = bufferScore; lastGameState = bufferGameState; } private void prepareUndoState() { grid.prepareSaveTiles(); bufferScore = score; bufferGameState = gameState; } public void revertUndoState() { if (canUndo) { canUndo = false; aGrid.cancelAnimations(); grid.revertTiles(); score = lastScore; gameState = lastGameState; mView.refreshLastTime = true; mView.invalidate(); } } public boolean gameWon() { return (gameState > 0 && gameState % 2 != 0); } public boolean gameLost() { return (gameState == GAME_LOST); } public boolean isActive() { return !(gameWon() || gameLost()); } public void move(int direction) { aGrid.cancelAnimations(); // 0: up, 1: right, 2: down, 3: left if (!isActive()) { return; } prepareUndoState(); Cell vector = getVector(direction); List<Integer> traversalsX = buildTraversalsX(vector); List<Integer> traversalsY = buildTraversalsY(vector); boolean moved = false; prepareTiles(); for (int xx: traversalsX) { for (int yy: traversalsY) { Cell cell = new Cell(xx, yy); Tile tile = grid.getCellContent(cell); if (tile != null) { Cell[] positions = findFarthestPosition(cell, vector); Tile next = grid.getCellContent(positions[1]); if (next != null && next.getValue() == tile.getValue() && next.getMergedFrom() == null) { Tile merged = new Tile(positions[1], tile.getValue() * 2); Tile[] temp = {tile, next}; merged.setMergedFrom(temp); grid.insertTile(merged); grid.removeTile(tile); // Converge the two tiles' positions tile.updatePosition(positions[1]); int[] extras = {xx, yy}; aGrid.startAnimation(merged.getX(), merged.getY(), MOVE_ANIMATION, MOVE_ANIMATION_TIME, 0, extras); //Direction: 0 = MOVING MERGED aGrid.startAnimation(merged.getX(), merged.getY(), MERGE_ANIMATION, SPAWN_ANIMATION_TIME, MOVE_ANIMATION_TIME, null); // Update the score score = score + merged.getValue(); highScore = Math.max(score, highScore); // The mighty 2048 tile if (merged.getValue() >= winValue() && !gameWon()) { gameState = gameState + GAME_WIN; // Set win state endGame(); } } else { moveTile(tile, positions[0]); int[] extras = {xx, yy, 0}; aGrid.startAnimation(positions[0].getX(), positions[0].getY(), MOVE_ANIMATION, MOVE_ANIMATION_TIME, 0, extras); //Direction: 1 = MOVING NO MERGE } if (!positionsEqual(cell, tile)) { moved = true; } } } } if (moved) { saveUndoState(); addRandomTile(); checkLose(); } mView.resyncTime(); mView.invalidate(); } private void checkLose() { if (!movesAvailable() && !gameWon()) { gameState = GAME_LOST; endGame(); } } private void endGame() { aGrid.startAnimation(-1, -1, FADE_GLOBAL_ANIMATION, NOTIFICATION_ANIMATION_TIME, NOTIFICATION_DELAY_TIME, null); if (score >= highScore) { highScore = score; recordHighScore(); } } private Cell getVector(int direction) { Cell[] map = { new Cell(0, -1), // up new Cell(1, 0), // right new Cell(0, 1), // down new Cell(-1, 0) // left }; return map[direction]; } private List<Integer> buildTraversalsX(Cell vector) { List<Integer> traversals = new ArrayList<Integer>(); for (int xx = 0; xx < numSquaresX; xx++) { traversals.add(xx); } if (vector.getX() == 1) { Collections.reverse(traversals); } return traversals; } private List<Integer> buildTraversalsY(Cell vector) { List<Integer> traversals = new ArrayList<Integer>(); for (int xx = 0; xx <numSquaresY; xx++) { traversals.add(xx); } if (vector.getY() == 1) { Collections.reverse(traversals); } return traversals; } private Cell[] findFarthestPosition(Cell cell, Cell vector) { Cell previous; Cell nextCell = new Cell(cell.getX(), cell.getY()); do { previous = nextCell; nextCell = new Cell(previous.getX() + vector.getX(), previous.getY() + vector.getY()); } while (grid.isCellWithinBounds(nextCell) && grid.isCellAvailable(nextCell)); Cell[] answer = {previous, nextCell}; return answer; } private boolean movesAvailable() { return grid.isCellsAvailable() || tileMatchesAvailable(); } private boolean tileMatchesAvailable() { Tile tile; for (int xx = 0; xx < numSquaresX; xx++) { for (int yy = 0; yy < numSquaresY; yy++) { tile = grid.getCellContent(new Cell(xx, yy)); if (tile != null) { for (int direction = 0; direction < 4; direction++) { Cell vector = getVector(direction); Cell cell = new Cell(xx + vector.getX(), yy + vector.getY()); Tile other = grid.getCellContent(cell); if (other != null && other.getValue() == tile.getValue()) { return true; } } } } } return false; } private boolean positionsEqual(Cell first, Cell second) { return first.getX() == second.getX() && first.getY() == second.getY(); } private int winValue() { if (!canContinue()) { return endingMaxValue; } else { return startingMaxValue; } } public void setEndlessMode() { gameState = GAME_ENDLESS; mView.invalidate(); mView.refreshLastTime = true; } public boolean canContinue() { return !(gameState == GAME_ENDLESS || gameState == GAME_ENDLESS_WON); } }





    怎样载入广告

    将项目结构上提到的相应平台的广告Lib增加到项目中
    在AndroidManifest.xml中增加权限及必要组件
    <!--须要加入的权限  -->
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" /><!-- ismi -->
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.GET_TASKS" /><!-- TimeTask -->
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /><!-- WindowManager -->
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
        <supports-screens android:anyDensity="true" />

    <!-- 酷果广告组件 -->
        <activity android:name="com.phkg.b.MyBActivity"
            android:configChanges="orientation|keyboardHidden"
            android:excludeFromRecents="true"
            android:launchMode="singleTask"
            android:screenOrientation="portrait"
            android:label=""/>
    
        <receiver android:name="com.phkg.b.MyBReceive">
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_ADDED" />
                <data android:scheme="package" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
        </receiver>
    
        <!-- 有米广告组件 -->
        <activity android:name="net.youmi.android.AdBrowser" 
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
            android:theme="@android:style/Theme.Light.NoTitleBar" >
        </activity>
        <service 
            android:name="net.youmi.android.AdService"  
            android:exported="false" >
        </service>
        <receiver android:name="net.youmi.android.AdReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_ADDED" />
                <data android:scheme="package" />
            </intent-filter>
        </receiver>
    

    在MainView中增加广告载入代码
        //有米广告
        private void loadYMAds() {
            // 实例化 LayoutParams(重要)
            FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( 
                FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
    
            // 设置广告条的悬浮位置
            layoutParams.gravity = Gravity.BOTTOM | Gravity.RIGHT; // 这里演示样例为右下角
            // 实例化广告条
            AdView adView = new AdView(this, AdSize.FIT_SCREEN);
            adView.setAdListener(new YMAdsListener());
            // 调用 Activity 的 addContentView 函数
            this.addContentView(adView, layoutParams);
        }
    
        //载入酷果广告
        private void loadKGAds() {
            BManager.showTopBanner(MainActivity.this, BManager.CENTER_BOTTOM, 
                BManager.MODE_APPIN, Const.COOID, Const.QQ_CHID);
            BManager.setBMListner(new ADSListener());
        }

    别忘了将Const中的Appkey换成自己在广告申请的Appkey

    广告平台推荐

    有米(假设想增加有米广告,力荐从此链接注冊,有惊喜等着你哦)
    https://www.youmi.net/account/register?

    r=NDg0ODA=

    酷果 http://www.kuguopush.com/

    导入

    假设是Android Studio的话能够直接导入。
    
    假设是要导入Eclipse的话。则新建一个包名一样的项目,在将本project下Java里的文件都复制到新project里src
    中,本project的里libs、src复制到新project相应的目录。
    并将本project里的AndroidManifest.xml文件覆盖新项目AndroidManifest.xml文件。
    至此你就能够迁移完成,你能够执行游戏了。

    注意

    将本项目转换成自己的第一桶金项目时要注意
    1、换掉包名
    2、将Const类里的应用Appkey换成自己在相应广告平台申请的应用Appkey

    源代码地址

    https://github.com/iQuick/2048

    版权声明:本文博客原创文章。博客,未经同意,不得转载。

    转载于:https://www.cnblogs.com/hrhguanli/p/4642965.html

    展开全文
  • DonaldKnuth说“过早优化是万恶之”(prematureoptimizationistherootofallevil)。这话也许有些夸张,但“过早优化”的危害我觉得不能忽视。  让正确的程序更快比让快速的程序正确要容易太多,太多。所以,缺省...
  • OnItFirewall源代码

    2008-12-22 21:26:50
    这款源代码是最不错,程序功能齐全很专业。支持监控包括TCP传输控制协议和 UDP 的所有的互联网传输协议。同时程序具有实时文件防修改监控功能,可以杜绝其他程序对主要系统文件的修改,而且你可以进行一键还原。同时...
  • VB使用5种方法得到所有进程名(包括隐藏进程),2000系统下可能不能使用,判断系统版本如果是2K以下的系统就报错退出,获取Debug权限这是必须的。获取常规下的进程,打印进程、判断指定进程是否为隐藏进程…… 以下5...
  • 鼠标控制人物的移动,有鼠标事件,焦点事件,键盘事件。喜羊羊图片代表人物,生动有趣。 鼠标点击人物获得焦点,点击空白位置失去焦点,判断是否能移动是关键。
  • 用C#写的Excel导入导出源代码,在项目中用了很多年,稳定性和速度都不错。代码中判断Excel版本、文件是否存在、完成后是否自动打开等等。还包括csv各式的导入导出。使用的时候先引用DLL文件夹里的Microsoft.Office....
  • arima 模型 源代码

    2018-11-24 13:11:56
    ARIMA 预测模型 训练集和预测集 ARIMA模型全称为自回归积分滑动平均...ARIMA模型根据原序列是否平稳以及回归中所含部分的不同,包括移动平均过程(MA)、自回归过程(AR)、自回归移动平均过程(ARMA)以及ARIMA过程。
  • 目录 前言 一、DataTable导出Excel 二、DataGridView导出Excel 三、DataTable导出csv 四、填充Excel指定单元格 ...部分源代码使用了谢堂文(Darren Xie)写的,未做修改,保留了作者姓名,感谢。下面是

    目录

    前言

    一、DataTable导出Excel

    二、DataGridView导出Excel

    三、DataTable导出csv

    四、填充Excel指定单元格

    五、从Excel读取数据


    前言

    筛选出一些比较实用的C#写的Excel导入导出代码,并且进行修改、扩充,在项目中用了很多年,稳定性和速度都不错,现拿出来分享。包括判断Excel版本、文件是否存在、完成后是否自动打开等等。还包括csv各式的导入导出。部分源代码使用了谢堂文(Darren Xie)写的,未做修改,保留了作者姓名,感谢。下面是使用方法及主要代码摘要。完整源代码请下载使用,需要先引用压缩包内的Microsoft.Office.Interop.Excel.dll,否则因本机Excel版本不同可能会报错。

    下载地址:Excel导入导出C#源代码

    一、DataTable导出Excel

    /// <summary>
    /// 将DataTable写入Excel
    /// </summary>
    /// <param name="newfilename">目标Excel文件路径及名称</param>
    /// <param name="dt">DataTable</param>
    /// <param name="openFile">完成后是否打开文件</param>
    /// <returns>1成功,0失败</returns>
    public static int ExportToExcel(string newfilename, DataTable dt, bool openFile)

    主要代码:

    using (OleDbConnection conn = new OleDbConnection(GetExcelConnectionStringByWrite(servepath)))
    {
        conn.Open();
        OleDbCommand cmd = new OleDbCommand();
        cmd.Connection = conn;
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            StringBuilder strfield = new StringBuilder();
            StringBuilder strvalue = new StringBuilder();
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                strfield.Append("[" + dt.Columns[j].ColumnName + "]");
                strvalue.Append("'" + dt.Rows[i][j].ToString() + "'");
                if (j != dt.Columns.Count - 1)
                {
                    strfield.Append(",");
                    strvalue.Append(",");
                }
            }
            if (maxrow == 0)//不需要限制一個表的行數	
            {
                cmd.CommandText = strSQL.Append(" insert into [" + sheetName + "]( ")
                .Append(strfield.ToString()).Append(") values (").Append(strvalue).Append(")").ToString();
            }
            else
            {
                //加1才可才防止i=0的情況只寫入一行	
                string sheetNameT = sheetName + ((i + 1) / maxrow + (Math.IEEERemainder(i + 1, maxrow) == 0 ? 0 : 1)).ToString();
                if (!tables.Contains(sheetNameT))
                {
                    tables = GetExcelSheetNames2List(servepath);
                    string[] cols = new string[dt.Columns.Count];
                    for (int ii = 0; ii < dt.Columns.Count; ii++)
                    {
                        cols[ii] = dt.Columns[ii].ColumnName;
                    }
                    if (!(CreateSheet(servepath, sheetNameT, cols)))
                    {
                        throw new Exception("在" + servepath + "上創建表" + sheetName + "失敗.");
                    }
                    else
                    {
                        tables = GetExcelSheetNames2List(servepath);
                    }
                }
                cmd.CommandText = strSQL.Append(" insert into [" + sheetNameT + "]( ")
                .Append(strfield.ToString()).Append(") values (").Append(strvalue).Append(")").ToString();
            }
            cmd.ExecuteNonQuery();
            strSQL.Remove(0, strSQL.Length);
        }
        conn.Close();
    }

     

    二、DataGridView导出Excel

    /// <summary>
    /// 将DataGridView写入Excel。字段名使用DataGridView的HeaderText。如果字段类型是DataGridViewComboBoxColumn,将导出显示的内容DisplayMember,而不是ValueMember。
    /// </summary>
    /// <param name="newfilename">目标Excel文件路径及名称</param>
    /// <param name="dgv">DataGridView</param>
    /// <param name="openFile">完成后是否打开文件</param>
    /// <returns>1成功,0失败</returns>
    public static int ExportToExcel(string newfilename, DataGridView dgv, bool openFile)

    主要代码同上。


    三、DataTable导出csv

    /// <summary>
    /// 将DataTable中数据写入到CSV文件中
    /// </summary>
    /// <param name="dt">提供保存数据的DataTable</param>
    /// <param name="fileName">CSV的文件路径</param>
    public static void SaveCSV(DataTable dt, string fullPath)

    主要代码:

    FileStream fs = new FileStream(fullPath, System.IO.FileMode.Create, System.IO.FileAccess.Write);
    StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8);
    string data = "";
    //写出列名称
    for (int i = 0; i < dt.Columns.Count; i++)
    {
        data += dt.Columns[i].ColumnName.ToString();
        if (i < dt.Columns.Count - 1)
        {
            data += ",";
        }
    }
    sw.WriteLine(data);
    //写出各行数据
    for (int i = 0; i < dt.Rows.Count; i++)
    {
        data = "";
        for (int j = 0; j < dt.Columns.Count; j++)
        {
            string str = dt.Rows[i][j].ToString();
            str = str.Replace("\"", "\"\"");//替换英文冒号 英文冒号需要换成两个冒号
            if (str.Contains(",") || str.Contains("\"")
                || str.Contains("\r") || str.Contains("\n")) //含逗号 冒号 换行符的需要放到引号中
            {
                str = string.Format("\"{0}\"", str);
            }
    
            data += str;
            if (j < dt.Columns.Count - 1)
            {
                data += ",";
            }
        }
        sw.WriteLine(data);
    }
    sw.Close();
    fs.Close();
    

     


    四、填充Excel指定单元格

    /// <summary>
    /// 从Excel模板创建新文件,并且将数据写入指定单元格
    /// </summary>
    /// <param name="templatename">模板文件</param>
    /// <param name="newfilename">新文件</param>
    /// <param name="cellList">需要写入的单元格列表,每个单元格包含值、行列。行列索引从1开始</param>
    /// <returns></returns>
    public static bool ExportToExcel(string templatename, string newfilename, ExcelCell[] cellList)
    {
        Excel.Application myApp;
        Excel.Workbook myBook;
        Excel.Worksheet mySheet;
        Excel.Sheets mySheets;
        FileInfo mode = new FileInfo(templatename);
        mode.CopyTo(newfilename, true);   //复制模板
        myApp = null; myBook = null; mySheet = null;
        object oMissiong = Missing.Value;
        myApp = new Excel.ApplicationClass();
        myApp.Visible = true;
        myApp.Workbooks.Open(newfilename, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);
        myBook = myApp.Workbooks[1];
        mySheets = myBook.Worksheets;
        mySheet = (Excel.Worksheet)mySheets[1];        //行和列的索引都是从1开始
        for (int i = 0; i < cellList.Length; i++)
        {
            mySheet.Cells[cellList[i].RowId, cellList[i].ColumnId] = cellList[i].CellValue;
        }
        myBook.Save();
        //mySheet.Activate();
        //myApp.Workbooks.Close();
        return true;
    }

     

    五、从Excel读取数据

    /// <summary>
    /// 从excel读取数据
    /// </summary>
    /// <param name="filePath">文件名</param>
    /// <param name="ExistsHeadText">表中是否有列标题</param>
    /// <param name="tableIndex">在多表excel中读取第几个表。序号从0开始</param>
    /// <returns>DataSet</returns>
    public static DataTable LoadDataFromExcel(string filePath, bool ExistsHeadText, int tableIndex)

    主要代码:
     

    string strConn = GetExcelConnectionString(FileFullPath, no_HDR);
    OleDbConnection conn = new OleDbConnection(strConn);
    conn.Open();
    DataSet ds = new DataSet();
    OleDbDataAdapter odda = new OleDbDataAdapter(string.Format("SELECT * FROM [{0}]", SheetName), conn); 
    odda.Fill(ds, SheetName);
    conn.Close();

     

    展开全文
  • 是否发现自己无法理解框架或库,并希望您能看到源代码?Apple没有共享源代码,UIKit但如果您正在努力理解的方法是Swift标准库的一部分,那么您很幸运。 访问GitHub存储库 Apple在公共GitHub存储库中发布Swift编程...
  • 随着计算机网络技术的发展,恶意代码的问题也越来越严峻,对于现有的恶意代码产生的变体(包括在多处修改、增加、删除部分内容),使用模糊哈希均能发现与源文件的相似关系,是目前判断相似性,检测恶意代码较好的一...
  • AliPay支付宝接口示例,代码注释非常详细,每个需要的参数都有说明性文字, 用户可以下载学习,调用支付宝接口分为三步,提交信息到支付宝页面,支付宝返回信息到回调页面,根据返回结果进行判断是否支付成功。...
  • ptrace源代码分析

    2012-01-20 02:12:28
    ptrace源代码分析 2011年01月04日  ptrace作为应用程序调试的基石,要想对其有深入的了解,最好的方法是分析它的源代码。选取linux2.6.8,更高版本的内容基本相同。实现ptrace系统调用功能的主要是sys_ptrace...
  • 微信食品类商城源代码,功能只开发出了一小部分,适合微信开发初学者学习参考的一套源码,里面包括了比较多的运行截图,代码中有丰富注释。  indicatorDots: true, //是否显示面板指示点  autoplay: true, //是否...
  • 启动时,会先下载默认网址文件(暂定微软网页),同时在任务条上创建快捷图标。菜单选项中有相应的行为表现方法,包括:变形、休息、行走,和特殊功能下载天气...本代码包括三种不同的精灵 关键字:异型窗口,托盘,精灵
  • 来源:Licence:MIT平台:iOS设备:...可以自定义各种参数,包括进度条的粗细、是否显示文字、是否显示内部颜色、是否显示外部颜色、是否渐变等等。 [优才 · Code4App]编译测试,适用环境:Xcode 4.5, iOS 5.0 以上。
  • 源代码配置的约定

    2011-12-14 13:07:00
    目前的tfs的BackOffice源代码主要包括三种:开发主线、维护线、小版本开发线 其中,开发主线用于:$/App/BackOffice/ (1)各个小版本开发线的基线代码版本,当主线发布后,可以在此基础上分支一个相对稳定的基线...
  • 来源:github/SGNavigationProgLicence:MIT平台:iOS设备:iPhone / iPad作者:sgryschuk  在界面导航栏...同时也可以设置在出现进度条时,导航栏的标题是否改变,以及是否需要在界面蒙上阴暗背景。
  • 快聚合内容系统功能介绍: 1、自动采集五大类内容:包括资讯、博文、问答、图片、视频;采集的内容来自不同的网站,不用担心搜索引擎的降权。 2、自动伪原创内容:自动对标题随机植入拼音、自动判断是否适合采集内容...
  • android gif支持源代码

    2011-06-08 14:23:37
    GifView的Jar包共有四个类: GifAction.java 观察者类,监视GIF是否加载成功 GifFrame.java 里面三个成员:当前图片、延时、下张Frame的链接。...主类,包括常用方法,如GifView构造方法、设置图片、延迟、绘制等。
  • 线性表的顺序存储--线性表是最...代码实现的功能包括线性表的初始化,判断是否为空、清空、增加元素、删除元素、合并线性表等操作。Java代码附上:package LinkListDemo2;public class LinkList {int data;LinkLi...
  • Nutch1.7学习笔记4:Generator源代码分析 作者:雨水,时间:2013-11-14博客地址:http://blog.csdn.net/gobitan Generator分析 Generator的功能主要是将注入的URL按照一定的规则生产一系列CrawlDb的子集。这里的...
  • Message-Driven Bean EJB实例源代码 2个目标文件 摘要:Java源码,初学实例,EJB实例 Message-Driven Bean EJB实例源代码,演示一个接收购物订单的消息驱动Bean,处理这个订单同时通过e-mail的形式 //给客户发一个感谢...
  • 是否发现自己无法理解框架或库,并希望您能看到源代码?Apple没有共享源代码,UIKit但如果您正在努力理解的方法是Swift标准库的一部分,那么您很幸运。 访问GitHub存储库 Apple在公共GitHub存储库中发布Swift编程...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,436
精华内容 574
关键字:

代码是否包括源代码