# Development of Gobang based on Android

## requirement analysis

1 chessboard and chess drawing
Make the rules of the game according to the rules of Gobang
3 mouse response in the game, you need to click the mouse to play chess
4. Game mode: duel between two players, which is the first and which is the second
5. The form and function of chess pieces are divided into black and white. Each side holds one piece. The chess pieces are matched by black and white
Finish the game of five consecutive beads by playing chess

## CheckWinner.java

```  package com.example.wuziqi;
import android.graphics.Point;
import java.util.List;
/**
* Created by Linux on 2016/4/8.
*/
public class CheckWinner {
private Point point1, point2;
private int checkModel = Constants.HORIZONTAL;
public boolean checkFiveInLineWinner(List<Point> points) {
for (Point point : points) {
int x = point.x;
int y = point.y;
if (checkHorizontal(x, y, points)) {
return true;
} else if (checkVertical(x, y, points)) {
return true;
} else if (checkLeftDiagonal(x, y, points)) {
return true;
} else if (checkRighttDiagonal(x, y, points)) {
return true;
}
}
return false;
}
private boolean check(int x, int y, List<Point> points, int checkOri) {
int count = 1;
for (int i = 1; i < Constants.MAX_COUNT_IN_LINE; i++) {
switch (checkOri) {
case Constants.HORIZONTAL:
point1 = new Point(x - i, y);
break;
case Constants.VERTICAL:
point1 = new Point(x, y - i);
break;
case Constants.LEFT_DIAGONAL:
point1 = new Point(x - i, y + i);
break;
case Constants.RIGHT_DIAGONAL:
point1 = new Point(x + i, y + i);
break;
}
if (points.contains(point1)) {
count++;
} else {
break;
}
}
for (int i = 1; i < Constants.MAX_COUNT_IN_LINE; i++) {
switch (checkOri) {
case Constants.HORIZONTAL:
point2 = new Point(x + i, y);
break;
case Constants.VERTICAL:
point2 = new Point(x, y + i);
break;
case Constants.LEFT_DIAGONAL:
point2 = new Point(x + i, y - i);
break;
case Constants.RIGHT_DIAGONAL:
point2 = new Point(x - i, y - i);
break;
}
if (points.contains(point2)) {
count++;
} else {
break;
}
}

if (count == Constants.MAX_COUNT_IN_LINE) {

return true;
}
return false;
}
// Horizontal judgement
private boolean checkHorizontal(int x, int y, List<Point> points) {
checkModel = Constants.HORIZONTAL;
return check(x, y, points, checkModel);
}

// Vertical judgement
private boolean checkVertical(int x, int y, List<Point> points) {
checkModel = Constants.VERTICAL;
return check(x, y, points, checkModel);
}

// Left oblique judgement
private boolean checkLeftDiagonal(int x, int y, List<Point> points) {
checkModel = Constants.LEFT_DIAGONAL;
return check(x, y, points, checkModel);
}

// Right skew judgement
private boolean checkRighttDiagonal(int x, int y, List<Point> points) {
checkModel = Constants.RIGHT_DIAGONAL;
return check(x, y, points, checkModel);
}

}
```

## ChessBoardView.java

```package com.example.wuziqi;

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.media.MediaPlayer;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import java.util.ArrayList;

public class ChessBoardView extends View {
// The width and length of the chessboard
private int mViewWidth;
// Length of each chessboard
private float maxLineHeight;
private Paint paint = new Paint();
// Define Bitmap of black and white chess pieces
private Bitmap mwhitePiece, mblackPiece;
private float ratioPieceOfLineHeight = 3 * 1.0f / 4;

// Judge whether the currently dropped pieces are white
private boolean mIsWhite = true;
// A list to record the location of black and white pieces
private ArrayList<Point> mwhiteArray = new ArrayList<>();
private ArrayList<Point> mblackArray = new ArrayList<>();

// Is the game over
private boolean mIsGameOver;
// The end of the game, whether it is a white square victory
private boolean mIsWhiteWinner;

public ChessBoardView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
paint.setColor(0x88000000);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);

mwhitePiece = BitmapFactory.decodeResource(getResources(), R.mipmap.stone_w2);
mblackPiece = BitmapFactory.decodeResource(getResources(), R.mipmap.stone_b1);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthModel = MeasureSpec.getMode(widthMeasureSpec);

int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightModel = MeasureSpec.getMode(heightMeasureSpec);

int width = Math.min(widthSize, heightSize);
if (widthModel == MeasureSpec.UNSPECIFIED) {
width = heightSize;
} else if (heightModel == MeasureSpec.UNSPECIFIED) {
width = widthSize;
}
setMeasuredDimension(width, width);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Draw the grid of chessboard
drawBoard(canvas);
// Black and white pieces for drawing chessboard
drawPieces(canvas);
// Check if the game is over
checkGameOver();
}
// Check if the game is over
private void checkGameOver() {
CheckWinner checkWinner = new CheckWinner();
boolean whiteWin = checkWinner.checkFiveInLineWinner(mwhiteArray);
boolean blackWin = checkWinner.checkFiveInLineWinner(mblackArray);
if (whiteWin || blackWin) {
mIsGameOver = true;
mIsWhiteWinner = whiteWin;
String text = mIsWhiteWinner ? "Victory in white chess" : "Black victory";
Toast.makeText(getContext(), text, Toast.LENGTH_SHORT).show();
}
}
// Draw pieces from an array of black and white pieces
private void drawPieces(Canvas canvas) {
for (int i = 0, n = mwhiteArray.size(); i < n; i++) {
Point whitePoint = mwhiteArray.get(i);
float left = (whitePoint.x + (1 - ratioPieceOfLineHeight) / 2) * maxLineHeight;
float top = (whitePoint.y + (1 - ratioPieceOfLineHeight) / 2) * maxLineHeight;
canvas.drawBitmap(mwhitePiece, left, top, null);
}
for (int i = 0, n = mblackArray.size(); i < n; i++) {
Point blackPoint = mblackArray.get(i);
float left = (blackPoint.x + (1 - ratioPieceOfLineHeight) / 2) * maxLineHeight;
float top = (blackPoint.y + (1 - ratioPieceOfLineHeight) / 2) * maxLineHeight;

canvas.drawBitmap(mblackPiece, left, top, null);
}
}
// Draw the net line of chessboard
private void drawBoard(Canvas canvas) {
int w = mViewWidth;
float lineHeight = maxLineHeight;
for (int i = 0; i < Constants.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);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mViewWidth = w;
maxLineHeight = mViewWidth * 1.0f / Constants.MAX_LINE;
int pieceWidth = (int) (maxLineHeight * 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_UP) {
int x = (int) event.getX();
int y = (int) event.getY();
Point point = getValidPoint(x, y);
if (mwhiteArray.contains(point) || mblackArray.contains(point)) {
return false;
}
if (mIsWhite) {
} else {
}
invalidate();
mIsWhite = !mIsWhite;
}
return true;
}
private Point getValidPoint(int x, int y) {
int validX = (int) (x / maxLineHeight);
int validY = (int) (y / maxLineHeight);
return new Point(validX, validY);
}
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_BLACK_ARRAY, mblackArray);
bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY, mwhiteArray);
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));
return;
}
super.onRestoreInstanceState(state);
}
// Another round.
public void start() {
mwhiteArray.clear();
mblackArray.clear();
mIsGameOver = false;
mIsWhiteWinner = false;
invalidate();
}
```

}

## Constants.java

``` package com.example.wuziqi;

/**
* Created by Linux on 2016/4/8.
*/
public class Constants {

// color ball
public final static int MAX_COUNT_IN_LINE = 5;
// Lines of chessboard
final static int MAX_LINE = 25;

// Direction of inspection
final static int HORIZONTAL = 0;
final static int VERTICAL = 1;
final static int LEFT_DIAGONAL = 2;
final static int RIGHT_DIAGONAL = 3;
}
```

## MainActivity.java

```package com.example.wuziqi;

import android.content.Intent;
import android.os.Bundle;

import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
private ChessBoardView chessBoardView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
chessBoardView = (ChessBoardView) findViewById(R.id.boardView);
}
public void doClick(View v) {
Intent intent = new Intent(MainActivity.this, MusicServer.class);
switch (v.getId()) {
case R.id.button1:
this.startService(intent);
break;
case R.id.button2:
this.stopService(intent);
break;
}
}
@Override
int id = item.getItemId();
// Another round.
if (id == R.id.action_setting) {
chessBoardView.start();
return true;
}
return super.onOptionsItemSelected(item);
}

@Override
return true;
}
```

}

## MusicServers.java

```package com.example.wuziqi;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.util.Log;
public class MusicServer extends Service {
private MediaPlayer mp;
public IBinder onBind(Intent intent) {
Log.e("Service", "onBind Be called");
mp.start();
return null;
}

public void onCreate() {
Log.e("Service", "onCreate Be called");
mp = MediaPlayer.create(this, R.raw.yinyue);
super.onCreate();
}

public void onDestroy() {
Log.e("Service", "onDestroy Be called");
mp.stop();
super.onDestroy();
}

public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("Service", "onStartCommand Be called");
mp.start();
return super.onStartCommand(intent, flags, startId);
}

public boolean onUnbind(Intent intent) {
Log.e("Service", "onUnbind Be called");
mp.stop();
return super.onUnbind(intent);
}
}
```

## AndroidManifest.xml

```<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.wuziqi">

<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">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

</activity>
<service
android:name=".MusicServer"
android:enabled="true"
android:exported="true"></service>
</application>
</manifest>
```

## 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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/bg1"
tools:context="com.example.wuziqi.MainActivity">

<com.example.wuziqi.ChessBoardView
android:id="@+id/boardView"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_centerHorizontal="true"
android:layout_marginTop="16dp"
android:onClick="doClick"
android:text="Opening music" />

<Button
android:id="@+id/button2"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/button1"
android:layout_alignStart="@+id/button1"
android:layout_marginStart="94dp"
android:layout_marginTop="-48dp"
android:onClick="doClick"
android:text="Stop music" />

</RelativeLayout>
```

```<?xml version="1.0" encoding="utf-8"?>
xmlns:android="http://schemas.android.com/apk/res/android">

<item android:id="@+id/action_setting"
android:title="Another round."
android:orderInCategory="100"
android:showAsAction="never"
tools:ignore="AppCompatResource" />
<item android:id="@+id/action_setting1"
android:title="Regret game"
android:orderInCategory="100"
android:showAsAction="never"
tools:ignore="AppCompatResource" />