О, я люблю ці ігри!
Тож спочатку все, для того, щоб комп'ютер грав у гру, йому потрібно:
- структура, з якою працювати
- правила грати
- виграшна умова працювати
Давайте вирішимо цю деталь за раз.
Будова
Оскільки плата є сіткою 8х8 (але її можна легко масштабувати), і кожен простір сітки може існувати лише в одному з п’яти станів, давайте визначимо ці стани:
[EMPTY, WHITE_PIECE, BLACK_PIECE, WHITE_PIECE_PROMOTED, BLACK_PIECE_PROMOTED]
Відповідно ENUM повинен:
[0, 1, 2, 3, 4]
Тепер, коли ми знаємо, яким може бути кожен пробіл, нам потрібен спосіб представити всі пробіли, або дошка, якщо ви хочете. Майже кожна сильна мова підтримуватиме багатовимірний масив (масив, де кожен елемент є масивом, що містить дані). Тому візьміть наступний слабій-код для визначення нашого масиву:
BOARD_ARRAY = array(8, 8)
Це дасть нам масив 8 x 8, в якому ми можемо зберігати цілі числа (наші перерахунки раніше):
(
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
)
Тепер ви вже можете бачити, як це починає виглядати як дошка! Я ніколи не грав варіант, згаданий у відео YouTube, але, здається, він починається з 2 рядів білих шматочків, один ряд знизу, і 2 ряди чорних шматочків, один ряд зверху. Що буде означати, коли ми починаємо гру, наш масив повинен виглядати так:
(
[0, 0, 0, 0, 0, 0, 0, 0],
[2, 2, 2, 2, 2, 2, 2, 2],
[2, 2, 2, 2, 2, 2, 2, 2],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 0, 0],
)
(Пам'ятайте, 2 позначає "BLACK_PIECE", а 1 являє собою "WHITE_PIECE")
Тож тепер комп'ютер має структуру, з якою працювати. Крок 1 завершений!
Правила
Давайте уявимо, що перед вами була встановлена фактична дошка, яка грала проти головного гравця. Якби ви спробували перенести одну з його частин, ви отримаєте руку. Якщо ви спробували перенести шматок так, як не змогли, ви потрапили в руки. Якщо ви спробували добре обдурити ... ви отримаєте думку. Але проблема полягає в тому, що комп’ютери ні. Тож наша робота - забезпечити суворі правила, в яких потрібно грати.
Нам потрібно створити спосіб перевірити, чи є певний хід "законним". Що означає, що нам спочатку потрібен якийсь спосіб представити "хід". Одним із способів було б використання позицій масиву; Наприклад, щоб перемістити фрагмент з [0, 0] до [0, 1], ми могли б створити функцію, яка буде оновлювати дошку з огляду на цей хід. Тож повертаємось до млявості:
MY_MOVE = array( [0, 0], [0, 1] )
Вищеописане являє собою одну частину, рухаючись на простір вниз від верхнього кута дошки (припустимо, що 0, 0 - верхній лівий кут). Ви також можете помітити, що я вирішив використовувати для переміщення багатовимірний масив. Це відбувається тому, що шматки теоретично можуть рухатися велику кількість разів за один виток (для «стрибків» інших фігур). Тож давайте зробимо вигляд, що на рівні 0, 1 з'явилася команда суперника, тобто ми висадимось у 0, 2:
MY_MOVE = array( [0, 0], [0, 2] )
Досить простий ах. Програма повинна розуміти, що якщо ми пропустимо пробіл, ми перестрибуємо інший шматок (інакше це незаконний хід, і слід викинути помилку). Тепер перескочимо дві частини:
MY_MOVE = array ( [0, 0], [0, 2], [0, 4] )
Це дає нам змогу описати будь-який хід на дошці. Так! Оскільки я не повністю розумію правила точної гри, про яку йдеться (хоча я в цей день грав трохи в канадські шашки), точну правомірність руху потрібно визначити саме ви. Хороший потік до цього моменту виглядатиме так:
FUNCTION_FIND_ALL_LEGAL_MOVES( MY_BOARD ) Returns: array ALL_LEGAL_MOVES
FUNCTION_FIND_BEST_MOVE( MY_BOARD, ALL_LEGAL_MOVES ) Returns: array MY_MOVE
FUNCTION_DO_MOVE( MY_BOARD, MY_MOVE ) Throws: error ILLEGAL_MOVE Updates: MY_BOARD
repeat from start for each turn
Наведене вище передбачає, що ви можете переглядати кожну частину, щоб знайти всі її законні кроки, а потім, отримавши колекцію всіх законних кроків, якимось чином вибрати найкращий (стратегія тут). Потім хід застосовується до дошки або видає помилку. Потім наступний гравець приймає свою чергу. Отже, у нас є AI, який вміє грати! Радість! Жити далі.
Перемога
Прості ігри чудові, адже перемога визначається дуже простим станом. На дошці немає білих шматочків? Ну я здогадуюсь ви виграли! Це реалізується на кроці 2, коли ми обираємо найкращий хід, щоб наблизити нас до умови виграшу.
Щоб зробити якийсь дуже розумний AI, ви могли б зберігати базу даних, яка зберігала всі можливі дошки як стан, при кожному можливому переході від усіх можливих станів, щоб знайти ланцюги до перемоги.
Ви також можете створити такі стратегії, як-от: якщо є фрагмент, який ЩО БУДЕ стрибнути, збережіть цю частину або якщо шматок здатний стрибати більше, ніж один інший фрагмент, виконайте цей стрибок.
Це повинно дати вам хороший стрибок з точки зору, це лише один метод буквально необмежених можливостей. Теоретично ви могли б створити гігантського робота для малювання кольоровими олівцями, а потім провести спектральний аналіз на кресленні, щоб вибрати рухи ..., але це не спрацювало б дуже добре чи швидко. Цей спосіб спрацював і раніше, і добре працював (: Сподіваюсь, що допомагає!
Кілька слів про реалізацію
Шашки - це те, що називається грою, що вирішується, оскільки ми можемо обчислювати кожен хід, не знаючи. Але це цілий штрих рухів! Тож немає ніякого способу зробити це вручну ... якби тільки були які ... о так, ми програмісти. кулаковий насос
SQL - прекрасний інструмент для зберігання всіх цих, здавалося б, нескінченних кроків. Для тих, хто не має досвіду роботи з SQL, mySQL - це безкоштовний (досить простий у користуванні) сервер з відкритим кодом SQL. SQL використовується для управління базами даних, подібними до електронних таблиць на стероїдах. Він також здатний зберігати серйозно великий обсяг даних і дуже швидко працювати з ними.
То як ми можемо цим скористатися? Оскільки ми знаємо, що якщо дошка знаходиться в точному стані (кожен шматок у певному положенні), ми можемо обчислити всі наявні рухи та зберегти їх. Наприклад:
+Board State+ +All Possible Moves+ +Best Move+
([0,0,1,2,3],[3..) ([0,1],[0,2]), ([7,6],[7,7],[5..) ([7,6],[7,7])
([0,0,2,2,3],[3..) ([0,1],[0,2]), ([7,6],[7,7],[5..) ([5,5],[5,4])
([0,0,1,3,3],[3..) ([0,1],[0,2]), ([7,6],[7,7],[5..) ([4,4],[4,3])
etc...
Отже, коли комп'ютер повинен зробити рух, він просто шукає стан плати (зберігається в якості основного ключа) в базі даних, і може або вибрати найкращий хід (повинен бути неперевершеним), або один з інших кроків, щоб зробити більш дружнім AI.
Чудово зараз давайте створимо цю базу даних. Спочатку нам потрібно обчислити кожен стан плати. Що можна зробити за допомогою великої неприємної петлі, якщо хтось хоче витратити якийсь час і опрацювати це, було б дивним. Подивіться на масив як на одне велике число, потім порахуйте вгору, за винятком бази 5 (0, 1, 2, 3, 4), і за умови, що у кожного гравця може бути лише 16 штук.
На даний момент у нас повинен зберігатися кожен стан плати і ми можемо провести обчислення всіх можливих кроків.
Після того, як всі можливі рухи будуть обчислені, це найцікавіша частина проходження найкращих кроків. Тут мої знання починають стихати, і такі речі, як Minimax або A *, починають грати. Вибачте, я не можу допомогти в цьому: /