কানেক্ট-এন সময়!


20

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

2 প্লেয়ার গেম কানেক্ট 4 এর কথা কি কেউ মনে করতে পারে? যারা এটি করেন না তাদের জন্য এটি একটি 6x7 বোর্ড ছিল যা কোনও পৃষ্ঠের উপরে উল্লম্বভাবে দাঁড়িয়ে থাকে। সংযোগ 4 এর লক্ষ্য, ভাল সংযোগ 4! সংযোগটি অনুভূমিক, তির্যক বা উল্লম্ব হলে গণনা করা হয়। আপনি কলামের শীর্ষে একটি টুকরোটি thatোকাতে বোর্ডে নিজের টুকরো বোর্ডে রাখুন যেখানে এটি column কলামের নীচে পড়ে। আমাদের নিয়মগুলি সংযোগ 4 এ 3 টি জিনিস পরিবর্তন করে।

  • পরিবর্তন # 1 জয়কে সবচেয়ে পয়েন্ট সহ খেলোয়াড় হিসাবে সংজ্ঞায়িত করা হয়। আপনি নিয়মে 4 টি সংযুক্ত করে পয়েন্ট পাবেন - এর পরে আরও more
  • পরিবর্তন # 2 আপনার প্রতি রাউন্ডে 3 জন খেলোয়াড় রয়েছে।
  • পরিবর্তন # 3 বোর্ডের আকার 9x9।

স্কোরিং:

স্কোরটি আপনি কত সারি পেয়েছেন তার উপর ভিত্তি করে। আপনার যদি সারিতে একটি গ্রুপ 4 থাকে তবে আপনি 1 পয়েন্ট পাবেন। আপনার যদি সারিতে একটি গ্রুপে 5 থাকে তবে আপনি 2 পয়েন্ট পাবেন, একটি সারিতে 3 এবং আরও।

উদাহরণ:

নোট করুন oএবং xআরও ভাল বিপরীতে জন্য যথাক্রমে #এবং প্রতিস্থাপন করা হয়~

খালি বোর্ডের উদাহরণ: (সমস্ত উদাহরণ 2 প্লেয়ার স্ট্যান্ডার্ড আকারের বোর্ড)

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

আমরা যদি টুকরো টুকরো টুকরো টুকরো টুকরো করে ফেলে রাখি তবে dএটি স্থানে নেমে আসবে 1d

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

যদি এখন আমরা dআবার টুকরো টুকরো টুকরো টুকরো টুকরো করে ফেলে রাখি তবে এটি স্থানে নেমে যাবে 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 |_|~|_|#|~|_|~|

এই ক্ষেত্রে, o1 পয়েন্ট উল্লম্বভাবে ( 1d 2d 3d 4d) পাওয়া যায়।

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

এই ক্ষেত্রে o2 পয়েন্ট অনুভূমিকভাবে ( 1c 1d 1e 1f 1g) এবং x1 পয়েন্ট আনুভূমিকভাবে ( 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)।

ইনপুট আউটপুট

আপনার 2 ডি অ্যারের মাধ্যমে বোর্ডে অ্যাক্সেস থাকবে। প্রতিটি অবস্থান intএকজন প্লেয়ার আইডির প্রতিনিধিত্ব করে। আপনার ফাংশনটিতে আপনার প্লেয়ার আইডিও পাস করা হবে। আপনি যে ধাক্কায় আপনার টুকরোটি ফেলে দিতে চান তা ফিরিয়ে আপনি নিজের পদক্ষেপ নিয়ে চলেছেন। প্রতি রাউন্ড 3 খেলোয়াড় খেলতে বেছে নেওয়া হবে। গেমের শেষে, সমস্ত খেলোয়াড় একটি সমান পরিমাণ গেম খেলবে।

এই মুহুর্তের জন্য 100k রাউন্ডগুলি চলবে (দ্রষ্টব্য এটি দীর্ঘ সময় নেয় , আপনি দ্রুত টার্নআরাউন্ড পরীক্ষার জন্য এটি হ্রাস করতে চাইতে পারেন)। সামগ্রিকভাবে বিজয়ী সবচেয়ে বেশি জয়যুক্ত খেলোয়াড়।

নিয়ামকটি এখানে পাওয়া যাবে: https://github.com/JJ-Atkinson/Connect-n/tree/master

বট রচনা:

বট লিখতে আপনাকে অবশ্যই Playerক্লাসটি প্রসারিত করতে হবে । Playerবিমূর্ত এবং বাস্তবায়নের জন্য একটি পদ্ধতি রয়েছে int makeMove(void),। ইন makeMoveআপনি সিদ্ধান্ত নিতে হবে Coll যা আপনি আপনার টুকরা ড্রপ করতে চাই। যদি আপনি একটি অবৈধ সংঘর্ষ বেছে নেন (যেমন সংঘর্ষের অস্তিত্ব নেই, ইতিমধ্যে সংঘর্ষটি পূর্ণ হয়ে গেছে), আপনার পালা এড়ানো হবে । ইন Playerবর্গ আপনি অনেক দরকারী সাহায্যকারী পদ্ধতি আছে। সর্বাধিক গুরুত্বপূর্ণগুলির একটি তালিকা নিম্নলিখিত:

  • boolean ensureValidMove(int coll): সংঘর্ষ বোর্ডে থাকলে এবং সংঘর্ষটি এখনও ভরাট না হলে সত্যটি প্রত্যাবর্তন করুন ।
  • int[] getBoardSize(): [0]কলামগুলির [1]সংখ্যা এবং সারি সংখ্যা হ'ল একটি int অ্যারে ফিরিয়ে দিন।
  • 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আপনার পছন্দ অনুসারে সেট করুন।

পরে যুক্ত হয়েছে:

  • বট মধ্যে যোগাযোগ নিষিদ্ধ করা হয়।

সম্পর্কিত: কানেক্ট 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সমস্ত পদ্ধতি উপলভ্য দেখতে ক্লাসটি পরীক্ষা করে দেখুন।
জে আতকিন

7
"একটি বর্গ 6x7" এটি বর্গক্ষেত্র নয়
ev3commander

1
খেলোয়াড়দের একটি অবৈধ পদক্ষেপের মাধ্যমে "পাস" করার ক্ষমতাটি গতিবেগকে কিছুটা পরিবর্তন করে। খেলাটি কি সবাই পাস করলে শেষ হয়?
হিস্টোক্র্যাট

1
হ্যাঁ, এজন্যই ব্যবহার করা অত্যন্ত গুরুত্বপূর্ণ ensureValidMove(যদি না আপনার কৌশলটি এই সময়টিকে পাস না করে)।
জে আটকিন

উত্তর:


11

MaxGayne

এই বটটি মূলত সংযুক্ত অংশগুলির দৈর্ঘ্যের উপর ভিত্তি করে প্রতিটি পজিশনে স্কোর বরাদ্দ করে। এটি প্রতিটি পর্যায়ে 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
জে আতকিন

আমি যখন UserBotআপনার চারপাশে খেলছিলাম তখন আমি কিছু লক্ষ্য করেছি এবং আপনার বটটি এমন ছিল যে কোনও বিন্দু পরে টার্নগুলি MaxGayneফেলে দেবে (উদাঃ 15 টি চালানোর পরে খেলাটি শেষ না হওয়া পর্যন্ত এটি প্রতিটি পালা এড়িয়ে যায়)।
জে আতকিন

এর কারণ সম্ভবত কাস্টমগেমের একটি বাগ। এটি মূল খেলার মতো 1-ভিত্তিক 0-ভিত্তিক প্লেয়ার আইডি ব্যবহার করছে। এটি কেবল আমার বটকে ভেঙে দেয়। আরও 2 টি সমস্যা আছে। javafx.util.PairEclipse এ কাজ করে না কারণ এটি জনসাধারণের API এর অংশ হিসাবে বিবেচিত হয় না। এবং কোথায় সন্ধান করব তা আমার কোনও ধারণা নেই sun.plugin.dom.exception.InvalidStateException। আপনি সম্ভবত বোঝানো java.lang.IllegalStateException
স্লেফার

এটি কিছুটা অদ্ভুত বলে মনে হচ্ছে ... যাইহোক Pair, এটি নিজের ঘূর্ণায়মান না করে যতটা তথ্য প্রকারের মতো পেতে চাই তার কাছাকাছি, সুতরাং যদি গ্রহনটি সংকলন না করে, আমি মনে করি এটি ঠিক আছে। # 3 হিসাবে, আপনি ঠিক বলেছেন, ইন্টেলিজজে আমার স্বতঃসিদ্ধ সবসময় সঠিক নয়। (বেশিরভাগ সময় এটি হ'ল আমি কেন চেক করি নি)
জে আতকিন

@ জ্যাটিন প্রকৃতপক্ষে, Pairসমস্যাটি কর্মগ্রন্থটিকে সঙ্কলন করতে বাধা দেয়, যদি না আপনি কাজটি জানেন না
স্লেফার

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

এই বটটিতে একটি মাত্র প্লে রয়েছে - এর টুকরোটি বামতম কোষে রাখুন যা বৈধ। অদ্ভুতভাবে এটি বেশ ভাল করে তোলে;)

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

ওয়ানপ্লেবটের অনুরূপ তবে শেষ পদক্ষেপটি অ্যাকাউন্টে নেয় এবং তারপরে পরবর্তী কলামটি কার্যকর হয় plays

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;
    }
}

কোডগল্ফে এটি আমার প্রথমবার, সুতরাং আমি আশা করি এই উত্তরটি যথেষ্ট ভাল হবে। আমি এটি এখনও পরীক্ষা করতে পারিনি, সুতরাং দয়া করে যদি কোনও ভুল থাকে তবে আমাকে ক্ষমা করুন।

সম্পাদনা : দ্বিতীয়টি ভাঙ্গার জন্য একটি লাইন যুক্ত করা হয়েছে for

সম্পাদনা 2 : কেন whileঅসীম তা খুঁজে পেয়েছি । এটি এখন সম্পূর্ণ এবং ব্যবহার করা যেতে পারে!


পিপিসিজিতে আপনাকে স্বাগতম, আপনি এই উত্তরটি দিয়ে আমাকে হাসিয়ে দিয়েছেন, দুর্দান্ত! শুধু আপনার অবস্থার সাথে যত্নশীল। আমার ধারণা বোর্ডটি ডিফল্টরূপে -1 মান দ্বারা ভরা হয়, তাই এতে if(board[col][row]!=null && board[col][row]!=id)পরিবর্তন করা উচিত if(board[col][row]!=-1....। আপনি যদি নিশ্চিত হতে চান তবে ওপির গিথুবে গেম.গেম.জেনবার্ড () পরীক্ষা করুন। আমি জানি না আপনার random()ইচ্ছা আপনি যা চান তা করতে পারেন, সম্ভবত ব্যবহার করবেন (int)Math.random()*col?
কাটেনকিও

@ কেটেনকিয়ো আপনাকে অনেক ধন্যবাদ, যদি আপনি হাসেন তবে আমি খুশি! random()পদ্ধতি রয়েছে Playerবর্গ! সুতরাং আমি মনে করি এটি কার্যকর হবে =) তবে হ্যাঁ, আমি আমার অবস্থার বিষয়ে আত্মবিশ্বাসী ছিলাম না। ওপির কোডে এটি কীভাবে সংজ্ঞায়িত করা হয়েছে তা আমি খুঁজে পাইনি তবে আমি আবার যাচাই করব। আপনাকে অনেক ধন্যবাদ!
কেকার

প্লেয়ার শ্রেণি এলোমেলোভাবে () হিসাবে সংজ্ঞায়িত করে public double random() {return ThreadLocalRandom.current().nextDouble();}। এটি কীভাবে কাজ করে তা আমি স্পষ্টভাবে জানি না তবে আমি ধরে নিলাম এটি 0 এবং 1 এর মধ্যে একটি মান ফেরত দেয়, তাই করার দরকার পড়তে পারে (int)random()*col:)
কেটেনকিও

@ কেটেনকিয়ো ওহ, আমি ভেবেছিলাম এটি ইতিমধ্যে এটি হয়েছে ... আমার খারাপ। আমি যখন বোর্ডে একটি খালি ঘরের জন্য সঠিক মান খুঁজে পেয়েছি তখন আমি এটি সম্পাদনা করব, আপনাকে আবারও ধন্যবাদ!
কেকার

@ কেটেনকিয়ো আপনি সঠিক, এবং এর nextDoubleমধ্যে একটি নম্বর প্রদান করে । আমি এটি অন্তর্ভুক্ত করেছি কারণ সিমুলেশনগুলি সমান্তরালভাবে চালিত হয়, এবং থ্রেড নিরাপদ নয়। 01Math.random()
জে আতকিন

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

প্রগতিশীল

প্রগতিশীল হ'ল ... প্রগতিশীল। তিনি সব কিছু খুঁজছেন পছন্দ , এবং কিছু! (আমি এর পদ্ধতি সম্পর্কে নিশ্চিত নই। এটি একবার বন্ধুর বিরুদ্ধে কাজ করেছিল once) এবং কোনও কারণে এটি শালীনভাবে কাজ করে।

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;
    }
}

@ জ্যাটিন দুঃখিত, আমার কোডটির একটি পুরানো সংস্করণ ছিল।
কনর ও'ব্রায়েন

3
@ জেআটকিন আমি আপনার সম্পাদনা প্রত্যাখ্যান করেছি। আপনার তাদের পোস্টে তাদের কোড ঠিক করার অনুমতি দেওয়া উচিত। যদি আপনি এটি আপনার নিয়ামকের জন্য ঠিক করতে চান তবে তা ঠিক আছে (আমি ব্যক্তিগতভাবে এখনও একটি নোট রেখে দেব), তবে এসই-তে কারও কোডের সম্পূর্ণরূপে পরিবর্তন অনুমোদিত নয়।
নাথান মেরিল


2

BuggyBot

আপনার মারার জন্য একটি নমুনা বট (এফওয়াইআই: এটি শক্ত নয়;)

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;
    }


}

@ জ্যাটিন এটিকে নির্দেশিত করার জন্য ধন্যবাদ, স্থির করেছেন :)
ক্যাটেনকিও

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
জে আতকিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.