Tworzenie własnego bota, cz. 1: Podstawy

02.11.2012 - Kuba Kowalski
Trudność

Tworzenie bota do gry Kółko i krzyżyk

Przedstawimy teraz krok po kroku metodę konstrukcji prostego bota grającego w grę Kółko i krzyżyk. Bot ten będzie stawiał swój symbol na losowym niezajętym dotychczas przez nikogo polu i zostanie przygotowany jedynie do standardowego trybu gry. Kod bota będzie tworzony równolegle w dwóch językach programowania: Python i C++.

Pola na planszy są to pary liczb. Ponieważ ograniczamy się do gry standardowej, możliwych jest 9 takich par: (0, 0), (0, 1), (0, 2), (1, 0), ..., (2, 2). Zauważmy, że korzystając z dzielenia całkowitoliczbowego oraz operacji modulo (reszty z dzielenia) możemy te pary zakodować jako dziewięć kolejnych liczb od 0 do 8. Wtedy np. liczbie 7 odpowiada para (2, 1) (bo 7/3 = 2 i 7%3 = 1), natomiast parze (1, 2) odpowiada liczba 5 (bo 5 = 1*3 + 2).

Zasada działania bota będzie polegała na pamiętaniu listy wolnych pól na planszy zakodowanych jako pojedyncze liczby i stopniowym usuwaniu ich jeśli któryś z zawodników postawi na nich swój symbol. Aby wykonać ruch, bot po prostu wylosuje jeden z pozostałych w liście elementów, odkoduje przypisane mu pole i usunie z listy.

Na początku wczytujemy odpowiednie biblioteki, inicjalizujemy generator liczb losowych, tworzymy i wypełniamy listę wolnych pól (początkowo są na niej wszystkie pola). Cała reszta kodu będzie się działa w nieskończonej pętli.

Python
1
2
3
4
5
import random
 
free = range(9)
 
while True:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdlib.h>
#include <time.h>
 
using namespace std;
 
int main ()
{
   int x, y;
   srand ( time(NULL) );
   vector<int> free (9, 0);
   for (int i = 0; i < 8; i++)
      free[i] = i;
 
   while (true)
   {

Pierwszą czynnością, którą chcemy aby nasz bot wykonał w każdej turze jest uzyskanie wiedzy o ostatnim wykonanym ruchu. Korzystamy w tym celu z zapytania LastMove zwracającego dwie liczby oddzielone spacją. Pozyskane współrzędne zapisujemy jako zmienne x i y.

Python
1
   x, y = map(int, raw_input("LastMove\n").split())

C++
1
2
      cout << "LastMove" << endl;
      cin >> x >> y;

Następnie chcemy usunąć to pole z listy wolnych pól, należy je więc zakodować jako jedną liczbę wzorem x*3+y. Musimy jednak pamiętać o przypadku gdy żaden ruch nie został wcześniej wykonany (zapytanie zwraca -1 -1), wtedy nic z listy nie usuwamy.

Python
1
2
   if x != -1:
      free.remove(x*3 + y)

C++
1
2
      if (x != -1)
         free.erase(remove(free.begin(), free.end(), x*3+y), free.end());

Kolejnym krokiem jest losowy wybór wolnego pola w postaci zakodowanej oraz usunięcie go z listy wolnych pól (za chwilę nie będzie ono wolne ponieważ zaraz postawimy tam symbol).

Python
1
2
   move = random.choice(free)
   free.remove(move)

C++
1
2
      int move = free[rand()%free.size()];
      free.erase(remove(free.begin(), free.end(), move), free.end());

Pozostało jedynie, korzystając z komendy PlaceSymbol 0 0, wysłać do gry wybrany ruch i zakończyć turę.

Python
1
2
   print "PlaceSymbol", move / 3, move % 3
   print "#END"

C++
1
2
3
      cout << "PlaceSymbol " << move / 3 << " " << move % 3 << endl << "#END" << endl;
   }
}

Strategia przedstawionego bota nie ma oczywiście większego sensu, pozwala natomiast zapoznać się z obsługą systemu i w szybki sposób zdobyć podstawową wiedzę "jak pisać boty". W drugiej części tego poradnika omówimy dokładniej proces testowania bota, a więc systemy wspomagające wykrywanie błędów.

Finalna wersja

Poniżej znajdują się pełne kody źródłowe przykładowego bota (bot ten jest dostępny w systemie pod nazwą TutorialBot):

Python
Pokaż/ukryj kod źródłowy
1
2
3
4
5
6
7
8
9
10
11
import random
 
free = range(9)
while True:
   x, y = map(int, raw_input("LastMove\n").split())
   if x != -1:
      free.remove(x*3 + y)
   move = random.choice(free)
   free.remove(move)
   print "PlaceSymbol", move / 3, move % 3
   print "#END"


C++
Pokaż/ukryj kod źródłowy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdlib.h>
#include <time.h>
 
using namespace std;
 
int main ()
{
   int x, y;
   srand ( time(NULL) );
   vector<int> free (9, 0);
   for (int i = 0; i < 8; i++)
      free[i] = i;
 
   while (true)
   {
      cout << "LastMove" << endl;
      cin >> x >> y;
      if (x != -1)
         free.erase(remove(free.begin(), free.end(), x*3+y), free.end());
 
      int move = free[rand()%free.size()];
      free.erase(remove(free.begin(), free.end(), move), free.end());
      cout << "PlaceSymbol " << move / 3 << " " << move % 3 << endl << "#END" << endl;
   }
}

0
Twoja ocena: Brak

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com