代码之家  ›  专栏  ›  技术社区  ›  Goku Farhana Naaz Ansari

如何在android平台上为tic-tac-toe游戏创建简单、中等和困难的关卡?

  •  0
  • Goku Farhana Naaz Ansari  · 技术社区  · 6 年前

    目前我正在用android开发井字游戏

    我成功地创建了游戏,但面临一些问题

    这是我迄今为止尝试过的代码

    这是我的板景

    public class BoardView extends View implements GestureDetector.OnGestureListener, ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
        private static final int STROKE_WIDTH = 10;
        private static final int SWEEPER_WIDTH = 20;
    
        private float[] gridLinePoints;
        private Paint gridPaint;
    
        private PointF[][] centerPoints;
        private Paint signPaint;
    
        private List<SignData> signDataList;
    
        private @Constants.WinLinePosition int winLinePosition;
        private Paint winLinePaint;
    
        private GestureDetector clickDetector;
        private OnBoardInteractionListener onBoardInteractionListener;
    
        private ValueAnimator clickAnimator;
        private ValueAnimator winLineAnimator;
        private ValueAnimator resetAnimator;
    
        private float signRadius;
        private float winLineLength;
        private float sweeperStartPosition;
    
        private Paint sweeperPaint;
        private int[] sweeperColors;
        private float[] sweeperStops;
    
        public BoardView(Context context) {
            super(context);
            init();
        }
    
        public BoardView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public BoardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        @TargetApi(Build.VERSION_CODES.M)
        private void init() {
            gridLinePoints = new float[16];
    
            centerPoints = new PointF[3][3];
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    centerPoints[i][j] = new PointF();
                }
            }
    
            signDataList = new ArrayList<>();
    
            winLinePosition = Constants.NONE;
    
            gridPaint = new Paint();
            gridPaint.setColor(getContext().getResources().getColor(R.color.holo_green_dark, null));
            gridPaint.setAntiAlias(true);
            gridPaint.setStrokeWidth(dpToPx(STROKE_WIDTH));
            gridPaint.setStrokeCap(Paint.Cap.ROUND);
    
            signPaint = new Paint();
            signPaint.setColor(getContext().getResources().getColor(R.color.holo_orange_dark, null));
            signPaint.setAntiAlias(true);
            signPaint.setStyle(Paint.Style.STROKE);
            signPaint.setStrokeWidth(dpToPx(STROKE_WIDTH));
            signPaint.setStrokeCap(Paint.Cap.ROUND);
    
            winLinePaint = new Paint();
            winLinePaint.setColor(getContext().getResources().getColor(R.color.holo_red_dark, null));
            winLinePaint.setAntiAlias(true);
            winLinePaint.setStrokeWidth(dpToPx(STROKE_WIDTH));
            winLinePaint.setStrokeCap(Paint.Cap.ROUND);
    
            clickDetector = new GestureDetector(getContext(), this);
    
            clickAnimator = new ValueAnimator();
            clickAnimator.setDuration(150);
            clickAnimator.setInterpolator(new DecelerateInterpolator());
            clickAnimator.addUpdateListener(this);
            clickAnimator.addListener(this);
    
            winLineAnimator = new ValueAnimator();
            winLineAnimator.setDuration(150);
            winLineAnimator.setInterpolator(new DecelerateInterpolator());
            winLineAnimator.addUpdateListener(this);
            winLineAnimator.addListener(this);
    
            resetAnimator = new ValueAnimator();
            resetAnimator.setDuration(500);
            resetAnimator.setInterpolator(new AccelerateInterpolator());
            resetAnimator.addUpdateListener(this);
            resetAnimator.addListener(this);
    
            sweeperPaint = new Paint();
            sweeperPaint.setAntiAlias(true);
            sweeperPaint.setStyle(Paint.Style.FILL);
    
            sweeperColors = new int[3];
            sweeperColors[0] = Color.parseColor("#0000DDFF");
            sweeperColors[1] = Color.parseColor("#FF00DDFF");
            sweeperColors[2] = Color.parseColor("#0000DDFF");
    
            sweeperStops = new float[3];
            sweeperStops[0] = 0;
            sweeperStops[1] = 0.5f;
            sweeperStops[2] = 1;
    
            setLayerType(LAYER_TYPE_SOFTWARE, sweeperPaint);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            getLayoutParams().height = getMeasuredWidth();
    
            setGridLinePoints();
            setCenterPoints();
            setAnimationValues();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            drawGrid(canvas);
            super.onDraw(canvas);
    
            if (resetAnimator.isRunning()) {
                canvas.clipRect(0, sweeperStartPosition, getMeasuredWidth(), getMeasuredWidth());
    
                setSweeperGradient();
                canvas.drawRect(0, sweeperStartPosition, getMeasuredWidth(), sweeperStartPosition + dpToPx(SWEEPER_WIDTH), sweeperPaint);
            }
    
            drawSigns(canvas);
            drawWinLine(canvas);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if ((!isEnabled()) || (clickAnimator.isRunning()) || (isAnimationFlagSet())) {
                return super.onTouchEvent(event);
            } else {
                return clickDetector.onTouchEvent(event);
            }
        }
    
        private boolean isAnimationFlagSet() {
            for (SignData signData : signDataList) {
                if (signData.isAnimationFlag()) {
                    return true;
                }
            }
            return false;
        }
    
        private void setGridLinePoints() {
            int side = getMeasuredWidth();
            float padding = dpToPx(STROKE_WIDTH / 2f);
    
            gridLinePoints[0] = gridLinePoints[4] = gridLinePoints[9] = gridLinePoints[13] = padding;
            gridLinePoints[1] = gridLinePoints[3] = gridLinePoints[8] = gridLinePoints[10] = side / 3f;
            gridLinePoints[2] = gridLinePoints[6] = gridLinePoints[11] = gridLinePoints[15] = side - padding;
            gridLinePoints[5] = gridLinePoints[7] = gridLinePoints[12] = gridLinePoints[14] = (2 * side) / 3f;
        }
    
        private void setCenterPoints() {
            float a = getMeasuredWidth() / 6f;
    
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    centerPoints[i][j].x = a + (j * (2 * a));
                    centerPoints[i][j].y = a + (i * (2 * a));
                }
            }
        }
    
        private void setAnimationValues() {
            clickAnimator.setFloatValues(0, (getMeasuredWidth() / 6f) - dpToPx(2 * STROKE_WIDTH));
            winLineAnimator.setFloatValues(0, getMeasuredWidth());
            resetAnimator.setFloatValues(-dpToPx(SWEEPER_WIDTH), getMeasuredWidth());
        }
    
        private void setSweeperGradient() {
            float axis = sweeperStartPosition + (dpToPx(SWEEPER_WIDTH / 2f));
    
            LinearGradient horizontalGradient = new LinearGradient(0, axis, getMeasuredWidth(), axis,
                    sweeperColors, sweeperStops, Shader.TileMode.CLAMP);
    
            LinearGradient verticalGradient = new LinearGradient(getMeasuredWidth() / 2f, sweeperStartPosition,
                    getMeasuredWidth() / 2f, sweeperStartPosition + dpToPx(SWEEPER_WIDTH), sweeperColors, sweeperStops,
                    Shader.TileMode.CLAMP);
    
            ComposeShader shader = new ComposeShader(horizontalGradient, verticalGradient, PorterDuff.Mode.MULTIPLY);
    
            sweeperPaint.setShader(shader);
        }
    
        private void drawGrid(Canvas canvas) {
            canvas.drawLines(gridLinePoints, gridPaint);
        }
    
        private void drawSigns(Canvas canvas) {
            for (int i = 0; i < signDataList.size(); i++) {
                SignData signData = signDataList.get(i);
    
                switch (signData.getSign()) {
                    case Constants.CIRCLE:
                        drawCircle(canvas, centerPoints[signData.getRow()][signData.getColumn()], signData.isAnimationFlag());
                        break;
                    case Constants.CROSS:
                        drawCross(canvas, centerPoints[signData.getRow()][signData.getColumn()], signData.isAnimationFlag());
                        break;
                    case Constants.EMPTY:
                        break;
                }
            }
        }
    
        private void drawCircle(Canvas canvas, PointF center, boolean animationFlag) {
            float radius = animationFlag ? signRadius : (getMeasuredWidth() / 6f) - dpToPx(2 * STROKE_WIDTH);
    
            canvas.drawCircle(center.x, center.y, radius, signPaint);
        }
    
        private void drawCross(Canvas canvas, PointF center, boolean animationFlag) {
            float radius = animationFlag ? signRadius : (getMeasuredWidth() / 6f) - dpToPx(2 * STROKE_WIDTH);
    
            canvas.drawLine(center.x - radius, center.y - radius, center.x + radius, center.y + radius, signPaint);
            canvas.drawLine(center.x - radius, center.y + radius, center.x + radius, center.y - radius, signPaint);
        }
    
        private void drawWinLine(Canvas canvas) {
            float length = winLineLength;
    
            float a = getMeasuredWidth() / 6f;
    
            float padding = dpToPx(STROKE_WIDTH);
    
            switch (winLinePosition) {
                case Constants.NONE:
                    break;
                case Constants.ROW_1:
                    canvas.drawLine(padding, a, length - padding, a, winLinePaint);
                    break;
                case Constants.ROW_2:
                    canvas.drawLine(padding, a + (2 * a), length - padding, a + (2 * a), winLinePaint);
                    break;
                case Constants.ROW_3:
                    canvas.drawLine(padding, a + (4 * a), length - padding, a + (4 * a), winLinePaint);
                    break;
                case Constants.COLUMN_1:
                    canvas.drawLine(a, padding, a, length - padding, winLinePaint);
                    break;
                case Constants.COLUMN_2:
                    canvas.drawLine(a + (2 * a), padding, a + (2 * a), length - padding, winLinePaint);
                    break;
                case Constants.COLUMN_3:
                    canvas.drawLine(a + (4 * a), padding, a + (4 * a), length - padding, winLinePaint);
                    break;
                case Constants.DIAGONAL_1:
                    canvas.drawLine(padding, padding, length - padding, length - padding, winLinePaint);
                    break;
                case Constants.DIAGONAL_2:
                    canvas.drawLine(getMeasuredWidth() - padding, padding, padding + getMeasuredWidth()
                            - length, length - padding, winLinePaint);
                    break;
            }
        }
    
        void addSignToBoard(@Constants.Sign int sign, int row, int column) {
            SignData signData = new SignData();
            signData.setSign(sign);
            signData.setRow(row);
            signData.setColumn(column);
            signData.setAnimationFlag(true);
    
            if (clickAnimator.isRunning()) {
                clickAnimator.end();
            }
    
            signDataList.add(signData);
            clickAnimator.start();
        }
    
        void showWinLine(@Constants.WinLinePosition int winLinePosition) {
            this.winLinePosition = winLinePosition;
    
            winLineAnimator.start();
        }
    
        void resetBoard() {
            if (!resetAnimator.isRunning()) {
                resetAnimator.start();
            }
        }
    
        boolean isAlreadyAdded(int row, int column) {
            for (int i = 0; i < signDataList.size(); i++) {
                SignData signData = signDataList.get(i);
    
                if ((signData.getRow() == row) && (signData.getColumn() == column)) {
                    return true;
                }
            }
    
            return false;
        }
    
        private float dpToPx(float dp) {
            return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
        }
    
        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }
    
        @Override
        public void onShowPress(MotionEvent e) {
    
        }
    
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            float x = e.getX();
            float y = e.getY();
    
            int row = detectIndexOfPartition(y);
            int column = detectIndexOfPartition(x);
    
            if ((row != -1) && (column != -1)) {
                onBoardInteractionListener.onBoardClick(BoardView.this, row, column);
            }
    
            return true;
        }
    
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return false;
        }
    
        @Override
        public void onLongPress(MotionEvent e) {
    
        }
    
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return false;
        }
    
        private int detectIndexOfPartition(float value) {
            float maxValue = getMeasuredWidth();
            float totalNumberOfPartitions = 3;
    
            float lengthOfSinglePartition = maxValue / totalNumberOfPartitions;
    
            return (int) (value / lengthOfSinglePartition);
        }
    
        public void setOnBoardInteractionListener(OnBoardInteractionListener onBoardInteractionListener) {
            this.onBoardInteractionListener = onBoardInteractionListener;
        }
    
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            if (animation == clickAnimator) {
                signRadius = (float) animation.getAnimatedValue();
            } else if (animation == winLineAnimator) {
                winLineLength = (float) animation.getAnimatedValue();
            } else if (animation == resetAnimator) {
                sweeperStartPosition = (float) animation.getAnimatedValue();
            }
            invalidate();
        }
    
        @Override
        public void onAnimationStart(Animator animation) {
    
        }
    
        @Override
        public void onAnimationEnd(Animator animation) {
            if (animation == clickAnimator) {
                SignData signData = signDataList.get(signDataList.size() - 1);
                signData.setAnimationFlag(false);
                onBoardInteractionListener.onSignAdded(signData.getSign(), signData.getRow(), signData.getColumn());
                signRadius = 0;
            } else if (animation == resetAnimator) {
                signDataList.clear();
                winLinePosition = Constants.NONE;
                onBoardInteractionListener.onBoardReset();
            }
        }
    
        @Override
        public void onAnimationCancel(Animator animation) {
    
        }
    
        @Override
        public void onAnimationRepeat(Animator animation) {
    
        }
    
        interface OnBoardInteractionListener {
    
            void onBoardClick(BoardView board, int row, int column);
    
            void onSignAdded(@Constants.Sign int sign, int row, int column);
    
            void onBoardReset();
        }
    
        private class SignData {
            private @Constants.Sign int sign;
            private int row;
            private int column;
            private boolean animationFlag;
    
            @Constants.Sign int getSign() {
                return sign;
            }
    
            void setSign(@Constants.Sign int sign) {
                this.sign = sign;
            }
    
            int getRow() {
                return row;
            }
    
            void setRow(int row) {
                this.row = row;
            }
    
            int getColumn() {
                return column;
            }
    
            void setColumn(int column) {
                this.column = column;
            }
    
            boolean isAnimationFlag() {
                return animationFlag;
            }
    
            void setAnimationFlag(boolean animationFlag) {
                this.animationFlag = animationFlag;
            }
        }
    }
    

    我的大脑课程

    class Brain {
        private static Brain INSTANCE;
    
        private @Constants.Sign
        int[][] board = new int[3][3];
    
        private int rowOfResult;
        private int columnOfResult;
    
        private int depth;
    
        private @Constants.Sign
        int computerSign;
        private @Constants.Sign
        int playerSign;
    
        private OnProcessCompleteListener onProcessCompleteListener;
    
        private static final int HORIZONTAL = 0;
        private static final int VERTICAL = 1;
        private static final int DIAGONAL = 2;
    
        @IntDef({HORIZONTAL, VERTICAL, DIAGONAL})
        @interface DirectionOfWinLine {
    
        }
    
        // References used by isWin function.
        private int[] winSequence = new int[3];
        private int[] row = new int[3];
        private int[] column = new int[3];
        private int[] diagonal1 = new int[3];
        private int[] diagonal2 = new int[3];
    
        private Brain() {
        }
    
        static Brain getInstance() {
            if (INSTANCE == null) {
                INSTANCE = new Brain();
            }
            return INSTANCE;
        }
    
        void play() {
            if (onProcessCompleteListener == null) {
                return;
            }
            calculateNextMove(computerSign, depth);
    
            onProcessCompleteListener.onNextMoveCalculated(rowOfResult, columnOfResult);
        }
    
        private int calculateNextMove(@Constants.Sign int sign, int depth) {
    
            if (isWin(computerSign, false)) {
                return 10 - depth;
            } else if (isWin(playerSign, false)) {
                return depth - 10;
            }
    
            if (depth >= 9) {
                return 0;
            }
    
            List<Integer> scores = new ArrayList<>(), rowIndices = new ArrayList<>(), columnIndices = new ArrayList<>();
    
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    if (board[i][j] == Constants.EMPTY) {
                        board[i][j] = sign;
                        scores.add(calculateNextMove(getOppositeSign(sign), depth + 1));
                        rowIndices.add(i);
                        columnIndices.add(j);
                        board[i][j] = Constants.EMPTY;
                    }
                }
            }
    
            if (sign == computerSign) {
                int maxScore = -100;
                for (int i = 0; i < scores.size(); i++) {
                    if (scores.get(i) > maxScore) {
                        maxScore = scores.get(i);
                    }
                }
                return randomizeScore(maxScore, scores, rowIndices, columnIndices);
    
            } else {
                int minScore = 100;
                for (int i = 0; i < scores.size(); i++) {
                    if (scores.get(i) < minScore) {
                        minScore = scores.get(i);
                    }
                }
                return randomizeScore(minScore, scores, rowIndices, columnIndices);
            }
        }
    
        private int randomizeScore(int score, List<Integer> scores, List<Integer> rowIndices, List<Integer> columnIndices) {
            List<Integer> equalScoreIndices = new ArrayList<>();
    
            for (int i = 0; i < scores.size(); i++) {
                if (scores.get(i) == score) {
                    equalScoreIndices.add(i);
                }
            }
    
            Random rand = new Random();
            int randomIndex = equalScoreIndices.get(rand.nextInt(equalScoreIndices.size()));
    
            rowOfResult = rowIndices.get(randomIndex);
            columnOfResult = columnIndices.get(randomIndex);
    
            return score;
        }
    
        private boolean isWin(@Constants.Sign int sign, boolean notifyWinEnabled) {
            for (int i = 0; i < 3; i++) {
                winSequence[i] = sign;
            }
    
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
    
                    if (i == j) {
                        diagonal1[i] = board[i][j];
                    }
                    if ((i + j) == 2) {
                        diagonal2[i] = board[i][j];
                    }
    
                    row[j] = board[i][j];
                    column[j] = board[j][i];
                }
    
                if (isEqual(row, winSequence)) {
                    if (notifyWinEnabled) {
                        notifyWin(sign, HORIZONTAL, i + 1);
                    }
                    return true;
                } else if (isEqual(column, winSequence)) {
                    if (notifyWinEnabled) {
                        notifyWin(sign, VERTICAL, i + 1);
                    }
                    return true;
                }
            }
    
            if (isEqual(diagonal1, winSequence)) {
                if (notifyWinEnabled) {
                    notifyWin(sign, DIAGONAL, 1);
                }
                return true;
            } else if (isEqual(diagonal2, winSequence)) {
                if (notifyWinEnabled) {
                    notifyWin(sign, DIAGONAL, 2);
                }
                return true;
            }
    
            return false;
        }
    
        private boolean isEqual(int[] x, int[] y) {
            for (int i = 0; i < 3; i++) {
                if (x[i] != y[i]) {
                    return false;
                }
            }
            return true;
        }
    
        void analyzeBoard() {
            if (onProcessCompleteListener == null) {
                return;
            }
    
            if ((!isWin(Constants.CIRCLE, true)) && (!isWin(Constants.CROSS, true)) && (depth >= 9)) {
                onProcessCompleteListener.onGameDraw();
            }
        }
    
        private void notifyWin(@Constants.Sign int sign, @DirectionOfWinLine int direction, int index) {
            if (onProcessCompleteListener == null) {
                return;
            }
    
            @Constants.WinLinePosition int winLinePosition = Constants.NONE;
    
            switch (direction) {
                case HORIZONTAL:
                    switch (index) {
                        case 1:
                            winLinePosition = Constants.ROW_1;
                            break;
                        case 2:
                            winLinePosition = Constants.ROW_2;
                            break;
                        case 3:
                            winLinePosition = Constants.ROW_3;
                            break;
                    }
                    break;
                case VERTICAL:
                    switch (index) {
                        case 1:
                            winLinePosition = Constants.COLUMN_1;
                            break;
                        case 2:
                            winLinePosition = Constants.COLUMN_2;
                            break;
                        case 3:
                            winLinePosition = Constants.COLUMN_3;
                            break;
                    }
                    break;
                case DIAGONAL:
                    switch (index) {
                        case 1:
                            winLinePosition = Constants.DIAGONAL_1;
                            break;
                        case 2:
                            winLinePosition = Constants.DIAGONAL_2;
                            break;
                    }
                    break;
            }
    
            onProcessCompleteListener.onGameWin(sign, winLinePosition);
        }
    
        void reset() {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    board[i][j] = Constants.EMPTY;
                }
            }
            depth = 0;
        }
    
        void setComputerSign(int computerSign) {
            this.computerSign = computerSign;
            playerSign = getOppositeSign(computerSign);
        }
    
        void updateBoard(@Constants.Sign int sign, int row, int column) {
            board[row][column] = sign;
            depth++;
        }
    
        private @Constants.Sign
        int getOppositeSign(@Constants.Sign int sign) {
            return sign == Constants.CIRCLE ? Constants.CROSS : Constants.CIRCLE;
        }
    
        void setOnProcessCompleteListener(OnProcessCompleteListener onProcessCompleteListener) {
            this.onProcessCompleteListener = onProcessCompleteListener;
        }
    
        interface OnProcessCompleteListener {
    
            void onNextMoveCalculated(int row, int column);
    
            void onGameWin(@Constants.Sign int sign, @Constants.WinLinePosition int winLinePosition);
    
            void onGameDraw();
        }
    
        void destroy() {
            INSTANCE = null;
        }
    }
    

    我已经为此创建了github repo,这里提供了所有代码

    https://github.com/SuperSaiyanGoku3/MyGame

    我在上面的代码中遇到了一些问题

    1. 上面的代码只支持硬层(不可能),如何在上面的游戏算法中再创建易中硬层的电脑(CPU)。
    2. 如何设置自定义图标而不是
    3. 如何在上面的代码中随机设置所有三种游戏模式,如易中硬级别,这样当用户启动游戏时,cpu会随机出现,枯萎易中硬。

    如果需要更多的信息请告诉我。提前谢谢。感谢您的努力。

    0 回复  |  直到 6 年前
        1
  •  4
  •   Stanley Ko    6 年前
    1. 实施难度: 对于支持简单和中等难度,我建议你只使用随机。你已经实现了困难的难度,所以你只需要做“错误”的较低难度的逻辑,这个错误可以随机实现。

      private void calculateNextMoveRandom() {
          Random rand = new Random();
      
          int randomRow;
          int randomColumn;
      
          while (true) {
              randomRow = rand.nextInt(3);
              randomColumn = rand.nextInt(3);
      
              if (Constants.EMPTY == board[randomRow][randomColumn]) {
                  rowOfResult = randomRow;
                  columnOfResult = randomColumn;
                  return;
              }
          }
      }
      


    位图标记: 你可以用 BitmapFactory.decodeResource() 在屏幕上绘制位图。

        private void drawCircle(Canvas canvas, PointF center, boolean animationFlag) {
            int iconSize = (int) LayoutUtil.getPixelFromDp(MARKER_SIZE, getContext());
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.android);
            Bitmap scaled = Bitmap.createScaledBitmap(bitmap, iconSize, iconSize, true);
            canvas.drawBitmap(scaled, center.x - (iconSize >> 1), center.y - (iconSize >> 1), signPaint);
        }
    


    三。 只是用随机设置难度。

        brain.setDifficulty(new Random().nextInt(3));
    

    这是我的请求:
    https://github.com/SuperSaiyanGoku3/MyGame/pull/1

    enter image description here

        2
  •  0
  •   Krishn Bera    6 年前

    如果您使用的是 minimax 策略玩井字游戏,你可以有多个开关情况,对应不同的难度水平在游戏中。最简单的方法是在minimax树中设置不同的深度阈值。例如,您可以将minimax游戏树展开到只有depth 2(假设为3*3 tic tac toe)的easy level,并说直到搜索树的末尾,以获得最高难度级别。您可以根据电路板大小和预期的难度设置此阈值。

    实现难度等级的另一种方法是通过实现不同的启发式函数来计算棋盘得分(对棋盘当前状态的一种良好度量)。您可以使用启发式函数,该函数根据您在行/列/对角线中占用的单元格数来计算单个行/列/对角线分数。例如,如果占用的单元格数为1,则score=x(x可以是任意数)。如果占用的单元格数为2,则得分=x^2,如果为3,则得分=x^3。然后将所有的分数相乘,得到每一行、每一列或每一对角线上的一个好的度量(或者你可以把它看作一个获胜的概率)。你可以为你的对手计算一个类似的分数,然后取一个差值来得到一个棋盘分数。因此,我们的想法是通过为每个难度级别设计不同的启发式函数来实现不同的方法来评估当前的电路板状态。一个糟糕的启发式函数将作为一个简单的水平,因为它将失去很多游戏,而一个适当设计的启发式将有一个不输的政策(它将最终赢得或画游戏)。

    为了在游戏的每次运行中随机选择一个难度等级,您可以使用随机数生成器来选择一个难度等级。可以将“0”分配为简单,“1”分配为中等,“2”分配为硬。您可以使用以下java函数来生成一个介于0和(n-1)之间的整数

    int random = Random.nextInt(n)

        3
  •  0
  •   akshay tilekar    6 年前

    Complete Tic Tac Toe with "n x n matrix"

    基本思想是我们只需要检查列/行/对角线元素是否相同。 用C#编写的代码,带有基本单元测试。