五子棋 手打稍加改变自慕课网hyman
来源:互联网 发布:微信加友软件免费下载 编辑:程序博客网 时间:2024/04/29 01:48
我整理了一下,顺便加了一点屏幕切换的代码,网速太不给力,好几次都坑了
直接上代码吧,稍后总结,简单粗暴,详情看题目
主程序:
package com.andy.andy.myapplication;import android.content.res.Configuration;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import android.widget.RelativeLayout;public class MainActivity extends ActionBarActivity { Button button; RelativeLayout layout; WuziqiPannel wuziqiPannel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); layout = (RelativeLayout) findViewById(R.id.layout); button = (Button) findViewById(R.id.button); wuziqiPannel = (WuziqiPannel) findViewById(R.id.wuziqi); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { wuziqiPannel.start(); } }); // int orientationPortrait = Configuration.ORIENTATION_PORTRAIT;//1 竖着的 // layout.addView(button, lp); } /** * 优点:我们可以随时监听屏幕旋转变化,并对应做出相应的操作; * 缺点:它只能一次旋转90度,如果一下子旋转180度,onConfigurationChanged函数不会被调用。 * * @param newConfig */ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); Log.e("lc---", "onConfigurationChanged"); // int isVer = getResources().getConfiguration().orientation; if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { // lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, R.id.button); lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); // button.setLayoutParams(new RelativeLayout.LayoutParams()); } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { // lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, R.id.button);// lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, R.id.button); lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); // button.setLayoutParams(lp);//好用 } button.setLayoutParams(lp); }}
自定义控件WuziqiPannel.java
package com.andy.andy.myapplication;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Point;import android.os.Bundle;import android.os.Parcelable;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.Toast;import java.util.ArrayList;import java.util.List;/** * Created by andy on 2016/6/12. */public class WuziqiPannel extends View { private int mPanelWidth; private float mLineHeight;//行高 为何是float?精度,屏幕的宽 通常计算出来通常不是整数 private int MAX_LINE = 10;//尺寸相关,在哪里初始化呢 onsizechange() private Paint mPaint = new Paint(); private Bitmap mWhitePiece; private Bitmap mBlackPiece; private float ratioPieceOfLineHeight = 3 * 1.0f / 4; //白起先手 还是轮到白起? private boolean mIsWhite = true;// private List<Point> mWhiteArray = new ArrayList<Point>();// private List<Point> mBlackArray = new ArrayList<Point>(); private ArrayList<Point> mWhiteArray = new ArrayList<Point>(); private ArrayList<Point> mBlackArray = new ArrayList<Point>(); private boolean mIsGameOver; private boolean mIsWhiteWinner; private int MAX_COUNT_IN_LINE = 5; public WuziqiPannel(Context context, AttributeSet attrs) { super(context, attrs); setBackgroundColor(0x44ff0000); init(); } private void init() { mPaint.setColor(0x88000000); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setStyle(Paint.Style.STROKE); mWhitePiece = BitmapFactory.decodeResource(getResources(), R.drawable.bai);//从 资源文件中 取图片 mBlackPiece = BitmapFactory.decodeResource(getResources(), R.drawable.hei); } /* 首先 view 的测量 */ @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); /* 这个判断主要解决 自定义view 嵌套在scrollview 中时,获取不到宽高,或者宽高为0 的情况的处理 */ if (widthMode == MeasureSpec.UNSPECIFIED) { width = heightSize; } else if (heightMode == MeasureSpec.UNSPECIFIED) { width = widthSize; } setMeasuredDimension(width, width);//一个正方形的框 } /** * 和尺寸相关的 初始化都写在这个地方 * * @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 * ratioPieceOfLineHeight); 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_DOWN) { return true; } if (action == MotionEvent.ACTION_UP) { int x = (int) event.getX(); int y = (int) event.getY(); // Point p = new Point(x,y);// 一个合法的区域 Point p = getValidPoint(x, y); if (mWhiteArray.contains(p) || mBlackArray.contains(p)) { return false;///?????---------o 不处理这个事件,不添加,不显示子 } if (mIsWhite) { mWhiteArray.add(p); } else { mBlackArray.add(p); } invalidate(); mIsWhite = !mIsWhite; // return true;//ACTION_DOWN一定要标明自己的态度,自己对这个事件感兴趣 } 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); drawPieces(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_SHORT).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 =checkLeftDiagonal(x,y,points); if (win){ return true; } win =checkRightDiagonal(x,y,points); if (win){ return true; } } return false; } /** * 判断 横向 是否 5 个相连 每次只对当前落子的位置进行 判断,还不是很耗时 * @param x * @param y * @param points * @return */ private boolean checkHorizontal(int x, int y, List<Point> points) { int count = 1; for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){ if (points.contains(new Point(x-i,y))){ count++; }else { break; } } if (count ==MAX_COUNT_IN_LINE)return true; for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){ if (points.contains(new Point(x+i,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; //shang xia for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){ if (points.contains(new Point(x,y-i))){ count++; }else { break; } } if (count ==MAX_COUNT_IN_LINE)return true; for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){ if (points.contains(new Point(x,y+i))){ count++; }else { break; } } if (count ==MAX_COUNT_IN_LINE)return true; return false; } private boolean checkLeftDiagonal(int x, int y, List<Point> points) { int count = 1; //shang xia for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){ if (points.contains(new Point(x-i,y-i))){ count++; }else { break; } } if (count ==MAX_COUNT_IN_LINE)return true; for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){ if (points.contains(new Point(x+i,y+i))){ count++; }else { break; } } if (count ==MAX_COUNT_IN_LINE)return true; return false; } private boolean checkRightDiagonal(int x, int y, List<Point> points) { int count = 1; //shang xia for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){ if (points.contains(new Point(x-i,y+i))){ count++; }else { break; } } if (count ==MAX_COUNT_IN_LINE)return true; for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){ if (points.contains(new Point(x+i,y-i))){ count++; }else { break; } } if (count ==MAX_COUNT_IN_LINE)return true; return false; } /** * 绘制棋子 测试 要减2 不知道是 什么鬼 gety 和 getRawy. * * @param canvas */ private void drawPieces(Canvas canvas) { for (int i = 0, n = mWhiteArray.size(); i < n; i++) { Point whitePoint = mWhiteArray.get(i); Log.e("lc---",(whitePoint.y)+""); canvas.drawBitmap(mWhitePiece, (whitePoint.x + (1 - ratioPieceOfLineHeight) / 2) * mLineHeight, (whitePoint.y + (1 - ratioPieceOfLineHeight) / 2) * mLineHeight, null);//// TODO: 2016/6/13 -2 } for (int i = 0, n = mBlackArray.size(); i < n; i++) { Point blackPoint = mBlackArray.get(i); canvas.drawBitmap(mBlackPiece, (blackPoint.x + (1 - ratioPieceOfLineHeight) / 2) * mLineHeight, (blackPoint.y + (1 - ratioPieceOfLineHeight) / 2) * mLineHeight, null); } } private void drawBoard(Canvas canvas) { //上下各有 半个的 lineheight 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); } } private static final String INSTANCE ="instance"; private static final String INSTANCE_GAME_OVER ="instance_game_over"; private static final String INSTANCE_WHITE_ARRAY ="instance_white_array"; private static final String INSTANCE_BLACK_ARRAY="instance_black_array"; @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable(INSTANCE,super.onSaveInstanceState()); bundle.putBoolean(INSTANCE_GAME_OVER, mIsGameOver); bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY, mWhiteArray); bundle.putParcelableArrayList(INSTANCE_BLACK_ARRAY,mBlackArray); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle){ Bundle bundle = (Bundle) state; mIsGameOver = bundle.getBoolean(INSTANCE_GAME_OVER); mWhiteArray = bundle.getParcelableArrayList(INSTANCE_WHITE_ARRAY); mBlackArray = bundle.getParcelableArrayList(INSTANCE_BLACK_ARRAY); super.onRestoreInstanceState(bundle.getParcelable(INSTANCE));//// TODO: 2016/6/15 和 下边这句 super 不重复吗 return; } super.onRestoreInstanceState(state);//--- } public void start(){ mWhiteArray.clear(); mBlackArray.clear(); mIsGameOver = false; mIsWhiteWinner = false; invalidate(); }}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.andy.andy.myapplication" > <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
资源文件,drawable-hdpi
activity_main.xml 布局文件
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/backg" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <!--加上id才能保存状态信息--> <com.andy.andy.myapplication.WuziqiPannel android:id="@+id/wuziqi" android:layout_width="match_parent" android:layout_height="match_parent" android:text="Hello World!" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="重开一局" /></RelativeLayout>
好了没有什么遗漏了.
总结下 自定义view的 步骤 思路:
- 编写xml布局
- 初始化测量 onMeasure 方法, onSizeChange()方法–初始化尺寸,
- 初始化 棋盘
- onTouch时间处理 down 的时候返回ture,表示我对这个触摸事件感兴趣,我要处理
- 绘制旗子 –
- 逻辑判断.三点 1 gameover 和 一个位置不可重复放子.2 在某个范围内 都下在 网格中心点上
- view的存储and恢复
- 再来一局
- 其他 屏幕尺寸改变需要注意的事项
备注: 自定义view的思路完全是自上而下的
0 0
- 五子棋 手打稍加改变自慕课网hyman
- 五子棋禁手判定算法
- 五子棋的各种禁手
- 生成元 手打
- 五子棋算法--禁手的判断
- 汕头手打牛肉丸
- 仿照springmvc 手打框架
- C++ BigInt模板手打
- 真情2008 -- 童谣【手打转载】
- 单手打字
- 指针啊排序 手打娱乐
- C++手打游戏--<<贪吃蛇>>讲解
- 手打推导拉格朗日乘子算法Lagrange Multiplier
- Java入门自绘学习,五子棋
- 五子棋
- 五子棋
- 五子棋
- 五子棋
- Redis-server在windows下闪退
- Struts2+Spring3+Hibernate4+JavaEE6 配置
- Java中动态代理使用
- UITableView
- KNN算法在保险业精准营销中的应用
- 五子棋 手打稍加改变自慕课网hyman
- Oracle学习02【持续更新】
- LNMP环境一键安装
- 1021. 个位数统计 (15) PAT 乙级
- 怎么用dos的cmd命令行查看网络连接打开的端口及服务
- Android富文本编辑器总结(三)
- R语言的基本操作
- Python 文本挖掘:使用gensim进行文本相似度计算
- 快速排序