Свинья-мультиплеер
Просто пример маленького консольного мультиплеера со сравнением нескольких случайных стратегий хода.
Сама игра - старая добрая "Свинка", только я не ограничивал максимальное количество ходов игрока, как и написано в англоязычной статье ("Players take turns to roll a single dice as many times as they wish").
Стратегия 1 равновероятно продолжает или завершает ход, стратегия 2 пытается учесть, сколько очков осталось до победы, третья просто всегда играет, пока за ход не набрано 20 очков, а четвёртая дополняет этот подход случайным выбором.
На серии из 1000 тестов стабильно лучшей оказывается третья, примерно так:
Player I (RAND): 40 total Player II (Q2WIN): 219 total Player III (AL20): 668 total Player IV (AL20T): 73 total
Ниже показан исходник приложения, которое выполнялось в консоли актуальной сборки Visual Studio 2019.
#include <windows.h> #include <iostream> #include <string> using namespace std; const int PLAYERS = 4, MAX_POINTS = 100; enum Moves { ROLL, HOLD }; class player { //Основной класс игрока public: player() { current_score = round_score = 0; } void addCurrScore() { current_score += round_score; } int getCurrScore() { return current_score; } int getRoundScore() { return round_score; } void addRoundScore(int rs) { round_score += rs; } void zeroRoundScore() { round_score = 0; } virtual int getMove() = 0; virtual ~player() {} protected: int current_score, round_score; }; class RAND_Player : public player { //Стратегия 1 virtual int getMove() { if (round_score + current_score >= MAX_POINTS) return HOLD; if (rand() % 10 < 5) return ROLL; if (round_score > 0) return HOLD; return ROLL; } }; class Q2WIN_Player : public player { //Стратегия 2 virtual int getMove() { if (round_score + current_score >= MAX_POINTS) return HOLD; int q = MAX_POINTS - current_score; if (q < 6) return ROLL; q /= 4; if (round_score < q) return ROLL; return HOLD; } }; class AL20_Player : public player { //Стратегия 3 virtual int getMove() { if (round_score + current_score >= MAX_POINTS) return HOLD; if (round_score < 20) return ROLL; return HOLD; } }; class AL20T_Player : public player { //Стратегия 4 virtual int getMove() { if (round_score + current_score >= MAX_POINTS) return HOLD; int d = (100 * round_score) / 20; if (round_score < 20 && d < rand() % 100) return ROLL; return HOLD; } }; class Auto_pigGame { //Автоплеер с 4 игроками public: Auto_pigGame() { _players[0] = new RAND_Player(); _players[1] = new Q2WIN_Player(); _players[2] = new AL20_Player(); _players[3] = new AL20T_Player(); } ~Auto_pigGame() { delete _players[3]; delete _players[2]; delete _players[1]; delete _players[0]; } int play() { //Вернёт номер игрока-победителя 0..PLAYERS-1 int die, p = 0; bool endGame = false; while (!endGame) { switch (_players[p]->getMove()) { case ROLL: die = rand() % 6 + 1; if (die == 1) { cout << "Player " << p + 1 << " rolled " << die << " - current score: " << _players[p]->getCurrScore() << endl << endl; nextTurn(p); continue; } _players[p]->addRoundScore(die); cout << "Player " << p + 1 << " rolled " << die << " - round score: " << _players[p]->getRoundScore() << endl; break; case HOLD: _players[p]->addCurrScore(); cout << "Player " << p + 1 << " holds - current score: " << _players[p]->getCurrScore() << endl << endl; if (_players[p]->getCurrScore() >= MAX_POINTS) endGame = true; else nextTurn(p); } } showScore(); return p; } private: void nextTurn(int& p) { //Переход хода _players[p]->zeroRoundScore(); ++p %= PLAYERS; } void showScore() { //Показать теущие результаты cout << endl; cout << "Player I (RAND): " << _players[0]->getCurrScore() << endl; cout << "Player II (Q2WIN): " << _players[1]->getCurrScore() << endl; cout << "Player III (AL20): " << _players[2]->getCurrScore() << endl; cout << "Player IV (AL20T): " << _players[3]->getCurrScore() << endl << endl; } player* _players[PLAYERS]; }; int main () { srand(GetTickCount64()); //или GetTickCount в 32-разрядной архитектуре const int tests = 1000; //количество тестов int stat [PLAYERS] = {0}; for (int i = 0; i < tests; i++) { Auto_pigGame pg; stat[pg.play()]++; } cout << endl; cout << "Player I (RAND): " << stat[0] << " total" << endl; cout << "Player II (Q2WIN): " << stat[1] << " total" << endl; cout << "Player III (AL20): " << stat[2] << " total" << endl; cout << "Player IV (AL20T): " << stat[3] << " total" << endl; return 0; }
28.10.2021, 18:51 [811 просмотров]