安卓模仿2048小游戏

话不多说,直接开撸!
刚开始进入Splash界面:
1.SplashActivity.java(两秒后进入开始界面,Splash界面的布局只有一个图片,在博客后,会展示给大家看)

public class SplashActivity extends Activity {
    
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);

        new Thread(new Runnable() {     
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                    Intent intent=new Intent(SplashActivity.this, LoginActivity.class);
                    startActivity(intent);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                finish();
            }
        }).start();
    }
}

2.LoginActivity(登陆界面)

   private Button btn1,btn2;
   private EditText etAcount,etPassword;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        initView();
    }
    private void initView() {
        btn1=(Button) findViewById(R.id.btn_login);
        btn2=(Button) findViewById(R.id.btn_register);

        etAcount=(EditText) findViewById(R.id.et_account);
        etPassword=(EditText) findViewById(R.id.et_pwd);
        btn1.setOnClickListener(new OnClickListener() {
            //登录按钮的监听
            @Override
            public void onClick(View v) {
                SharedPreferences sharedPreferences=getSharedPreferences("user", MODE_PRIVATE);
                String number=sharedPreferences.getString("number", "");
                int a,b;
                if (number=="") {
                    a=0;//记录用户个数
                }else {
                    a=Integer.parseInt(number);
                }
                String account;
                String password;
                for (b=0;b<a;b++) {
    
    
                    account="account"+b;
                    password="password"+b;
                    String jname=sharedPreferences.getString(account,"");
                    String jpwd=sharedPreferences.getString(password, "");

                    if (jname.equals(etAcount.getText().toString())||jpwd.equals(etPassword.getText().toString())) {
                         if (jname.equals(etAcount.getText().toString())&&jpwd.equals(etPassword.getText().toString())) {
                             finish();
                             Intent intent=new Intent(LoginActivity.this, MainActivity.class);
                             startActivity(intent);
                             break;
                         }else if (jname.equals(etAcount.getText().toString())) {
                            Toast.makeText(LoginActivity.this, "密码错误", Toast.LENGTH_SHORT).show();  
                        }
                    }
                }
                if (b==a) {
                    Toast.makeText(LoginActivity.this, "用户未注册", Toast.LENGTH_SHORT).show();
                }
            }
        });
        //注册按钮的监听
        btn2.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                String account;
                String password;
                SharedPreferences sharedPreferences=getSharedPreferences("user",MODE_PRIVATE);
                String number=sharedPreferences.getString("number", "");
                int a;
                int b;
                if (number=="") {
                    a=0;
                }else {
                    a=Integer.parseInt(number);
                }
                for (b = 0; b <a; b++) {
    
    
                    account="account"+b;
                    password="password"+b;
                    String jname=sharedPreferences.getString(account,"");
                    if (jname.equals(etAcount.getText().toString())) {
                        break;
                    }
                }
                if (b==a) {
                    if (etAcount.getText().toString().equals("")&&etPassword.getText().toString().equals("")) {
                        Toast.makeText(LoginActivity.this,"用户名密码不能为空", Toast.LENGTH_SHORT).show();
                    }else {
                        account="account"+b;
                        password="password"+b;
                        a++;
                        SharedPreferences.Editor editor=sharedPreferences.edit();
                        editor.putString(account,etAcount.getText().toString());
                        editor.putString(password,etPassword.getText().toString());
                        editor.putString("number",a+"");
                        editor.commit();
                        Toast.makeText(LoginActivity.this,"注册成功", Toast.LENGTH_SHORT).show();
                    }
                }else {
                    Toast.makeText(LoginActivity.this,"该账户已存在", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }   
}

LoginActivity的布局如下:

    <ImageView
        android:id="@+id/img_head"
        android:layout_width="match_parent"
        android:layout_height="260dp"
        android:background="@drawable/head_game" />

    <EditText   
        android:id="@+id/et_account"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_below="@id/img_head"
        android:layout_marginLeft="50dp"
        android:layout_marginRight="50dp"
        android:layout_marginTop="40dp"
        android:background="@drawable/set_charge_top"
        android:drawableLeft="@drawable/login_img2"
        android:hint="请输入账号" />

        <EditText
            android:id="@+id/et_pwd"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_below="@id/et_account"
            android:layout_marginLeft="50dp"
            android:layout_marginTop="10dp"
            android:layout_marginRight="50dp"
            android:background="@drawable/set_charge_top"
            android:drawableLeft="@drawable/login_img3"
            android:hint="请输入密码" />
     <Button 
         android:id="@+id/btn_login"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="登录"
         android:layout_below="@id/et_pwd"
         android:layout_marginTop="10dp"
         android:layout_marginLeft="70dp"/>
     <Button 
         android:id="@+id/btn_register"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="注册"
         android:layout_below="@id/et_pwd"
         android:layout_toRightOf="@id/btn_login"
         android:layout_marginTop="10dp"
         android:layout_marginLeft="60dp"/>

3.MainActivity.java(主页面)

public class MainActivity extends Activity {
    
    
    private TextView tvScore;
    private Animation animation;
    private static MainActivity mainActivity = null;
    private int score = 0;
    private ImageView imageView;
    private GameView gameView;
    public static MainActivity getMainActivity() {
        return mainActivity;
    }

    public MainActivity() {
        mainActivity = this;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvScore = (TextView) findViewById(R.id.tvScore);
        imageView=(ImageView) findViewById(R.id.img_monkey);
    }

    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.btn_help://帮助按钮,弹出对话框
            animation=AnimationUtils.loadAnimation(this,R.anim.anim_monkey);
            AlertDialog.Builder dialog2=new AlertDialog.Builder(this);
            dialog2.setTitle("嘲讽+藐视");
            dialog2.setMessage("这么简单的游戏你还要帮助!!你咋不上天呢");
            dialog2.setPositiveButton("给我绑个窜天猴", new OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                     imageView.startAnimation(animation);//为ImageView设置动画
                }
            });
            dialog2.setNegativeButton("继续玩~", new OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {

                }
            });
            dialog2.show();
            break;
        case R.id.btn_quit://退出按钮的点击事件
            AlertDialog.Builder dialog = new AlertDialog.Builder(this);
            dialog.setTitle("提示:");
            dialog.setMessage("主人,你真的要离开我么?");
            dialog.setPositiveButton("确定", new OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    System.exit(0);
                }
            });
            dialog.setNegativeButton("取消", new OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {

                }
            });
            dialog.show();
            break;

        default:

            break;
        }
    }
    public void clearScore() {
   
   //清除分数
        score = 0;
        showScore();
    }
    public void showScore() {
   
   //展示分数
        tvScore.setText(score + "");
    }
    public void addScore(int s) {
   
   //添加分数
        score += s;
        showScore();
    }
}

MainActivity的布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.jerry.game2048.MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:background="#574336"
         >
        <TextView 
            android:layout_marginLeft="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/score"
            android:textSize="24sp"
            android:textColor="#FFFFFF"
            android:textStyle="bold"/>
        <TextView 
            android:id="@+id/tvScore"
            android:textSize="25sp"
            android:textColor="#FFFFFF"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
     <com.jerry.game2048.GameView
         android:id="@+id/gameView"
         android:layout_width="fill_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
         ></com.jerry.game2048.GameView>
    <ImageView 
        android:id="@+id/img_monkey"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:visibility="visible"
        android:layout_gravity="center_horizontal"
        android:src="@drawable/icon10"
        android:scaleType="fitXY"
        />
   <LinearLayout
         android:id="@+id/ly_btns"
         android:layout_marginTop="20dp"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="horizontal" 
         android:background="#ddada0"
         >
         <Button 
             android:id="@+id/btn_help"
             android:layout_width="0dp"
             android:layout_weight="1"
             android:layout_height="wrap_content"
             android:layout_marginLeft="20dp"
             android:text="游戏帮助"
             android:textSize="20sp"
             android:onClick="onClick"/>
         <Button 
             android:id="@+id/btn_quit"
             android:layout_width="0dp"
             android:layout_weight="1"
             android:layout_height="wrap_content"
             android:text="退出游戏"
             android:layout_marginRight="20dp"
             android:textSize="20sp"
             android:onClick="onClick"/>

     </LinearLayout>
     <TextView 
         android:layout_width="match_parent"
         android:layout_height="40dp"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:focusable="true"
         android:focusableInTouchMode="true"
         android:marqueeRepeatLimit="marquee_forever"
         android:scrollHorizontally="true"
         android:textSize="30sp"
         android:background="#000000"
         android:textColor="#ffffff"
         android:text="这里写实际项目中,你所需要添加广告信息,这是一个跑马灯的效果,遇到问题,可在本博客下留下邮箱和问题,可以为您解答,转载请注明出处,谢谢"/>
</LinearLayout>

4.Card.java(卡片类)

public class Card extends FrameLayout {
    
    
    private int num=0;
    private TextView label;
    public Card(Context context) {
        super(context);
        label=new TextView(getContext());   
        label.setTextSize(32);
        label.setGravity(Gravity.CENTER);

        label.setBackgroundColor(0x33ffffff);//设置每个卡片的颜色

        LayoutParams lp=new LayoutParams(-1,-1);//该类用来初始化layout控件textView里的宽高属性
        lp.setMargins(10, 10, 0, 0);//设置间隔
        addView(label,lp);           
        setNum(0);
    }

    public int getNum() {
        return num;
    }
    public void setNum(int num) {   
        this.num=num;
        if (num<=0) {
            label.setText("");
        }else {
            label.setText(num+"");
        }
    }
    //重写equals方法,判断卡片绑定的数字是否相等
    public boolean equals(Card o) {
        return getNum()==o.getNum();
    }  
}

5.GameView.java(主要逻辑)

public class GameView extends GridLayout {
    
    
    private Card[][] cardsMap = new Card[4][4];
    //用来存放cardsMap下标用的Point类的集合
    private List<Point> emptyPoints = new ArrayList<Point>();

    public GameView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initGameView();
    }

    public GameView(Context context) {
        super(context);
        initGameView();
    }

    public GameView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initGameView();
    }

    private void initGameView() {
        setColumnCount(4);
        setBackgroundColor(0xffddada0);

        setOnTouchListener(new OnTouchListener() {
            // 添加触摸事件 开始
            private float startX, startY, offsetX, offsetY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    startX = event.getX();
                    startY = event.getY();
                    break;
                case MotionEvent.ACTION_UP:
                    offsetX = event.getX() - startX;// 大于0则代表向右滑
                    offsetY = event.getY() - startY;// 小于0代表向上滑

                    if (Math.abs(offsetX) > Math.abs(offsetY)) {
                        if (offsetX > 5) {
                            swipeRight();
                        } else if (offsetX < -5) {
                            swipeLeft();
                        }
                    } else {
                        if (offsetY > 5) {
                            swipeDown();
                        } else if (offsetY < -5) {
                            swipeUp();
                        }
                    }
                    break;
                }
                return true;
            }
        });
    }
    //根据卡片宽和高
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        //该方法就是宽高发生改变的时候我们可以得到当前的宽高是多少 
        //该方法也是在游戏一被创建的时候就调用,也就是用来初始宽高的方法
        super.onSizeChanged(w, h, oldw, oldh);

        //获取手机较窄的长度,-10是用来间隔每个卡片的距离,用手机的宽除以4就是每个卡片的长度了
        int cardWidth = (Math.min(w, h) - 10) / 4;
        addCards(cardWidth, cardWidth);

        startGame();
    }

    //增加卡片,形成4*4的矩阵
    private void addCards(int cardWidth, int cardHeight) {
        Card c;
        for (int y = 0; y < 4; y++) {
            for (int x = 0; x < 4; x++) {
                c = new Card(getContext());
                c.setNum(2);
                addView(
                        c, cardWidth, cardHeight);
               //顺便把初始化时新建的卡片存放在新建的二维数组中
                cardsMap[x][y] = c;
            }
        }
    }
    //开始游戏,初始化16个card
    public void startGame() {
        MainActivity.getMainActivity().clearScore();
        for (int y = 0; y < 4; y++) {
            for (int x = 0; x < 4; x++) {
                cardsMap[x][y].setNum(0);
            }
        }
        addRondomNum();
        addRondomNum();
    }
    //判断游戏结束
    private void endGame(){
        boolean isfull=true;//判断卡片是否铺满的标志变量
        for (int x = 0; x < 4; x++) {
            for (int y = 0; y < 4; y++) {
                if (cardsMap[x][y].getNum()==0
                        ||(x>0&&cardsMap[x][y].equals(cardsMap[x-1][y]))
                        ||(x<3&&cardsMap[x][y].equals(cardsMap[x+1][y]))
                        ||(y>0&&cardsMap[x][y].equals(cardsMap[x][y-1]))
                        ||(y<3&&cardsMap[x][y].equals(cardsMap[x][y+1]))) {
                    isfull=false;
                    break;
                }
            }
        }
        if (isfull) {
            AlertDialog.Builder dialog=new AlertDialog.Builder(getContext());
            dialog.setTitle("Game Over!");
            dialog.setMessage("你太菜了!想要再玩一次么?");
            dialog.setCancelable(false);

            dialog.setPositiveButton("重新开始",new DialogInterface.OnClickListener() {

                public void onClick(DialogInterface dialog, int which) {
                    startGame();
                }
            });
            dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // TODO Auto-generated method stub

                }
            });
            dialog.show();
        }
    }
    private void addRondomNum() {
       //把这个point清空,每次调用添加随机数时就清空之前的emptyPoints
        emptyPoints.clear();
       //对所有的位置进行遍历:即为每个卡片加上了可以控制的Point 
        for (int y = 0; y < 4; y++) {
            for (int x = 0; x < 4; x++) {
                if (cardsMap[x][y].getNum() <= 0) {
                    emptyPoints.add(new Point(x, y));
                }
            }
        }
        //通过随机的从存放了的Point的List集合里去获取Card的位置,并给这个card设置文本属性,并且只能存2或
        //通过point对象来充当下标的角色来控制存放card的二维数组cardsMap,然后随机给定位到的card对象赋值
        Point p = emptyPoints.remove((int) (Math.random() * emptyPoints.size()));
        cardsMap[p.x][p.y].setNum(Math.random() > 0.1 ? 2 : 4);
    }
     //左移
    private void swipeLeft() {
        boolean add=false;
        for (int y = 0; y < 4; y++) { 
            for (int x = 0; x < 4; x++) {
                for (int x1 = x + 1; x1 < 4; x1++) {
                    if (cardsMap[x1][y].getNum() > 0) {
   
   //除了第一列以外的数,如果存在一个数大于0
                        if (cardsMap[x][y].getNum() <= 0) {
   
   //如果左边没有数
                            cardsMap[x][y].setNum(cardsMap[x1][y].getNum());//将右边的数移到左边
                            cardsMap[x1][y].setNum(0);//右边数清零
                            x--;
                            add=true;
                            break;
                        } else if (cardsMap[x][y].equals(cardsMap[x1][y])) {
                            cardsMap[x][y].setNum(cardsMap[x][y].getNum() * 2);
                            cardsMap[x1][y].setNum(0);

                            MainActivity.getMainActivity().addScore(
                                    cardsMap[x][y].getNum());

                            add=true;
                        }
                        break;
                    }
                }
            }
        }
        if (add) {
            addRondomNum();
            endGame();//判断是否结束
        }
    }
    //右移
    private void swipeRight() {
        boolean add=false;
        for (int y = 0; y < 4; y++) {
            for (int x = 3; x >= 0; x--) {
                for (int x1 = x - 1; x1 >= 0; x1--) {
                    if (cardsMap[x1][y].getNum() > 0) {
                        if (cardsMap[x][y].getNum() <= 0) {
                            cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
                            cardsMap[x1][y].setNum(0);
                            x++;
                            add=true;
                            break;
                        } else if (cardsMap[x][y].equals(cardsMap[x1][y])) {
                            cardsMap[x][y].setNum(cardsMap[x][y].getNum() * 2);
                            cardsMap[x1][y].setNum(0);
                            MainActivity.getMainActivity().addScore(
                                    cardsMap[x][y].getNum());
                            add=true;
                        }
                        break;
                    }
                }
            }
        }
        if (add) {
            addRondomNum();
            endGame();
        }
    }

    private void swipeUp() {
        boolean add=false;
        for (int x = 0; x < 4; x++) {
            for (int y = 0; y < 4; y++) {
                for (int y1 = y + 1; y1 < 4; y1++) {
                    if (cardsMap[x][y1].getNum() > 0) {
                        if (cardsMap[x][y].getNum() <= 0) {
                            cardsMap[x][y].setNum(cardsMap[x][y1].getNum());
                            cardsMap[x][y1].setNum(0);
                            y--;
                            add=true;
                            break;
                        } else if (cardsMap[x][y].equals(cardsMap[x][y1])) {
                            cardsMap[x][y].setNum(cardsMap[x][y].getNum() * 2);
                            cardsMap[x][y1].setNum(0);
                            MainActivity.getMainActivity().addScore(
                                    cardsMap[x][y].getNum());
                            add=true;

                        }
                        break;
                    }
                }
            }
        }
        if (add) {
            addRondomNum();
            endGame();
        }
    }

    private void swipeDown() {
        boolean add=false;
        for (int x = 0; x < 4; x++) {
            for (int y = 3; y >= 0; y--) {
                for (int y1 = y - 1; y1 >= 0; y1--) {
                    if (cardsMap[x][y1].getNum() > 0) {
                        if (cardsMap[x][y].getNum() <= 0) {
                            cardsMap[x][y].setNum(cardsMap[x][y1].getNum());
                            cardsMap[x][y1].setNum(0);
                            y++;
                            add=true;
                            break;
                        } else if (cardsMap[x][y].equals(cardsMap[x][y1])) {
                            cardsMap[x][y].setNum(cardsMap[x][y].getNum() * 2);
                            cardsMap[x][y1].setNum(0);
                            MainActivity.getMainActivity().addScore(
                                    cardsMap[x][y].getNum());
                            add=true;
                        }
                        break;
                    }
                }
            }
        }
        if (add) {
            addRondomNum();
            endGame();
        }
    }
}

6.最后不要忘记在清单配置文件中配置信息

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jerry.game2048"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="17"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/game2048"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.jerry.game2048.MainActivity"
            android:label="@string/app_name"
            //设置屏幕为竖屏
             android:screenOrientation="portrait" >
        </activity>
        <activity
            android:name=".SplashActivity"
            android:label="@string/title_activity_splash" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".LoginActivity"
            android:label="@string/title_activity_login" >
        </activity>
    </application>
</manifest>

7.其中的窜天猴的动画效果实现如下:

  1. 在res文件下新建一个anim文件夹
  2. 在anim文件夹下新建一个anim_monky.xml的布局文件

    anim_monky.xml

    扫描二维码关注公众号,回复: 12079529 查看本文章
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="0"
        android:toXDelta="40"
        android:fromYDelta="0"
        android:toYDelta="-5000"
        android:duration="4000"/>
     <alpha 
         android:fromAlpha="1"
         android:toAlpha="0"
         android:duration="5000"
         />
</set>

效果图如下:


本项目完整课运行, 遇到问题,可在本博客下留下邮箱和问题,可以为您解答,转载请注明出处,谢谢。

猜你喜欢

转载自blog.csdn.net/Json_Jerry/article/details/52852115