接続n時間!


20

https://en.wikipedia.org/wiki/Connect_Four

2プレイヤーゲーム接続4を覚えている人はいますか?そうでない人にとっては、表面に垂直に立っている6x7のボードでした。接続4の目標は、接続4です!接続は、水平、斜め、または垂直の場合にカウントされます。ピースをボードの上部に置くには、ピースをその列の一番下に落ちるようにボードの上部に置きます。ルールは、コネクト4で3つのことを変更します。

  • 変更#1の勝ちは、最も多くのポイントを持つプレーヤーとして定義されます。ルールのように4をつなげることでポイントを獲得します-それについては後で詳しく説明します。
  • 変更#2各ラウンドに3人のプレイヤーがいます。
  • 変更#3ボードサイズは9x9です。

得点:

スコアは、連続して取得する数に基づいています。行グループに4がある場合、1ポイントを獲得します。行グループに5がある場合、2ポイント、行3に6などが続きます。

例:

注意ox置き換えられます#し、~より良好なコントラストのために、それぞれ

空のボードの例:(すべての例は2プレーヤーの標準サイズのボードです)

   a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | | | | | | |
1 |_|_|_|_|_|_|_|

coll dにピースをドロップすると、その場所に着陸します1d

   a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | | | | | | |
1 |_|_|_|#|_|_|_|

dここで再びcollにピースをドロップすると、locationに着陸します2d。行の位置に4つの例を示します。

   a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | |~| | | |
3 | | |~|#| | | |
2 | |~|#|~| |#| |
1 |~|#|~|#|_|#|_|

この場合、x斜めに1ポイント(1a 2b 3c 4d)を取得します。

  a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | |#| | | |
3 | | | |#| | | |
2 | | | |#| | | |
1 |_|~|_|#|~|_|~|

この場合、o垂直に1ポイントを取得します(1d 2d 3d 4d)。

   a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | |#|#|#|#| |
1 |_|_|~|~|~|~|~|

この場合、o水平に2ポイント(1c 1d 1e 1f 1g)をx取得し、水平に1ポイント()を取得し2c 2d 2e 2fます。

   a b c d e f g
6 | | |#| | | | |
5 | | |#| | | | |
4 | | |#| | | | |
3 | | |#| | |~| |
2 |~| |#| | |#|~|
1 |~|_|#|~| |~|~|

今回xは、6連続で3ポイントを獲得し1c 2c 3c 4c 5c 6cます()。

入出力

2Dアレイを介してボードにアクセスできます。各場所はint、プレーヤーIDを表すことで表されます。また、プレーヤーIDを関数に渡します。作品をドロップしたいコラージュを返すことで、あなたは動きます。各ラウンド3人のプレイヤーがプレイするために選択されます。ゲームの終わりに、すべてのプレイヤーはゲームを均等にプレイします。

100kのラウンドが実行される瞬間(注これにかかる長い時間を、あなたは、高速のターンアラウンド・テストのためにそれを軽減することができます)。全体的に勝者は、最も勝ったプレーヤーです。

コントローラはhttps://github.com/JJ-Atkinson/Connect-n/tree/masterにあります

ボットの作成:

ボットを作成するには、Playerクラスを拡張する必要があります。Playerは抽象的で、実装するメソッドが1つありint makeMove(void)ます。ではmakeMoveもしあなたがにあなたの作品をドロップしたいどの蔵決定します。無効なcollを選択した場合(例:collが存在しない、colが既に入力されている場合)、あなたのターンはスキップされます。ではPlayerクラスあなたは多くの有用なヘルパーメソッドを持っています。最も重要なもののリストは次のとおりです。

  • boolean ensureValidMove(int coll):collがボード上にあり、colがまだ満たされていない場合、trueを返します。
  • int[] getBoardSize():int配列を返します。ここ[0]で、は列[1]数、は行数です。
  • int[][] getBoard():ボードのコピーを返します。次のようにアクセスする必要があります[coll number][row number from bottom]
  • 残りを見つけるには、Playerクラスを見てください。
  • EMPTY_CELL:空のセルの値

これはマルチスレッド化されるため、random必要な場合は関数も含めています。

ボットのデバッグ:

ボットのデバッグを簡単にするために、コントローラーにいくつかのものを含めました。最初のものはRunner#SHOW_STATISTICSです。これが有効になっている場合、ボットの勝ち数を含む、プレイされたプレーヤーグループのプリントアウトが表示されます。例:

OnePlayBot, PackingBot, BuggyBot, 
OnePlayBot -> 6
PackingBot -> 5
BuggyBot -> 3
Draw -> 1

connectn.game.CustomGameクラスでカスタムゲームを作成することもできます。各ラウンドのスコアと勝者を確認できます。で自分をミックスに追加することもできますUserBot

ボットの追加:

ボットをラインアップにPlayerFactory追加するには、静的ブロックに移動して次の行を追加します。

playerCreator.put(MyBot.class, MyBot::new);

その他の注意事項:

  • シミュレーションはマルチスレッドです。それをオフにしたい場合は、Runner#runGames()この行(.parallel())に移動してコメントしてください。
  • ゲーム数を変更するには、Runner#MINIMUM_NUMBER_OF_GAMESお好みに設定します。

後で追加:

  • ボット間の通信は許可されていません。

関連:Play Connect 4!

================================

スコアボード:(100,000ゲーム)

MaxGayne -> 22662
RowBot -> 17884
OnePlayBot -> 10354
JealousBot -> 10140
Progressive -> 7965
Draw -> 7553
StraightForwardBot -> 7542
RandomBot -> 6700
PackingBot -> 5317
BasicBlockBot -> 1282
BuggyBot -> 1114
FairDiceRoll -> 853
Steve -> 634

================================


ゲームがオンになっているターンを決定する機能を追加できますか?
コナーオブライエン

すでに完了していPlayerます。クラスをチェックして、使用可能なすべてのメソッドを確認してください。
Jアトキン

7
広場ではありません「平方6X7」
ev3commander

1
プレイヤーに違法な動きをさせることで「パス」する能力を与えると、ダイナミクスが少し変わります。全員がパスするとゲームは終了しますか?
histocrat

1
はい、それが使用することが非常に重要である理由ですensureValidMove(もちろん、あなたの戦略がこのターンをパスすることでない限り)。
Jアトキン

回答:


11

マックスゲイン

このボットは、主に接続されたパーツの長さに基づいて、各位置にスコアを割り当てます。各ステージで3つの見栄えの良い動きを詳細に調べて、3つの動きに深く見え、最大予想スコアを持つものを選択します。

package connectn.players;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class MaxGayne extends Player {
    private static final int PLAYERS = 3;

    private static class Result {
        protected final int[] score;
        protected int lastCol;

        public Result(int[] score, int lastCol) {
            super();
            this.score = score;
            this.lastCol = lastCol;
        }

        public Result() {
            this(new int[PLAYERS], -1);
        }

        public Result(Result other) {
            this(new int[PLAYERS], other.lastCol);
            System.arraycopy(other.score, 0, this.score, 0, PLAYERS);
        }

        public int getRelativeScore(int player) {
            int max = Integer.MIN_VALUE;
            for (int i = 0; i < PLAYERS; ++ i) {
                if (i != player && score[i] > max) {
                    max = score[i];
                }
            }
            return score[player] - max;
        }
    }

    private static class Board extends Result {
        private final int cols;
        private final int rows;
        private final int[] data;
        private final int[] used;

        public Board(int cols, int rows) {
            super();
            this.cols = cols;
            this.rows = rows;
            this.data = new int[cols * rows];
            Arrays.fill(this.data, -1);
            this.used = new int[cols];
        }

        public Board(Board other) {
            super(other);
            this.cols = other.cols;
            this.rows = other.rows;
            this.data = new int[cols * rows];
            System.arraycopy(other.data, 0, this.data, 0, this.data.length);
            this.used = new int[cols];
            System.arraycopy(other.used, 0, this.used, 0, this.used.length);
        }

        private void updatePartScore(int player, int length, int open, int factor) {
            switch (length) {
                case 1:
                    score[player] += factor * open;
                    break;
                case 2:
                    score[player] += factor * (100 + open * 10);
                    break;
                case 3:
                    score[player] += factor * (10_000 + open * 1_000);
                    break;
                default:
                    score[player] += factor * ((length - 3) * 1_000_000 + open * 100_000);
                    break;
            }
        }

        private void updateLineScore(int col, int row, int colOff, int rowOff, int length, int factor) {
            int open = 0;
            int player = -1;
            int partLength = 0;
            for (int i = 0; i < length; ++ i) {
                int newPlayer = data[(col + i * colOff) * rows + row + i * rowOff];
                if (newPlayer < 0) {
                    if (player < 0) {
                        if (i == 0) {
                            open = 1;
                        }
                    } else {
                        updatePartScore(player, partLength, open + 1, factor);
                        open = 1;
                        player = newPlayer;
                        partLength = 0;
                    }
                } else {
                    if (newPlayer == player) {
                        ++ partLength;
                    } else {
                        if (player >= 0) {
                            updatePartScore(player, partLength, open, factor);
                            open = 0;
                        }
                        player = newPlayer;
                        partLength = 1;
                    }
                }
            }
            if (player >= 0) {
                updatePartScore(player, partLength, open, factor);
            }
        }

        private void updateIntersectionScore(int col, int row, int factor) {
            updateLineScore(col, 0, 0, 1, rows, factor);
            updateLineScore(0, row, 1, 0, cols, factor);
            if (row > col) {
                updateLineScore(0, row - col, 1, 1, Math.min(rows - row, cols), factor);
            } else {
                updateLineScore(col - row, 0, 1, 1, Math.min(cols - col, rows), factor);
            }
            if (row > cols - col - 1) {
                updateLineScore(cols - 1, row - (cols - col - 1), -1, 1, Math.min(rows - row, cols), factor);
            } else {
                updateLineScore(col + row, 0, -1, 1, Math.min(col + 1, rows), factor);
            }
        }

        private void updatePiece(int player, int col, int row) {
            updateIntersectionScore(col, row, -1);
            data[col * rows + row] = player;
            ++ used[col];
            lastCol = col;
            updateIntersectionScore(col, row, 1);
        }

        public Board updatePiece(int player, int col) {
            int row = used[col];
            if (row >= rows) {
                return null;
            } else {
                Board result = new Board(this);
                result.updatePiece(player, col, row);
                return result;
            }
        }

        private void updateBoard(int[][] board) {
            for (int col = 0; col < cols; ++ col) {
                for (int row = 0; row < rows; ++ row) {
                    int oldPlayer = data[col * rows + row];
                    int newPlayer = board[col][row] - 1;
                    if (newPlayer < 0) {
                        if (oldPlayer < 0) {
                            break;
                        } else {
                            throw new RuntimeException("[" + col + ", " + row + "] == "  + oldPlayer + " >= 0");
                        }
                    } else {
                        if (oldPlayer < 0) {
                            updatePiece(newPlayer, col, row);
                        } else if (newPlayer != oldPlayer) {
                            throw new RuntimeException("[" + col + ", " + row + "] == "  + oldPlayer + " >= " + newPlayer);
                        }
                    }
                }
            }
        }

        private Result bestMove(int depth, int player) {
            List<Board> boards = new ArrayList<>();
            for (int col = 0; col < cols; ++ col) {
                Board board = updatePiece(player, col);
                if (board != null) {
                    boards.add(board);
                }
            }
            if (boards.isEmpty()) {
                return null;
            }
            Collections.sort(boards, (o1, o2) -> Integer.compare(o2.getRelativeScore(player), o1.getRelativeScore(player)));
            if (depth <= 1) {
                return new Result(boards.get(0).score, boards.get(0).lastCol);
            }
            List<Result> results = new ArrayList<>();
            for (int i = 0; i < 3 && i < boards.size(); ++ i) {
                Board board = boards.get(i);
                Result result = board.bestMove(depth - 1, (player + 1) % PLAYERS);
                if (result == null) {
                    results.add(new Result(board.score, board.lastCol));
                } else {
                    results.add(new Result(result.score, board.lastCol));
                }
            }
            Collections.sort(results, (o1, o2) -> Integer.compare(o2.getRelativeScore(player), o1.getRelativeScore(player)));
            return results.get(0);
        }
    }

    private Board board = null;

    @Override
    public int makeMove() {
        if (board == null) {
            int[][] data = getBoard();
            board = new Board(data.length, data[0].length);
            board.updateBoard(data);
        } else {
            board.updateBoard(getBoard());
        }

        Result result = board.bestMove(3, getID() - 1);
        return result == null ? -1 : result.lastCol;
    }
}

とってもとっても素敵!+1
Jアトキン

私が遊んでいる間に気づいたことはUserBot、あなたのボットは、あるポイントの後、MaxGayneターンを捨てることです(例えば、15の動きの後、ゲームが終了するまで毎ターンスキップします)。
Jアトキン

この原因は、おそらくCustomGameのバグです。メインゲームのような1ベースの代わりに0ベースのプレーヤーIDを使用しています。これは単にボットを壊します。さらに2つの問題があります。javafx.util.PairEclipseでは機能しません。これは、パブリックAPIの一部と見なされないためです。そして、私はどこを探すべきかわかりませんsun.plugin.dom.exception.InvalidStateException。おそらくあなたが意味したjava.lang.IllegalStateException
Sleafar

それは少し奇妙に思えます...とにかくPair、それは私が自分でローリングせずに必要なデータ型に到達できる限り近いので、Eclipseがコンパイルされない限り、それは大丈夫だと思います。#3に関して、あなたは正しいです、IntelliJの私のオートコンプリートは常に正しいとは限りません。(ほとんどの場合、それは私がチェックしなかった理由です)
Jアトキン

@JAtkin実際に、回避策Pairがわからない限り、問題はEclipseでのコンパイルを本当に妨げます。
Sleafar

6

RowBot

すべての方向を見て、最適な列を決定します。対戦相手に同じことをさせないようにしながら、彼の作品をつなげようとします。

package connectn.players;

import connectn.game.Game;
import java.util.ArrayList;
import java.util.List;

public class RowBot extends Player {

    @Override
    public int makeMove() {
        int[][] board = getBoard();
        int best = -1;
        int bestScore = -10;
        for (int col = 0; col < board.length; col++) {
            if (ensureValidMove(col)) {
                int score = score(board, col, false);
                score -= score(board, col, true);
                if (score > bestScore) {
                    bestScore = score;
                    best = col;
                }
            }
        }
        return best;
    }

    private int score(int[][] board, int col, boolean simulateMode) {
        int me = getID();
        int row = getLowestEmptyRow(board, col);
        List<Score> scores = new ArrayList<>();
        if (!simulateMode) {
            scores.add(getScoreVertical(board, col, row));
        } else {
            row += 1;
        }
        scores.addAll(getScoreHorizontal(board, col, row));
        scores.addAll(getScoreDiagonal(board, col, row));
        int score = 0;
        for (Score s : scores) {
            if (s.player == me) {
                score += s.points > 2 ? 100 : s.points * 5;
            } else if (s.player != Game.EMPTY_CELL) {
                score += s.points > 2 ? 50 : 0;
            } else {
                score += 1;
            }
        }
        return score;
    }

    private Score getScoreVertical(int[][] board, int col, int row) {
        return getScore(board, col, row, 0, -1);
    }

    private List<Score> getScoreHorizontal(int[][] board, int col, int row) {
        List<Score> scores = new ArrayList<>();

        Score left = getScore(board, col, row, -1, 0);
        Score right = getScore(board, col, row, 1, 0);
        if (left.player == right.player) {
            left.points += right.points;
            scores.add(left);
        } else {
            scores.add(left);
            scores.add(right);
        }
        return scores;
    }

    private List<Score> getScoreDiagonal(int[][] board, int col, int row) {
        List<Score> scores = new ArrayList<>();

        Score leftB = getScore(board, col, row, -1, -1);
        Score rightU = getScore(board, col, row, 1, 1);
        Score leftBottomToRightUp = leftB;
        if (leftB.player == rightU.player) {
            leftBottomToRightUp.points += rightU.points;
        } else if (leftB.points < rightU.points || leftB.player == Game.EMPTY_CELL) {
            leftBottomToRightUp = rightU;
        }

        Score leftU = getScore(board, col, row, -1, 1);
        Score rightB = getScore(board, col, row, 1, -1);
        Score rightBottomToLeftUp = leftU;
        if (leftU.player == rightB.player) {
            rightBottomToLeftUp.points += rightB.points;
        } else if (leftU.points < rightB.points || leftU.player == Game.EMPTY_CELL) {
            rightBottomToLeftUp = rightB;
        }

        if (leftBottomToRightUp.player == rightBottomToLeftUp.player) {
            leftBottomToRightUp.points += rightBottomToLeftUp.points;
            scores.add(leftBottomToRightUp);
        } else {
            scores.add(leftBottomToRightUp);
            scores.add(rightBottomToLeftUp);
        }
        return scores;
    }

    private Score getScore(int[][] board, int initCol, int initRow, int colOffset, int rowOffset) {
        Score score = new Score();
        outerLoop: for (int c = initCol + colOffset;; c += colOffset) {
            for (int r = initRow + rowOffset;; r += rowOffset) {
                if (outside(c, r) || board[c][r] == Game.EMPTY_CELL) {
                    break outerLoop;
                }
                if (score.player == Game.EMPTY_CELL) {
                    score.player = board[c][r];
                }

                if (score.player == board[c][r]) {
                    score.points++;
                } else {
                    break outerLoop;
                }

                if (rowOffset == 0) {
                    break;
                }
            }
            if (colOffset == 0) {
                break;
            }
        }
        return score;
    }

    private boolean outside(int col, int row) {
        return !boardContains(col, row);
    }

    private int getLowestEmptyRow(int[][] board, int col) {
        int[] rows = board[col];
        for (int row = 0; row < rows.length; row++) {
            if (rows[row] == Game.EMPTY_CELL){
                return row;
            }
        }
        return -1;
    }

    private class Score {
        private int player = Game.EMPTY_CELL;
        private int points = 0;
    }
}

5

OnePlayBot

このボットのプレイは1つだけです。有効な左端のセルにピースを配置します。奇妙なことに、それはかなり良いです;)

static class OnePlayBot extends Player {
    @Override
    int makeMove() {
        int attemptedMove = 0;

        for (int i = 0; i < getBoardSize()[0]; i++)
            if (ensureValidMove(i)) {
                attemptedMove = i;
                break;
            }

        return attemptedMove;
    }
}

3

RandomBot

有効な場所にピースを置くだけです。

static class RandomBot extends Player {
    @Override
    int makeMove() {
        int attemptedMove = (int)Math.round(random() * getBoardSize()[0]);
        while (!ensureValidMove(attemptedMove))
            attemptedMove = (int)Math.round(random() * getBoardSize()[0]);

        return attemptedMove;
    }
}

3

StraightForwardBot

OnePlayBotに似ていますが、最後の動きを考慮し、有効な次の列を再生します。

static class StraightForwardBot extends Player {
    private int lastMove = 0;

    @Override
    int makeMove() { 
        for (int i = lastMove + 1; i < getBoardSize()[0]; i++) {
            if (ensureValidMove(i)) {
                lastMove = i;
                return i;
            }
        }
        for (int i = 0; i < lastMove; i++) {
            if (ensureValidMove(i)) {
                lastMove = i;
                return i;
            }
        }
        return 0;
    }
}

3

JealousBot

このボットは他のプレイヤーを嫌います。そして、彼はボードにピースを落とすのが好きではありません。そこで彼は、列にピースを落とした最後の人になろうとします。

public class JealousBot extends Player {

    @Override
    public int makeMove() {
        int move = 0;
        boolean madeMove = false;
        int[] boardSize = getBoardSize();
        int id = getID();
        int[][] board = getBoard();

        if(getTurn()!=0) {
            for(int col = 0; col<boardSize[0]; col++) {
                for(int row = 0; row<boardSize[1]; row++) {
                    if(ensureValidMove(col)) {
                        if(board[col][row]!=EMPTY_CELL && board[col][row]!=id) {
                            move = col;
                            madeMove = true;
                            break;
                        }
                    }
                }
                if(madeMove) break;
            }

            if(!madeMove) {
                int temp = (int)Math.round(random()*boardSize[0]);
                while(madeMove!=true) {
                    temp = (int)Math.round(random()*boardSize[0]);
                    if(ensureValidMove(temp)) {
                        madeMove = true;
                    }
                }
                move = temp;
            }
        } else {
            move = (int)Math.round(random()*boardSize[0]);
        }

        return move;
    }
}

CodeGolfを使うのは初めてなので、この答えで十分だと思います。まだテストできなかったので、間違いがある場合はご容赦ください。

編集:2番目を壊すために行を追加しましたfor

編集2whileが無限であった理由を解明しました。これで完成し、使用できるようになりました!


PPCGへようこそ、あなたはこの答えで私を笑わせました、それは素晴らしいことです!あなたの状態に注意してください。ボードにはデフォルトで-1の値が設定されていると思うので、if(board[col][row]!=null && board[col][row]!=id)に変更する必要がありますif(board[col][row]!=-1....。確認したい場合は、OPのgithubでgame.Game.genBoard()をチェックインします。あなたのrandom()意志があなたが望むことをするかどうか、私は知りません、多分使用し(int)Math.random()*colますか?
かてんきょう

@Katenkyoどうもありがとう、笑わせてくれたら嬉しいです!random()この方法は、中にあるPlayerクラス!だから、うまくいくと思う=)しかし、ええ、私は自分の状態に自信がありませんでした。OPのコードでどのように定義されているかわかりませんでしたが、もう一度確認します。どうもありがとうございました!
ケッカー

Playerクラスはrandom()をとして定義しますpublic double random() {return ThreadLocalRandom.current().nextDouble();}。私はそれがどのように機能するかを正確に知りませんが、0から1の間の値を返すと仮定するので、そうする必要があるかもしれません(int)random()*col:)
Katenkyo

@Katenkyoああ、私はすでにそれをやったと思った...私の悪い。ボードの空のセルに適切な値が見つかったら編集します。ありがとうございます!
ケッカー

@Katenkyoあなたは正しいです、とのnextDouble間の数を返します。シミュレーションが並行して実行され、スレッドセーフではないため、これを含めました。01Math.random()
Jアトキン

3

BasicBlockBot

シンプルな(そして素朴な)ブロックボット。彼は、あなたが水平にまたは斜めに連続して4を作ることができることを知りません!

static class BasicBlockBot extends Player {
    @Override
    int makeMove() {
        List<Integer> inARows = detectInARows();
        double chanceOfBlock = 0.5;

        if (inARows.isEmpty())
            chanceOfBlock = 0;

        if (random() < chanceOfBlock) {
            return inARows.get((int)Math.round(random() * (inARows.size() - 1)));
        } else {
            return (int)Math.round(random() * getBoardSize()[0]);
        }
    }


    /**
     * Very limited - just detects vertical in a rows
     *
     * @return A list of colls that have 4 in a row vertical
     */
    private List<Integer> detectInARows() {
        List<Integer> ret = new ArrayList<>();
        int[][] board = getBoard();

        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                int currId = board[i][j];
                if (currId != -1 && is4InARowVertical(i, j, board)) {
                    ret.add(i);
                }
            }
        }

        return ret;
    }

    private boolean is4InARowVertical(int coll, int row, int[][] board) {
        int id = board[coll][row];

        for (int i = 0; i < 4; i++) {
            int y = row + i;
            if (!boardContains(coll,y) || board[coll][y] != id)
                return false;
        }
        return true;
    }

}

3

プログレッシブ

プログレッシブは...プログレッシブです。彼はすべてを見るのが好きで、何人かも!(この方法論は定かではありません。一度、友人に対して機能しました。)そして、何らかの理由で、それはきちんと機能します。

static class Progressive extends Player{
    @Override
    int makeMove(){
        int move = 0;
        boolean statusBroken = false;
        for(int n=getBoardSize()[0];n>2;n-=2){
            for(int i=0;i<getBoardSize()[0];i+=n){
                if(ensureValidMove(i)){
                    move = i;
                    statusBroken = true;
                    break;
                }
                if(statusBroken) break;
            }
        }
        return move;
    }
}

@JAtkin申し訳ありませんが、古いバージョンのコードがありました。
コナーオブライエン

3
@JAtkin編集を拒否しました。投稿でコードを修正できるようにする必要があります。コントローラー用に修正したい場合は問題ありません(個人的にはメモを残しておきます)が、SE上の誰かのコードを完全に変更することは許可されていません。
ネイサンメリル


2

バギーボット

あなたが勝つためのサンプルボット(FYI:それは難しくありません;)

static class BuggyBot extends Player {
    @Override
    int makeMove() {
        return getBoardSize()[1] - 1;
    }
}

2

PackingBot

このボットはポイントを直接狙っていません。ボードがいっぱいになるまで、彼は最大トークンを詰め込もうとします。彼は単純に何度も何度も馬鹿げているので、自分の「ドメイン」の周りにランダムにトークンを置くことを理解していました。

彼はすべての方向でいくつかのポイントを獲得できるはずですが、最高ではありません!

(未検証)

package connectn.players;

static class PackingBot extends Player
{
    @Override
    int makeMove()
    {
        int move = 0;
        int[] sizes = getBoardSize();
        if(getTurn()==0)
            return sizes[0]/2+sizes[0]%2;

        int[][] board = getBoard();
        int[] flatBoard =new int[sizes[0]];
        //Creating a flat mapping of my tokens
        for(int i=0;i<sizes[0];i++)
            for (int j=0;j<sizes[1];j++)
                if(board[i][j]!=getID())
                    flatBoard[i]++;

        int max=0;
        int range=0;
        for(int i=0;i<flatBoard.length;i++)
        {
            if(flatBoard[i]!=0)
                range++;
            if(flatBoard[i]>flatBoard[max])
                max=i;
        }

        int sens = (Math.random()>0.5)?1:-1;
        move=((int)(Math.random()*(range+1)*sens))+max;

        while(!ensureValidMove(move))
        {
            move=(move+1*sens)%sizes[0];
            if(move<0)
                move=sizes[0]-1;
        }
        return move;
    }


}

@JAtkinそれを指摘してくれてありがとう、修正:)
Katenkyo

2

スティーブ

package connectn.players;

import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

import connectn.game.Game;

public class Steve extends Player {
    @Override
    public int makeMove() {
        Random r=ThreadLocalRandom.current();
        int attemptedMove = 0;
        int[][]board=getBoard();
        int ec=Game.EMPTY_CELL;
        for(int c=0;c<board.length;c++){
            int j=board[c].length-1;
            for(;j>=0;j--){
                if(board[c][j]!=ec)break;
            }

            if(j>2+r.nextInt(3)&&r.nextDouble()<0.8)return c;
        }
        int k=-2+board.length/2+r.nextInt(5);
        if(ensureValidMove(k))return k;
        for (int i = 0; i < getBoardSize()[0]; i++)
            if (ensureValidMove(i)) {
                attemptedMove = i;
                break;
            }

        return attemptedMove;
    }
}

2
スティーブは苦労しています、彼は得点しBasicBlockBotます。
Jアトキン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.