(更新)女友是第一生产力之Android实现“2048”游戏

起因是这样的,今早安卓开发课布置了写2048小游戏的实验,并且给了源代码,我照着源代码一顿猛敲,做出了个老师要的版本。
想到女朋友也挺喜欢玩2048的,就想得瑟一下,发了个apk过去。
没想到遭到一阵嫌弃,“你这数字都是黑色好模糊啊我都看不清”,“我都快到2048了走错一步,哎呀你这个怎么都不能回退一步的”
emmmmmm好吧,谁叫咱想装逼呢,那么就针对甲方这两个需求,开始敲代码

继昨日后续,甲方说“阿sir,你这个怎么都没有最高分的?”
对哦,身为一个游戏,不断挑战最高分,才是它的好玩之处。着手修改

2048游戏的实现

结果展示

1.结果1.0
在这里插入图片描述
2.结果2.0
在这里插入图片描述

思路

  1. 改颜色
    改颜色这个很容易,但是要找ARGB的颜色来改Card类中每个数字的颜色
  2. 实现回退
    这里我用四个ArrayList分别来存放当前的位置、当前的数值、上一步的位置、上一步的数值。
    每次进行上下左右滑动的时候,就把当前的位置、当前的数值覆盖掉上次记录的上一步的位置、上一步的数值。然后再记录新的当前的位置、当前的数值。
    每次回退就把上一步的位置和上一步的数值加载进这个界面。
    回退当然也要回退分数,这里用两个整型变量来传递就好了。
  3. 记录最高分
    最简单的我想到就是利用SharedPreferences来保存信息,这里我觉得还需要判断是不是第一次启动,如果是第一次启动那我就创建一个最高分文件来储存,如果不是第一次启动,那就直接从里面拿东西。同样,判断第一次启动我也用的是SharedPreferences。

源码

  1. 首先看看我的文件树
    在这里插入图片描述
  2. Card类
package com.example.minigame;

import android.content.Context;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;


public class Card extends FrameLayout {
    private TextView text;
    private int number=0;
    public int getNumber(){
        return number;
    }
    public void setNumber(int number){
        this.number=number;
        if(number<2){
            text.setText("");
        }else{
            if(number==2){
                text.setTextColor(0xFFFFFF00);
            }else if(number==4){
                text.setTextColor(0xFF00FF00);
            }
            else if(number==8){
                text.setTextColor(0xFF00FFFF);
            }
            else if(number==16){
                text.setTextColor(0xFF0000FF);
            }
            else if(number==32){
                text.setTextColor(0xFFFF00FF);
            }
            else if(number==64){
                text.setTextColor(0xFF7F007F);
            }
            else if(number==128){
                text.setTextColor(0xFFFF7F00);
            }
            else if(number==256){
                text.setTextColor(0xFF996633);
            }
            else if(number==512){
                text.setTextColor(0xFFFF0000);
            }
            else if(number==1024){
                text.setTextColor(0xFF350D04);
            }
            else if(number==2048){
                text.setTextColor(0xFFFF3800);
            }
            else{
                text.setTextColor(0xFF95090C);
            }
            text.setText(number+"");
        }
    }
    public Card(@NonNull Context context) {
        super(context);
        text=new TextView(context);
        text.setTextSize(28);
        text.setBackgroundColor(0x9966cccc);
        text.setGravity(Gravity.CENTER);
        LayoutParams params=new LayoutParams(-1,-1);
        params.setMargins(10,10,0,0);
        addView(text,params);
    }
}

  1. GameView类
package com.example.minigame;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.GridLayout;
import android.content.SharedPreferences;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class GameView extends GridLayout {
    //定义4*4的卡片布局
    private Card cards[][]=new Card[4][4];
    //记录空卡片
    private List<Point> emptyCards=new ArrayList<Point>();
    //随机数
    Random rd=new Random();
    //分数
    int score=0;
    int oldscore=0;
    int currentscore=0;
    int bscore;

    public int getBscore() {
        return bscore;
    }

    public void setBscore(int bscore) {
        this.bscore = bscore;
    }

    //记录所有卡片位置及当前分数
    private List<Point> backCards=new ArrayList<Point>();
    private List<Point> oldbackCards=new ArrayList<Point>();
    private List<Integer> backCardsnums=new ArrayList<Integer>();
    private List<Integer> oldbackCardsnums=new ArrayList<Integer>();


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

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

    public GameView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initGame();
    }
    //游戏初始界面
    private void initGame() {
        setColumnCount(4);  //设置列的数量
        setBackgroundColor(0xffffcccc); //设置背景颜色
        setOnTouchListener(new OnTouchListener() {  //触摸监听
            private float startX,startY;
            private float offsetX,offsetY;
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:   //手势事件开启
                        startX=event.getX();    //获取当前x坐标
                        startY=event.getY();    //获取当前y坐标
                        break;
                    case MotionEvent.ACTION_UP:     //手势事件结束
                        Gameover();
                        offsetX=event.getX()-startX;    //获取当前x坐标跟移动前坐标的x差值
                        offsetY=event.getY()-startY;    //获取当前y坐标跟移动前坐标的y差值
                        if(Math.abs(offsetX)>Math.abs(offsetY)){    //x差值大于y差值,说明是左右移动
                            if(offsetX<-3){ //左移
                                moveLeft();
                                System.out.println("----左");
                            }else if(offsetX>3){    //右移
                                moveRight();
                                System.out.println("----右");
                            }
                        }
                        else{
                            if(offsetY<-3){
                                moveUp();
                                System.out.println("----上");
                            }else if(offsetY>3){
                                moveDown();
                                System.out.println("----下");
                            }
                        }
                        break;
                    default:
                        break;
                }
                return true;
            }
        });
    }
    private void moveRight(){
        boolean flage=false;//移动是否有效
        for(int y=0;y<4;y++){
            for(int x=3;x>=0;x--){
                for(int x1=x-1;x1>=0;x1--){
                    if(cards[x1][y].getNumber()>0){//准备往右的这张卡片,需要判断是否有数值
                        if(cards[x][y].getNumber()<2){//在右边的这张卡片,如果没数值,就用准备往右的这张卡片的数值替代它
                            cards[x][y].setNumber(cards[x1][y].getNumber());
                            cards[x1][y].setNumber(0);
                            x++;
                            flage=true;
                            score+=2;
                        }else if(cards[x][y].getNumber()==cards[x1][y].getNumber()){//在右边的这张卡片,如果数值与准备往右的这张卡片的数值相同,就合并数值
                            cards[x][y].setNumber(cards[x][y].getNumber()*2);
                            score+=cards[x][y].getNumber();
                            cards[x1][y].setNumber(0);
                            flage=true;
                        }
                        break;
                    }
                }
            }
        }
        oldremeberCard();
        if(flage){//移动有效就创建新卡片
            creatRandomCard();
            remeberCard();
        }
    }
    private void moveLeft(){
        boolean flage=false;
        for(int y=0;y<4;y++){
            for(int x=0;x<4;x++){
                for(int x1=x+1;x1<4;x1++){
                    if(cards[x1][y].getNumber()>0){
                        if(cards[x][y].getNumber()<2){
                            cards[x][y].setNumber(cards[x1][y].getNumber());
                            cards[x1][y].setNumber(0);
                            x--;
                            flage=true;
                            score+=2;
                        }else if(cards[x][y].getNumber()==cards[x1][y].getNumber()){
                            cards[x][y].setNumber(cards[x][y].getNumber()*2);
                            score+=cards[x][y].getNumber();
                            cards[x1][y].setNumber(0);
                            flage=true;
                        }
                        break;
                    }
                }
            }
        }
        oldremeberCard();
        if(flage){
            creatRandomCard();
            remeberCard();
        }
    }
    private void moveDown(){
        boolean flage=false;
        for(int x=0;x<4;x++){
            for(int y=3;y>=0;y--){
                for(int y1=y-1;y1>=0;y1--){
                    if(cards[x][y1].getNumber()>0){
                        if(cards[x][y].getNumber()<2){
                            cards[x][y].setNumber(cards[x][y1].getNumber());
                            cards[x][y1].setNumber(0);
                            y++;
                            flage=true;
                            score+=2;
                        }else if(cards[x][y].getNumber()==cards[x][y1].getNumber()){
                            cards[x][y].setNumber(cards[x][y].getNumber()*2);
                            score+=cards[x][y].getNumber();
                            cards[x][y1].setNumber(0);
                            flage=true;
                        }
                        break;
                    }
                }
            }
        }
        oldremeberCard();
        if(flage){
            creatRandomCard();
            remeberCard();
        }
    }
    private void moveUp(){
        boolean flage=false;
        for(int x=0;x<4;x++){
            for(int y=0;y<4;y++){
                for(int y1=y+1;y1<4;y1++){
                    if(cards[x][y1].getNumber()>0){
                        if(cards[x][y].getNumber()<2){
                            cards[x][y].setNumber(cards[x][y1].getNumber());
                            cards[x][y1].setNumber(0);
                            y--;
                            flage=true;
                            score+=2;
                        }else if(cards[x][y].getNumber()==cards[x][y1].getNumber()){
                            cards[x][y].setNumber(cards[x][y].getNumber()*2);
                            score+=cards[x][y].getNumber();
                            cards[x][y1].setNumber(0);
                            flage=true;
                        }
                        break;
                    }
                }
            }
        }
        oldremeberCard();
        if(flage){
            creatRandomCard();
            remeberCard();
        }
    }
    private void Gameover(){//判断游戏是否结束
        boolean OverGame=true;
        for(int y=0;y<4;y++){
            for(int x=0;x<4;x++){
                if(cards[x][y].getNumber()<=0 ||    //有一个卡片数值为0说明有空位
                        (x>0&&cards[x][y].getNumber()==cards[x-1][y].getNumber())|| //有相同卡片说明可以合并,下同
                        (x<3&&cards[x][y].getNumber()==cards[x+1][y].getNumber())||
                        (y>0&&cards[x][y].getNumber()==cards[x][y-1].getNumber())||
                        (y<3&&cards[x][y].getNumber()==cards[x][y+1].getNumber())){
                    OverGame=false;
                }
            }
        }
        if(OverGame){   //提示游戏结束
            //游戏结束时判断最高分
            if(score>bscore){
                bscore=score;
            }
            new AlertDialog.Builder(getContext()).setTitle("游戏结束").setMessage("请选择是否继续挑战")
                    .setPositiveButton("好呀好呀",new AlertDialog.OnClickListener(){ //选择是的话就继续开启新游戏
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            GameStart();
                            score=0;
                        }
                    }).setNegativeButton("不啦不啦",null).show();
        }
    }
    private void Addard(int width,int height){
        Card c;
        for(int y=0;y<4;y++){
            for(int x=0;x<4;x++){
                c=new Card(getContext());
                cards[x][y]=c;
                c.setNumber(0);
                addView(c,width,height);
            }
        }
    }
    @Override
    protected void onSizeChanged(int w,int h,int oldw,int oldh){    //界面尺寸变化适应函数
        super.onSizeChanged(w,h,oldw,oldh);
        int width=(w-10)/4;
        Addard(width,width);
        GameStart();
    }
    private void oldremeberCard(){
        oldbackCards.clear();
        oldbackCardsnums.clear();
        oldbackCards.addAll(backCards);
        oldbackCardsnums.addAll(backCardsnums);
        oldscore=currentscore;
    }
    private void remeberCard(){    //记录当前操作
        backCards.clear();
        backCardsnums.clear();
        for(int y=0;y<4;y++){   //重新记录卡片位置
            for(int x=0;x<4;x++){
                Point point=new Point(x,y);
                backCards.add(point);
                backCardsnums.add(cards[x][y].getNumber());
            }
        }
        currentscore=score; //记录当前分数
    }
    private void creatRandomCard(){
        emptyCards.clear(); //卡片位置为空的数组清空
        for(int y=0;y<4;y++){   //重新记录卡片位置为空的数组
            for(int x=0;x<4;x++){
                if(cards[x][y].getNumber()<2){
                    Point point=new Point(x,y);
                    emptyCards.add(point);
                }
            }
        }
        int selat=rd.nextInt(emptyCards.size());//写一个随机数
        Point p=emptyCards.get(selat);//随机取一个空着的卡片
        emptyCards.remove(selat);//取到的卡片准备赋值,所以这个卡片不为空了,踢出去
        int number=0;
        if(rd.nextInt(10)>4){
            number=4;
        }else{
            number=2;
        }
        cards[p.x][p.y].setNumber(number);
    }
    public void GameStart(){//全部卡片置为0,创建两张新卡片
        if(score>bscore){
            bscore=score;
        }
        for(int y=0;y<4;y++){
            for (int x=0;x<4;x++){
                cards[x][y].setNumber(0);
            }
        }
        oldbackCards.clear();
        oldbackCardsnums.clear();
        creatRandomCard();
        creatRandomCard();
        remeberCard();
    }
    public void Gameback(){ //返回上一步操作
        if(oldbackCardsnums.isEmpty() && oldbackCards.isEmpty()){
            System.out.println("没有值,回退不了");
        }
        else {
            for (int y = 0; y < 4; y++) {
                for (int x = 0; x < 4; x++) {
                    Point p = oldbackCards.get(y * 4 + x);//拿出位置
                    cards[p.x][p.y].setNumber(oldbackCardsnums.get(y * 4 + x));//拿出值放在该位置上
                }
            }
            score=oldscore;
            remeberCard();
        }
    }
}

  1. MainActivity类
package com.example.minigame;

import androidx.annotation.NonNull;

import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends Activity {
    TextView score_show;    //分数展示
    TextView bestscore_show;    //最高分展示
    GameView gv;    //子控件布局
    Button new_game;    //新游戏按钮
    Button rollback;    //反悔按钮
    SharedPreferences.Editor editor=null;
    Handler handler=new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            int num=msg.arg1;
            score_show.setText(num+"");
        }
    };
    Handler handler1=new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            int num=msg.arg1;
            bestscore_show.setText(num+"");
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        score_show=(TextView)findViewById(R.id.tv_score_show);
        gv=(GameView)findViewById(R.id.gv_show);
        new_game=(Button) findViewById(R.id.tv_newganme);
        bestscore_show=(TextView)findViewById(R.id.tv_bestscore_show);
        //判断是不是第一次运行
        iffirstrun();
        bestscore_show.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }
            @Override
            public void afterTextChanged(Editable s) {
                editor=getSharedPreferences("mybestscore",0).edit();
                editor.putString("bestscore",Integer.toString(gv.getBscore()));
                editor.commit();
            }
        });
        new_game.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                gv.GameStart();
                gv.score=0;
            }
        });
        rollback=(Button)findViewById(R.id.tv_rockback);
        rollback.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                gv.Gameback();
                System.out.println("我反悔了");
            }
        });
        //定时器,定时刷新分数
        Timer timer=new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Message msg=new Message();
                msg.arg1=gv.score;
                handler.sendMessage(msg);
            }
        },80,150);
        score_show.setText(100+"");

        //定时器,定时刷新最高分数
        Timer timer1=new Timer();
        timer1.schedule(new TimerTask() {
            @Override
            public void run() {
                Message msg=new Message();
                msg.arg1=gv.bscore;
                handler1.sendMessage(msg);
            }
        },80,150);
    }

    private void iffirstrun() {
        SharedPreferences sharedPreferences = this.getSharedPreferences("share", MODE_PRIVATE);
        boolean isFirstRun = sharedPreferences.getBoolean("isFirstRun", true);
        SharedPreferences.Editor ed = sharedPreferences.edit();
        if (isFirstRun){//第一次运行就创建最高分文件
            Log.d("debug", "第一次运行");
            editor=getSharedPreferences("mybestscore",0).edit();
            editor.putString("bestscore",bestscore_show.getText().toString());
            editor.commit();
            ed.putBoolean("isFirstRun", false);
            ed.commit();
        }else{
            Log.d("debug", "不是第一次运行");
            String bestscore=getSharedPreferences("mybestscore",0).getString("bestscore","");
            bestscore_show.setText(bestscore);
            gv.setBscore(Integer.parseInt(bestscore));
        }
    }
}

  1. 布局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="2048"
            android:textColor="#EE82EE"
            android:textSize="30dp"
            android:gravity="center_horizontal"
            android:textStyle="bold"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_gravity="center_horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/tv_score_text"
            android:textSize="18dp"
            android:textColor="#000000"
            android:padding="8dp"
            android:text="得分:"/>

        <TextView
            android:id="@+id/tv_score_show"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="0"
            android:textColor="#000000"
            android:textSize="20dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18dp"
            android:textColor="#000000"
            android:layout_marginLeft="70dp"
            android:padding="8dp"
            android:text="最高分:"/>

        <TextView
            android:id="@+id/tv_bestscore_show"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="0"
            android:textColor="#000000"
            android:textSize="20dp" />

    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_gravity="center_horizontal">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/tv_newganme"
            android:textSize="18dp"
            android:textColor="#000000"
            android:paddingTop="8dp"
            android:paddingLeft="20dp"
            android:text="新的一局" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18dp"
            android:textColor="#000000"
            android:paddingTop="8dp"
            android:paddingLeft="10dp"

            android:id="@+id/tv_rockback"
            android:text="我要反悔" />
    </LinearLayout>
    <com.example.minigame.GameView
        android:id="@+id/gv_show"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1"/>
</LinearLayout>

猜你喜欢

转载自blog.csdn.net/weixin_41541562/article/details/106671675