手机渔乐无穷游戏机玩法moster cards玩法

近日,一位帅气男老师因在画“人体骨骼图”红遍网络。
一辆轿车撞断护栏,一根直插驾驶室,司机半边脸撕裂。
声明:本文由入驻搜狐公众平台的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。
  通常古典的OH Cards使用法在三圈之后就结束,在这个时候,所有的三种组合都可以被排出来,它们可能的相互作用也可以被检视。事实上,OH Cards的其中一种玩法就是使用三种组合的牌,在这种玩法里面,这些所抽的牌组的互相作用和连接形成了探索的基础,这种有趣的方式也可以一个人自己玩。
  一、集中使用法(2至12个人―一种很好的暖身)
  将八张或更多的文字卡放在团体的中间,面朝上。第一个成员抽出一张图卡,将它摆在他认为最合适的文字卡上面,面朝上,接着每一位成员轮流将同样的那张图卡放在任何文字卡上面来形成一个组合。不同的成员也可以使用同样的文字。当每一个人都用过了那个图卡,那么就再抽出另外一张新的图卡,以同样的方式来操作。另外一种集中使用法就是使用图卡作为两张或更多张文字卡的”桥梁“,以此来作出一个更大的组合。这是一种沉默的游戏,是视觉艺术的一个形式,不需要有解释、评语、或反应。又有另外一种集中使用法就是直接作一个跟那个组合有关的简短陈述。又另外一种就是在轮过一次之后大家可以讨论关于玩牌的准则。如果大家变成在讨论,而那些牌被遗忘了,那也没有关系。在OH Cards的游戏当中,旅途就是目标。集中使用法说明了OH Cards可以成为产生互相了解的催化剂。集中使用法也可以跟OH Cards的故事一起使用。
  二、跟小孩玩OH Cards
  当跟小孩一起玩OH Cards的时候,大人必须特别关注要遵守OH Cards的礼节。你可以自由挑出你所要的的牌。OH Cards的故事似乎是最好的玩法。在学校里,OH Cards的组合或单张的图案可以被用来作为艺术作品、散文、诗和歌曲的材料。有一些老师用OH Cards来激发创造力和发展直觉:来写作文或画图――有时候是用这些牌所建议的相反的东西来操作。既然OH Cards有很多种语言版本,它们也可以被用来帮助外语训练。
  三、不用语言来使用OH Cards(4个人以上)
  这种不使用语言的用法是很有趣的。每一位参加者抽出一个牌组(图案卡加文字卡)然后透过没有文字的声音来传递他们的解释。在经过几个回合之后,身体的动作也可以被用来作为解释。几个回合之后再度使用声音。这种做法可以作为基础,进一步推演到即兴戏剧、哑剧、和语言的创造等等。
  四、单独一个人玩
  OH Cards提供一面有趣的镜子,一个自我探索的机会,衡量感情的温度,或是提供一个跳板来进入到另外一个领域和检视各种选择。
  一个人可以每天抽一组牌,起床的时候抽,或是睡前抽。当有需要做决定的时候也可以抽OH Cards,它可以提供你不同的观点。在这种情况下,也许抽三组牌会更好。
  一个更复杂的内省的个人玩法就是创造出一个圆形的曼达拉:一圈的牌,中间放一组牌。从每一组牌里面抽出7张、9张、或13张来做组合。将最有感觉的或是你直觉上觉得最有意义的那一组摆在一个六角形、八角形或12星座的中间,将其他的牌摆在周围的点。检视那些牌,大声讲出周围的卡跟中间的卡的关系,以及周围的卡相互之间的关系。渐渐地,将会有一个图画浮现,有一些秩序会变清楚,而且也许某些洞见会变成看得见。
  推荐您看一本心理入门书籍:《心理学与生活》
欢迎举报抄袭、转载、暴力色情及含有欺诈和虚假信息的不良文章。
请先登录再操作
请先登录再操作
微信扫一扫分享至朋友圈
搜狐公众平台官方账号
生活时尚&搭配博主 /生活时尚自媒体 /时尚类书籍作者
搜狐网教育频道官方账号
全球最大华文占星网站-专业研究星座命理及测算服务机构
京师博仁应用心理发展研究中心隶属于京师博仁教育科技中心,致...
主演:黄晓明/陈乔恩/乔任梁/谢君豪/吕佳容/戚迹
主演:陈晓/陈妍希/张馨予/杨明娜/毛晓彤/孙耀琦
主演:陈键锋/李依晓/张迪/郑亦桐/张明明/何彦霓
主演:尚格?云顿/乔?弗拉尼甘/Bianca Bree
主演:艾斯?库珀/ 查宁?塔图姆/ 乔纳?希尔
baby14岁写真曝光
李冰冰向成龙撒娇争宠
李湘遭闺蜜曝光旧爱
美女模特教老板走秀
曝搬砖男神奇葩择偶观
柳岩被迫成赚钱工具
大屁小P虐心恋
匆匆那年大结局
乔杉遭粉丝骚扰
男闺蜜的尴尬初夜
客服热线:86-10-
客服邮箱:今天看啥 热点:
极客学院Android之2048游戏开发全过程,android2048
2048完整开发
课1、游戏2048玩法介绍
同一条线上的相同数字折叠
课2、创建2048游戏项目
&LinearLayout xmlns:android=&/apk/res/android&
xmlns:tools=&/tools&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:orientation=&vertical&
tools:context=&.MainActivity& &
android:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:text=&@string/hello_world& /&
&/LinearLayout&
准备MainActivity
package com.jikexueyuan.game2048;
import android.os.B
import android.app.A
import android.view.M
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
public boolean onCreateOptionsMenu(Menu menu) {
// I this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
课3 设计2048游戏布局
&LinearLayout xmlns:android=&/apk/res/android&
xmlns:tools=&/tools&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:orientation=&vertical&
tools:context=&.MainActivity& &
&LinearLayout android:layout_width=&fill_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:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:id=&@+id/tvScore&/&
&/LinearLayout&
&GridLayout
android:layout_width=&fill_parent&
android:layout_height=&0dp&
android:layout_weight=&1&
android:id=&@+id/gameView&&&/GridLayout&
&/LinearLayout&
课4 实现2048游戏主类GameView
新建一个GameView类继承GridView,目的为了把layout里的GridView替换掉而绑定该自定义的控件类
GameView.class
package com.jikexueyuan.game2048;
import android.content.C
import android.util.AttributeS
import android.widget.GridL
public class GameView extends GridLayout {
//我们为了让xml绑定该类,我们就把该类的全路径把原来的GridLayout替换掉
* 这三个构造函数的创建是为了可以访问到layout里面的Gridview控件
* @param context
* @param attrs
* @param defStyle
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(){
替换了GridView后的layout
&com.jikexueyuan.game2048.GameView
android:layout_width=&fill_parent&
android:layout_height=&0dp&
android:layout_weight=&1&
android:id=&@+id/gameView&&&/com.jikexueyuan.game2048.GameView&
课5 游戏2048在Android平台的触控交互设计
在我们自定义的控件里加上侦听用户水平滑动垂直滑动控件空间里的操作代码
package com.jikexueyuan.game2048;
import android.content.C
import android.util.AttributeS
import android.view.MotionE
import android.view.V
import android.widget.GridL
public class GameView extends GridLayout {
//我们为了让xml绑定该类,我们就把该类的全路径把原来的GridLayout替换掉
* 这三个构造函数的创建是为了可以访问到layout里面的Gridview控件
* @param context
* @param attrs
* @param defStyle
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(){
//如何创建手势操作呢?
setOnTouchListener(new OnTouchListener() {
//如何判断用户的意图?判断用户按下的意图和判断用户手指离开的意图
private float startX,startY,offsetX,offsetY;
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
case MotionEvent.ACTION_UP:
offsetX = event.getX()-startX;
offsetY = event.getY()-startY;
//防止用户不是左右直线手势滑动而是斜方向滑动的判断代码
if(Math.abs(offsetX)&(Math.abs(offsetY))){//表示手势往右滑动不太偏离水平的时候
if(offsetX&-5){//手势往左,-5表示范围
System.out.println(&left操作&);
swipeLeft();//侦听用户操作后执行该方法
}else if (offsetX&5){//往右
System.out.println(&rigth操作&);
swipeRight();//侦听用户操作后执行该方法
}else{//这个else判断用户的手势上下滑动不太偏离垂直线
if(offsetY&-5){//手势往左,-5表示范围
System.out.println(&up操作&);
swipeUp();//侦听用户操作后执行该方法
}else if (offsetY&5){//往右
System.out.println(&down操作&);
swipeDown();//侦听用户操作后执行该方法
private void swipeLeft(){
Toast.makeText(getContext(), &向左滑动了&, 0).show();
private void swipeRight(){
Toast.makeText(getContext(), &向右滑动了&, 0).show();
private void swipeUp(){
Toast.makeText(getContext(), &向上滑动了&, 0).show();
private void swipeDown(){
Toast.makeText(getContext(), &向下滑动了&, 0).show();
课6 实现2048游戏的卡片类
我们需要控制2048里面的卡片类,首先要创建出该卡片类
Card.class
package com.jikexueyuan.game2048;
import android.content.C
import android.widget.FrameL
import android.widget.TextV
public class Card extends FrameLayout {
//首先该卡片类是一个FrameLayout控件类,即在该类里可以嵌入其他控件类例如文本控件什么的,所以当该类一实现了以后就会初始化文本控件,而通过构造函数里的初始化而同时初始化了文本控件的属性
//构造函数:初始化
public Card(Context context) {
super(context);
//初始化文本
label = new TextView(getContext());
//设置文本的大小
label.setTextSize(32);
//布局参数用来控制
LayoutParams lp = new LayoutParams(-1,-1);//该类用来初始化layout控件textView里的高和宽属性
addView(label, lp);//该方法是用来给label控件加上已经初始化了的高和宽属性
setNum(0);
public int getNum() {
public void setNum(int num) {
this.num =
label.setText(num+&&);
private int num = 0;
//需要呈现文字
private TextV
//判断两张卡片数字是否一样?
public boolean equals(Card o) {
return getNum()==o.getNum();
课7 添加2048游戏卡片
往自定义布局GridView里添加卡片了
由于考虑到不同手机的宽高不一致,所以我们在布局里添加卡片的时候需要动态地去计算卡片的宽高根据具体的手机
&application
android:allowBackup=&true&
android:icon=&@drawable/ic_launcher&
android:label=&@string/app_name&
android:theme=&@style/AppTheme& &
android:name=&com.jikexueyuan.game2048.MainActivity&
android:label=&@string/app_name&
android:screenOrientation=&portrait& &&!-- 限制游戏发生横屏 --&
GameView.class
package com.jikexueyuan.game2048;
import android.content.C
import android.util.AttributeS
import android.view.MotionE
import android.view.V
import android.widget.GridL
import android.widget.T
public class GameView extends GridLayout {
//我们为了让xml绑定该类,我们就把该类的全路径把原来的GridLayout替换掉
* 这三个构造函数的创建是为了可以访问到layout里面的Gridview控件
* @param context
* @param attrs
* @param defStyle
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(){
//由于在添加完卡片之后发现在GameView里创建的16个卡片都排成一行了
//因此在这里设置有多少列
* ColumnCount is used only to generate default column/column indices
* when they are not specified by a component's layout parameters.
setColumnCount(4);
//在给GameView的背景颜色加上颜色
setBackgroundColor(0xffbbada0);
//如何创建手势操作呢?
setOnTouchListener(new OnTouchListener() {
//如何判断用户的意图?判断用户按下的意图和判断用户手指离开的意图
private float startX,startY,offsetX,offsetY;
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
case MotionEvent.ACTION_UP:
offsetX = event.getX()-startX;
offsetY = event.getY()-startY;
//防止用户不是左右直线手势滑动而是斜方向滑动的判断代码
if(Math.abs(offsetX)&(Math.abs(offsetY))){//表示手势往右滑动不太偏离水平的时候
if(offsetX&-5){//手势往左,-5表示范围
System.out.println(&left操作&);
swipeLeft();//侦听用户操作后执行该方法
}else if (offsetX&5){//往右
System.out.println(&rigth操作&);
swipeRight();//侦听用户操作后执行该方法
}else{//这个else判断用户的手势上下滑动不太偏离垂直线
if(offsetY&-5){//手势往左,-5表示范围
System.out.println(&up操作&);
swipeUp();//侦听用户操作后执行该方法
}else if (offsetY&5){//往右
System.out.println(&down操作&);
swipeDown();//侦听用户操作后执行该方法
//怎么动态地计算卡片的宽高呢?
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;
//在该方法初始化的时候新建16个卡片,以下是方法
addCards(cardWidth,cardWidth);
private void addCards(int cardWidth, int cardHeight) {
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] =
private void swipeLeft(){
Toast.makeText(getContext(), &向左滑动了&, 0).show();
private void swipeRight(){
Toast.makeText(getContext(), &向右滑动了&, 0).show();
private void swipeUp(){
Toast.makeText(getContext(), &向上滑动了&, 0).show();
private void swipeDown(){
Toast.makeText(getContext(), &向下滑动了&, 0).show();
//我们需要定义一个二维数组来记录GameView初始化时生成的16个卡片类
private Card[][] cardsMap = new Card[4][4];
Card.class
package com.jikexueyuan.game2048;
import android.content.C
import android.view.G
import android.widget.FrameL
import android.widget.TextV
public class Card extends FrameLayout {
//首先该卡片类是一个FrameLayout控件类,即在该类里可以嵌入其他控件类例如文本控件什么的,所以当该类一实现了以后就会初始化文本控件,而通过构造函数里的初始化而同时初始化了文本控件的属性
//构造函数:初始化
public Card(Context context) {
super(context);
//初始化文本
label = new TextView(getContext());
//设置文本的大小
label.setTextSize(32);
//设置控件card的背景颜色
label.setBackgroundColor(0x33ffffff);
//把放在控件里的文本居中处理
label.setGravity(Gravity.CENTER);
//布局参数用来控制
LayoutParams lp = new LayoutParams(-1,-1);//该类用来初始化layout控件textView里的高和宽属性
//给每个textView的左和上设置margin,右和下就不需要了
lp.setMargins(10, 10, 0, 0);
addView(label, lp);//该方法是用来给label控件加上已经初始化了的高和宽属性
setNum(0);
public int getNum() {
public void setNum(int num) {
this.num =
label.setText(num+&&);
private int num = 0;
//需要呈现文字
private TextV
//判断两张卡片数字是否一样?
public boolean equals(Card o) {
return getNum()==o.getNum();
课8 在2048游戏中添加随机数
1、要在Card的setNum方法里加上判断,用来判断导入的随机算不能大于0或小于0
public void setNum(int num) { this.num = //呈现
//由于我们需要在这个设置数字的方法导入随机数字,而为了排除出现0,我们需要在原方法里加上判断语句
if(num&=0){
label.setText(&&);
label.setText(num+&&);
label.setText(num+&&); }
2、在GameView里加上设置随机数的方法
void addRandomNum(){}
3、设置一个用来存放控制 Card[][] cardsMap 下标用的Point类的List集合
private List&Point& emptyPoints = new ArrayList&Point&();
4、通过这个集合在addRandomNum()方法里去控制每个card对象的文本属性
1、通过坐标轴给Card[][] cardsMap 里的每个card对象绑定上了Point,换句话说就是用 Point来记录每个Card所在的坐标轴,然后把Point存放在List集合里
//把这个point清空,每次调用添加随机数时就清空之前所控制的指针
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));//给List存放控制卡片用的指针(通过坐标轴来控制)
2、通过随机的控制而从存放了的Point的List集合里去获取Card的位置,并给这个card设置文本属性,并且只能存2或4,而且2的几率比4的大。
//一个for循环走完我们就从List里取出一个控制指针的point对象
Point p = emptyPoints.remove((int)(Math.random()*emptyPoints.size()));
cardsMap[p.x][p.y].setNum(Math.random()&0.1?2:4);//通过point对象来充当下标的角色来控制存放card的二维数组cardsMap,然后随机给定位到的card对象赋值
5、设置一个开始游戏的方法startGame():该方法会初始化16个card对象的状态
1、首先遍历了所有的card,给card的属性赋上0
for (int y = 0; y & 4; y++) {
for (int x = 0; x & 4; x++) {
cardsMap[x][y].setNum(0);
2、根据游戏规则去给这么多个card对象的其中两个加上随机数,也就是调用两次addRandomNum();方法
GameView.java
package com.jikexueyuan.game2048;
import java.util.ArrayL
import java.util.L
import android.content.C
import android.graphics.P
import android.util.AttributeS
import android.view.MotionE
import android.view.V
import android.widget.GridL
import android.widget.T
public class GameView extends GridLayout {
//我们为了让xml绑定该类,我们就把该类的全路径把原来的GridLayout替换掉
* 这三个构造函数的创建是为了可以访问到layout里面的Gridview控件
* @param context
* @param attrs
* @param defStyle
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(){
//由于在添加完卡片之后发现在GameView里创建的16个卡片都排成一行了
//因此在这里设置有多少列
* ColumnCount is used only to generate default column/column indices
* when they are not specified by a component's layout parameters.
setColumnCount(4);
//在给GameView的背景颜色加上颜色
setBackgroundColor(0xffbbada0);
//如何创建手势操作呢?
setOnTouchListener(new OnTouchListener() {
//如何判断用户的意图?判断用户按下的意图和判断用户手指离开的意图
private float startX,startY,offsetX,offsetY;
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
case MotionEvent.ACTION_UP:
offsetX = event.getX()-startX;
offsetY = event.getY()-startY;
//防止用户不是左右直线手势滑动而是斜方向滑动的判断代码
if(Math.abs(offsetX)&(Math.abs(offsetY))){//表示手势往右滑动不太偏离水平的时候
if(offsetX&-5){//手势往左,-5表示范围
System.out.println(&left操作&);
swipeLeft();//侦听用户操作后执行该方法
}else if (offsetX&5){//往右
System.out.println(&rigth操作&);
swipeRight();//侦听用户操作后执行该方法
}else{//这个else判断用户的手势上下滑动不太偏离垂直线
if(offsetY&-5){//手势往左,-5表示范围
System.out.println(&up操作&);
swipeUp();//侦听用户操作后执行该方法
}else if (offsetY&5){//往右
System.out.println(&down操作&);
swipeDown();//侦听用户操作后执行该方法
//怎么动态地计算卡片的宽高呢?
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;
//在该方法初始化的时候新建16个卡片,以下是方法
addCards(cardWidth,cardWidth);
startGame();
private void addCards(int cardWidth, int cardHeight) {
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] =
//现在可以开始使用这些随机数了
private void startGame(){
//清理阶段:初始化阶段
for (int y = 0; y & 4; y++) {
for (int x = 0; x & 4; x++) {
cardsMap[x][y].setNum(0);
//然后就是添加随机数阶段
addRandomNum();
addRandomNum();
//设置随机数的方法
private void addRandomNum(){
//把这个point清空,每次调用添加随机数时就清空之前所控制的指针
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));//给List存放控制卡片用的指针(通过坐标轴来控制)
//一个for循环走完我们就从List里取出一个控制指针的point对象
Point p = emptyPoints.remove((int)(Math.random()*emptyPoints.size()));
cardsMap[p.x][p.y].setNum(Math.random()&0.1?2:4);//通过point对象来充当下标的角色来控制存放card的二维数组cardsMap,然后随机给定位到的card对象赋值
private void swipeLeft(){
Toast.makeText(getContext(), &向左滑动了&, 0).show();
private void swipeRight(){
Toast.makeText(getContext(), &向右滑动了&, 0).show();
private void swipeUp(){
Toast.makeText(getContext(), &向上滑动了&, 0).show();
private void swipeDown(){
Toast.makeText(getContext(), &向下滑动了&, 0).show();
//我们需要定义一个二维数组来记录GameView初始化时生成的16个卡片类
private Card[][] cardsMap = new Card[4][4];
//我们添加一个list来存放Point来控制随机数方法里的随机数
//注意这里有一个Point的类不熟悉
private List&Point& emptyPoints = new ArrayList&Point&();
package com.jikexueyuan.game2048;
import android.content.C
import android.view.G
import android.widget.FrameL
import android.widget.TextV
public class Card extends FrameLayout {
//首先该卡片类是一个FrameLayout控件类,即在该类里可以嵌入其他控件类例如文本控件什么的,所以当该类一实现了以后就会初始化文本控件,而通过构造函数里的初始化而同时初始化了文本控件的属性
//构造函数:初始化
public Card(Context context) {
super(context);
//初始化文本
label = new TextView(getContext());
//设置文本的大小
label.setTextSize(32);
//设置控件card的背景颜色
label.setBackgroundColor(0x33ffffff);
//把放在控件里的文本居中处理
label.setGravity(Gravity.CENTER);
//布局参数用来控制
LayoutParams lp = new LayoutParams(-1,-1);//该类用来初始化layout控件textView里的高和宽属性
//给每个textView的左和上设置margin,右和下就不需要了
lp.setMargins(10, 10, 0, 0);
addView(label, lp);//该方法是用来给label控件加上已经初始化了的高和宽属性
setNum(0);
public int getNum() {
public void setNum(int num) {
this.num =
//由于我们需要在这个设置数字的方法导入随机数字,而为了排除出现0,我们需要在原方法里加上判断语句
if(num&=0){
label.setText(&&);
label.setText(num+&&);
label.setText(num+&&);
private int num = 0;
//需要呈现文字
private TextV
//判断两张卡片数字是否一样?
public boolean equals(Card o) {
return getNum()==o.getNum();
课9 实现2048游戏逻辑
private void swipeLeft(){
//Toast.makeText(getContext(), &向左滑动了&, 0).show();
//以下两行for循环实现了一行一行的遍历,在向左滑动的时候
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);
//第二层循环,即同一层的不同列退一格继续循环,这样做的原因是为了继续固定这个格子而去检查与它同一水平上的别的格子的内容,因为其他格子是什么个情况还需要继续在第二层进行判断
//这个break为了在操作完这固定格子遍历的过程操作完后跳出遍历,因为只要有操作这个条件,就没有继续遍历下去的需要了
}else if (cardsMap[x][y].equals(cardsMap[x1][y])) {//这层判断是判断相邻两个数相同的情况
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x1][y].setNum(0);
private void swipeRight(){
//Toast.makeText(getContext(), &向右滑动了&, 0).show();
for (int y = 0; y & 4; y++) {
for (int x = 4-1; 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++;
}else if (cardsMap[x][y].equals(cardsMap[x1][y])) {
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x1][y].setNum(0);
private void swipeUp(){
//Toast.makeText(getContext(), &向上滑动了&, 0).show();
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);
}else if (cardsMap[x][y].equals(cardsMap[x][y1])) {
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x][y1].setNum(0);
private void swipeDown(){
Toast.makeText(getContext(), &向下滑动了&, 0).show();
for (int x = 0; x & 4; x++) {
for (int y = 4-1; 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++;
}else if (cardsMap[x][y].equals(cardsMap[x][y1])) {
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x][y1].setNum(0);
课10 游戏2048计分
1、在MainActivity中的Score(TextView控件)进行分数显示,并加上方法去控制分数
package com.jikexueyuan.game2048;
import android.os.B
import android.app.A
import android.widget.TextV
public class MainActivity extends Activity {
private TextView tvS
private int score = 0;
//提供一个单例设计模式给别的类去调用该类中的处理分数的方法
private static MainActivity mainActivity =
public MainActivity(){
mainActivity =
public static MainActivity getMainActivity(){
return mainA
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvScore = (TextView) findViewById(R.id.tvScore);
//分数清零
public void clearScore(){
score = 0;
showScore();
//在控件上显示分数
public void showScore(){
tvScore.setText(score+&&);
//使用方法添加分数,并显示出来
public void addScore(int s){
score+=s;
showScore();
2、在GameView里通过MainActivity里的单例思想获得对象去操作MainActivity里的操作分数的方法,并在滑动手势里进行识别加分,且继续增加随机数
private void swipeLeft(){
boolean merge =//控制每滑动一次画面就加一个随机数到画面,也就是在下面所有for循环之后
Toast.makeText(getContext(), &向左滑动了&, 0).show();
//以下两行for循环实现了一行一行的遍历,在向左滑动的时候
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);
//第二层循环,即同一层的不同列退一格继续循环,这样做的原因是为了继续固定这个格子而去检查与它同一水平上的别的格子的内容,因为其他格子是什么个情况还需要继续在第二层进行判断
//只要有移动就要加随机数
}else if (cardsMap[x][y].equals(cardsMap[x1][y])) {//这层判断是判断相邻两个数相同的情况
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x1][y].setNum(0);
//在这要给MainActivity中的score加上分数
//而这里MainActivity设计成了单例设计模式,所以要使用get方法获得对象
MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
//只要有移动就要加随机数
//这个break为了在操作完这固定格子遍历的过程操作完后跳出遍历,因为只要有操作这个条件,就没有继续遍历下去的需要了
if (merge) {
addRandomNum();
课11 检查2048游戏结束
两个条件来判断结束
1、所有的格子都有数字
2、所有相邻的格子都没有相同的数字
* 方法放在滑动手势里,每次滑动是用来判断每个格子的上下左右没有相同的数字,和格子是否为空,以此弹出对话框来提示用户并调用重新开始方法
private void checkComplete(){
boolean complete =
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&4-1&&cardsMap[x][y].equals(cardsMap[x+1][y]))||
(y&0&&cardsMap[x][y].equals(cardsMap[x][y-1]))||
(y&4-1&&cardsMap[x][y].equals(cardsMap[x][y+1]))) {
complete =
break ALL;
if (complete) {//通过标记来判断当前格子是否满足条件,满足则弹出对话框,并点击按钮后激活开始方法
new AlertDialog.Builder(getContext()).setTitle(&你好&).setMessage(&游戏结束&).setPositiveButton(&重新开始&, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
startGame();
}).show();
工程代码:
&LinearLayout xmlns:android=&/apk/res/android&
xmlns:tools=&/tools&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:orientation=&vertical&
tools:context=&.MainActivity& &
&LinearLayout android:layout_width=&fill_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:layout_width=&wrap_content&
android:layout_height=&wrap_content&
android:id=&@+id/tvScore&/&
&/LinearLayout&
&com.jikexueyuan.game2048.GameView
android:layout_width=&fill_parent&
android:layout_height=&0dp&
android:layout_weight=&1&
android:id=&@+id/gameView&&&/com.jikexueyuan.game2048.GameView&
&/LinearLayout&
package com.jikexueyuan.game2048;
import android.content.C
import android.view.G
import android.widget.FrameL
import android.widget.TextV
public class Card extends FrameLayout {
//首先该卡片类是一个FrameLayout控件类,即在该类里可以嵌入其他控件类例如文本控件什么的,所以当该类一实现了以后就会初始化文本控件,而通过构造函数里的初始化而同时初始化了文本控件的属性
//构造函数:初始化
public Card(Context context) {
super(context);
//初始化文本
label = new TextView(getContext());
//设置文本的大小
label.setTextSize(32);
//设置控件card的背景颜色
label.setBackgroundColor(0x33ffffff);
//把放在控件里的文本居中处理
label.setGravity(Gravity.CENTER);
//布局参数用来控制
LayoutParams lp = new LayoutParams(-1,-1);//该类用来初始化layout控件textView里的高和宽属性
//给每个textView的左和上设置margin,右和下就不需要了
lp.setMargins(10, 10, 0, 0);
addView(label, lp);//该方法是用来给label控件加上已经初始化了的高和宽属性
setNum(0);
public int getNum() {
public void setNum(int num) {
this.num =
//由于我们需要在这个设置数字的方法导入随机数字,而为了排除出现0,我们需要在原方法里加上判断语句
if(num&=0){
label.setText(&&);
label.setText(num+&&);
label.setText(num+&&);
private int num = 0;
//需要呈现文字
private TextV
//判断两张卡片数字是否一样?
public boolean equals(Card o) {
return getNum()==o.getNum();
GameView.java
package com.jikexueyuan.game2048;
import java.util.ArrayL
import java.util.L
import android.app.AlertD
import android.content.C
import android.content.DialogI
import android.graphics.P
import android.util.AttributeS
import android.view.MotionE
import android.view.V
import android.widget.GridL
public class GameView extends GridLayout {
//我们为了让xml绑定该类,我们就把该类的全路径把原来的GridLayout替换掉
* 这三个构造函数的创建是为了可以访问到layout里面的Gridview控件
* @param context
* @param attrs
* @param defStyle
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(){
//由于在添加完卡片之后发现在GameView里创建的16个卡片都排成一行了
//因此在这里设置有多少列
* ColumnCount is used only to generate default column/column indices
* when they are not specified by a component's layout parameters.
setColumnCount(4);
//在给GameView的背景颜色加上颜色
setBackgroundColor(0xffbbada0);
//如何创建手势操作呢?
setOnTouchListener(new OnTouchListener() {
//如何判断用户的意图?判断用户按下的意图和判断用户手指离开的意图
private float startX,startY,offsetX,offsetY;
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
case MotionEvent.ACTION_UP:
offsetX = event.getX()-startX;
offsetY = event.getY()-startY;
//防止用户不是左右直线手势滑动而是斜方向滑动的判断代码
if(Math.abs(offsetX)&(Math.abs(offsetY))){//表示手势往右滑动不太偏离水平的时候
if(offsetX&-5){//手势往左,-5表示范围
System.out.println(&left操作&);
swipeLeft();//侦听用户操作后执行该方法
}else if (offsetX&5){//往右
System.out.println(&rigth操作&);
swipeRight();//侦听用户操作后执行该方法
}else{//这个else判断用户的手势上下滑动不太偏离垂直线
if(offsetY&-5){//手势往左,-5表示范围
System.out.println(&up操作&);
swipeUp();//侦听用户操作后执行该方法
}else if (offsetY&5){//往右
System.out.println(&down操作&);
swipeDown();//侦听用户操作后执行该方法
//怎么动态地计算卡片的宽高呢?
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;
//在该方法初始化的时候新建16个卡片,以下是方法
addCards(cardWidth,cardWidth);
startGame();
private void addCards(int cardWidth, int cardHeight) {
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] =
//现在可以开始使用这些随机数了
private void startGame(){
//重新开始的时候分数清零
MainActivity aty = MainActivity.getMainActivity();
aty.clearScore();
//清理阶段:初始化阶段
for (int y = 0; y & 4; y++) {
for (int x = 0; x & 4; x++) {
cardsMap[x][y].setNum(0);
//然后就是添加随机数阶段
addRandomNum();
addRandomNum();
addRandomNum();
addRandomNum();
addRandomNum();
addRandomNum();
addRandomNum();
addRandomNum();
//设置随机数的方法
private void addRandomNum(){
//把这个point清空,每次调用添加随机数时就清空之前所控制的指针
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));//给List存放控制卡片用的指针(通过坐标轴来控制)
//一个for循环走完我们就从List里取出一个控制指针的point对象
Point p = emptyPoints.remove((int)(Math.random()*emptyPoints.size()));
cardsMap[p.x][p.y].setNum(Math.random()&0.1?2:4);//通过point对象来充当下标的角色来控制存放card的二维数组cardsMap,然后随机给定位到的card对象赋值
private void swipeLeft(){
boolean merge =//控制每滑动一次画面就加一个随机数到画面,也就是在下面所有for循环之后
Toast.makeText(getContext(), &向左滑动了&, 0).show();
//以下两行for循环实现了一行一行的遍历,在向左滑动的时候
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);
//第二层循环,即同一层的不同列退一格继续循环,这样做的原因是为了继续固定这个格子而去检查与它同一水平上的别的格子的内容,因为其他格子是什么个情况还需要继续在第二层进行判断
//只要有移动就要加随机数
}else if (cardsMap[x][y].equals(cardsMap[x1][y])) {//这层判断是判断相邻两个数相同的情况
cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
cardsMap[x1][y].setNum(0);
//在这要给MainActivity中的score加上分数
//而这里MainActivity设计成了单例设计模式,所以要使用get方法获得对象
MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
//只要有移动就要加随机数
//这个break为了在操作完这固定格子遍历的过程操作完后跳出遍历,因为只要有操作这个条件,就没有继续遍历下去的需要了
if (merge) {
addRandomNum();
checkComplete();
private void swipeRight(){
boolean merge =//控制每滑动一次画面就加一个随机数到画面,也就是在下面所有for循环之后
Toast.makeText(getContext(), &向右滑动了&, 0).show();
for (int y = 0; y & 4; y++) {
for (int x = 4-1; 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++;
//只要有移动就要加随机数
}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());
//只要有移动就要加随机数
if (merge) {
addRandomNum();
checkComplete();
private void swipeUp(){
boolean merge =//控制每滑动一次画面就加一个随机数到画面,也就是在下面所有for循环之后
Toast.makeText(getContext(), &向上滑动了&, 0).show();
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);
//只要有移动就要加随机数
}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());
//只要有移动就要加随机数
if (merge) {
addRandomNum();
checkComplete();
private void swipeDown(){
boolean merge =//控制每滑动一次画面就加一个随机数到画面,也就是在下面所有for循环之后
Toast.makeText(getContext(), &向下滑动了&, 0).show();
for (int x = 0; x & 4; x++) {
for (int y = 4-1; 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++;
//只要有移动就要加随机数
}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());
//只要有移动就要加随机数
if (merge) {
addRandomNum();
checkComplete();
* 方法放在滑动手势里,每次滑动是用来判断每个格子的上下左右没有相同的数字,和格子是否为空,以此弹出对话框来提示用户并调用重新开始方法
private void checkComplete(){
boolean complete =
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&4-1&&cardsMap[x][y].equals(cardsMap[x+1][y]))||
(y&0&&cardsMap[x][y].equals(cardsMap[x][y-1]))||
(y&4-1&&cardsMap[x][y].equals(cardsMap[x][y+1]))) {
complete =
break ALL;
if (complete) {//通过标记来判断当前格子是否满足条件,满足则弹出对话框,并点击按钮后激活开始方法
new AlertDialog.Builder(getContext()).setTitle(&你好&).setMessage(&游戏结束&).setPositiveButton(&重新开始&, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
startGame();
}).show();
//我们需要定义一个二维数组来记录GameView初始化时生成的16个卡片类
private Card[][] cardsMap = new Card[4][4];
//我们添加一个list来存放Point来控制随机数方法里的随机数
//注意这里有一个Point的类不熟悉
private List&Point& emptyPoints = new ArrayList&Point&();
MainActivity.class
package com.jikexueyuan.game2048;
import android.os.B
import android.app.A
import android.widget.TextV
public class MainActivity extends Activity {
private TextView tvS
private int score = 0;
//提供一个单例设计模式给别的类去调用该类中的处理分数的方法
private static MainActivity mainActivity =
public MainActivity(){
mainActivity =
public static MainActivity getMainActivity(){
return mainA
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvScore = (TextView) findViewById(R.id.tvScore);
//分数清零
public void clearScore(){
score = 0;
showScore();
//在控件上显示分数
public void showScore(){
tvScore.setText(score+&&);
//使用方法添加分数,并显示出来
public void addScore(int s){
score+=s;
showScore();
AndroidManifest.xml
&?xml version=&1.0& encoding=&utf-8&?&
&manifest xmlns:android=&/apk/res/android&
package=&com.jikexueyuan.game2048&
android:versionCode=&1&
android:versionName=&1.0& &
android:minSdkVersion=&14&
android:targetSdkVersion=&17& /&
&application
android:allowBackup=&true&
android:icon=&@drawable/ic_launcher&
android:label=&@string/app_name&
android:theme=&@style/AppTheme& &
android:name=&com.jikexueyuan.game2048.MainActivity&
android:label=&@string/app_name&
android:screenOrientation=&portrait& &&!-- 限制游戏发生横屏 --&
&intent-filter&
&action android:name=&android.intent.action.MAIN& /&
&category android:name=&android.intent.category.LAUNCHER& /&
&/intent-filter&
&/activity&
&/application&
&/manifest&
相关搜索:
相关阅读:
相关频道:
Android教程最近更新}

我要回帖

更多关于 捕鱼游戏机玩法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信