功能:
双人对战五子棋
效果:
基础知识:
- View组件自带绘图方法onDraw(Canvas canvas),利用invalidate()方法可以刷新onDraw(Canvas canvas)方法
- View组件自带响应事件方法onTouchEvent(MotionEvent event),在里面可以直接写事件逻辑
- 游戏相当于一帧一帧的动画拼合在一起,每一个画面显示什么由你决定,大多数游戏都遵循这样的流程:逻辑——绘图——逻辑——绘图。。。,不停的循环就可以展现一个完整的游戏
思路:
- 游戏内容简单,利用View视图框架
- 利用点击事件触发绘图逻辑
- 抽象出一个Chess类,Chess包括3种状态:黑,白,无,棋盘有多少个坐标点就实例化多少个Chess,一开始Chess集合的状态都为无,当点击某一个Chess是就改变它的状态为黑或白,这样就可以逻辑和绘图分离开来,在绘图方法中只需要根据Chess的状态画相应的棋子,而逻辑方法中只需要改变Chess的状态即可
- 划分游戏状态,根据不同的游戏状态,执行不同的逻辑和绘图方法
**
代码结构:
**
**
完整代码:
MainActivity:
package com.next.gobang;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Window;
import android.view.WindowManager;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//无标题
requestWindowFeature(Window.FEATURE_NO_TITLE);
//全屏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new GameView(this));
}
}
Chess:
package com.next.gobang;
/**
* Created by Administrator on 2016/3/12 0012.
*/
public class Chess {
public static final int STATUS_NULL = 0;
public static final int STATUS_BLACK = 1;
public static final int STATUS_WHITE = -1;
//棋子的相对坐标和状态
private int x, y, status;
public Chess(int x, int y) {
this.x = x;
this.y = y;
this.status = this.STATUS_NULL;
}
public Chess(int x, int y, int status) {
this.x = x;
this.y = y;
this.status = status;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
GameView:
package com.next.gobang;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by Next on 2016/3/12 0012.
* weixin:xinshouit
*/
public class GameView extends View {
//划分游戏状态
enum GameState{
Menu,
Playing,
Over
}
GameState gameState = GameState.Menu;
static final int MAX_X = 15;//棋盘列数
static final int MAX_Y = 15;//棋盘行数
int cWidth;//棋子宽度
int scrW;//屏幕宽
int scrH;//屏幕高
int offsetX;//偏移x
int offsetY;//偏移y,用于调整棋盘在屏幕中的位置
Paint paint;
Chess[][] chesses;//棋盘上所有棋子的矩阵
Chess touchChess;//点击的棋子
int turn;
public GameView(Context context) {
super(context);
scrW = ((MainActivity)context).getWindowManager().getDefaultDisplay().getWidth();
scrH = ((MainActivity) context).getWindowManager().getDefaultDisplay().getHeight();
cWidth = scrW / MAX_X;
offsetX = 0;
offsetY = (scrH - scrW)/2;//使棋盘位于屏幕中央
paint = new Paint();
chesses = new Chess[MAX_X][MAX_Y];
setKeepScreenOn(true);//保持屏幕常亮
}
//初始化游戏
private void newGame() {
for (int x = 0; x < MAX_X; x++) {
for (int y = 0; y < MAX_Y; y++) {
chesses[x][y] = new Chess(x, y, Chess.STATUS_NULL);
}
}
turn = Chess.STATUS_WHITE;//白先黑后你懂的
}
@Override
protected void onDraw(Canvas canvas) {
switch (gameState) {
case Menu:
menuDraw(canvas);
break;
case Playing:
playingDraw(canvas);
break;
case Over:
overDraw(canvas);
break;
default:
break;
}
}
private void menuDraw(Canvas canvas) {
canvas.drawColor(Color.GRAY);
paint.setColor(Color.BLACK);
paint.setTextSize(200);
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText("五子棋", scrW/2, scrH/4, paint);
canvas.drawText("点击开始", scrW / 2, scrH / 2, paint);
}
private void playingDraw(Canvas canvas) {
canvas.drawColor(Color.GRAY);
//画棋盘
paint.setColor(Color.BLACK);
paint.setStrokeWidth(10);
for (int x = 0; x < MAX_X; x++) {
canvas.drawLine(offsetX+x*cWidth+cWidth/2, offsetY+cWidth/2, offsetX+x*cWidth+cWidth/2, offsetY+cWidth*MAX_Y-cWidth/2, paint);
}
for (int y = 0; y < MAX_Y; y++) {
canvas.drawLine(offsetX+cWidth/2, offsetY+y*cWidth+cWidth/2, offsetX+MAX_X*cWidth-cWidth/2, offsetY+y*cWidth+cWidth/2, paint);
}
//画棋子
for (int x = 0; x < MAX_X; x++) {
for (int y = 0; y < MAX_Y; y++) {
if (chesses[x][y].getStatus() == Chess.STATUS_NULL) {
continue;
}
if (chesses[x][y].getStatus() == Chess.STATUS_BLACK) {
paint.setColor(Color.BLACK);
}
if (chesses[x][y].getStatus() == Chess.STATUS_WHITE) {
paint.setColor(Color.WHITE);
}
canvas.drawCircle(offsetX+x*cWidth+cWidth/2, offsetY+y*cWidth+cWidth/2, cWidth/2, paint);
}
}
}
private void overDraw(Canvas canvas) {
canvas.drawColor(Color.GRAY);
paint.setColor(Color.BLACK);
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(100);
if (touchChess.getStatus() == Chess.STATUS_BLACK){
canvas.drawText("黑棋胜", scrW/2, scrH/4, paint);
}else {
canvas.drawText("白棋胜", scrW/2, scrH/4, paint);
}
canvas.drawText("点击重新开始", scrW/2, scrH/2, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (gameState) {
case Menu:
menuLogic(event);
break;
case Playing:
playLogic(event);
break;
case Over:
overLogic(event);
break;
}
return super.onTouchEvent(event);
}
private void menuLogic(MotionEvent event) {
if (event.getX() > 0) {
gameState = GameState.Playing;
newGame();
invalidate();
}
}
private void playLogic(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
if (x > offsetX && x < offsetX+MAX_X*cWidth && y > offsetY && y< offsetY+MAX_Y*cWidth) {
int touchX = (x - offsetX)/cWidth;
int touchY = (y - offsetY)/cWidth;
touchChess = chesses[touchX][touchY];
if (touchChess.getStatus() == Chess.STATUS_NULL) {
if (turn == Chess.STATUS_BLACK) {
touchChess.setStatus(Chess.STATUS_BLACK);
turn = Chess.STATUS_WHITE;
}else {
touchChess.setStatus(Chess.STATUS_WHITE);
turn = Chess.STATUS_BLACK;
}
invalidate();//刷新界面
judgeOver();//判断输赢
}
}
}
private void overLogic(MotionEvent event) {
if (event.getX() > 0) {
gameState = GameState.Playing;
newGame();
invalidate();
}
}
private void judgeOver() {
//遍历横向是否连成五子
int fiveCount = 0;
for (int x = 0;x < MAX_X;x++){
if (chesses[x][touchChess.getY()].getStatus() == touchChess.getStatus()){
fiveCount++;
if (fiveCount == 5){
gameState = GameState.Over;
return;
}
}else {
fiveCount=0;
}
}
//遍历纵向
fiveCount = 0;
for (int y = 0;y < MAX_Y;y++){
if (chesses[touchChess.getX()][y].getStatus() == touchChess.getStatus()){
fiveCount++;
if (fiveCount == 5){
gameState = GameState.Over;
return;
}
}else {
fiveCount=0;
}
}
//遍历右下斜向
fiveCount = 0;
int f = touchChess.getY() - touchChess.getX();
for (int x = 0;x < MAX_X;x++){
if (f+x < 0 || f+x > MAX_Y-1){
continue;
}
if (chesses[x][f+x].getStatus() == touchChess.getStatus()){
fiveCount++;
if (fiveCount == 5){
gameState = GameState.Over;
return;
}
}
else {
fiveCount = 0;
}
}
//遍历右上斜向
fiveCount = 0;
f = touchChess.getX() + touchChess.getY();
for (int x = 0;x < MAX_X;x++){
if (f-x < 0 || f-x > MAX_Y-1){
continue;
}
if (chesses[x][f-x].getStatus() == touchChess.getStatus()){
fiveCount++;
if (fiveCount == 5){
gameState = GameState.Over;
return;
}
}
else {
fiveCount = 0;
}
}
}
}
**
最后说两句:
由于心情不好,所以界面都是黑白灰。。。
第一个小游戏,尽可能逻辑清晰,但水平有限有些方法可能实现的不够简单,尽力了。。。
游戏的核心还是算法,这里只实现了双人对战的五子棋,本来应该做人机对战的,但,我要去吃饭了。。。
下次可能写2048,更新我会在公众号(xinshouit)通知,大家支持一下
**