五子棋的的制作主要是练习自定义View,看慕课网上的视屏做了个简单的五子棋。----------欢迎指出问题
自定义View(主要是对棋盘的绘制,设置点击事件绘制棋子)
先在onMeasure()方法里获得设置自定义view的宽高,在onSizeChanged()中获得有效宽度并设置棋子大小使棋子适应棋盘,通过设置棋盘的行数MAX_LINE与有效宽度获得行高,在onDraw()方法里通过画笔绘制棋盘,每次重绘时判断是否玩家胜利,在onTouchEvent()方法中设置点击事件通过记录在棋盘上绘制棋子,设置自定义方法startGame()清空棋子重新开始游戏。
<span style="font-size:18px;">public class MyView extends View {
private int mWidth;
private double mLineHeight;
private int MAX_LINE=10;
private Paint paint=new Paint();
private boolean gameOver=false;
private Bitmap mWhite;
private Bitmap mBlack;
private Boolean isWhite=true;
private List<Point> mWhiteList=new ArrayList<Point>();
private List<Point> mBlackList=new ArrayList<Point>();
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context) {
super(context);
init();
}
/**
* 设置行列数
* @param MAX_LINE
*/
public void setMAX_LINE(int MAX_LINE){
this.MAX_LINE=MAX_LINE;
}
/**
* 初始化画笔及棋子
*/
private void init() {
paint.setColor(Color.WHITE);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
mWhite= BitmapFactory.decodeResource(getResources(),R.drawable.stone_w2);
mBlack= BitmapFactory.decodeResource(getResources(),R.drawable.stone_b1);
}
@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);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth=w;
mLineHeight=mWidth*1.0/MAX_LINE;
int pieceWidth= (int) (mLineHeight*3.0/4);
mWhite=Bitmap.createScaledBitmap(mWhite,pieceWidth,pieceWidth,false);
mBlack=Bitmap.createScaledBitmap(mBlack,pieceWidth,pieceWidth,false);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(gameOver) return false;
int action=event.getAction();
if(action==MotionEvent.ACTION_UP){
int x= (int) event.getX();
int y= (int) event.getY();
Point p=getPoint(x,y);
if(mWhiteList.contains(p)||mBlackList.contains(p)){
return false;
}
if(isWhite){
mWhiteList.add(p);
}
else{
mBlackList.add(p);
}
isWhite=!isWhite;
}
invalidate();
return true;
}
private Point getPoint(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);
if(IsWin.isWin(mWhiteList)){
Toast.makeText(getContext(),"White Win",Toast.LENGTH_SHORT).show();
gameOver=true;
}
if(IsWin.isWin(mBlackList)){
Toast.makeText(getContext(),"Black Win",Toast.LENGTH_SHORT).show();
gameOver=true;
}
}
/**
* 绘制已有棋子
* @param canvas
*/
private void drawPieces(Canvas canvas) {
for(int i=0;i<mWhiteList.size();i++){
Point p=mWhiteList.get(i);
canvas.drawBitmap( mWhite,(float) ((p.x+(1-3.0/4)/2)*mLineHeight),(float) ((p.y+(1-3.0/4)/2)*mLineHeight),null);
}
for(int i=0;i<mBlackList.size();i++){
Point p=mBlackList.get(i);
canvas.drawBitmap( mBlack,(float) ((p.x+(1-3.0/4)/2)*mLineHeight),(float) ((p.y+(1-3.0/4)/2)*mLineHeight),null);
}
}
/**
* 绘制棋盘
* @param canvas
*/
private void drawBoard(Canvas canvas) {
int w=mWidth;
double 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,paint);
canvas.drawLine(y,startX,y,endX,paint);
}
}
/**
* 使用List的removeAll(Collection collection)方法移除mWhiteList和mBlackList所有元素,然后完成重绘
* (removeAll(Collection collection)方法意思为移除List中collection中的所有相同元素--所以我们把他
* 自身放入后就是移除该List中的所有元素了)
*/
protected void startGame(){
mWhiteList.removeAll(mWhiteList);
mBlackList.removeAll(mBlackList);
gameOver=false;
invalidate();
}
}</span>
<span style="font-size:18px;"><strong>
</strong></span>
<span style="font-size:18px;"><strong>activity代码</strong></span>
<span style="font-size:18px;"></span><pre name="code" class="java">public class MainActivity extends AppCompatActivity {
private Button restart;
private MyView borad;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
blind();
restartLinstener();
}
private void blind(){
restart=(Button)findViewById(R.id.restart);
borad=(MyView)findViewById(R.id.borad);
}
/**
<span style="font-family: Arial, Helvetica, sans-serif;">*调用View里的方法清空棋盘并重绘</span>
<span style="font-family: Arial, Helvetica, sans-serif;"> */</span>
private void restartLinstener(){
restart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
borad.startGame();
}
});
}
}
判断是否胜利类(传入所有棋子位置,主要判断四个方向上是否存在五个连续的棋子,主要算法思想--判断每个棋子在一方向上的连续棋子数是否够5个 )
<span style="font-size:18px;"></span><pre name="code" class="java">public class IsWin {
public static boolean isWin(List<Point> list){
for(int i=0;i<list.size();i++){
if(isCenterWin(list.get(i).x,list.get(i).y,list)){
return true;
}
}
for(int i=0;i<list.size();i++){
if(isVertialWin(list.get(i).x,list.get(i).y,list)){
return true;
}
}
for(int i=0;i<list.size();i++){
if(isRightWin(list.get(i).x,list.get(i).y,list)){
return true;
}
}
for(int i=0;i<list.size();i++){
if(isLeftWin(list.get(i).x,list.get(i).y,list)){
return true;
}
}
return false;
}
public static boolean isCenterWin(int x,int y,List<Point> list){
int count=1;
for(int i=1;i<5;i++){
if(list.contains(new Point(x+i,y))){
count++;
}
else{
break;
}
}
for(int i=1;i<5;i++){
if(list.contains(new Point(x-i,y))){
count++;
}
else{
break;
}
}
if(count==5){
return true;
}
return false;
}
public static boolean isVertialWin(int x,int y,List<Point> list){
int count=1;
for(int i=1;i<5;i++){
if(list.contains(new Point(x,y+i))){
count++;
}
else{
break;
}
}
for(int i=1;i<5;i++){
if(list.contains(new Point(x,y-i))){
count++;
}
else{
break;
}
}
if(count==5){
return true;
}
return false;
}
public static boolean isRightWin(int x,int y,List<Point> list){
int count=1;
for(int i=1;i<5;i++){
if(list.contains(new Point(x-i,y+i))){
count++;
}
else{
break;
}
}
for(int i=1;i<5;i++){
if(list.contains(new Point(x+i,y-i))){
count++;
}
else{
break;
}
}
if(count==5){
return true;
}
return false;
}
public static boolean isLeftWin(int x,int y,List<Point> list){
int count=1;
for(int i=1;i<5;i++){
if(list.contains(new Point(x+i,y+i))){
count++;
}
else{
break;
}
}
for(int i=1;i<5;i++){
if(list.contains(new Point(x-i,y-i))){
count++;
}
else{
break;
}
}
if(count==5){
return true;
}
return false;
}
}
五子棋源码