স্লাইম: টেরিটরি যুদ্ধ


18

আপনি চিকন একটি গ্লোব। স্বাভাবিকভাবেই, স্লাইম হওয়ার কারণে, আপনি যতটা সম্ভব এলাকাতে ওঠাতে চান। তবে আরও 3 টি স্লাইম রয়েছে যারা একই জিনিসটি করতে চায়। কে হবে উন্নত চর্বি?

বিবরণ

সমস্ত স্লাইম এক অঙ্গনে জড়ো করা হবে। বিচারকরা (অর্থাত্ নিয়ন্ত্রণ প্রোগ্রাম) সমস্ত সম্ভাব্য 4-স্লাইম সংমিশ্রণের একটি বিস্তৃত তালিকার মধ্য দিয়ে যাবেন, এগুলি একটি টেবিলের কোণায় রাখবেন এবং কোন অঞ্চলটি সবচেয়ে বেশি অঞ্চল জুড়ে বেরিয়ে আসে তা পর্যবেক্ষণ করবেন।

আপনার স্লাইমগুলি প্রতি বারে 3 টির মধ্যে একটি ক্রিয়াকলাপ করতে পারে: ছড়িয়ে পড়ে, লাফিয়ে যায় বা মার্জ করে। এগুলি কী বোঝায় তা সম্পর্কে আরও বিবরণ আউটপুট বিভাগে সরবরাহ করা হবে।

বোর্ড / এরিনা

অঙ্গনটি একটি বর্গ বোর্ড হবে (বর্তমানে 8x8, তবে এটি ভবিষ্যতে পরিবর্তন হতে পারে)। এখানে একটি গেমের অগ্রগতির উদাহরণ রয়েছে:

11111222
11111444
11.22444
.1222.4.
333.3244
33333.44
333...44
333....4

স্লাইমটি 1 থেকে 4 সংখ্যক (প্লেয়ার 1 থেকে 4) দ্বারা উপস্থাপিত হয় এবং খালি স্থানটি একটি বিন্দু দ্বারা প্রতিনিধিত্ব করে ( .)। প্রথমদিকে, বোর্ডটি বাম কোণার উপরে প্লেয়ার 1 এর কাঁচের একক ইউনিট, উপরের ডানদিকে প্লেয়ার 2, নীচে বাম দিকে প্লেয়ার 3 এবং নীচে ডানদিকে প্লেয়ার 4 ব্যতীত সমস্ত খালি স্থান হিসাবে শুরু করবে।

কোডটিতে পাঠযোগ্যতার জন্য স্থানাঙ্কগুলি 0-ভিত্তিক সারি এবং কলাম সূচক দ্বারা প্রতিনিধিত্ব করা হয়। উদাহরণস্বরূপ, স্থানাঙ্কগুলি (3, 6) 4 র্থ সারিতে 7 ম বর্গের প্রতিনিধিত্ব করে (উপরের উদাহরণে ক 4)। (এটি স্কোয়ারগুলিতে অ্যাক্সেস করা সহজ করে তোলে:। board[coords.x][coords.y]) এখানে একটি চাক্ষুষ চিত্র রয়েছে:

(0, 0) (0, 1) (0, 2)
(1, 0) (1, 1) (1, 2)
(2, 0) (2, 1) (2, 2)

ইনপুট

আপনার প্রোগ্রামের ইনপুটটি আপনি কোন খেলোয়াড় (1, 2, 3, বা 4), একটি কমা ( ,), তারপরে বোর্ড / অঙ্গনের সামগ্রী (কমা দিয়ে প্রতিস্থাপন করা নতুন লাইনের সাথে) থাকবে be উদাহরণস্বরূপ, আপনি যদি উপরের দৃশ্যে 3 খেলোয়াড় হন তবে আপনার ইনপুটটি হবে:

3,11111222,11111444,11.22444,.1222.4.,333.3244,33333.44,333...44,333....4

আউটপুট

আপনার প্রোগ্রামটি অবশ্যই 4 পূর্ণসংখ্যার আউটপুট দেয়। প্রথম দুটি হ'ল আপনি যে স্লাইমটি সরাতে চান তার যথাক্রমে সারি এবং কলাম সূচক এবং পরের দুটি হ'ল আপনি যেখানে সরাতে চান তার সারি এবং কলাম সূচী।

প্রতিটি বারে আপনার কাছে তিনটি পছন্দ রয়েছে: ছড়িয়ে পড়া, লাফানো বা একত্রীকরণ।

  • বিস্তার

    ছড়িয়ে দেওয়ার জন্য, লক্ষ্য স্থানাঙ্কগুলি স্লাইম সরানো থেকে ঠিক এক বর্গ দূরে থাকতে হবে এবং লক্ষ্য স্থানাঙ্কের বর্গক্ষেত্রটি অবশ্যই ফাঁকা স্থান হতে হবে। ছড়িয়ে পড়ার সময় লক্ষ্য স্থানাঙ্কগুলিতে একটি নতুন স্লাইম তৈরি করা হয় এবং পুরাতন পাতলা সরানো হয় না । নতুন স্লাইম তৈরি হওয়ার পরে, এই নতুন স্লাইমের চারপাশে 8 স্কোয়ারের সমস্ত শত্রু স্লাইম সরানো প্লেয়ারে রূপান্তরিত হয়।

    উদাহরণস্বরূপ, চিত্র 1-এ বোর্ডের সাথে, প্লেয়ার 1 যদি আউটপুট দেয় 0 1 1 2তবে ফলাফলটি ডুমুর 2-এ বোর্ড হবে।

    1.         2.
      11.22      11.12
      1..22      1.112
      ..22.      ..11.
      .....      .....
    
  • ঝাঁপ দাও

    লাফানোর জন্য, লক্ষ্য স্থানাঙ্কগুলি স্লাইম সরানো থেকে ঠিক দুটি স্কোয়ার দূরে থাকতে হবে এবং লক্ষ্য স্থানাঙ্কের বর্গক্ষেত্রটি অবশ্যই ফাঁকা স্থান হতে হবে। যখন জুপমিং হয়, লক্ষ্য স্থানাঙ্কগুলিতে একটি নতুন স্লাইম তৈরি করা হয় এবং পুরাতন কাটা সরানো হয়। নতুন স্লাইম তৈরি হওয়ার পরে, এই নতুন স্লাইমের চারপাশে 8 স্কোয়ারের সমস্ত শত্রু স্লাইম সরানো প্লেয়ারে রূপান্তরিত হয়।

    উদাহরণস্বরূপ, চিত্র 1-এ বোর্ডের সাথে, প্লেয়ার 1 যদি আউটপুট দেয় 0 1 2 3তবে ফলাফলটি ডুমুর 2-এ বোর্ড হবে।

    1.         2.    
      11..2      1...2
      1...2      1...1
      ....2      ...11
      ...22      ...11
    
  • একত্রিত করা

    মার্জ করার জন্য, লক্ষ্য স্থানাঙ্কগুলি স্লাইম সরানো থেকে ঠিক এক বর্গ দূরে থাকতে হবে এবং লক্ষ্য স্থানাঙ্কের বর্গক্ষেত্রটি অবশ্যই একই প্লেয়ারের কাটা হতে হবে। মার্জ করার সময়, পুরানো পাতলা সরানো হয়। তারপরে, লক্ষ্য স্লাইমের চারপাশে 8 স্কোয়ারের সমস্ত খালি স্থানগুলি সরানো প্লেয়ারে রূপান্তরিত হয় (পুরানো কাটা সরানো সহ নয়)।

    উদাহরণস্বরূপ, চিত্র 1-এ বোর্ডের সাথে, প্লেয়ার 1 যদি আউটপুট দেয় 0 1 1 2তবে ফলাফলটি ডুমুর 2-এ বোর্ড হবে।

    1.         2.
      11..2      1.112
      1.1.2      11112
      ....2      .1112
      ..222      ..222
    

আপনি কেবল অবৈধ স্থানাঙ্ক (প্রাক্তন 0 0 0 0) আউটপুট করেও পাস করতে পারেন ।

বিধি ও সীমাবদ্ধতা

অতিরিক্ত বিধিগুলি হ'ল:

  • ডেটা অব্যাহত রাখতে আপনি নিজের ফোল্ডারে ফাইল পড়তে এবং লিখতে পারেন (জমাগুলি সংরক্ষণ করা হবে players/YourBotName/yourBotName.language) তবে আপনি এর বাইরে অন্য কোনও কিছুর সংশোধন বা অ্যাক্সেস করতে পারবেন না not ইন্টারনেট অ্যাক্সেস নিষিদ্ধ।
  • আপনার জমাটি বিশেষত কোনও কোড জমা দেওয়া বা অন্য জমা দেওয়ার জন্য কোড করা যাবে না। (আপনার একাধিক জমা থাকতে পারে তবে তাদের অবশ্যই কোনওভাবেই একে অপরের সাথে ইন্টারঅ্যাক্ট করা উচিত নয়))
  • আপনার জমা দিতে প্রতি সেকেন্ডে 0.1 সেকেন্ডের বেশি লাগবে না। আপনার জমা যদি মাঝে মাঝে 0.105 সেকেন্ড সময় নেয় তবে তা ঠিক আছে তবে এই সময়সীমাটির চেয়ে এটি ধারাবাহিকভাবে বেশি সময় নিতে পারে না। (অত্যধিক দীর্ঘ সময় নিরীক্ষণ এড়াতে এটি মূলত একটি স্যানিটি চেক))
  • আপনার জমাটি অন্য কোনওর মতো সঠিক সদৃশ (যেমন সঠিক একই যুক্তি ব্যবহার করুন) হওয়া উচিত নয়, এমনকি এটি অন্য ভাষায় হলেও।
  • আপনার জমাটি অবশ্যই একটি গুরুতর জমা দিতে হবে। এটি মতামতভিত্তিক, তবে আপনার জমাটি যদি চ্যালেঞ্জটি সমাধান করার জন্য স্পষ্টভাবে চেষ্টা না করে (উদাহরণস্বরূপ, আপনি প্রতিটি পালা পেরিয়ে যান), এটি অযোগ্য ঘোষণা করা হবে।

আপনার জমাটি যদি এই নিয়মগুলির কোনও ভঙ্গ করে বা স্পেসিফিকেশন অনুসরণ না করে তবে এটি অযোগ্য ঘোষণা করা হবে, এখান থেকে সরানো playerlist.txtহবে এবং গেমটি শুরু থেকেই পুনরায় শুরু হবে। যদি আপনার জমাটি অযোগ্য ঘোষণা করা হয় তবে আমি কেন আপনার পোস্টে একটি মন্তব্য করব। অন্যথায়, আপনার জমাটি লিডারবোর্ডে যুক্ত করা হবে। (যদি আপনি লিডারবোর্ডে আপনার জমাটি দেখতে না পান, আপনার পোস্টে কোনও ব্যাখ্যামূলক মন্তব্য না করেন এবং নীচে "শেষ আপডেট" সময়ের আগে আপনার জমা পোস্ট করেছেন, দয়া করে আমাকে বলুন! আমি সম্ভবত অজান্তে এটি উপেক্ষা করেছি))

আপনার প্রবেশে, দয়া করে অন্তর্ভুক্ত করুন:

  • একটি নাম.
  • শেল কমান্ড (উদাহরণস্বরূপ, আপনার প্রোগ্রাম চালানোর জন্য java MyBot.java, ruby MyBot.rb, python3 MyBot.py, ইত্যাদি)।
    • নোট করুন যে ইনপুট (আপনার প্লেয়ার এবং মানচিত্র) এতে একটি কমান্ড লাইনের যুক্তি হিসাবে যুক্ত হবে।
    • প্রোগ্রামগুলি উবুন্টু ১৪.০৪-এ পরীক্ষা করা হবে, সুতরাং আপনার কোডটি এতে (অবাধে) চালানো যেতে পারে তা নিশ্চিত করুন।
  • একটি সংস্করণ নম্বর, যদি আপনার কোডটি আপনার ভাষার বিভিন্ন সংস্করণে আলাদাভাবে কাজ করে।
  • আপনার বট কোড
  • কীভাবে কোডটি সংকলন করতে হবে তার নির্দেশাবলী

নিয়ামক কোড / পরীক্ষা, উদাহরণ বট

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

simplebot.rb, একটি খুব সাধারণ বট যা প্রতিটি মোড় এলোমেলো স্থানে ছড়িয়ে পড়ে বা এলোমেলোভাবে লাফ দেয়, এছাড়াও গিতুব পোস্ট করা হয়

স্কোরিং এবং লিডারবোর্ড

বোর্ডের সমস্ত স্কোয়ারগুলি পূর্ণ হয়ে গেলে, খেলাটি শেষ হয় এবং স্কোরগুলি গণনা করা হয়। কোনও খেলোয়াড়ের চূড়ান্ত স্কোর হল স্কোয়ারের পরিমাণ যা গেমের শেষে তাদের পাতলা করে contain যদি 2000 টার্নগুলি (প্রতিটি খেলোয়াড়ের জন্য 500) কেটে যায় এবং গেমটি এখনও শেষ না হয় তবে গেমটি যেভাবেই শেষ হবে এবং স্কোরগুলি এমনভাবে রিপোর্ট করা হবে যেন গেমটি শেষ হয়ে গেছে।

টুর্নামেন্টের শেষে, সমস্ত গেমের স্কোরগুলি গড়ে প্রতিটি খেলোয়াড়ের চূড়ান্ত স্কোর গণনা করতে হবে, যা লিডারবোর্ডে পোস্ট করা হবে। জমা দেওয়ার সময়সীমা নেই; নতুন জমাগুলি আসার সাথে সাথে আমি পর্যায়ক্রমে লিডারবোর্ড আপডেট করতে থাকব to

একটি আসল লিডারবোর্ড উপস্থিত না হওয়া পর্যন্ত 4 টি জমা দেওয়ার প্রয়োজন।

+--------------------------+-----------+--------------------+
| Name                     | Avg Score | Last Updated (UTC) |
+--------------------------+-----------+--------------------+
| GreedySlime              | 47.000    | Jul 22 10:27 PM    |
| Jumper                   | 12.000    | Jul 22 10:27 PM    |
| ShallowBlue              | 5.000     | Jul 22 10:27 PM    |
| Lichen                   | 0.000     | Jul 22 10:27 PM    |
+--------------------------+-----------+--------------------+

শেষ আপডেট: জুলাই 22 10:27 অপরাহ্ন (ইউটিসি)।


হুঁ, আমি হয়ত এটি মিস করেছি, তবে আপনি কী ব্যাখ্যা করেছেন যে খেলোয়াড়দের মধ্যে মিথস্ক্রিয়াটি কীভাবে হবে? সবাই কি একই সাথে চলাফেরা করে? প্লেয়ার 1 প্রথম?
6:54 এ জাস্টহেল্ফ

1
সম্ভবত এটি কেবল আমিই এটি একটি সামান্য অস্পষ্ট খুঁজে পেয়েছি তবে আপনি কীভাবে "দুটি বর্গ দূরে" সংজ্ঞায়িত করবেন?
আর্শাজি

নব্বইয়ের দশক থেকে পানীয়ের উপর ভিত্তি করে আমাকে প্রচুর খেলা মনে করিয়ে দেয়। ;-)
বেনি

@ আসরফাল্ট প্লেয়ার 1 প্রথমে চলে আসে।
ডুরকনব

1
@arshaii "দুই স্কোয়ার দূরে" এর অর্থ, আনুষ্ঠানিকভাবে, "এমন কোনও অবস্থানে যেখানে এক্সের পরিবর্তন এবং Y এর পরিবর্তনের সর্বাধিক ২.র সমান।"
ডুরকনব

উত্তর:


4

GreedySlime

স্লাইম ইউনিটগুলির সর্বাধিক নেট লাভ অর্জন করে এমন পদক্ষেপটি কেবল তৈরি করে।

দ্রষ্টব্য যে এটি পাইথন ২.x এ লেখা হয়েছে ।

def gen_moves(board, pos):
    """Generate valid moves for a given position.

    Return value is a tuple of the form
       (type, from_x, from_y, to_x, to_y)

    The move 'type' is a single character with:
        - 's' = spread
        - 'j' = jump
        - 'm' = merge
    """

    N = len(board)
    x0, y0 = pos
    player = board[x0][y0]

    for i in -2,-1,0,1,2:
        for j in -2,-1,0,1,2:
            if (i == 0 and j == 0):
                continue

            x1, y1 = x0 + i, y0 + j

            if not ((0 <= x1 < N) and (0 <= y1 < N)):
                continue

            c = board[x1][y1]

            if -1 <= i <= 1 and -1 <= j <= 1:
                if c == '.':
                    yield ('s', x0, y0, x1, y1)
                elif c == player:
                    yield ('m', x0, y0, x1, y1)
            else:
                if c == '.':
                    yield ('j', x0, y0, x1, y1)

def eval_move(board, move, initial_net={'s': 1, 'j': 0, 'm': -1}):
    """Evaluates given move in given context.

    - Assumes move is valid.
    - `move` argument is a tuple of the form
       (type, from_x, from_y, to_x, to_y)
    - The move 'type' is a single character with:
        - 's' = spread
        - 'j' = jump
        - 'm' = merge
    """

    N = len(board)
    move_type = move[0]
    x0, y0, x1, y1 = move[1:]
    player = board[x0][y0]

    net = initial_net[move_type]
    for i in -1,0,1:
        for j in -1,0,1:
            if (i == 0 and j == 0):
                continue

            x2, y2 = x1 + i, y1 + j

            if not ((0 <= x2 < N) and (0 <= y2 < N)):
                continue

            c = board[x2][y2]

            if (move_type == 'm' and c == '.') or (move_type != 'm' and c != player and c != '.'):
                net += 1

    return net

def main():
    from sys import argv
    data = argv[1]

    player, board = data.split(',', 1)
    board = map(list, board.split(','))
    N = len(board)

    all_pos_gen = ((a,b) for a in range(N) for b in range(N) if board[a][b] == player)
    all_move_gen = (move for pos in all_pos_gen for move in gen_moves(board, pos))
    move = max(all_move_gen, key=lambda move: eval_move(board, move))

    print move[1], move[2], move[3], move[4]

if __name__ == "__main__":
    main()

উদাহরণ রান (চ্যালেঞ্জের বিবরণে প্রদত্ত উদাহরণটি ব্যবহার করে, এবং কোড ধরে নেওয়া কোনও ফাইলে সংরক্ষণ করা হয়েছে বলে ধরে নেওয়া slime.py):

$ python slime.py 3,11111222,11111444,11.22444,.1222.4.,333.3244,33333.44,333...44,333....4
4 0 2 2

3

অগভীর নীল

অগভীর নীল সম্ভাব্য পদক্ষেপের একটি নিখরচায় গাছের অনুসন্ধান করে ভবিষ্যতে কী ঘটতে পারে তা বোঝার চেষ্টা করে, দুর্ভাগ্যক্রমে, তিনি তার পরবর্তী পালা ছাড়া আর কিছু পান না। তার পরের বারের পরে তিনি প্রতিটি সম্ভাব্য বোর্ডস্টেটে কিছু অর্ধ-মূল্যায়িত স্কোরকে থাপ্পড় মারেন, সমান হাস্যকর সূত্রের সাথে প্রতিটি স্বতন্ত্র শাখার জন্য একটি স্কোর গণনা করেন এবং: ভয়েলা আদর্শ পদক্ষেপটি জানা যায়!

সম্পাদনা: মূল কোডটি খুব ধীরে ধীরে চলতে পারে তাই আমি এটিকে সংশোধন করেছি যাতে এটি কেবল সমস্ত সম্ভাব্য পদক্ষেপের একটি এলোমেলো নমুনা নেয়। যখন খুব সামান্য চালচলন সম্ভব হবে এবং যখন আরও বেশি চলন সম্ভব হয় তখন একটি ছোট শতাংশ শতাংশ এটি প্রায় সমস্ত চাল চেষ্টা করবে try

import java.awt.Point;  

    public class ShallowBlue {
        private static final int MAX_ROUNDS = 5, PLAYERS = 4;
        static int me = 0;

        public static void main(String[] args) {
            if (args[0] == null) {
                return;
            }

            me = Integer.parseInt(args[0].split(",", 2)[0]);
    String board = args[0].split(",", 2)[1];

    System.out.println(getBestMove(board, me, MAX_ROUNDS - 1));
}

private static String getBestMove(String board, int player, int rounds) {
    String [] boards = new String[24];
    int checkedBoards = 1;
    char playerChar = Integer.toString(player).charAt(0);
    String tempMove = getMove(0, 0, 0, 0);
    String tempBoard = calculateMove(board, tempMove); 
    boards[0] = tempBoard;
    String bestMove = tempMove;
    double us = numberOfUs(board, playerChar); 
    double skip = (us*2.5/(us*2.5 + 1))/4 + 0.735;
    if (rounds == MAX_ROUNDS - 2) {
        skip = skip*skip;
    }

    float bestScore, worstScore, averageScore, tempScore;
    int scores;

    if (rounds == 0) {
        tempScore = calculateScore(tempBoard, MAX_ROUNDS - rounds - 1);
    } else {
        tempScore = getScore(getBestMove(tempBoard, player%PLAYERS + 1, rounds - 1));
    }

    scores = 1;
    bestScore = tempScore;
    worstScore = tempScore;
    averageScore = tempScore;

    for (int x = 0; x < 8; x++) {
        for (int y = 0; y < 8; y++) {
            if (getCharAt(board, x, y) == playerChar) {
                Point[] possibleMergers = getNeighboringMatches(board, new Point(x, y), playerChar);
                if (possibleMergers[0] != null) {
                    tempMove = getMove(possibleMergers[0].x, possibleMergers[0].y, x, y); 
                    tempBoard = calculateMove(board, tempMove);
                    if (addIfUnique(boards, tempBoard, checkedBoards)) {
                        checkedBoards++;
                        if ((rounds != MAX_ROUNDS - 1) && (rounds == 0 || Math.random() < skip)) {
                            tempScore = calculateScore(tempBoard, MAX_ROUNDS - rounds - 1);
                        } else {
                            tempScore = getScore(getBestMove(tempBoard, player%PLAYERS + 1, rounds - 1));
                        }

                        if (tempScore > bestScore) {
                            bestMove = tempMove;
                        }
                        bestScore = Math.max(tempScore, bestScore);
                        worstScore = Math.min(tempScore, worstScore);

                        scores++;
                        averageScore = (averageScore*(scores - 1) + tempScore)/scores;
                    }
                }
            } else if (getCharAt(board, x, y) == '.') {
                Point[] possibleSpreaders = getNeighboringMatches(board, new Point(x, y), playerChar);
                int i = 0;
                while (i < possibleSpreaders.length && possibleSpreaders[i] != null) {
                    tempMove = getMove(possibleSpreaders[i].x, possibleSpreaders[i].y, x, y); 
                    tempBoard = calculateMove(board, tempMove);
                    if ((rounds != MAX_ROUNDS - 1) && (rounds == 0 || Math.random() < skip)) {
                        tempScore = calculateScore(tempBoard, MAX_ROUNDS - rounds - 1);
                    } else {
                        tempScore = getScore(getBestMove(tempBoard, player%PLAYERS + 1, rounds - 1));
                    }

                    if (tempScore > bestScore) {
                        bestMove = tempMove;
                    }
                    bestScore = Math.max(tempScore, bestScore);
                    worstScore = Math.min(tempScore, worstScore);

                    scores++;
                    averageScore = (averageScore*(scores - 1) + tempScore)/scores;

                    i++;
                }
                Point[] possibleJumpers = getNextNeighboringMatches(board, new Point(x, y), playerChar);
                i = 0;
                while (i < possibleJumpers.length && possibleJumpers[i] != null) {
                    tempMove = getMove(possibleJumpers[i].x, possibleJumpers[i].y, x, y); 
                    tempBoard = calculateMove(board, tempMove);
                    if ((rounds != MAX_ROUNDS - 1) && (rounds == 0 || Math.random() < skip)) {
                        tempScore = calculateScore(tempBoard, MAX_ROUNDS - rounds - 1);
                    } else {
                        tempScore = getScore(getBestMove(tempBoard, player%PLAYERS + 1, rounds - 1));
                    }

                    if (tempScore > bestScore) {
                        bestMove = tempMove;
                    }
                    bestScore = Math.max(tempScore, bestScore);
                    worstScore = Math.min(tempScore, worstScore);

                    scores++;
                    averageScore = (averageScore*(scores - 1) + tempScore)/scores;

                    i++;
                }
            }
        }
    }

    if (rounds == MAX_ROUNDS - 1) {
        return (bestMove);
    } else {
        return getScoreString(bestScore, worstScore, averageScore);
    }
}

private static int numberOfUs(String board, char playerChar) {
    int us = 0;

    for (int i = 0; i < board.length(); i++ ) {
         if (board.charAt(i) == playerChar) {
            us++;
        }
    }

    return us;
}

private static float calculateScore(String board, int roundsPassed) {
    int empties = 0;
    int us = 0;
    int enemy1 = 0;
    int enemy2 = 0;
    int enemy3 = 0;
    for (int i = 0; i < board.length(); i++ ) {
        if (board.charAt(i) == '.') {
            empties++;
        } else if (board.charAt(i) == Integer.toString(me).charAt(0)) {
            us++;
        } else if (board.charAt(i) == Integer.toString(me%PLAYERS + 1).charAt(0)) {
            enemy1++;
        } else if (board.charAt(i) == Integer.toString(me%PLAYERS + 2).charAt(0)) {
            enemy2++;
        } else if (board.charAt(i) == Integer.toString(me%PLAYERS + 3).charAt(0)) {
            enemy3++;
        }
    }

    if (us != 0) {
        us += roundsPassed;
    }

    if (enemy1 != 0) { 
        enemy1 = enemy1 + (roundsPassed + 3)%PLAYERS;
    }

    if (enemy2 != 0) { 
        enemy2 = enemy2 + (roundsPassed + 2)%PLAYERS;
    }

    if (enemy3 != 0) { 
        enemy3 = enemy3 + (roundsPassed + 1)%PLAYERS;
    }

    return us*(empties + 1)/(Math.max(Math.max(enemy1, enemy2), enemy3) + 1);
}

private static float getScore(String scoreString) {
    float bestScore, worstScore, averageScore;
    String[] scores = new String[3];

    scores = scoreString.split(",");
    bestScore = Float.parseFloat(scores[0]);
    worstScore = Float.parseFloat(scores[1]);
    averageScore = Float.parseFloat(scores[2]);


    return (float) Math.sqrt(Math.sqrt(bestScore*averageScore*worstScore*worstScore));
}

private static String getScoreString(float bestScore, float worstScore, float averageScore) {
    return Float.toString(bestScore) + ',' + Float.toString(worstScore) + ',' + Float.toString(averageScore);
}

private static boolean addIfUnique(String[] boards, String board, int checkedBoards) {
    int i = 0;

    while (i < boards.length && boards[i] != null) {
        if (boards[i].equals(board)) {
            return false;
        }
        i++;
    }

    if (i < boards.length) {
        boards[i] = board;
    } else {
        boards[checkedBoards%boards.length] = board;
    }

    return true;
}

private static String calculateMove(String board, String move) {
    int x1 = Integer.parseInt(Character.toString(move.charAt(0)));
    int y1 = Integer.parseInt(Character.toString(move.charAt(2)));
    int x2 = Integer.parseInt(Character.toString(move.charAt(4)));
    int y2 = Integer.parseInt(Character.toString(move.charAt(6)));

    if ((Math.abs(y1 - y2) == 2 || Math.abs(x1 - x2) == 2) 
            &&  getCharAt(board, x2, y2) == '.') {
        Point[] enemies = new Point[8];

        enemies = getNeighboringEnemies(board, new Point(x1, y1), Integer.parseInt(Character.toString(getCharAt(board, x1, y1))));

        board = replace(board, enemies, getCharAt(board, x1, y1));
        Point[] middle = {new Point(x1, y1)};
        board = replace(board, middle, '.');
    }

    if ((Math.abs(y1 - y2) == 1 || Math.abs(x1 - x2) == 1)) { 
        if (getCharAt(board, x2, y2) == '.' || getCharAt(board, x1, y1) == getCharAt(board, x2, y2)) {
            boolean merge = true;
            if (getCharAt(board, x2, y2) == '.') {
                merge = false;
            }

            Point[] spaces = new Point[8];
            spaces = getNeighboringMatches(board, new Point(x1, y1), '.');
            board = replace(board, spaces, getCharAt(board, x1, y1));

            if (merge) {
                Point[] source = {new Point(x1, y1)};
                board = replace(board, source, '.');
            }
        }
    }

    return board;
}

private static String replace(String board, Point[] targets, char source) {
    int i = 0;

    while (i < targets.length && targets[i] != null) {
        if (targets[i].x == 7 && targets[i].y == 7) {
            board = board.substring(0, getIndexAt(targets[i].x, targets[i].y)) + source;
        } else if (targets[i].x == 0 && targets[i].y == 0) {
            board = source + board.substring(getIndexAt(targets[i].x, targets[i].y) + 1);
        } else {
            board = board.substring(0, getIndexAt(targets[i].x, targets[i].y)) + source + board.substring(getIndexAt(targets[i].x, targets[i].y) + 1);
        }
        i++;
    }

    return board;
}

private static Point[] getNeighboringMatches(String board, Point coord, char match) {
    Point[] matches = new Point[8];

    int i = 0;
    for (int x = coord.x - 1; x <= coord.x + 1; x++) {
        for (int y = coord.y - 1; y <= coord.y + 1; y++) {
            if ((y != coord.y || x != coord.x ) && getCharAt(board, x, y) == match){
                matches[i] = new Point(x, y);
                i++;
            }
        }
    }

    return matches;
}

private static Point[] getNeighboringEnemies(String board, Point coord, int player) {
    Point[] enemies = new Point[8];

    for (int i = 1; i <= PLAYERS; i++){
        enemies = mergeArr(enemies, getNeighboringMatches(board, coord, Integer.toString((player + i - 1)%PLAYERS + 1).charAt(0)));
    }

    return enemies;
}

private static Point[] getNextNeighboringMatches(String board, Point coord, char match) {
    Point[] matches = new Point[16];

    int i = 0;
    for (int x = coord.x - 2; x <= coord.x + 2; x++) {
        for (int y = coord.y - 2; y <= coord.y + 2; y++) {
            if ((Math.abs(y - coord.y) == 2 || Math.abs(x - coord.x) == 2) && getCharAt(board, x, y) == match){
                matches[i] = new Point(x, y);
                i++;
            }
        }
    }

    return matches;
}

private static char getCharAt(String board, int x, int y) {

    if (x >= 0 && x < 8 && y >= 0 && y < 8) {
        return board.charAt(9*x + y);
    } else {
        return '\0';
    }
}

private static int getIndexAt(int x, int y) {
    return 9*x + y;
}

private static Point[] mergeArr(Point[] arr1, Point[] arr2) {
    int i = 0;
    int j = 0;

    while (i < arr1.length && arr1[i] != null) {
        i++;
    }

    while (j < arr2.length && arr2[j] != null) {
        arr1[i + j] = arr2[j];
        j++;
    }

    return arr1;
}

private static String getMove(int x1, int y1, int x2, int y2) {
    return Integer.toString(x1) + " " + Integer.toString(y1) + " " + Integer.toString(x2) + " " + Integer.toString(y2);
    }
}

আমি খুব বেশি প্রোগ্রামার নই এবং এই ধারণাটি আমার প্রত্যাশার চেয়েও জটিল ছিল, আমি এই কোডটি এখনও পরীক্ষা করেছি না (মোটেও) এটি সকাল 3 টা এবং আমাকে আগামীকাল কাজ শুরু করতে হবে। এটি বেশ সম্ভব যে আমার বট শেষ হয়ে যাবে বা ঠিক তেমন কাজ করবে না। আমি স্থানাঙ্কগুলিও ভুলভাবে পেয়েছি, আমি আগামীকাল তাজা চোখ দিয়ে এটিকে আবার দেখব, তবে একটি অতিরিক্ত জুড়ি (বা আরও) সর্বদা স্বাগত জানাই, (অতিরিক্ত অভিজ্ঞ) চোখের একটি অতিরিক্ত জুটি।
ওভাররেੈਕਟਰ

আমি এর জন্য বেশ কিছু ব্যতিক্রম পাচ্ছি ( স্ট্যাকট্রেসের জন্য চ্যাট দেখুন )।
ডোরকনবব

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

যেহেতু এটি গল্ফড নয়, আপনি কোড পর্যালোচনাতে পোস্ট করতে পারেন ... এটি কি বিধিগুলির মধ্যে থাকবে বা এটি ভ্রান্ত হবে?
ট্রাইকোপ্লাক্স

1
আমি এই উত্তরটি দুই দিন আগে দেখেছি, তবে আমি কেবল বুঝতে পেরেছি যে "অগভীর নীল" বিখ্যাত "ডিপ ব্লু" এর জন্য একটি পাং।
জাস্টহেল্ফ

2

মাথা গলান জামাবিশেষ

ঝাঁপিয়ে পড়া পছন্দ করে, আরও অনেক কিছু মাঝের দিকে।

কোনও স্লাইম লাফাতে না পারলে পাস করবে।

সি ++ , সঙ্গে সহজেই সংকলন করা উচিতg++ jumper.cpp -o jumper

#include <math.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#define maxn(x, y) ((x) > (y) ? (x) : (y))
#define absn(x) ((x) < 0 ? -(x) : (x))
class Board {
 public:
    Board(std::string input_string);
    void Move();
 private:
    void ParseBoardState(std::string console_string);
    int Slimes(int cell);
    void GetXY(int cell, int& r, int& c);
    bool CanJumpFromHere(int cell, int& jump_to_cell, int& rad);
    int CalcRadius(int cell);
    bool CheckJumpDist(int x, int y);

    int player_num_;
    std::size_t board_dim_;
    std::size_t sq_;
    std::vector< std::vector<int> > slimes_;
};
Board::Board(std::string input_string) 
    : player_num_(0), 
      board_dim_(0),
      slimes_() {
    board_dim_ = std::count(input_string.begin(), input_string.end(), ',');
    sq_ = board_dim_ * board_dim_;
    std::istringstream temp(input_string.substr(0,1));
    temp >> player_num_;
    ParseBoardState(input_string);
}
void Board::ParseBoardState(std::string console_string) {
    int place = 0;
    for (std::size_t row = 0; row < board_dim_; ++row ) {
        slimes_.push_back(std::vector<int>());
        place = console_string.find(",",place+1);
        std::string temp2 = console_string.substr(place+1, 8);
        for (std::size_t col = 0; col < board_dim_; ++col ) {
            int sl = 0;
            std::istringstream bint(temp2.substr(col,1));
            bint >> sl;
            slimes_[row].push_back(sl);
        }
    }
}
int Board::Slimes(int cell) {
    int r = 0;
    int c = 0;
    GetXY(cell, r, c);
    return  slimes_[r][c];
}
void Board::GetXY(int cell, int& r, int& c) {
    for (std::size_t row = 0; row < board_dim_; ++row ) {
        for (std::size_t col = 0; col < board_dim_ ; ++col ) {
            if ( (row * board_dim_ + col) == cell) {
                r = row;
                c = col;
            }
        }
    }
}
void Board::Move() {

    // go through each cell:
    int index = 0;
    int jump_to_cell = 0;
    int rad = 0;
    int min_rad = 1000;
    int best_jump_to = -1;
    int best_jump_from = -1;
    for (int c = 0; c < sq_; ++c) {
        if (Slimes(c) == player_num_) {
            if (CanJumpFromHere(c, jump_to_cell , rad)) {
                if (rad < min_rad) {
                    best_jump_from = c;
                    best_jump_to = jump_to_cell;
                    min_rad = rad;
                }
                index += 1;
            }
        }
    }

    int ret_row = 0;
    int ret_col = 0;

    if (index == 0) {
        // can't jump so dont bother:
        std::cout << "0 0 0 0" << std::endl;
    } else {
        GetXY(best_jump_from, ret_row, ret_col);
        std::cout << ret_row << " " << ret_col  << " ";
        GetXY(best_jump_to, ret_row, ret_col);
        std::cout << ret_row << " " << ret_col << std::endl;
    }
}
bool Board::CanJumpFromHere(int cell, int& ret_jump_to_cell, int & ret_rad) {
    int r = 0;
    int c = 0;
    int rad = 10000;
    int jump_to_cell = 0;
    int rad_min_for_this_cell = 10000;
    GetXY(cell, r, c);
    bool jumpable = false;
    for (int row_test = -2; row_test < 3; ++row_test) {
        for (int col_test = -2; col_test < 3; ++col_test) {
            if ( (r + row_test) > 0 &
                 (r + row_test) < board_dim_ &&
                 (c + col_test) > 0 &&
                 (c + col_test) < board_dim_ &&
                 (CheckJumpDist(col_test, row_test)) &&
                 (slimes_[r+row_test][c+col_test] == 0)) {

                jumpable = true;
                jump_to_cell = (r + row_test) * board_dim_ + c + col_test;
                rad = CalcRadius(jump_to_cell);

                if (rad < rad_min_for_this_cell) {
                    ret_rad = rad;
                    ret_jump_to_cell = jump_to_cell;
                    rad_min_for_this_cell = ret_rad;
                }
            }
        }
    }
    return jumpable;
}
bool Board::CheckJumpDist(int x, int y) {
    int maxDelta = maxn(absn(x), absn(y));
    if (maxDelta <= 0 || maxDelta > 2) {
        return false;
    } else {
        return true;
    }
}
int Board::CalcRadius(int cell) {
    int r = 0;
    int c = 0;
    GetXY(cell, r, c);
    // unnecessary accuracy considering how bad this bot is:
    float mid = static_cast<float>(board_dim_) / 2;
    float rad = sqrt((r - mid) * (r - mid) + (c-mid)*(c-mid));
    int ret = static_cast<int>(rad + 0.5);
    return ret;
}
int main(int argc, char* argv[]) {
    if (argc != 2) {
        return 0;
    } else {
        std::string input_string(argv[1]);
        Board board(input_string);
        board.Move();
    }
    return 0;
}

আমি আপনার পদক্ষেপ যাচাইকরণ চুরি করেছি। এছাড়াও আমি শুরু করার ঠিক পরে সঠিক কোডিং অনুশীলন ত্যাগ করেছি, তাই দেখুন না। যাইহোক, এটি বোর্ডের যে কোনও আকারে চলবে বলে মনে হয়।


2

ডেথস্লাইম :

বর্ণনা : দুর্বলতম শত্রুকে শিকার করার এবং তাদের ধ্বংস করার চেষ্টা করে। পদ্ধতি পুনরাবৃত্তি করুন।

কীভাবে চালাবেন : রুবি ডেথস্লাইম.আরবি

রুবি সংস্করণ : ২.১.২

#!/usr/bin/env ruby
class PlayerPosition;
  attr_accessor :x, :y;
  def initialize(x, y) @x = x; @y = y; end
  def distance(pos) Math.sqrt((pos.x - @x)**2 + (pos.y - @y)**2); end
end

class Board
  attr_reader :player, :empty_positions
  def initialize(player_id, game_state_string)
    @player_positions = {}
    @empty_positions = []

    @enemies = []
    @player = Player.new

    row = 0
    col = 0
    game_state_string.chars.each do |tile|
      row += 1 and col = 0 and next if tile == ','
      @empty_positions << PlayerPosition.new(col, row) and col += 1 and next if tile == '.'

      @player_positions[tile] ||= []
      @player_positions[tile] << PlayerPosition.new(col, row)
      col += 1
    end

    @player_positions.each do |id, positions|
      @enemies << Player.new(id, positions) if id != player_id
      @player = Player.new(id, positions) if id == player_id
    end
  end

  def border_space(player_positions, possible_border, allowance = 1)
    near = []
    possible_border.each do |border|
      is_near = false
      player_positions.each {|pos| is_near = true and break if pos.distance(border) <= allowance}
      near << border if is_near
    end
    near
  end

  def closest_to(player_positions, enemy_positions)
    player_closest_block = nil
    shortest_distance = 1000
    enemy_closest_block = nil
    player_positions.each do |player|
      enemy_positions.each do |enemy|
        if player.distance(enemy) < shortest_distance
          shortest_distance = player.distance(enemy)
          enemy_closest_block = enemy
          player_closest_block = player
        end
      end
    end
    return player_closest_block, enemy_closest_block
  end

  def empty_space_near(player_positions, allowance = 1); border_space(player_positions, @empty_positions, allowance); end
  def weakest_enemy; @enemies.select{|enemy| !enemy.dead? }.sort {|x,y| x.strength <=> y.strength}.first; end
end

class Player
  attr_reader :positions
  def initialize(id = -1, positions = []); @id = id; @positions = positions; end
  def dead?; @positions.length == 0; end
  def strength; @positions.length; end
  def can_hurt?(enemy)
    is_close_enough = false
    self.positions.each do |my_pos|
      enemy.positions.each {|enemy_pos| is_close_enough = true and break if my_pos.distance(enemy_pos) <= 2 }
    end
    is_close_enough
  end
end




class DeathSlime

  def initialize(arg_string)
    game_state = arg_string[2..-1]
    player_id = arg_string[0]
    @board = Board.new(player_id, game_state)
  end

  def attack
    if @board.weakest_enemy
      try_to_spread_to_weakest || try_to_jump_to_weakest || try_to_merge_to_weakest || try_to_move_to_weakest
    else
      try_to_move if @empty_positions.length > 0
    end
  end


  def try_to_spread_to_weakest
    mine = @board.empty_space_near(@board.player.positions, 1)
    theirs = @board.empty_space_near(@board.weakest_enemy.positions, 1)
    target_space = mine.detect{|space| theirs.include?(space) }
    return move(@board.closest_to(@board.player.positions, [target_space]).first, target_space) if target_space
    false
  end

  def try_to_jump_to_weakest
    mine = @board.empty_space_near(@board.player.positions, 2)
    theirs = @board.empty_space_near(@board.weakest_enemy.positions, 1)
    target_space = mine.detect{|space| theirs.include?(space) }
    return move(@board.closest_to(@board.player.positions, [target_space]).first, target_space) if target_space
    false
  end

  def try_to_merge_to_weakest
    definite_border = nil
    definite_merge = nil
    possible_border = @board.border_space(@board.weakest_enemy.positions, @board.player.positions)
    possible_border.each do |border|
      possible_merges = @board.border_space([ border ], @board.player.positions.select{|space| space != border })
      definite_merge = possible_merges.first and definite_border = border and break if possible_merges.length > 0
    end
    return move(definite_merge, definite_border) if definite_border && definite_merge
    false
  end

  def try_to_move_to_weakest
    player_closest, enemy_closest = @board.closest_to(@board.player.positions, @board.weakest_enemy.positions)
    spreading_distance = @board.empty_space_near([player_closest], 1)
    jumping_distance = @board.empty_space_near([player_closest], 2)
    theirs = @board.empty_space_near(@board.player.positions, 2)

    spreading_space = spreading_distance.detect{|space| theirs.include?(space) }
    return move(@board.closest_to(@board.player.positions, [spreading_space]).first, spreading_space) if spreading_space

    jumping_space = jumping_distance.detect{|space| theirs.include?(space) }
    return move(@board.closest_to(@board.player.positions, [jumping_space]).first, jumping_space) if jumping_space

    return move(@board.closest_to(@board.player.positions, [spreading_distance]).first, spreading_distance) if spreading_distance.length > 0
    return move(@board.closest_to(@board.player.positions, [jumping_distance]).first, jumping_distance) if jumping_distance.length > 0

    #merge randomly
    closest_enemy = @board.closest_to(@board.player.positions, @board.weakest_enemy.positions).first
    return move(@board.closest_to(@board.player.positions.select{|space| space != closest_enemy }, [closest_enemy]).first, closest_enemy)
  end

  def try_to_move
    spreading_distance = @board.empty_space_near(board.player.positions, 1)
    jumping_distance = @board.empty_space_near(board.player.positions, 2)

    return move(@board.closest_to(@board.player.positions, [spreading_distance]).first, spreading_distance) if spreading_distance.length > 0
    return move(@board.closest_to(@board.player.positions, [jumping_distance]).first, jumping_distance) if jumping_distance.length > 0
  end

  def move(start_block, end_block)
    STDOUT.write "#{start_block.x} #{start_block.y} #{end_block.x} #{end_block.y}"
    true
  end
end

slime_of_death = DeathSlime.new(ARGV[0])
slime_of_death.attack

1

শৈবাল

এটি আর-তে লেখা একটি বট, এটি ব্যবহার করে ট্রিগার করা দরকার Rscript Lichen.R

input <- strsplit(commandArgs(TRUE),split=",")[[1]]
me <- input[1]
arena <- do.call(rbind,strsplit(input[-1],""))
n <- sum(arena==me)
where <- which(arena==me,arr.ind=TRUE)
closest <- function(a,b){
    x <- abs(outer(a[,1],b[,1],`-`))
    y <- abs(outer(a[,2],b[,2],`-`))
    matrix(which(x<2&y<2,arr.ind=TRUE),ncol=2)
    }
if(n==0){ #No slime on the board
    out <- "0 0 0 0"
    }else if(n==1){ #One slime on the board
        x <- where[1]+c(1,-1)
        y <- where[2]+c(1,-1)
        out <- paste(where[1]-1,where[2]-1,x[x%in%2:(nrow(arena)-1)]-1,y[y%in%2:(nrow(arena)-1)]-1,sep=" ")
    }else{
        area <- apply(which(arena==me,arr.ind=TRUE),2,range,na.rm=TRUE)
        empty <- matrix(which(arena==".",arr.ind=TRUE),ncol=2)
        opponents <- c("1","2","3","4")[c("1","2","3","4")!=me]
        for(i in seq_along(opponents)){
            if(i==1){
                other <- which(arena==opponents[i],arr.ind=TRUE)
                }else{other <- rbind(other,which(arena==opponents[i],arr.ind=TRUE))}
            }
        fillable <- matrix(empty[empty[,1]%in%area[1,1]:area[2,1]&empty[,2]%in%area[1,2]:area[2,2],],ncol=2)
        enemies <- matrix(other[other[,1]%in%area[1,1]:area[2,1]&other[,2]%in%area[1,2]:area[2,2],],ncol=2)
        if(length(unique(where[,2]))==1 | length(unique(where[,2]))==1){ #Slimes form a line
            W <- closest(where,empty)
            if(nrow(W)){
                out <- paste(c(where[W[1,1],]-1,empty[W[1,2],]-1),collapse=" ")
            }else{out <- "0 0 0 0"}
        }else if(length(enemies)&length(fillable)){ #There are enemies and empty spaces in habitable area
            w <- closest(enemies, fillable)
            if(nrow(w)){
                X <- abs(where[,1]-fillable[w[1,2],1])
                Y <- abs(where[,2]-fillable[w[1,2],2])
                W <- which(X<2&Y<2)
                out <- paste(c(where[W[1],]-1,fillable[w[1,2],]-1),collapse=" ")
            }else{out <- "0 0 0 0"}
        }else if(length(fillable)){ #There are empty spaces in habitable area
            w <- closest(fillable,where)
            out <- paste(c(where[w[1,2],]-1,fillable[w[1,1],]-1),collapse=" ")
        }else{
            x <- area[!area[,1]%in%c(1,nrow(arena)),1]
            y <- area[!area[,2]%in%c(1,ncol(arena)),2]
            if(sum(arena[x+(-1:1),y+(-1:1)]==".")>1){
                w <- where[where[,1]%in%(x+c(1,-1))&where[,2]%in%(y+c(1,-1)),]
                out <- paste(w[1]-1,w[2]-1,x-1,y-1,sep=" ")
            }else{
                W <- closest(where, empty)
                if(nrow(W)){
                    out <- paste(c(where[W[1,1],]-1,empty[W[1,2],]-1),collapse=" ")
                }else{out <- "0 0 0 0"}
            }
        }
    }
cat(out)

উদ্দেশ্যযুক্ত অ্যালগরিদমটি এটি একটি আয়তক্ষেত্রাকার অঞ্চলটি coverাকতে চেষ্টা করে (ফাঁকা অংশটি ব্যবহার করে spread)। আয়তক্ষেত্রটি সম্পূর্ণ হয়ে mergesগেলে , "বাসযোগ্য" অঞ্চলটি প্রসারিত করার জন্য এটির এক কোণার (বোর্ডের কোণায় সবচেয়ে দূরে এক) দুটি স্লাইমস, তারপরে সেই নতুন সংজ্ঞায়িত আয়তক্ষেত্রটি পূরণ করুন, এটি ব্যবহার করে না jump

.....   .....   .....   .....   .....   ..333
.....   .333.   3333.   3333.   3333.   33333
333..   3333.   3333.   3333.   3333.   33.33
333..   3.33.   3.33.   3333.   3333.   3333.
333..   333..   333..   333..   3333.   3333.

কোনও শত্রু যদি আবাসযোগ্য স্থানে থাকে এবং সেই সাথে খালি জায়গাও থাকে তবে এটি তার পাশের খালি জায়গাটি পূরণ করে। আবাসযোগ্য অঞ্চলটি প্রসারিত করার সময় যে পাতাগুলি একত্রীকরণ করতে হবে তা যদি শত্রুদের দ্বারা ঘিরে থাকে, তবে spreadএই একীভূত হওয়ার পরিবর্তে একটি প্লেইম হবে ।


আমি এর জন্য একগুচ্ছ ত্রুটি পাচ্ছি ( স্ট্যাকট্রেসের জন্য চ্যাট দেখুন )।
ডুরকনব

0 0 0 0বোর্ডে কোনও স্লাইম না থাকলে বট এখন পাঠান ।
প্ল্যানাপাস

0

CornerSlime

এই স্লাইমের কোণগুলির একটি ধারণা রয়েছে, বা কমপক্ষে আমি যখন এটি প্রথম # সি-এ লিখেছিলাম তখন আমি আর নিশ্চিত নই।

সি ++ এ লিখিত, সম্ভবত জিসিসি দিয়ে জরিমানা সংকলন করবে এবং কোনও যুক্তি ছাড়াই থাকবে না; আশা করি দুর্ঘটনাক্রমে আমি নির্দিষ্ট কিছু এমএসভিসি ব্যবহার করিনি।

পরিবর্তিত সার্ভারে নিজের বিরুদ্ধে একচেটিয়াভাবে পরীক্ষিত (যেখানে আমি আছি সেখানে নতুন কোনও সি ++ সংকলক নেই) সুতরাং এটি কীভাবে সম্পাদন করবে তা সম্পর্কে আমার কোনও ধারণা নেই, আশাকরি এটি খুব ধীর হওয়ার কারণে অযোগ্য ঘোষণা করা হবে না। এই বটটিতে বর্তমানে কোনও এলোমেলোতা নেই তবে পরবর্তী সময়ে আমি কিছু যুক্ত করতে পারি।

এটি সি #+ কে সি ++ (গতির উদ্বেগের কারণে) এর মাধ্যমে যুক্ত করা হয়েছে যারা সত্যিকার অর্থে সি ++ জানেন না এবং ভয়াবহ। এটি সেলগুলির একটি অ্যারে তৈরি করে শুরু হয়, যা এরপরে এটি চারপাশের কোষগুলির সম্পর্কে সমস্ত ধরণের অস্বাস্থ্যকর তথ্য (আমার কোষের সংখ্যা, আমার স্লাইমের সংখ্যা, সেই ধরণের জিনিস) দিয়ে পূর্ণ করে। তারপরে এটি এই তথ্যটি তৈরি করতে ব্যবহৃত তথ্যটি আরও ঘনিষ্ঠভাবে দেখার প্রয়োজন কিনা তা সিদ্ধান্ত নিতে এটি ব্যবহার করে এবং তারপরে একটি অর্থবহ আউটপুট উত্পাদন করার জন্য সম্ভাব্যভাবে বলা তথ্য ব্যবহার করে।

#include <iostream>

#define min(a,b) a>b?b:a;
#define max(a,b) a>b?a:b;

#define null 0 // fun times

struct Cell
{
public:
    int t;
    int x, y;
    int counts1[5];
    int counts2[5];
    int ecount1;
    int ecount2;
    bool safe1;
    bool safe2;

    bool canspread;
    bool canjump;
    bool canmerge;

    bool spreadable;
    bool jumpable;
    bool mergeable;

    Cell()
    {
        for (int i = 0; i < 5; i++)
        {
            counts2[i]=counts1[i]=0;
        }
        ecount1=ecount2=0;
        safe1=safe2=mergeable=jumpable=spreadable=canmerge=canjump=canspread=false;
    }

    Cell(int tN, int xN, int yN) // not sure why I can't call () constructor here
    {
        for (int i = 0; i < 5; i++)
        {
            counts2[i]=counts1[i]=0;
        }
        ecount1=ecount2=0;
        safe1=safe2=mergeable=jumpable=spreadable=canmerge=canjump=canspread=false;

        t = tN;
        x = xN;
        y = yN;
    }

    void findOptions(int moi)
    {
        if (t == 0)
        {
            if (counts1[moi] > 0)
                spreadable = true;
            if (counts2[moi] > 0)
                jumpable = true;
        }
        else if (t == moi)
        {
            if (counts1[moi] > 0)
                mergeable = canmerge = true;
            if (counts1[0] > 0)
                canspread = true;
            if (counts2[0] > 0)
                canjump = true;
        }
    }
};

const int dim = 8;
const int hdim = 4;

int moi;
int chezMoi;

int target;
int chezTarget;

Cell cells[dim][dim];

int cornerCounts[4][5];
int totalCounts[5];

// ring ness - why why why

// end ring ness

int tlx;
int tly;
int thx;
int thy;

int alx;
int aly;
int ahx;
int ahy;

int rj;
int rstate;

void ring(int x, int y, int dist)
{   
    tlx=x-dist;
    tly=y-dist;
    thx=x+dist;
    thy=y+dist;

    alx=max(0, tlx);
    aly=max(0, tly);
    ahx=min(dim-1, thx);
    ahy=min(dim-1, thy);

    rstate = 0;
}

bool nextR(Cell** outc)
{
    if (rstate == 1)
    {
        goto state1;
    }
    if (rstate == 2)
    {
        goto state2;
    }
    if (rstate == 3)
    {
        goto state3;
    }
    if (rstate == 4)
    {
        goto state4;
    }

    if (alx == tlx)
    {
        rj = aly - 1;
        rstate = 1;
    }
state1:
    if (alx == tlx)
    {
        if (++rj <= ahy)
        {
            *outc = (cells[alx]+rj);
            return true;
        }
        alx++;
    }

    if (ahx == thx)
    {
        rj = aly - 1;
        rstate = 2;
    }
state2:
    if (ahx == thx)
    {
        if (++rj <= ahy)
        {
            *outc = (cells[ahx]+rj);
            return true;
        }
        ahx--;
    }

    if (aly == tly)
    {
        rj = alx - 1;
        rstate = 3;
    }
state3:
    if (aly == tly)
    {
        if (++rj <= ahx)
        {
            *outc = (cells[rj]+aly);
            return true;
        }
    }

    if (ahy == thy)
    {
        rj = alx - 1;
        rstate = 4;
    }
state4:
    if (ahy == thy)
    {
        if (++rj <= ahx)
        {
            *outc = (cells[rj]+ahy);
            return true;
        }
    }

    return null;
}

int cox;
int coy;

int ci;
int cj;

void corner(int idx)
{
    cox = (idx / 2) * hdim;
    coy = (idx % 2) * hdim;

    ci = 0;
    cj = -1;
}

bool nextC(Cell** outc)
{
    for (;ci < hdim;ci++)
    {
        for (;++cj < hdim;)
        {
            *outc = (cells[ci+cox]+cj+coy);
            return true;
        }
        cj = -1;
    }

    return false;
}

void cornerCount(int idx, int* c)
{
    int ox = (idx / 2) * hdim;
    int oy = (idx % 2) * hdim;

    for (int i = 0; i < hdim; i++)
    {
        for (int j = 0; j < hdim; j++)
        {
            c[cells[i+ox][j+oy].t]++;
        }
    }
}

void ringCount(int x, int y, int dist, int* c)
{
    int tlx=x-dist;
    int tly=y-dist;
    int thx=x+dist;
    int thy=y+dist;

    int alx=max(0, tlx);
    int aly=max(0, tly);
    int ahx=min(dim-1, thx);
    int ahy=min(dim-1, thy);

    if (alx == tlx)
    {
        for (int j = aly; j <= ahy; j++)
            c[cells[alx][j].t]++;
        alx++;
    }
    if (ahx == thx)
    {
        for (int j = aly; j <= ahy; j++)
            c[cells[ahx][j].t]++;
        ahx--;
    }
    if (aly == tly)
    {
        for (int i = alx; i <= ahx; i++)
            c[cells[i][aly].t]++;
    }
    if (ahy == thy)
    {
        for (int i = alx; i <= ahx; i++)
            c[cells[i][ahy].t]++;
    }
}

int trans(char c)
{
    return c<48?0:c-48;
}

std::string res(Cell* ca, Cell* cb)
{
    char buff[100]; // shhh
    sprintf_s(buff, "%d %d %d %d\n", ca->x, ca->y, cb->x, cb->y);
    return std::string(buff);
}

std::string go(char* inp)
{
    moi = trans(inp[0]);

    int a = 2;

    for (int i = 0; i < dim; i++)
    {
        for (int j = 0; j < dim; j++)
        {
            cells[i][j] = Cell(trans(inp[a]), i, j);
            a++;
        }
        a++;
    }

    // count corners and totals
    for (int i = 0; i < 4; i++)
    {
        cornerCount(i, cornerCounts[i]);
        for (int j = 0; j < 5; j++)
        {
            totalCounts[j] += cornerCounts[i][j];
        }
    }

    // count and find cell options
    for (int i = 0; i < dim; i++)
    {
        for (int j = 0; j < dim; j++)
        {
            Cell* c = cells[i]+j;

            ringCount(i, j, 1, c->counts1);
            ringCount(i, j, 2, c->counts2);

            // safeness
            for (int r = 1; r < 5; r++)
            {
                if (r != moi)
                {
                    c->ecount1 += c->counts1[r];
                    c->ecount2 += c->counts2[r];
                }
            }
            c->safe1 = c->ecount1 == 0 && c->counts1[0] == 0; // surrounded by moi
            c->safe2 = c->ecount1 == 0 && c->ecount2 == 0; // no enemies in sight

            // that funcion which does stuff
            c->findOptions(moi);
        }
    }

    // find chezMoi
    chezMoi = moi-1; // might work, can't be bothered to work it out
    for (int i = 1; i < 4; i++)
    {
        if (cornerCounts[i][moi] > cornerCounts[chezMoi][moi])
            chezMoi = i;
    }

    int best = 0;

    if (cornerCounts[chezMoi][moi] < hdim * hdim)
    {
        // fill our corner
        best = 0;
        Cell* ac = null;
        Cell* bc = null;

        corner(chezMoi);
        Cell* c;
        while (nextC(&c))
        {
            if (c->spreadable && c->ecount1 + 1 > best)
            {
                ring(c->x, c->y, 1);
                Cell* oc;
                while (nextR(&oc))
                {
                    if (oc->canspread)
                    {
                        best = c->ecount1 + 1;
                        ac = oc;
                        bc = c;
                        break;
                    }
                }
            }
            if (c->mergeable && c->counts1[0] - 1 > best)
            {
                ring(c->x, c->y, 1);
                Cell* oc;
                while (nextR(&oc))
                {
                    if (oc->safe2 && oc->canmerge && c->counts1[0] > 0)
                    {
                        best = c->counts1[0] - 1;
                        ac = oc;
                        bc = c;
                        break;
                    }
                }
            }
        }

        if (bc != null)
        {
            return res(ac, bc);
        }
    }

    // pick target (why?)
    target = -1;
    best = 0;
    for (int i = 0; i < 4; i++)
    {
        if (i == moi)
            continue;
        int cur = totalCounts[i];
        if (target == -1 || cur > best)
        {
            target = i;
            best = cur; 
        }
    }

    if (target != -1)
    {
        for (int i = 0; i < 4; i++)
        {
            if (i == chezMoi)
                continue;
            int cur = cornerCounts[i][target];
            if (chezTarget == -1 || cur > best)
            {
                chezTarget = i;
                best = cur;
            }
        }

        // attack chosen target (not sure it does this anymore...)
        best = 0;
        Cell* ac = null;
        Cell* bc = null;

        for (int i = 0; i < dim; i++)
        {
            for (int j = 0; j < dim; j++)
            {
                Cell* c = cells[i]+j;

                if (c->spreadable && c->ecount1 + 1 > best)
                {
                    ring(c->x, c->y, 1);
                    Cell* oc;
                    while (nextR(&oc))
                    {
                        if (oc->canspread)
                        {
                            best = c->ecount1 + 1;
                            ac = oc;
                            bc = c;
                            break;
                        }
                    }
                }
                if (c->jumpable && c->ecount1 - 1 > best)
                {
                    ring(c->x, c->y, 2);
                    Cell* oc;
                    while (nextR(&oc))
                    {
                        if (oc->safe2 && oc->canjump)
                        {
                            best = c->ecount1 - 1;
                            ac = oc;
                            bc = c;
                            break;
                        }
                    }
                }
            }
        }

        if (bc != null)
        {
            return res(ac, bc);
        }
    }

    return "0 0 0 0\n";
}

int main(int argc, char* args[])
{
    printf(go(args[1]).c_str());
    return 0;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.