|
连连看的主要源代码
java代码:
package com.xmobilapp.linkup;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import android.graphics.Point;
import android.os.Handler;
import android.os.Message;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.xmobilapp.linkup.GameView.OnItemClickListener;
public class GameController {
// 列数
private static final int countX = 10;
// 行数
private static final int countY = 12;
// 图片大小
private static final int iconSize = 35;
private Main app;
private GameView gameView;
// 游戏布局
private int[][] map;
private List<oint> path = new ArrayList<Point>();
private RefreshHandler redrawHandler = new RefreshHandler();
class RefreshHandler extends Handler {
public static final int UPDATE_TXT = 0;
public static final int UPDATE_IMAGE = 1;
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
// 更新文本显示
case UPDATE_TXT:
TextView t = (TextView) app.findViewById(R.id.timing);
t.setText("剩余时间:" + remainTime + "秒 帮助:" + help + "次");
if (remainTime <= 0) {
timer.cancel();
app.setState(Main.STATE_LOSE);
}
break;
// 更新视图
case UPDATE_IMAGE:
gameView.invalidate();
if (win()) {
timer.cancel();
app.setState(Main.STATE_WIN);
} else if (die()) {
shuffle();
}
break;
}
}
// 延时刷新视图
public void sleep(long delayMillis) {
this.removeMessages(0);
Message msg = new Message();
msg.what = UPDATE_IMAGE;
sendMessageDelayed(msg, delayMillis);
}
};
private OnItemClickListener itemClickListener = new OnItemClickListener() {
public void onClick(Point position) {
List<Point> selected = gameView.getSelected();
// 如果已选中一个,判断是否可消除,否则选中当前点击图片
if (selected.size() == 1) {
if (link(selected.get(0), position)) {
selected.add(position);
gameView.drawLine(path.toArray(new Point[] {})); // 画线
redrawHandler.sleep(500); // 500ms后更新视图,消除连线和图片
} else {
// 不可消除则更新选中图片
selected.clear();
selected.add(position);
gameView.invalidate();
}
} else {
selected.add(position);
gameView.invalidate();
}
}
};
// 总时间
private static final long totalTime = 200;
// 剩余时间
private long remainTime;
// 开始时间
private long startTime;
// 计时器
private Timer timer;
// 可用帮助次数
private int help;
class GameTimerTask extends TimerTask {
@Override
public void run() {
// 更新剩余时间
remainTime = totalTime
- ((System.currentTimeMillis() - startTime) / 1000);
Message msg = new Message();
msg.what = RefreshHandler.UPDATE_TXT;
redrawHandler.sendMessage(msg);
}
};
// 开始游戏,初始化界面和布局
public void startGame(Main m) {
generateMap();
help = 5;
remainTime = totalTime;
resume(m);
}
public void pause() {
timer.cancel();
}
public void resume(Main m) {
app = m;
gameView = new GameView(app);
LinearLayout gameViewParent = (LinearLayout) app.findViewById(R.id.GameView);
gameView.setIconWidth(iconSize);
gameView.setIconHeight(iconSize);
gameView.setIcons(Main.icons);
gameView.setOnItemClickListener(itemClickListener);
gameView.setMap(map);
gameViewParent.addView(gameView, ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT);
startTime = System.currentTimeMillis() - (totalTime - remainTime)
* 1000;
timer = new Timer();
timer.schedule(new GameTimerTask(), 0, 100);
}
// 生成初始化布局
private void generateMap() {
int x = 1;
int y = 0;
map = new int[countX][countY];
for (int i = 1; i < countX - 1; i++) {
for (int j = 1; j < countY - 1; j++) {
map[j] = x;
if (y == 1) {
x++;
y = 0;
if (x == Main.iconsCount + 1) {
x = 1;
}
} else {
y = 1;
}
}
}
shuffle();
}
// 随机交换
private void shuffle() {
Random random = new Random();
int tmpV, tmpX, tmpY;
for (int y = 1; y < countY - 1; y++) {
for (int x = 1; x < countX - 1; x++) {
tmpV = map[x][y];
tmpX = random.nextInt(countX - 2) + 1;
tmpY = random.nextInt(countY - 2) + 1;
map[x][y] = map[tmpX][tmpY];
map[tmpX][tmpY] = tmpV;
}
}
if (die()) {
shuffle();
}
}
List<Point> p1E = new ArrayList<Point>();
List<Point> p2E = new ArrayList<Point>();
private boolean link(Point p1, Point p2) {
if (p1.equals(p2)) {
return false;
}
path.clear();
if (map[p1.x][p1.y] == map[p2.x][p2.y]) {
// 直连
if (linkD(p1, p2)) {
path.add(p1);
path.add(p2);
return true;
}
// 一折
Point p = new Point(p1.x, p2.y);
if (map[p.x][p.y] == 0) {
if (linkD(p1, p) && linkD(p, p2)) {
path.add(p1);
path.add(p);
path.add(p2);
return true;
}
}
p = new Point(p2.x, p1.y);
if (map[p.x][p.y] == 0) {
if (linkD(p1, p) && linkD(p, p2)) {
path.add(p1);
path.add(p);
path.add(p2);
return true;
}
}
// 二折
// 横向搜索
expandH(p1, p1E);
expandH(p2, p2E);
// 判断是否可连
for (Point pt1 : p1E) {
for (Point pt2 : p2E) {
if (pt1.x == pt2.x) {
if (linkD(pt1, pt2)) {
path.add(p1);
path.add(pt1);
path.add(pt2);
path.add(p2);
return true;
}
}
}
}
// 纵向搜索
expandV(p1, p1E);
expandV(p2, p2E);
// 判断是否可连
for (Point pt1 : p1E) {
for (Point pt2 : p2E) {
if (pt1.y == pt2.y) {
if (linkD(pt1, pt2)) {
path.add(p1);
path.add(pt1);
path.add(pt2);
path.add(p2);
return true;
}
}
}
}
return false;
}
return false;
}
// 判断是否能直连
private boolean linkD(Point p1, Point p2) {
if (p1.x == p2.x) {
int y1 = Math.min(p1.y, p2.y);
int y2 = Math.max(p1.y, p2.y);
boolean flag = true;
for (int y = y1 + 1; y < y2; y++) {
if (map[p1.x][y] != 0) {
flag = false;
break;
}
}
if (flag) {
return true;
}
}
if (p1.y == p2.y) {
int x1 = Math.min(p1.x, p2.x);
int x2 = Math.max(p1.x, p2.x);
boolean flag = true;
for (int x = x1 + 1; x < x2; x++) {
if (map[x][p1.y] != 0) {
flag = false;
break;
}
}
if (flag) {
return true;
}
}
return false;
}
// 横向寻找可达的点
private void expandH(Point p, List<Point> l) {
l.clear();
for (int x = p.x + 1; x < countX; x++) {
if (map[x][p.y] != 0) {
break;
}
l.add(new Point(x, p.y));
}
for (int x = p.x - 1; x >= 0; x--) {
if (map[x][p.y] != 0) {
break;
}
l.add(new Point(x, p.y));
}
}
// 纵向寻找可达的点
private void expandV(Point p, List<Point> l) {
l.clear();
for (int y = p.y + 1; y < countY; y++) {
if (map[p.x][y] != 0) {
break;
}
l.add(new Point(p.x, y));
}
for (int y = p.y - 1; y >= 0; y--) {
if (map[p.x][y] != 0) {
break;
}
l.add(new Point(p.x, y));
}
}
// 判断是否有可连的点
private boolean die() {
for (int y = 1; y < countY - 1; y++) {
for (int x = 1; x < countX - 1; x++) {
if (map[x][y] != 0) {
for (int j = y; j < countY - 1; j++) {
if (j == y) {
for (int i = x + 1; i < countX - 1; i++) {
if (map[j] == map[x][y]
&& link(new Point(x, y),
new Point(i, j))) {
return false;
}
}
} else {
for (int i = 1; i < countX - 1; i++) {
if (map[j] == map[x][y]
&& link(new Point(x, y),
new Point(i, j))) {
return false;
}
}
}
}
}
}
}
return true;
}
// 判断是否已完全消除
private boolean win() {
for (int x = 0; x < countX; x++) {
for (int y = 0; y < countY; y++) {
if (map[x][y] != 0)
return false;
}
}
return true;
}
// 点帮助时自动消除
public void autoErase() {
if (help == 0)
return;
help--;
die();
List<Point> l = gameView.getSelected();
l.clear();
l.add(path.get(0));
l.add(path.get(path.size() - 1));
gameView.drawLine(path.toArray(new Point[] {}));
redrawHandler.sleep(500);
}
}
复制代码java代码:
package com.xmobilapp.linkup;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Paint.Style;
import android.view.MotionEvent;
import android.view.View;
public class GameView extends View {
// 被选中的图片坐标
private List<Point> selected = new ArrayList<Point>();
// 图片宽度
private int iconWidth;
// 图片高度
private int iconHeight;
// 连线的折点
private Point[] path = null;
// 图片点击事件的监听者
private OnItemClickListener mOnClickListener;
// 游戏布局数据
private int[][] map;
// 图片在横向上的偏移值
private int offsetX;
// 图片在纵向上的偏移值
private int offsetY;
// 图片资源
private Bitmap[] icons;
interface OnItemClickListener {
public void onClick(Point position);
}
public List<Point> getSelected() {
return selected;
}
public void setSelected(List<Point> selected) {
this.selected = selected;
}
public void setIcons(Bitmap[] icons) {
this.icons = icons;
}
public int getIconWidth() {
return iconWidth;
}
public void setIconWidth(int iconWidth) {
this.iconWidth = iconWidth;
}
public int getIconHeight() {
return iconHeight;
}
public void setIconHeight(int iconHeight) {
this.iconHeight = iconHeight;
}
public void setOnItemClickListener(OnItemClickListener l) {
mOnClickListener = l;
}
public void setMap(int[][] map) {
this.map = map;
invalidate();
}
public GameView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Point position : selected) {
Paint paint = new Paint();
paint.setColor(Color.YELLOW);
paint.setStyle(Style.FILL);
Point p = index2screen(position.x, position.y);
canvas.drawRect(p.x, p.y, p.x + iconWidth, p.y + iconHeight, paint);
}
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map.length; j++) {
if (map[j] != 0) {
Bitmap bitmap = icons[map[j] - 1];
Point p = index2screen(i, j);
canvas.drawBitmap(bitmap, null, new Rect(p.x, p.y, p.x
+ iconWidth, p.y + iconHeight), null);
}
}
}
if (path != null && path.length >= 2) {
for (int i = 0; i < path.length - 1; i++) {
Paint paint = new Paint();
paint.setARGB(255, 60, 60, 200);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
Point p1 = index2screen(path.x, path.y);
Point p2 = index2screen(path[i + 1].x, path[i + 1].y);
canvas.drawLine(p1.x + iconWidth / 2, p1.y + iconHeight / 2,
p2.x + iconWidth / 2, p2.y + iconHeight / 2, paint);
}
Point p = path[0];
map[p.x][p.y] = 0;
p = path[path.length - 1];
map[p.x][p.y] = 0;
selected.clear();
path = null;
}
}
private Point screen2index(int x, int y) {
return new Point((x + offsetX) / iconWidth, (y + offsetY) / iconHeight);
}
private Point index2screen(int x, int y) {
return new Point(x * iconWidth - offsetX, y * iconHeight - offsetY);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN) {
return false;
}
int x = (int) event.getX();
int y = (int) event.getY();
Point p = screen2index(x, y);
if (map[p.x][p.y] != 0)
mOnClickListener.onClick(p);
return true;
}
public void drawLine(Point[] path) {
this.path = path;
this.invalidate();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
offsetX = iconWidth - (right - left - (map.length - 2) * iconWidth)
/ 2;
offsetY = iconHeight
- (bottom - top - (map[0].length - 2) * iconHeight) / 2;
}
}
}
复制代码java代码:
package com.xmobilapp.linkup;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class Main extends Activity {
/** Called when the activity is first created. */
public static final int STATE_MENU = 0;
public static final int STATE_GAME = 1;//开始
public static final int STATE_WIN = 2;//赢
public static final int STATE_LOSE = 3;//输
public static final int STATE_PAUSE = 4;//停止
private static int state = STATE_MENU;
private static GameController gameController = null;
public static final int iconsCount = 27;
public static Bitmap[] icons = new Bitmap[iconsCount];
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onStart() {
super.onStart();
loadMenu();
}
private void loadMenu() {
setContentView(R.layout.main);
if (gameController == null) {
gameController = new GameController();
loadIcons();
}
final Button start = (Button) findViewById(R.id.start);
start.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
state = STATE_GAME;
setContentView(R.layout.game);
gameController.startGame(Main.this);
}
});
final Button exit = (Button) findViewById(R.id.exit);
exit.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Main.this.finish();
}
});
final TextView title = (TextView) findViewById(R.id.title);
if (state == STATE_WIN) {
title.setText("恭喜您过关!");
start.setText("再玩一遍");
} else if (state == STATE_LOSE) {
title.setText("英雄请重新来过!");
start.setText("重试");
}
if (state == STATE_PAUSE) {
start.setText("新游戏");
Button resume = (Button) findViewById(R.id.resume);
resume.setVisibility(View.VISIBLE);
resume.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
state = STATE_GAME;
setContentView(R.layout.game);
gameController.resume(Main.this);
}
});
}
}
private void loadIcons() {
Resources r = getResources();
for (int i = 0; i < icons.length; i++) {
icons = ((BitmapDrawable) r.getDrawable(R.drawable.i1 + i))
.getBitmap();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (state == STATE_GAME) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
gameController.autoErase();
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
gameController.pause();
state = STATE_PAUSE;
loadMenu();
break;
}
}
return true;
}
public void setState(int state) {
this.state = state;
if (state == STATE_WIN || state == STATE_LOSE) {
loadMenu();
}
}
@Override
protected void onPause() {
super.onPause();
if (state == STATE_GAME) {
state = STATE_PAUSE;
gameController.pause();
}
}
}
复制代码
xml我就不给大家分享了,找一些好的图片。
登录才可以下载或查看附件。没有帐号?免费加入 |
|