哈喽,我又来了。
前段时间看了慕课网上的一个小游戏,自己比较喜欢,然后就跟着写了一遍,感觉还不错,一直没来得及跟你们分享,今天整好有空就来跟你们聊聊。
我是用的studio写的,你们也可以用别的尝试尝试。来,上菜,呸,代码。
一。这次先来看看自定义view中是怎么写的吧
public class wuziqi extends View {
//游戏是否结束
private boolean mIsGameOver;
//当前是否是白子赢
private boolean mIsWhiteWinner;
private int mPanelWidth;
private float mLineHeight;
private int Max_LINE=10;
private Paint mPaint =new Paint();
private Bitmap mWhitePiece;
private Bitmap mBlackPiece;
//白棋先手,当前轮到白棋
private boolean mIsWhite=true;
private ArrayList<Point> mWhiteArray=new ArrayList<Point>();
private ArrayList<Point> mBlackArray=new ArrayList<Point>();
private float radioPieceOfLineHeight=3*1.0f/4;
private int Max_Count_IN_LINE=5;
public wuziqi(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint.setColor(0x88000000);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mWhitePiece= BitmapFactory.decodeResource(getResources(), R.drawable.baiqi);
mBlackPiece=BitmapFactory.decodeResource(getResources(),R.drawable.heiqi);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize=MeasureSpec.getSize(widthMeasureSpec);
int widthMode=MeasureSpec.getMode(widthMeasureSpec);
int heightSize=MeasureSpec.getSize(heightMeasureSpec);
int heightMode=MeasureSpec.getMode(heightMeasureSpec);
int width=Math.min(widthSize,heightSize);
if(widthMode==MeasureSpec.UNSPECIFIED){
width=heightSize;
}else if(heightMode==MeasureSpec.UNSPECIFIED){
width=widthSize;
}
setMeasuredDimension(width,width);
}
/**
* 跟尺寸相关的要在onSizeChanged中编写
* @param w
* @param h
* @param oldw
* @param oldh
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mPanelWidth=w;
mLineHeight=mPanelWidth * 1.0f/Max_LINE;
int pieceWidth= (int) (mLineHeight*radioPieceOfLineHeight);
mWhitePiece=Bitmap.createScaledBitmap(mWhitePiece,pieceWidth,pieceWidth,false);
mBlackPiece=Bitmap.createScaledBitmap(mBlackPiece,pieceWidth,pieceWidth,false);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(mIsGameOver)return false;
int action=event.getAction();
if(action==MotionEvent.ACTION_UP){
int x= (int) event.getX();
int y=(int) event.getY();
Point p = getValidPoint(x,y);
if(mWhiteArray.contains(p)||mBlackArray.contains(p)){
return false;
}
if(mIsWhite){
mWhiteArray.add(p);
}else{
mBlackArray.add(p);
}
invalidate();
mIsWhite=!mIsWhite;
}
return true;
}
private Point getValidPoint(int x, int y) {
return new Point((int)(x/mLineHeight),(int)(y/mLineHeight));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawBoard(canvas);
drawPiece(canvas);
checkGameOver();
}
//检查游戏是否结束
private void checkGameOver() {
boolean whiteWin=checkFiveInLine(mWhiteArray);
boolean blackWin=checkFiveInLine(mBlackArray);
if(whiteWin||blackWin){
mIsGameOver=true;
mIsWhiteWinner=whiteWin;
String text=mIsWhiteWinner ?"白棋胜利":"黑棋胜利";
Toast.makeText(getContext(),text,Toast.LENGTH_LONG).show();
}
}
//检查五子是否在一条线上
private boolean checkFiveInLine(List<Point> points) {
for (Point p:points){
int x=p.x;
int y=p.y;
//是否是水平
boolean win=checkHorizontal(x,y,points);
if(win)return true;
//是否是垂直
win=checkVertical(x,y,points);
if(win)return true;
win=checkLeft(x,y,points);//是否是左斜
if(win)return true;
win=checkRight(x,y,points);//是否是右斜
if(win)return true;
}
return false;
}
/**
* 判断x,y位置的棋子,是否横向有相邻的五个一致。
* @param x
* @param y
* @param points
* @return
*/
private boolean checkHorizontal(int x, int y, List<Point> points) {
int count=1;
//左
for (int j=1;j<Max_Count_IN_LINE;j++){
if(points.contains(new Point(x-j,y))){
count++;
}else{
break;
}
}
if(count==Max_Count_IN_LINE)return true;
//右
for (int j=1;j<Max_Count_IN_LINE;j++){
if(points.contains(new Point(x+j,y))){
count++;
}else{
break;
}
}
if(count==Max_Count_IN_LINE)return true;
return false;
}
private boolean checkVertical(int x, int y, List<Point> points) {
int count=1;
//上
for (int j=1;j<Max_Count_IN_LINE;j++){
if(points.contains(new Point(x,y-j))){
count++;
}else{
break;
}
}
if(count==Max_Count_IN_LINE)return true;
for (int j=1;j<Max_Count_IN_LINE;j++){
if(points.contains(new Point(x,y+j))){
count++;
}else{
break;
}
}
if(count==Max_Count_IN_LINE)return true;
return false;
}
private boolean checkLeft(int x, int y, List<Point> points) {
int count=1;
for (int j=1;j<Max_Count_IN_LINE;j++){
if(points.contains(new Point(x-j,y+j))){
count++;
}else{
break;
}
}
if(count==Max_Count_IN_LINE)return true;
for (int j=1;j<Max_Count_IN_LINE;j++){
if(points.contains(new Point(x+j,y-j))){
count++;
}else{
break;
}
}
if(count==Max_Count_IN_LINE)return true;
return false;
}
private boolean checkRight(int x, int y, List<Point> points) {
int count=1;
//上
for (int j=1;j<Max_Count_IN_LINE;j++){
if(points.contains(new Point(x-j,y-j))){
count++;
}else{
break;
}
}
if(count==Max_Count_IN_LINE)return true;
//下
for (int j=1;j<Max_Count_IN_LINE;j++){
if(points.contains(new Point(x+j,y+j))){
count++;
}else{
break;
}
}
if(count==Max_Count_IN_LINE)return true;
return false;
}
private void drawPiece(Canvas canvas) {
for (int i=0,n=mWhiteArray.size();i<n;i++){
Point whitePoint=mWhiteArray.get(i);
canvas.drawBitmap(mWhitePiece,
(whitePoint.x+(1-radioPieceOfLineHeight)/2)*mLineHeight,
(whitePoint.y+(1-radioPieceOfLineHeight)/2)*mLineHeight,null);
}
for (int i=0,n=mBlackArray.size();i<n;i++){
Point blackPoint=mBlackArray.get(i);
canvas.drawBitmap(mBlackPiece,
(blackPoint.x+(1-radioPieceOfLineHeight)/2)*mLineHeight,
(blackPoint.y+(1-radioPieceOfLineHeight)/2)*mLineHeight,null);
}
}
private void drawBoard(Canvas canvas) {
int w=mPanelWidth;
float lineHeight=mLineHeight;
for (int i=0;i<Max_LINE;i++){
int startX=(int)(lineHeight/2);
int endX=(int)(w-lineHeight/2);
int y= (int) ((0.5+i)*lineHeight);
//横向的坐标
canvas.drawLine(startX, y, endX, y, mPaint);
//纵向的坐标
canvas.drawLine(y, startX, y, endX, mPaint);
}
}
//重新开始游戏时的操作,在MainActivity中调用
public void start(){
mWhiteArray.clear();
mBlackArray.clear();
mIsGameOver=false;
mIsWhiteWinner=false;
invalidate();;
}
private static final String INSTANCE="instance";
private static final String INSTANCE_GAMEOVER="instance_gameover";
private static final String INSTANCE_WHITEARRAY="instance_whiteArray";
private static final String INSTANCE_BLACKARRAY="instance_blackArray";
/**
* 存储view
* @return
*/
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle=new Bundle();
bundle.putParcelable(INSTANCE,super.onSaveInstanceState());
bundle.putBoolean(INSTANCE_GAMEOVER,mIsGameOver);
bundle.putParcelableArrayList(INSTANCE_WHITEARRAY,mWhiteArray);
bundle.putParcelableArrayList(INSTANCE_BLACKARRAY,mBlackArray);
return bundle;
}
/**
* 恢复view
* @param state
*/
@Override
protected void onRestoreInstanceState(Parcelable state) {
if(state instanceof Bundle){
Bundle bundle= (Bundle) state;
mIsGameOver=bundle.getBoolean(INSTANCE_GAMEOVER);
mWhiteArray=bundle.getParcelableArrayList(INSTANCE_WHITEARRAY);
mBlackArray=bundle.getParcelableArrayList(INSTANCE_BLACKARRAY);
super.onRestoreInstanceState(bundle.getParcelable(INSTANCE));
return;
}
super.onRestoreInstanceState(state);
}
}
二。上面的主要步骤写完,就已经快完成了,下面的代码就很简单了,在MainActivity中调用,找到自定义view的id就可以了。我也做了一些小的完善,如果你游戏结束了,就点击menu键。选择重新开始,再来一局。
@Override public boolean onOptionsItemSelected(MenuItem item) { int id=item.getItemId(); if(id==R.id.action_settings){ wuziqiPanel.start(); return true; } return super.onOptionsItemSelected(item); }三。其实到这里,就全部完成了。xml中的代码相信你们都会,将view引用进来就可以了
<com.example.wuziqi.com.example.view.wuziqi
android:id="@+id/wuziqi"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
好了,这就是整个游戏的完整代码。我自己玩了一会,挺好的,就是自己跟自己对弈,哈哈,有点无聊。
就这样了。^-^ ^-^ ^-^