日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux控制台单人五子棋简书,实现一个质量过硬五子棋

發布時間:2024/3/26 linux 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux控制台单人五子棋简书,实现一个质量过硬五子棋 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

測試棋力在相同配置下,初級水平基本相當于五子棋大師的特級大師水平。

一樓上圖:

主頁面.png

五子棋的引擎和自定義控件我封裝在lib中,可以通過

implementation 'win.regin:renju:1.0.0'來引用,而ndk的調用類Ai是用kotlin編寫的,上傳的時候傳不上去,做為一個jar包引用了。

五子棋自定義控件代碼,關鍵地方有注釋:

package win.regin.renju;

import android.annotation.SuppressLint;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Point;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import java.util.ArrayList;

import java.util.List;

/**

* @author :Reginer in 2018/7/9 20:00.

* 聯系方式:QQ:282921012

* 功能描述:

*/

public class RenjuView extends View {

/**

* 棋盤面板寬度

*/

private int mPanelWidth;

/**

* 棋盤每格的行高

*/

private float mLineHeight;

/**

* 棋盤尺寸

*/

private static final int MAX_LINE = 15;

/**

* 棋子占行高比例

*/

private float ratioPieceOfLineHeight = 0.9f;

private float startPos;

private float endPos;

/**

* 白棋數組

*/

private ArrayList mWhiteArray = new ArrayList<>();

/**

* 黑棋數組

*/

private ArrayList mBlackArray = new ArrayList<>();

/**

* 棋盤數組

*/

private ArrayList chessArray = new ArrayList<>();

private int[][] mBoard = new int[MAX_LINE][MAX_LINE];

/**

* 勝利玩家

*/

private int mWinner;

/**

* 連成五個的棋子

*/

private ArrayList fiveArray = new ArrayList<>();

/**

* 游戲是否結束

*/

private boolean mIsGameOver = false;

private int gameMode = RenjuConstant.HUMAN_COMPUTER;

/**

* 玩家以及AI得分紀錄

*/

private int userScore, aiScore;

/**

* 玩家執子

*/

private int userChess;

/**

* 當前回合是否輪到玩家

*/

private boolean isUserBout;

/**

* 顯示棋子編號

*/

private boolean isDrawChessNum = true;

private RenjuCallback callBack;

private Paint mPaint = new Paint();

private Bitmap mWhitePiece;

private Bitmap mBlackPiece;

private Point suggestPoint;

public RenjuView(Context context) {

this(context, null);

}

public RenjuView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public RenjuView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

mPaint.setColor(Color.BLACK);

//抗鋸齒

mPaint.setAntiAlias(true);

mPaint.setDither(true);

mPaint.setStyle(Paint.Style.STROKE);

mPaint.setTextSize(24);

mPaint.setTextAlign(Paint.Align.CENTER);

mWhitePiece = BitmapFactory.decodeResource(getResources(), R.drawable.ic_white_chess);

mBlackPiece = BitmapFactory.decodeResource(getResources(), R.drawable.ic_black_chess);

userScore = 0;

aiScore = 0;

start();

}

@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 measureSize = Math.min(widthSize, heightSize);

if (widthMode == MeasureSpec.UNSPECIFIED) {

measureSize = heightSize;

} else if (heightMode == MeasureSpec.UNSPECIFIED) {

measureSize = widthSize;

}

setMeasuredDimension(measureSize, measureSize);

}

@Override

protected void onSizeChanged(int w, int h, int oldW, int oldH) {

super.onSizeChanged(w, h, oldW, oldH);

mPanelWidth = w;

float outLine = 10.0f;

mLineHeight = (mPanelWidth * 1.0f - 2.0f * outLine) / MAX_LINE;

startPos = outLine;

endPos = w - outLine;

int pieceSize = (int) (mLineHeight * ratioPieceOfLineHeight);

mWhitePiece = Bitmap.createScaledBitmap(mWhitePiece, pieceSize, pieceSize, false);

mBlackPiece = Bitmap.createScaledBitmap(mBlackPiece, pieceSize, pieceSize, false);

}

private Point getValidPoint(int x, int y) {

return new Point((int) (x / mLineHeight), (int) (y / mLineHeight));

}

public int getChessCount() {

return chessArray.size();

}

public void removeLastChess() {

Point p = chessArray.get(chessArray.size() - 1);

chessArray.remove(chessArray.size() - 1);

if (mBoard[p.y][p.x] == RenjuConstant.BLACK_CHESS) {

mBlackArray.remove(mBlackArray.size() - 1);

} else if (mBoard[p.y][p.x] == RenjuConstant.WHITE_CHESS) {

mWhiteArray.remove(mWhiteArray.size() - 1);

}

mBoard[p.y][p.x] = RenjuConstant.N0_CHESS;

}

public void undo() {

final int canUndoSize = 2;

if (chessArray.size() >= canUndoSize) {

mIsGameOver = false;

suggestPoint = null;

removeLastChess();

removeLastChess();

}

postInvalidate();

}

@SuppressLint("ClickableViewAccessibility")

@Override

public boolean onTouchEvent(MotionEvent event) {

if (mIsGameOver || !isUserBout) {

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 = getValidPoint(x, y);

if (mWhiteArray.contains(p) || mBlackArray.contains(p)) {

return false;

}

suggestPoint = null;

addChess(p, userChess);

setUserBout(!isHumanComputer());

if (!isHumanComputer()) {

userChess = (userChess == RenjuConstant.WHITE_CHESS) ? RenjuConstant.BLACK_CHESS : RenjuConstant.WHITE_CHESS;

}

checkGameOver();

invalidate();

if (!mIsGameOver) {

callBack.atBell(p, false, isUserBlack());

}

return true;

}

return super.onTouchEvent(event);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

drawBoard(canvas);

drawPiece(canvas);

}

public void addChess(Point point, int chessType) {

mBoard[point.y][point.x] = chessType;

chessArray.add(point);

if (chessType == RenjuConstant.BLACK_CHESS) {

mBlackArray.add(point);

} else if (chessType == RenjuConstant.WHITE_CHESS) {

mWhiteArray.add(point);

}

invalidate();

}

public void setGameMode(int gameMode) {

this.gameMode = gameMode;

}

public int getGameMode() {

return gameMode;

}

public void checkGameOver() {

boolean blackWin = checkFiveInLine(mBlackArray);

boolean whiteWin = !blackWin && checkFiveInLine(mWhiteArray);

if (whiteWin || blackWin) {

mIsGameOver = true;

mWinner = whiteWin ? RenjuConstant.WHITE_CHESS : RenjuConstant.BLACK_CHESS;

if (mWinner == userChess) {

userScore++;

} else {

aiScore++;

}

callBack.gameOver(mWinner);

invalidate();

} else if (isFull()) {

mIsGameOver = true;

mWinner = RenjuConstant.N0_CHESS;

callBack.gameOver(mWinner);

invalidate();

}

}

public boolean checkFiveInLine(List points) {

List dirArray = new ArrayList<>();

dirArray.add(new Point(1, 0));

dirArray.add(new Point(0, 1));

dirArray.add(new Point(1, 1));

dirArray.add(new Point(1, -1));

for (Point p : points) {

for (Point dir : dirArray) {

if (checkFiveOneLine(dir, p.x, p.y, points)) {

return true;

}

}

}

return false;

}

/**

* 檢查棋子在某個方向是否已經連五

*

* @param dir dir

* @param x x

* @param y y

* @param points points

* @return 勝利

*/

public boolean checkFiveOneLine(Point dir, int x, int y, List points) {

int count = 1;

fiveArray.clear();

fiveArray.add(new Point(x, y));

final int successSize = 5;

for (int i = 1; i < successSize; i++) {

Point p = new Point(x + dir.x * i, y + dir.y * i);

if (points.contains(p)) {

fiveArray.add(p);

count++;

} else {

break;

}

}

for (int i = 1; i < successSize; i++) {

Point p = new Point(x - dir.x * i, y - dir.y * i);

if (points.contains(p)) {

fiveArray.add(p);

count++;

} else {

break;

}

}

return count >= 5;

}

private void drawPiece(Canvas canvas) {

mPaint.setStrokeWidth(2.0f);

mPaint.setTextSize(24);

Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();

for (int i = 0; i < mWhiteArray.size(); i++) {

Point whitePoint = mWhiteArray.get(i);

float left = startPos + (whitePoint.x + (1 - ratioPieceOfLineHeight) / 2) * mLineHeight;

float top = startPos + (whitePoint.y + (1 - ratioPieceOfLineHeight) / 2) * mLineHeight;

canvas.drawBitmap(mWhitePiece, left, top, null);

if (isDrawChessNum) {

mPaint.setColor(Color.BLACK);

float textTop = startPos + whitePoint.y * mLineHeight;

float textBottom = textTop + mLineHeight;

float baseline = (textTop + textBottom - fontMetrics.ascent - fontMetrics.descent) / 2;

float centerX = startPos + (whitePoint.x + 0.5f) * mLineHeight;

canvas.drawText(String.format("%S", 2 + i * 2), centerX, baseline, mPaint);

}

}

for (int i = 0; i < mBlackArray.size(); i++) {

Point blackPoint = mBlackArray.get(i);

float left = startPos + (blackPoint.x + (1 - ratioPieceOfLineHeight) / 2) * mLineHeight;

float top = startPos + (blackPoint.y + (1 - ratioPieceOfLineHeight) / 2) * mLineHeight;

canvas.drawBitmap(mBlackPiece, left, top, null);

if (isDrawChessNum) {

mPaint.setColor(Color.WHITE);

float textTop = startPos + blackPoint.y * mLineHeight;

float textBottom = textTop + mLineHeight;

float baseline = (textTop + textBottom - fontMetrics.ascent - fontMetrics.descent) / 2;

float centerX = startPos + (blackPoint.x + 0.5f) * mLineHeight;

canvas.drawText(String.format("%S", 1 + i * 2), centerX, baseline, mPaint);

}

}

}

private void drawBoard(Canvas canvas) {

mPaint.setColor(Color.BLACK);

mPaint.setStrokeWidth(2.0f);

int w = mPanelWidth;

float lineHeight = mLineHeight;

//畫棋盤線

for (int i = 0; i < MAX_LINE; i++) {

int startX = (int) (startPos + lineHeight / 2);

int endX = (int) (endPos - lineHeight / 2);

int y = (int) (startPos + (0.5 + i) * lineHeight);

canvas.drawLine(startX, y, endX, y, mPaint);

}

for (int i = 0; i < MAX_LINE; i++) {

int startY = (int) (startPos + lineHeight / 2);

int endY = (int) (endPos - lineHeight / 2);

int x = (int) (startPos + (0.5 + i) * lineHeight);

canvas.drawLine(x, startY, x, endY, mPaint);

}

//畫棋盤坐標

mPaint.setTextSize(20);

mPaint.setStrokeWidth(1.7f);

Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();

for (int i = 0; i < MAX_LINE; i++) {

float y = startPos + (0.5f + i) * lineHeight;

float textTop = y - 0.5f * mLineHeight;

float textBottom = y + 0.5f * mLineHeight;

float baseline = (textTop + textBottom - fontMetrics.ascent - fontMetrics.descent) / 2;

float x = 12;

canvas.drawText(String.format("%S", MAX_LINE - i), x, baseline, mPaint);

}

for (int i = 0; i < MAX_LINE; i++) {

float y = w - 12;

float textTop = y - 0.5f * mLineHeight;

float textBottom = y + 0.5f * mLineHeight;

float baseline = (textTop + textBottom - fontMetrics.ascent - fontMetrics.descent) / 2;

float x = startPos + (0.5f + i) * lineHeight;

String text = String.valueOf((char) ('A' + i));

canvas.drawText(text, x, baseline, mPaint);

}

//棋盤邊緣線

mPaint.setStrokeWidth(4.0f);

int min = (int) lineHeight / 2 + 4, max = w - min;

canvas.drawLine(min - 2, min, max + 2, min, mPaint);

canvas.drawLine(min - 2, max, max + 2, max, mPaint);

canvas.drawLine(min, min, min, max, mPaint);

canvas.drawLine(max, min, max, max, mPaint);

//畫五個小黑點

mPaint.setStrokeWidth(8f);

final float startSize = 3.5f;

final float endSize = MAX_LINE - 3.5f;

final float middleSize = MAX_LINE / 2f;

//左上

canvas.drawCircle(startPos + startSize * lineHeight, startPos + startSize * lineHeight, 5, mPaint);

//右上

canvas.drawCircle(startPos + endSize * lineHeight, startPos + startSize * lineHeight, 5, mPaint);

//左下

canvas.drawCircle(startPos + startSize * lineHeight, startPos + endSize * lineHeight, 5, mPaint);

//右下

canvas.drawCircle(startPos + endSize * lineHeight, startPos + endSize * lineHeight, 5, mPaint);

//中間

canvas.drawCircle(startPos + middleSize * lineHeight, startPos + middleSize * lineHeight, 5, mPaint);

mPaint.setColor(Color.GREEN);

mPaint.setStrokeWidth(4.0f);

if (!mIsGameOver) {

//標識最后一子

if (chessArray.size() > 0) {

drawCircle(canvas, chessArray.get(chessArray.size() - 1));

}

//標識建議位置

if (suggestPoint != null) {

mPaint.setColor(Color.GRAY);

drawCircle(canvas, suggestPoint);

}

} else {

//標識連五

for (Point point : fiveArray) {

drawCircle(canvas, point);

}

}

}

public void drawCircle(Canvas canvas, Point point) {

float cx = startPos + (0.5f + point.x) * mLineHeight;

float cy = startPos + (0.5f + point.y) * mLineHeight;

float radius = ratioPieceOfLineHeight * mLineHeight / 2;

canvas.drawCircle(cx, cy, radius, mPaint);

}

public void showSuggest(Point point) {

this.suggestPoint = point;

postInvalidate();

}

public void showChessNum() {

isDrawChessNum = !isDrawChessNum;

postInvalidate();

}

public void start() {

for (int i = 0; i < MAX_LINE; i++) {

for (int j = 0; j < MAX_LINE; j++) {

mBoard[i][j] = 0;

}

}

mBlackArray.clear();

mWhiteArray.clear();

chessArray.clear();

suggestPoint = null;

mIsGameOver = false;

mWinner = 0;

userChess = RenjuConstant.BLACK_CHESS;

invalidate();

}

public boolean isFull() {

for (int i = 0; i < MAX_LINE; i++) {

for (int j = 0; j < MAX_LINE; j++) {

if (mBoard[i][j] == RenjuConstant.N0_CHESS) {

return false;

}

}

}

return true;

}

public void setUserChess(int userChess) {

this.userChess = userChess;

}

public void setUserBout(boolean userBout) {

isUserBout = userBout;

}

public void setCallBack(RenjuCallback callBack) {

this.callBack = callBack;

}

public int getUserScore() {

return userScore;

}

public int getAiScore() {

return aiScore;

}

public boolean isGameOver() {

return mIsGameOver;

}

public int getUserChess() {

return userChess;

}

/**

* 玩家是否執黑

*

* @return boolean

*/

public boolean isUserBlack() {

return userChess == (isHumanComputer() ? RenjuConstant.BLACK_CHESS : RenjuConstant.WHITE_CHESS);

}

/**

* 是否人機

*

* @return 人機

*/

public boolean isHumanComputer() {

return gameMode == RenjuConstant.HUMAN_COMPUTER;

}

}

主要都在onDraw方法中:

坐標.png

棋盤線和小黑點.png

用約束布局布置頁面:

布局頁面.png

Ai實現類代碼,也就是jar包代碼,如果需要定制,可修改方法的訪問修飾符:

package win.regin.renju

import android.graphics.Point

import kotlinx.coroutines.experimental.android.UI

import kotlinx.coroutines.experimental.launch

/**

* @author :Reginer in 2018/7/9 20:07.

* 聯系方式:QQ:282921012

* 功能描述:五子棋ai

*/

class Ai(private val callBack: RenjuCallback) {

var aiChess: Int = RenjuConstant.N0_CHESS

private val aiObject: Long

private var lastPoint: Point? = null

private val timeMap = arrayListOf(2000, 5000, 10000, 30000, 60000)

/**

* ai是否正在思考

*/

var isAiThing = false

/**

* 獲取ai

*/

private external fun getAiObject(): Long

/**

* 思考最佳點

*/

private external fun getBestPoint(aiObject: Long, move: Int): Int

/**

* 重新開始

*/

private external fun aiRestart(aiObject: Long)

/**

* 悔棋

*/

private external fun aiUndo(aiObject: Long)

/**

* 玩家下一子

*/

private external fun aiMove(aiObject: Long, move: Int)

/**

* 思考結束時間

*/

private external fun setStepTime(aiObject: Long, time: Int)

/**

* 提示

*/

private external fun getSuggest(aiObject: Long): Int

init {

this.aiObject = getAiObject()

}

/**

* 當前回合輪到AI

*

* @param p p

*/

fun aiBout(p: Point?) {

launch {

isAiThing = true

lastPoint = p

val lastMove: Int = if (null == lastPoint) {

-1

} else {

lastPoint!!.x * 16 + lastPoint!!.y

}

val best = getBestPoint(aiObject, lastMove)

val bestPoint = Point(getPointX(best), getPointY(best))

launch(UI) {

callBack.atBell(bestPoint, true, aiChess == RenjuConstant.BLACK_CHESS)

isAiThing = false

}

}

}

fun addChess(p: Point) {

lastPoint = p

aiMove(aiObject, p.x * 16 + p.y)

}

/**

* AI建議

*

* @return Point

*/

fun suggest(): Point {

isAiThing = true

val p = getSuggest(aiObject)

isAiThing = false

return Point(getPointX(p), getPointY(p))

}

fun restart() {

isAiThing = true

aiRestart(aiObject)

isAiThing = false

}

fun undo() {

isAiThing = true

aiUndo(aiObject)

isAiThing = false

}

/**

* 設置級別

* @param level 0初級 1中級 2高級 3大師 4特大

*/

fun setLevel(level: Int) {

isAiThing = true

setStepTime(aiObject, timeMap[level])

isAiThing = false

}

/**

* 獲取玩家執子

*/

fun getUserChess(): Int {

return if (aiChess == RenjuConstant.WHITE_CHESS) RenjuConstant.BLACK_CHESS else RenjuConstant.WHITE_CHESS

}

private fun getPointX(p: Int): Int {

return p shr 4

}

private fun getPointY(p: Int): Int {

return p and 15

}

companion object {

init {

System.loadLibrary("renju-lib")

}

}

}

下面開始擼代碼:

進入頁面選擇執子:

/**

* 初始化PopWindow

*

* @param width 寬度

* @param height 高度

*/

private fun initPop(width: Int, height: Int) {

if (mChooseChess == null) {

val view = View.inflate(this, R.layout.view_pop_choose_chess, null)

val white = view.findViewById(R.id.choose_white)

val black = view.findViewById(R.id.choose_black)

white.setOnClickListener {

SoundPlayUtils.play(HintConstant.GAME_START)

rvRenju.setUserBout(false)

rvRenju.userChess = RenjuConstant.WHITE_CHESS

mAi.aiChess = RenjuConstant.BLACK_CHESS

aiThink(null)

mChooseChess?.dismiss()

}

black.setOnClickListener {

SoundPlayUtils.play(HintConstant.GAME_START)

rvRenju.setUserBout(true)

rvRenju.userChess = RenjuConstant.BLACK_CHESS

mAi.aiChess = RenjuConstant.WHITE_CHESS

mChooseChess?.dismiss()

}

mChooseChess = PopupWindow(view, width, height)

mChooseChess?.isOutsideTouchable = false

mChooseChess?.showAtLocation(rvRenju, Gravity.CENTER, 0, 0)

}

}

落子:

override fun atBell(p0: Point, isAi: Boolean, isBlack: Boolean) {

imgFlag.setImageResource(if (isBlack) R.drawable.ic_white_chess

else R.drawable.ic_black_chess)

SoundPlayUtils.play(HintConstant.GAME_MOVE)

if (isAi) aiAtBell(p0) else userAtBell(p0)

}

/**

* ai落子

*/

private fun aiAtBell(p: Point?) {

rvRenju.addChess(p, mAi.aiChess)

rvRenju.setUserBout(true)

rvRenju.checkGameOver()

}

/**

* 玩家落子

*/

private fun userAtBell(p: Point) {

if (rvRenju.isHumanComputer) aiThink(p) else mAi.addChess(p)

}

新局:

newRenju -> {

if (rvRenju.isHumanComputer) {

mChooseChess?.showAtLocation(rvRenju, Gravity.CENTER, 0, 0)

}

mAi.restart()

rvRenju.start()

}

悔棋:

undo -> {

if (rvRenju.chessCount >= 2) {

mAi.undo()

rvRenju.undo()

}

}

Ai級別:

level -> {

var levelPosition = SpUtils[RenjuConstant.RENJU_LEVEL, 0] as Int

levelPosition = if (levelPosition < 4) levelPosition + 1 else 0

level.text = resources.getStringArray(R.array.renju_level)[levelPosition]

SpUtils.put(RenjuConstant.RENJU_LEVEL,levelPosition)

mAi.setLevel(levelPosition)

}

提示:

suggest -> {

if (!rvRenju.isGameOver) {

rvRenju.setUserBout(false)

launch {

val suggestPoint = mAi.suggest()

launch(UI) {

rvRenju.setUserBout(true)

rvRenju.showSuggest(suggestPoint)

}

}

}

}

模式:人機、人人:

mode -> {

if (TextUtils.equals(mode.text.toString(), getString(R.string.human_human))) {

mode.text = getString(R.string.human_computer)

rvRenju.gameMode = RenjuConstant.HUMAN_COMPUTER

mAi.aiChess = rvRenju.userChess

rvRenju.userChess = mAi.getUserChess()

rvRenju.setUserBout(false)

aiThink(null)

} else {

mode.text = getString(R.string.human_human)

rvRenju.gameMode = RenjuConstant.HUMAN_HUMAN

}

}

游戲結束:

override fun gameOver(winner: Int) {

SoundPlayUtils.play(HintConstant.GAME_OVER)

toast(

when (winner) {

RenjuConstant.BLACK_CHESS -> R.string.black_win

RenjuConstant.WHITE_CHESS -> R.string.white_win

else -> R.string.no_win

})

}

總結

以上是生活随笔為你收集整理的linux控制台单人五子棋简书,实现一个质量过硬五子棋的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。