之前是在eclipse上写的,后面换成了android sudio。
2048游戏的UI整体可以采用线性布局,即LinearLayout,其中嵌套一个线性布局和一个GridLayout,内嵌的线性布局填充文本框,以显示分数,GridLayout中填充4×4的继承自FrameLayout的card类作为主要的游戏界面。由于大部分操作都在GridLayout中进行,可以自定义一个继承自GridLayout的类GameView,类中定义判定上下左右滑动的方法和每次滑动后自动添加一个随机数字的方法以及每次滑动后判断游戏是否可以继续进行的方法。
主布局activity_main.xml代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<
LinearLayout
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
xmlns
:
tools
=
"http://schemas.android.com/tools"
android
:
id
=
"@+id/container"
//match_parent表示布局充满整个屏幕
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"match_parent"
tools
:
context
=
"com.example.administractor.game2048.MainActivity"
//里面的组件垂直放置
android
:
orientation
=
"vertical"
tools
:
ignore
=
"MergeRootFrame"
>
<
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
=
"Your Score:"
/
>
<
TextView
android
:
id
=
"@+id/tvScore"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"wrap_content"
/
>
<
/
LinearLayout
>
//使用自定义的GridLayout
<
com
.
example
.
administractor
.
game2048
.
GameView
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"0dp"
android
:
layout_weight
=
"1"
android
:
id
=
"@+id/GameView"
>
<
/
com
.
example
.
administractor
.
game2048
.
GameView
>
<
/
LinearLayout
>
|
GameView.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
|
package
com
.
example
.
administrator
.
game2048
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
List
;
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
;
public
class
GameView
extends
GridLayout
{
//调用类构造方法
public
GameView
(
Context
context
,
AttributeSet
attrs
,
int
defStyle
)
{
super
(
context
,
attrs
,
defStyle
)
;
//初始化游戏
InitGameView
(
)
;
}
public
GameView
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
)
;
InitGameView
(
)
;
}
public
GameView
(
Context
context
)
{
super
(
context
)
;
InitGameView
(
)
;
}
private
void
InitGameView
(
)
{
//设置为4x4个方格
setColumnCount
(
4
)
;
//设置背景颜色
setBackgroundColor
(
0xffeee4da
)
;
//判定滑动方向
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
;
offsety
=
event
.
getY
(
)
-
starty
;
if
(
Math
.
abs
(
offsetx
)
>
Math
.
abs
(
offsety
)
)
{
if
(
offsetx
<
-
5
)
{
swipeLeft
(
)
;
}
else
if
(
offsetx
>
5
)
{
swipeRight
(
)
;
}
}
else
{
if
(
offsety
<
-
5
)
{
swipeUp
(
)
;
}
else
if
(
offsetx
>
3
)
{
swipeDown
(
)
;
}
}
break
;
}
return
true
;
}
}
)
;
}
//适应不同大小的屏幕
@
Override
protected
void
onSizeChanged
(
int
w
,
int
h
,
int
oldw
,
int
oldh
)
{
super
.
onSizeChanged
(
w
,
h
,
oldw
,
oldh
)
;
int
cardWidth
=
(
Math
.
min
(
h
,
w
)
)
/
4
;
addCards
(
cardWidth
,
cardWidth
)
;
startGame
(
)
;
}
//在4x4的方格上添加满卡片
public
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
(
0
)
;
addView
(
c
,
cardwidth
,
cardheight
)
;
cardmap
[
x
]
[
y
]
=
c
;
}
}
}
//游戏开始时每个卡片默认值设为0,并随机添加两张带数字的卡片
private
void
startGame
(
)
{
MainActivity
.
getMainActivity
(
)
.
clearScore
(
)
;
for
(
int
y
=
0
;
y
<
4
;
y
++
)
{
for
(
int
x
=
0
;
x
<
4
;
x
++
)
{
cardmap
[
x
]
[
y
]
.
setNum
(
0
)
;
}
}
addRandomNum
(
)
;
addRandomNum
(
)
;
}
private
void
addRandomNum
(
)
{
//使用emptypoints将数字为0的card提取出来,并随即选择一个空card赋值
emptyPoints
.
clear
(
)
;
for
(
int
y
=
0
;
y
<
4
;
y
++
)
{
for
(
int
x
=
0
;
x
<
4
;
x
++
)
{
if
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
<=
0
)
{
emptyPoints
.
add
(
new
Point
(
x
,
y
)
)
;
}
}
}
Point
p
=
emptyPoints
.
remove
(
(
int
)
(
Math
.
random
(
)
*
emptyPoints
.
size
(
)
)
)
;
//2和4出现的概率控制在1:9
cardmap
[
p
.
x
]
[
p
.
y
]
.
setNum
(
Math
.
random
(
)
>
0.1
?
2
:
4
)
;
}
//左滑方法
private
void
swipeLeft
(
)
{
//merge作为判断能否滑动的flag
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
(
cardmap
[
x1
]
[
y
]
.
getNum
(
)
>
0
)
{
if
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
<=
0
)
{
cardmap
[
x
]
[
y
]
.
setNum
(
cardmap
[
x1
]
[
y
]
.
getNum
(
)
)
;
cardmap
[
x1
]
[
y
]
.
setNum
(
0
)
;
merge
=
true
;
x
--
;
}
else
if
(
cardmap
[
x
]
[
y
]
.
equal
(
cardmap
[
x1
]
[
y
]
)
)
{
cardmap
[
x
]
[
y
]
.
setNum
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
*
2
)
;
cardmap
[
x1
]
[
y
]
.
setNum
(
0
)
;
MainActivity
.
getMainActivity
(
)
.
addScore
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
)
;
merge
=
true
;
}
break
;
}
}
}
}
if
(
merge
)
{
addRandomNum
(
)
;
checkComplete
(
)
;
}
}
//下滑
private
void
swipeDown
(
)
{
boolean
merge
=
false
;
for
(
int
x
=
0
;
x
<
4
;
x
++
)
{
for
(
int
y
=
3
;
y
>=
0
;
y
--
)
{
for
(
int
y1
=
y
-
1
;
y1
>=
0
;
y1
--
)
{
if
(
cardmap
[
x
]
[
y1
]
.
getNum
(
)
>
0
)
{
if
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
<=
0
)
{
cardmap
[
x
]
[
y
]
.
setNum
(
cardmap
[
x
]
[
y1
]
.
getNum
(
)
)
;
cardmap
[
x
]
[
y1
]
.
setNum
(
0
)
;
y
++
;
merge
=
true
;
}
else
if
(
cardmap
[
x
]
[
y
]
.
equal
(
cardmap
[
x
]
[
y1
]
)
)
{
cardmap
[
x
]
[
y
]
.
setNum
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
*
2
)
;
cardmap
[
x
]
[
y1
]
.
setNum
(
0
)
;
MainActivity
.
getMainActivity
(
)
.
addScore
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
)
;
merge
=
true
;
}
break
;
}
}
}
}
if
(
merge
)
{
addRandomNum
(
)
;
checkComplete
(
)
;
}
}
//上滑
private
void
swipeUp
(
)
{
boolean
merge
=
false
;
for
(
int
x
=
0
;
x
<
4
;
x
++
)
{
for
(
int
y
=
0
;
y
<
4
;
y
++
)
{
for
(
int
y1
=
y
+
1
;
y1
<
4
;
y1
++
)
{
if
(
cardmap
[
x
]
[
y1
]
.
getNum
(
)
>
0
)
{
if
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
<=
0
)
{
cardmap
[
x
]
[
y
]
.
setNum
(
cardmap
[
x
]
[
y1
]
.
getNum
(
)
)
;
cardmap
[
x
]
[
y1
]
.
setNum
(
0
)
;
y
--
;
merge
=
true
;
}
else
if
(
cardmap
[
x
]
[
y
]
.
equal
(
cardmap
[
x
]
[
y1
]
)
)
{
cardmap
[
x
]
[
y
]
.
setNum
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
*
2
)
;
cardmap
[
x
]
[
y1
]
.
setNum
(
0
)
;
MainActivity
.
getMainActivity
(
)
.
addScore
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
)
;
merge
=
true
;
}
break
;
}
}
}
}
if
(
merge
)
{
addRandomNum
(
)
;
checkComplete
(
)
;
}
}
//右滑
private
void
swipeRight
(
)
{
boolean
merge
=
false
;
for
(
int
y
=
0
;
y
<
4
;
y
++
)
{
for
(
int
x
=
3
;
x
>=
0
;
x
--
)
{
for
(
int
x1
=
x
-
1
;
x1
>=
0
;
x1
--
)
{
if
(
cardmap
[
x1
]
[
y
]
.
getNum
(
)
>
0
)
{
if
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
<=
0
)
{
cardmap
[
x
]
[
y
]
.
setNum
(
cardmap
[
x1
]
[
y
]
.
getNum
(
)
)
;
cardmap
[
x1
]
[
y
]
.
setNum
(
0
)
;
x
++
;
merge
=
true
;
}
else
if
(
cardmap
[
x
]
[
y
]
.
equal
(
cardmap
[
x1
]
[
y
]
)
)
{
cardmap
[
x
]
[
y
]
.
setNum
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
*
2
)
;
cardmap
[
x1
]
[
y
]
.
setNum
(
0
)
;
MainActivity
.
getMainActivity
(
)
.
addScore
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
)
;
merge
=
true
;
}
break
;
}
}
}
}
if
(
merge
)
{
addRandomNum
(
)
;
checkComplete
(
)
;
}
}
//如果有空卡片或者相邻的值相同卡片则游戏还能进行
public
void
checkComplete
(
)
{
boolean
complete
=
true
;
ALL
:
for
(
int
y
=
0
;
y
<
4
;
y
++
)
{
for
(
int
x
=
0
;
x
<
4
;
x
++
)
{
if
(
cardmap
[
x
]
[
y
]
.
getNum
(
)
==
0
||
x
>
0
&&
cardmap
[
x
]
[
y
]
.
equal
(
cardmap
[
x
-
1
]
[
y
]
)
||
x
<
3
&&
cardmap
[
x
]
[
y
]
.
equal
(
cardmap
[
x
+
1
]
[
y
]
)
||
y
>
0
&&
cardmap
[
x
]
[
y
]
.
equal
(
cardmap
[
x
]
[
y
-
1
]
)
||
y
<
3
&&
cardmap
[
x
]
[
y
]
.
equal
(
cardmap
[
x
]
[
y
+
1
]
)
)
{
complete
=
false
;
break
ALL
;
}
}
}
//游戏结束弹出alert提示窗口
if
(
complete
)
{
new
AlertDialog
.
Builder
(
getContext
(
)
)
.
setTitle
(
"大林哥温馨提示"
)
.
setMessage
(
"游戏结束"
)
.
setPositiveButton
(
"重来"
,
new
DialogInterface
.
OnClickListener
(
)
{
@
Override
public
void
onClick
(
DialogInterface
arg0
,
int
arg1
)
{
startGame
(
)
;
}
}
)
.
show
(
)
;
}
}
private
Card
[
]
[
]
cardmap
=
new
Card
[
4
]
[
4
]
;
private
List
<
Point
>
emptyPoints
=
new
ArrayList
<
Point
>
(
)
;
}
|
主类MainActivity.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
package
com
.
example
.
administrator
.
game2048
;
import
android
.
app
.
Activity
;
import
android
.
os
.
Bundle
;
import
android
.
widget
.
TextView
;
public
class
MainActivity
extends
Activity
{
public
MainActivity
(
)
{
mainActivity
=
this
;
}
@
Override
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
(
)
;
}
private
TextView
tvscore
;
private
int
score
=
0
;
public
static
MainActivity
mainActivity
=
null
;
public
static
MainActivity
getMainActivity
(
)
{
return
mainActivity
;
}
}
|
Card.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
package
com
.
example
.
administrator
.
game2048
;
import
android
.
content
.
Context
;
import
android
.
view
.
Gravity
;
import
android
.
view
.
View
;
import
android
.
widget
.
FrameLayout
;
import
android
.
widget
.
TextView
;
public
class
Card
extends
FrameLayout
{
public
Card
(
Context
context
)
{
super
(
context
)
;
LayoutParams
lp
=
null
;
View
background
=
new
View
(
getContext
(
)
)
;
//参数-1表示layoutparams填充满整个父容器
lp
=
new
LayoutParams
(
-
1
,
-
1
)
;
//设置卡片之间有10像素的间隔
lp
.
setMargins
(
10
,
10
,
0
,
0
)
;
background
.
setBackgroundColor
(
0x33ffffff
)
;
addView
(
background
,
lp
)
;
label
=
new
TextView
(
getContext
(
)
)
;
label
.
setTextSize
(
28
)
;
label
.
setGravity
(
Gravity
.
CENTER
)
;
lp
=
new
LayoutParams
(
-
1
,
-
1
)
;
lp
.
setMargins
(
10
,
10
,
0
,
0
)
;
addView
(
label
,
lp
)
;
setNum
(
0
)
;
}
private
int
n
=
0
;
public
int
getNum
(
)
{
return
n
;
}
//设置数字及对应的背景颜色
public
void
setNum
(
int
n
)
{
this
.
n
=
n
;
if
(
n
<=
0
)
{
label
.
setText
(
""
)
;
}
else
{
label
.
setText
(
n
+
""
)
;
}
switch
(
n
)
{
case
0
:
label
.
setBackgroundColor
(
0x00000000
)
;
break
;
case
2
:
label
.
setBackgroundColor
(
0xffeee4da
)
;
break
;
case
4
:
label
.
setBackgroundColor
(
0xffede0c8
)
;
break
;
case
8
:
label
.
setBackgroundColor
(
0xfff2b179
)
;
break
;
case
16
:
label
.
setBackgroundColor
(
0xfff59563
)
;
break
;
case
32
:
label
.
setBackgroundColor
(
0xfff67c5f
)
;
break
;
case
64
:
label
.
setBackgroundColor
(
0xfff65e3b
)
;
break
;
case
128
:
label
.
setBackgroundColor
(
0xffedcf72
)
;
break
;
case
256
:
label
.
setBackgroundColor
(
0xffedcc61
)
;
break
;
case
512
:
label
.
setBackgroundColor
(
0xffedc850
)
;
break
;
case
1024
:
label
.
setBackgroundColor
(
0xffedc53f
)
;
break
;
case
2048
:
label
.
setBackgroundColor
(
0xffedc22e
)
;
break
;
default
:
label
.
setBackgroundColor
(
0xff3c3a32
)
;
break
;
}
}
//判断卡片是否相等
public
boolean
equal
(
Card
o
)
{
return
getNum
(
)
==
o
.
getNum
(
)
;
}
private
TextView
label
;
}
|
转载请注明:静觅 » Android开发之2048安卓版