asder

Δημιουργία παίχνιδιού Specker

Recommended Posts

λοιπόν φτιάχνω ένα παιχνίδι για μια εργασια.Οι κανονες είναι οι εξής:

Στη γενίκευση που μας ενδιαφέρει, στο παιχνίδι συμμετέχουν p παίκτες (αριθμημένοι από 0 έως p1)
και υπάρχουν n σωροί με ομοειδή κέρματα (αριθμημένοι από 0 έως n  1). Ο παίκτης 0 παίζει πρώτος,
μετά ο παίκτης 1, κ.ο.κ., εως τον παίκτη n  1, μετά τον οποίο παίζει πάλι ο παίκτης 0, κυκλικά.
Σε κάθε κίνηση, ο παίκτης που παίζει επιλέγει δύο σωρούς, έστω το σωρό i και το σωρό j, αφαιρεί
k > 0 κέρματα από το σωρό i (αυτό φυσικά πρέπει να είναι δυνατό να συμβεί, δηλαδή ο σωρός i πρέπει
να έχει τουλάχιστον k κέρματα) και βάζει m κέρματα (όπου 0  m < k) στο σωρό j. Προσέξτε ότι αν
επιλέξει m = 0 (δηλαδή να μη βάλει κανένα κέρμα), τότε η επιλογή του σωρού j δεν είναι σημαντική.
Το παιχνίδι τελειώνει όταν αφαιρεθούν όλα τα κέρματα από όλους τους σωρούς και ο παίκτης που
κερδίζει είναι ο τελευταίος που έπαιξε.

To ερώτημα μπόνους λέει: 

Υλοποιήστε μία κλάση παίκτη  η οποία να παίζει το παιχνίδι με όποια στρατηγική εσείς επιθυμείτε. Προσέξτε ότι στην
επιλογή της κίνησης δεν μπορείτε να ξέρετε πόσοι παίκτες συμμετέχουν στο παιχνίδι, ούτε με ποια σειρά
παίζετε εσείς.

έχει κανείς καμία ιδέα πως να φτιάξω έναν πιο έξυπνο πάιχτη, από ότι έχω καταλάβει minmax και τέτοια δεν πάιζουν λόγω των περιορισμών οπότε είμαι σε αδιέξοδο.
Ορίστε ο κώδικας μόνο με τους απλόυς παίχτες που κάνουν συνέχεια το ιδιο πράγμα (αν θέλετε να το τρέξετε ονλινε ο κωδικας είναι εδω https://repl.it/@stavrosa/specker)

 

#include <iostream>
#include <stdexcept>

using namespace std;

class Move {
private:
    int source_heap, source_coins, target_heap, target_coins;

public:
    Move(int sh, int sc, int th, int tc) {
        source_heap = sh;
        source_coins = sc;
        target_heap = th;
        target_coins = tc;
    }

    int getSource() const {
        return source_heap;
    }
    int getSourceCoins() const {
        return source_coins;
    }
    int getTarget() const {
        return target_heap;
    }
    int getTargetCoins() const {
        return target_coins;
    }

    // Let's do some operator overloading
    friend ostream &operator<<(ostream &out, const Move &move) {
        if (move.getTargetCoins()) {
            out << "takes " << move.getSourceCoins() << " coins from heap "
                << move.getSource() << " and puts " << move.getTargetCoins()
                << " coins to heap " << move.getTarget();

        } else {
            out << "takes " << move.getSourceCoins() << " coins from heap "
                << move.getSource() << " and puts nothing";
        }
    }
};

class State {
    // State with h heaps, where the i-th heap starts with c[i] coins.
private:
    int heaps, *heap_coins;

public:
    State(int h, const int c[]) {
        heaps = h;
        heap_coins = new int[heaps];
        for (int i = 0; i < heaps; i++)
            heap_coins[i] = c[i];
    }

    ~State() {
        delete[] heap_coins;
        return;
    }

    int getCoins(int h) const throw(logic_error) {
        if (h < 0 || h > heaps) {
            throw logic_error(
                "Invalid heap number, enter a number between 1 and heaps!");
            return 1;
        } else {
            return heap_coins[h];
        }
    }
    void next(const Move &move) throw(logic_error) {
        if ((move.getSource() < 0) || (move.getSource() > heaps) ||
            (move.getTarget() < 0) || (move.getTarget() > heaps)) {
            throw logic_error("Invalid Heap!");
            return;
        } else if (
            (move.getSourceCoins() < 1) || (move.getTargetCoins() < 0) ||
            (move.getSourceCoins() <= move.getTargetCoins()) ||
            (move.getSourceCoins() > getCoins(move.getSource()))) {
            throw logic_error("Invalid Coin number!");
        } else {
            heap_coins[move.getSource()] -= move.getSourceCoins();
            heap_coins[move.getTarget()] += move.getTargetCoins();
        }
    }

    bool winning() const {
        int s = 0;
        for (int i = 0; i < heaps; i++)
            s += getCoins(i);
        return not s; // yeah i know how booleans work :P
    }

    int getHeaps() const {
        return heaps;
    }

    friend ostream &operator<<(ostream &out, const State &state) {
        for (int i = 0; i < state.getHeaps(); i++) {
            out << state.heap_coins[i];
            if (i != state.getHeaps() - 1)
                out << ", ";
        }
        return out;
    }
};

class Player {
public:
    Player(const string &n);
    virtual ~Player();

    virtual const string &getType() const = 0;
    virtual Move play(const State &s) = 0;

    friend ostream &operator<<(ostream &out, const Player &player);

protected:
    string player_name;
};

class GreedyPlayer : public Player {
private:
    string player_type;

public:
    GreedyPlayer(const string &n) : Player(n) {
        player_type = "Greedy";
    }
    virtual const string &getType() const override {
        return player_type;
    }
    virtual Move play(const State &s) override {
        int source_heap = 0;
        int source_coins = 0;
        for (int i = 0; i < s.getHeaps(); i++) {
            if (s.getCoins(i) > source_coins) {
                source_heap = i;
                source_coins = s.getCoins(i);
            }
        }
        Move GreedyObject(source_heap, source_coins, 0, 0);
        return GreedyObject;
    }
};

class SpartanPlayer : public Player {
public:
    SpartanPlayer(const string &n) : Player(n) {
        player_type = "Spartan";
    }
    virtual const string &getType() const override {
        return player_type;
    }

    virtual Move play(const State &s) override {
        int source_heap = 0;
        int source_coins = 0;
        for (int i = 0; i < s.getHeaps(); i++) {
            if (s.getCoins(i) > source_coins) {
                source_heap = i;
                source_coins = s.getCoins(i);
            }
        }
        Move SpartanObject(source_heap, 1, 0, 0);
        return SpartanObject;
    }

private:
    string player_type;
};

class SneakyPlayer : public Player {
public:
    SneakyPlayer(const string &n) : Player(n) {
        player_type = "Sneaky";
    }
    virtual const string &getType() const override {
        return player_type;
    }

    virtual Move play(const State &s) override {
        int j = 0;
        while (s.getCoins(j) == 0) {
            j++;
        }
        int source_heap = j;
        int source_coins = s.getCoins(j);
        for (int i = j + 1; i < s.getHeaps(); i++) {
            if ((s.getCoins(i) < source_coins) && (s.getCoins(i) > 0)) {
                source_heap = i;
                source_coins = s.getCoins(i);
            }
        }
        Move SneakyObject(source_heap, source_coins, 0, 0);
        return SneakyObject;
    }

private:
    string player_type;
};

class RighteousPlayer : public Player {
public:
    RighteousPlayer(const string &n) : Player(n) {
        player_type = "Righteous";
    }
    virtual const string &getType() const override {
        return player_type;
    }

    virtual Move play(const State &s) override {
        int target_heap = 0;
        int source_heap = 0;
        int source_coins = s.getCoins(0);
        int target_coins = source_coins;

        for (int i = 1; i < s.getHeaps(); i++) {
            if (s.getCoins(i) > source_coins) {
                source_heap = i;
                source_coins = s.getCoins(i);
            } else if (s.getCoins(i) < target_coins) {
                target_heap = i;
                target_coins = s.getCoins(i);
            }
        }
        source_coins -= source_coins / 2;
        Move RighteousObject(
            source_heap, source_coins, target_heap, source_coins - 1);
        return RighteousObject;
    }

private:
    string player_type;
};

Player::Player(const string &n) {
    player_name = n;
}

Player::~Player() {
    player_name.clear();
}

ostream &operator<<(ostream &out, const Player &player) {
    out << player.getType() << " player " << player.player_name;
    return out;
}

class Game {
private:
    int game_heaps, game_players, current_heap, current_player;
    int *heap_coins;
    Player **players_list;

public:
    Game(int heaps, int players) {
        heap_coins= new int [heaps];
        game_heaps = heaps;
        game_players = players;
        current_heap = 0;
        current_player = 0;
        players_list = new Player*[players];
    }
    ~Game() {
        delete[] heap_coins;
        delete[] players_list;
    }
    void addHeap(int coins) throw(logic_error) {
        if (current_heap > game_heaps)
            throw logic_error("All heaps are full with coins!");
        else if (coins < 0)
            throw logic_error("Coins must be a positive number!"); 
        else {
                heap_coins[current_heap++] = coins;
            }
    }
    void addPlayer(Player *player) throw(logic_error) {
        if (current_player > game_players)
            throw logic_error("All players are added!");
        else {
            players_list[current_player++] = player;
        }
    }
    void play(ostream &out) throw(logic_error) {
        if ((current_player != game_players) && (current_heap != game_heaps)) {
            throw logic_error("Have you added all heaps and players?");
        } else {
            int i = 0;
            State currentState(game_heaps, heap_coins);
            while (!currentState.winning()) {
                out << "State: " << currentState << endl;
                out << *players_list[i % game_players] << " "
                    << players_list[i % game_players]->play(currentState) << endl;
                currentState.next(
                    players_list[i % game_players]->play(currentState));

                i++;
            }
            out << "State: " << currentState << endl;
            i--;
            out << *players_list[i % game_players] << " wins" << endl;
        }
    }
};


int main() {
 Game specker(3, 4);
 specker.addHeap(10);
 specker.addHeap(20);
 specker.addHeap(17);
 specker.addPlayer(new SneakyPlayer("Tom"));
 specker.addPlayer(new SpartanPlayer("Mary"));
 specker.addPlayer(new GreedyPlayer("Alan"));
 specker.addPlayer(new RighteousPlayer("Robin"));
 specker.play(cout);

}

 

Edited by asder
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now