2048游戏开发

2016-05-27  本文已影响516人  努力努力再努力_姜姜
游戏布局的设计
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout    
xmlns:android="http://schemas.android.com/apk/res/android"    
android:layout_width="match_parent"    
android:layout_height="match_parent"    
android:orientation="vertical"    >    
<LinearLayout       
 android:layout_width="match_parent"     
android:layout_height="wrap_content"        
android:orientation="horizontal">      
  <TextView         
   android:layout_width="wrap_content"            
android:layout_height="wrap_content"            
android:text="@string/score"/>   
     <TextView        
    android:id="@+id/show_score"            
android:layout_width="wrap_content"            
android:layout_height="wrap_content" />   
 </LinearLayout>   
 <!-- 铺满剩余空间-->
   <!-- 将类和xml绑定到一起-->    
<com.jiangjiang.game2048.GameView
 android:layout_width="match_parent" 
android:layout_height="0dp"      
android:layout_weight="1"     
android:id="@+id/gameView">    
</com.jiangjiang.game2048.GameView>
</LinearLayout>
实现2048游戏的主类
public class GameView extends GridLayout {    
        public GameView(Context context) {        
                    super(context);        
                    initGameView();    
        }    
         public GameView(Context context, AttributeSet attrs) 
          {
               super(context, attrs);
                initGameView();
            } 
         public GameView(Context context, AttributeSet attrs, int defStyleAttr)
         {
                  super(context, attrs, defStyleAttr); 
                   initGameView();
          }
}

android平台的触控交互设计
    private float startX,startY,offsetX,offsetY;//纪录x、y 轴的偏移
    @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:
                offsetX = event.getX()-startX;//计算x的偏移量
                offsetY = event.getY()-startY;//计算y的偏移量
                if (Math.abs(offsetX)>Math.abs(offsetY))
                //判断x的绝对值大还是y的绝对值,x>y说明是水平方向
                 {
                    if(offsetX<-5)//向左,给一定的误差范围5
                    {
                        swipeLeft();
                    }else if (offsetX > 5)//向右
                     {
                         swipeRight();
                    }
                }else{
                    if (offsetY<-5)//向上
                    {
                        swipeUp();
                    }else if(offsetY > 5)//向下
                    {
                        swipeDown();
                    }
                }
                break;
        }
        return true;//一定要返回true
    }});
游戏卡片类的实现
public class Card extends FrameLayout {
    public Card(Context context) {
        super(context);
        label = new TextView(getContext());
        label.setTextSize(32);
        label.setBackgroundColor(0x33ffffff);
        label.setGravity(Gravity.CENTER);
        LayoutParams lp = new LayoutParams(-1,-1);
        lp.setMargins(10,10,0,0);//设置字之间的间隔
        addView(label,lp);
        setNum(0);//默认情况设置0
    }
    private int num = 0;//与卡片绑定的number
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
        if(num <= 0 )
        {
            label.setText("");
        }else {
            label.setText(num + "");//setText的参数是字符串
        }
    }
    public boolean equals(Card c) {
        return getNum() == c.getNum();//判断卡片是否相同
    }
    private TextView label;
}
添加卡片类

将方块抽象成卡片

public class Card extends FrameLayout {
    public Card(Context context) {
        super(context);
        label = new TextView(getContext());//初始化呈现文字的textview
        label.setTextSize(32);
        label.setBackgroundColor(0x33ffffff);//设置文本框的背景
        label.setGravity(Gravity.CENTER);
        LayoutParams lp = new LayoutParams(-1,-1);
        //填充满整个父级容器
        lp.setMargins(10,10,0,0);//设置卡片之间的间隔
        addView(label,lp);//添加进
        setNum(0);//默认的number
    }
    private int num = 0;//与卡片绑定的number
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
        if(num <= 0 )
        {
            label.setText("");
        }else {
            label.setText(num + "");
            //setText的参数是字符串。所以不能直接传num进去
        }
    }
    //判断卡片是否相同
    public boolean equals(Card c) {
        return getNum() == c.getNum();
    }
    private TextView label;
}
添加卡片

android:screenOrientation="portrait"//屏幕是竖直的,这样子onSetChanged()方法就只会在布局创建的时候被执行。

//动态的计算卡片的宽高
@Overrideprotected
 void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    int cardWidth = (Math.min(w,h)-10)/4;
  //卡片的宽高,求宽高的最小值,减一个数字是为了在屏幕边缘留下空隙
    addCard(cardWidth,cardWidth);//添加卡片
    startGame();
}
private void addCard(int cardWidth,int cardHeight){
    Card c ;
    //添加16张卡片
    for(int y = 0;y<4;y++)//四列
    {
        for(int x = 0;x<4;x++)//四行
        {
            c = new Card(getContext());
            c.setNum(0);//初始时全部添加0
            addView(c,cardWidth,cardHeight);//添加到当前的GridVIew中
            cardsMap[x][y] = c;//将创建的卡片纪录到二维数组中
        }
    }
}

setColumnCount(4);//说明GridLayout 是4列的

在游戏中添加随机数
private void addRandomNum(){
    emptyPoints.clear();
    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 p = emptyPoints.remove((int)(Math.random()*emptyPoints.size()));//随机移除一个点
    //将这个点对应的值设置成2,或者4,比例是9:1
    cardsMap[p.x][p.y].setNum(Math.random()>0.1?2:4);//2:4 = 9:1
}
private void startGame(){
    MainActivity.getMainActivity().clearScore();
    for(int y = 0;y<4;y++)
    {
        for(int x = 0;x<4;x++)
        {
            cardsMap[x][y].setNum(0);
        }
    }
    addRandomNum();//要显示两个数字,所以要添加两次
    addRandomNum();
}
实现2048 的逻辑
private void swipeLeft(){
    boolean merge = 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)//如果右边不为空
                {
                    if (cardsMap[x][y].getNum()<=0)//如果当前位置的卡片为空
                    {
                        //将右边的值放到右边去
                        cardsMap[x][y].setNum(cardsMap[x1][y].getNum()) ;
                        cardsMap[x1][y].setNum(0);
                        x--;//再遍历一次
                       merge = true;
                    }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());
                        merge = true;
                    }
                    break;
                }
            }
        }
    }
    if (merge)
    {
        addRandomNum();
        checkComplete();
    }
}
游戏的计分
public MainActivity(){
    mainActivity = this;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    showScore = (TextView)findViewById(R.id.show_score);
}
public  void clearScore(){//将score重新归0
    score = 0;
    showScore();
}
private void showScore(){//呈现分数
    showScore.setText(score+"");
}
public void addScore(int s){//添加score
    score += s;
    showScore();
}
private int score = 0;
private TextView showScore;
检查游戏的结束
private void checkComplete(){
    boolean complete = true;
    ALL:
    for(int y = 0;y<4;y++)
    {
        for(int x = 0;x<4;x++)
        {
            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]))
                    )
            {
                complete = false;
                break ALL;
            }
        }
    }
    if (complete)
    {
        new AlertDialog.Builder(getContext()).setTitle("你好").setMessage("游戏结束").setPositiveButton("重来", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                startGame();
            }
        }).show();
    }
}
上一篇下一篇

猜你喜欢

热点阅读