Grafica su C++

Pubblicità
Visto che usi C++ è corretto rappresentare la board come una classe e gestire tutte le funzioni del caso al suo interno; tra le variabili della classe avrai (privato, preferibilmente) il tuo array che rappresenta la board.
Più ovviamente le dimensioni, magari accessibili dall'esterno, e costanti.

Sempre qui dichiari tutte le funzioni che operano sulla board: rappresentare lo stato del click su una casella, o della presenza dell'avversario, dire se la casella è piena, se la board è piena etc.
Puoi usare int (o byte) o char. Purtroppo visto che hai 3 stati non puoi usare un boolean.
Questo oggetto una volta creato sarà sempre lui per tutta la durata del programma (ovviamente). Verrà creato, idealmente, da una classe che si occupa di gestire l'input dell'utente (non direttamente però) e che sarà incaricata a far muovere l'avversario (se devi usare un avversario non umano). Sempre idealmente potrebbe essere fuori dal game loop.

Inviato da ONEPLUS A5000 tramite App ufficiale di Tom\'s Hardware Italia Forum
 
Visto che usi C++ è corretto rappresentare la board come una classe e gestire tutte le funzioni del caso al suo interno; tra le variabili della classe avrai (privato, preferibilmente) il tuo array che rappresenta la board.
Più ovviamente le dimensioni, magari accessibili dall'esterno, e costanti.

Sempre qui dichiari tutte le funzioni che operano sulla board: rappresentare lo stato del click su una casella, o della presenza dell'avversario, dire se la casella è piena, se la board è piena etc.
Puoi usare int (o byte) o char. Purtroppo visto che hai 3 stati non puoi usare un boolean.
Questo oggetto una volta creato sarà sempre lui per tutta la durata del programma (ovviamente). Verrà creato, idealmente, da una classe che si occupa di gestire l'input dell'utente (non direttamente però) e che sarà incaricata a far muovere l'avversario (se devi usare un avversario non umano). Sempre idealmente potrebbe essere fuori dal game loop.

Inviato da ONEPLUS A5000 tramite App ufficiale di Tom\'s Hardware Italia Forum
C++:
#pragma once
#include <SFML\Graphics.hpp>
#include <vector>

using namespace std;
using namespace sf;

class TicTacToe
{
public:
    TicTacToe();
    virtual ~TicTacToe();

    void game_loop();
    int check_win();
    void set_player_c(const Vector2i&);
    void logic();
    void draw_sprites();

    inline Vector2i get_valid_p(const Vector2i&);

private:
    int grid[9];
    RenderWindow window;
    vector<Sprite> sprites_to_draw;
    int win; //prob questa variabile non servirà mai

};
C++:
#include "stdafx.h"
#include "Tic Tac Toe.h"
#include "file_exception.h"
#include <cstdlib>
#include <iostream>
using namespace sf;
using namespace std;

TicTacToe::TicTacToe()
    : win(0)
{
    for (int i = 0; i < 9; i++)
        grid[i] = 0;
    sprites_to_draw.resize(0);
    window.create(VideoMode(520, 520), "TicTacToe", Style::Close);

    Image icon;
    if (!icon.loadFromFile("icon.png"))
        throw file_exception();
    window.setIcon(225, 225, icon.getPixelsPtr());

    Texture grid_texture;
    if (!grid_texture.loadFromFile("grid.jpg"))
        throw file_exception();
    Sprite grid;
    grid.setTexture(grid_texture);

    sprites_to_draw.push_back(grid);

    game_loop();

}

TicTacToe::~TicTacToe()
{
}

void TicTacToe::game_loop()
{
    while (window.isOpen() && check_win() == 0)
    {
        Event event;

        do
        {
            window.pollEvent(event);
            if (event.type == Event::Closed)
                exit(0);

        } while (event.type != Event::MouseButtonPressed);

        set_player_c(get_valid_p(Mouse::getPosition(window)));

        for (int i = 0; i < 9; i++)
            cout << grid[i] << " ";
    }
}

void TicTacToe::set_player_c(const Vector2i& position)
{
    if (grid[3 * (position.y / 173) + (position.x / 173)] == 0)
    {
        grid[3 * (position.y / 173) + (position.x / 173)] = 1;
    }
}

int TicTacToe::check_win()
{
    for (int i = 0; i <= 6; i += 3)
        if (grid[i] == grid[i + 1] && grid[i] == grid[i + 2] && grid[i] != 0)
            return grid[i];

    for (int i = 0; i < 3; i++)
        if (grid[i] == grid[i + 3] && grid[i] == grid[i + 6] && grid[0] != 0)
            return grid[i];

    if (grid[0] == grid[4] && grid[0] == grid[8] && grid[0]!=0)
        return grid[0];

    if (grid[6] == grid[4] && grid[6] == grid[2] && grid[6] != 0)
        return grid[6];

    return 0;
}

inline Vector2i TicTacToe::get_valid_p(const Vector2i& position)
{
    return { position.x / 3 * 3, position.y / 3 * 3 };
}

Funziona tutto correttamente. Ora devo solo implementare la logica dell'avversario e infine la grafica. L'algoritmo che dovrei usare è MiniMax vero?
 
Ultima modifica:
C++:
#pragma once
#include 
#include 

using namespace std;
using namespace sf;

class TicTacToe
{
public:
TicTacToe();
virtual ~TicTacToe();

void game_loop();
int check_win();
void set_player_c(const Vector2i&);
void logic();
void draw_sprites();

inline Vector2i get_valid_p(const Vector2i&);

private:
int grid[9];
RenderWindow window;
vector sprites_to_draw;
int win; //prob questa variabile non servirà mai

};
C++:
#include "stdafx.h"
#include "Tic Tac Toe.h"
#include "file_exception.h"
#include 
#include 
using namespace sf;
using namespace std;

TicTacToe::TicTacToe()
: win(0)
{
for (int i = 0; i < 9; i++)
grid[i] = 0;
sprites_to_draw.resize(0);
window.create(VideoMode(520, 520), "TicTacToe", Style::Close);

Image icon;
if (!icon.loadFromFile("icon.png"))
throw file_exception();
window.setIcon(225, 225, icon.getPixelsPtr());

Texture grid_texture;
if (!grid_texture.loadFromFile("grid.jpg"))
throw file_exception();
Sprite grid;
grid.setTexture(grid_texture);

sprites_to_draw.push_back(grid);

game_loop();

}

TicTacToe::~TicTacToe()
{
}

void TicTacToe::game_loop()
{
while (window.isOpen() && check_win() == 0)
{
Event event;

do
{
window.pollEvent(event);
if (event.type == Event::Closed)
exit(0);

} while (event.type != Event::MouseButtonPressed);

set_player_c(get_valid_p(Mouse::getPosition(window)));

for (int i = 0; i < 9; i++)
cout  }
}

void TicTacToe::set_player_c(const Vector2i& position)
{
if (grid[3 * (position.y / 173) + (position.x / 173)] == 0)
{
grid[3 * (position.y / 173) + (position.x / 173)] = 1;
}
}

int TicTacToe::check_win()
{
for (int i = 0; i  if (grid[i] == grid[i + 1] && grid[i] == grid[i + 2] && grid[i] != 0)
return grid[i];

for (int i = 0; i < 3; i++)
if (grid[i] == grid[i + 3] && grid[i] == grid[i + 6] && grid[0] != 0)
return grid[i];

if (grid[0] == grid[4] && grid[0] == grid[8] && grid[0]!=0)
return grid[0];

if (grid[6] == grid[4] && grid[6] == grid[2] && grid[6] != 0)
return grid[6];

return 0;
}

inline Vector2i TicTacToe::get_valid_p(const Vector2i& position)
{
return { position.x / 3 * 3, position.y / 3 * 3 };
}

Funziona tutto correttamente. Ora devo solo implementare la logica dell'avversario e infine la grafica. L'algoritmo che dovrei usare è MiniMax vero?
Appena entro da pc leggo tutto il codice e ti rispondo per bene.
Volevo solo precisare che il MiniMax è già uno degli algoritmi che tipicamente si vede quando si mette mano alla base di IA. Lo scopo di MiniMax, detto in maniera informale (ma corretta), è quella di minimizzare le possibilità di vittoria dell'avversario. Il presupposto è che l'avversario faccia la stessa cosa (quindi sia un agente perfetto, che non sbaglia).
Ciò che fa è prendere lo stato corrente e simulare delle partite. Quando perde, vince o pareggia, torna un valore (quella funzione di utilità). Praticamente espande l'intero albero delle mosse per capire qual è la giocata migliore.
In pratica se correttamente implementato accade questo:
- se giochi senza sbagliare, non vinci mai (pareggi) ;
- se sbagli perdi.
Applicato a Forza 4, ad esempio, sarebbe la stessa cosa. Con giochi complessi (scacchi) non è applicabile nemmeno con la potatura alpha-beta.

Tutto questo per darti un quadro della complessità che sta dietro.
Ti consiglierei quindi di evitare MiniMax al momento. Puoi usare logiche più "basilari" verificando semplicemente se ci sono 3 valori uguali in verticale, orizzontale o diagonale.
Puoi anche verificare le caselle circostanti alla mossa appena fatta, così non guardi tutto l'array.

Inviato da ONEPLUS A5000 tramite App ufficiale di Tom\'s Hardware Italia Forum
 
Appena entro da pc leggo tutto il codice e ti rispondo per bene.
Volevo solo precisare che il MiniMax è già uno degli algoritmi che tipicamente si vede quando si mette mano alla base di IA. Lo scopo di MiniMax, detto in maniera informale (ma corretta), è quella di minimizzare le possibilità di vittoria dell'avversario. Il presupposto è che l'avversario faccia la stessa cosa (quindi sia un agente perfetto, che non sbaglia).
Ciò che fa è prendere lo stato corrente e simulare delle partite. Quando perde, vince o pareggia, torna un valore (quella funzione di utilità). Praticamente espande l'intero albero delle mosse per capire qual è la giocata migliore.
In pratica se correttamente implementato accade questo:
- se giochi senza sbagliare, non vinci mai (pareggi) ;
- se sbagli perdi.
Applicato a Forza 4, ad esempio, sarebbe la stessa cosa. Con giochi complessi (scacchi) non è applicabile nemmeno con la potatura alpha-beta.

Tutto questo per darti un quadro della complessità che sta dietro.
Ti consiglierei quindi di evitare MiniMax al momento. Puoi usare logiche più "basilari" verificando semplicemente se ci sono 3 valori uguali in verticale, orizzontale o diagonale.
Puoi anche verificare le caselle circostanti alla mossa appena fatta, così non guardi tutto l'array.

Inviato da ONEPLUS A5000 tramite App ufficiale di Tom\'s Hardware Italia Forum
Grazie mille. Intanto posto una soluzione migliore che ho ricreato da 0.
C++:
#include <SFML\Graphics.hpp>
#include "file_exception.h"

#include <vector>

#define window_dimension 520

#define _ICON_FILE_STRING "icon.png"
#define _GRID_FILE_STRING "grid.jpg"
#define _X_FILE_STRING "x.png"
#define _FONT_FILE_STRING "Calibri.ttf"
#define _ICON_DIMENSION 225

enum WINNER { DRAW = 1, PLAYER = 2, COMPUTER = 3};

using namespace std;
using namespace sf;

class TicTacToe
{
public:
    TicTacToe();

    void get_winner();

private:
    void draw_sprites();
    void game_loop();
    int check_win();
    void set_player_point(const Vector2i&);
    void logic();

    Vector2i get_valid_position(const Vector2i& position)
    {
        return { position.x / 3 * 3, position.y / 3 * 3 };
    }

    int grid[9];
    WINNER winner;

    RenderWindow window;
    vector<Sprite> sprites;

};

TicTacToe::TicTacToe()
    : winner(DRAW),
    window(VideoMode(window_dimension, window_dimension), "Tic Tac Toe", Style::Close),
    sprites(0)
{
    for (int i = 0; i < 9; i++)
        grid[i] = 0;

    Image icon;
    if (!icon.loadFromFile(_ICON_FILE_STRING))
        throw file_exception();
    window.setIcon(_ICON_DIMENSION, _ICON_DIMENSION, icon.getPixelsPtr());

    Texture grid_texture;
    if (!grid_texture.loadFromFile(_GRID_FILE_STRING))
        throw file_exception();
    Sprite grid;
    grid.setTexture(grid_texture);
    sprites.push_back(grid);

    game_loop();

}

void TicTacToe::get_winner()
{
    sprites.resize(0);

    Font _winner_written_font;
    if (!_winner_written_font.loadFromFile(_FONT_FILE_STRING))
        throw file_exception();

    Text winner_written;
    winner_written.setFont(_winner_written_font);
    winner_written.setCharacterSize(60);
    winner_written.setPosition({ 175, window_dimension / 2 - 60 });
    winner_written.setFillColor(Color::Black);
    switch (winner)
    {
    case DRAW:
        winner_written.setString("Draw!");
        break;
    case PLAYER:
        winner_written.setString("Player wins!");
        break;
    case COMPUTER:
        winner_written.setString("Computer wins!");
        break;
    }
    while (window.isOpen())
    {
        Event event;

        while (window.pollEvent(event))
            if (event.type == Event::Closed)
                window.close();

        window.clear(Color::White);
        window.draw(winner_written);
        window.display();
    }

}

void TicTacToe::draw_sprites()
{
    window.clear();

    for (int i = 0; i < sprites.size(); i++)
        window.draw(sprites[i]);

    window.display();
}

void TicTacToe::game_loop()
{
    draw_sprites();

    Event player_event;

    while (window.isOpen() && check_win() == 0)
    {
        do
        {
            window.pollEvent(player_event);

            if (player_event.type == Event::Closed)
                exit(0);

        } while (player_event.type != Event::MouseButtonPressed);

        set_player_point(get_valid_position(Mouse::getPosition(window)));

        draw_sprites();

        if (check_win() != 0)
            break;

        draw_sprites();
    }

    switch (check_win())
    {
    case 1:
        winner = PLAYER;
        break;
    case 2:
        winner = COMPUTER;
    case 3:
        winner = DRAW;
    }

    get_winner();
}

int TicTacToe::check_win()
{
    for (int i = 0; i <= 6; i += 3)
        if (grid[i] == grid[i + 1] && grid[i] == grid[i + 2] && grid[i] != 0)
            return grid[i];

    for (int i = 0; i < 3; i++)
        if (grid[i] == grid[i + 3] && grid[i] == grid[i + 6] && grid[0] != 0)
            return grid[i];

    if (grid[0] == grid[4] && grid[0] == grid[8] && grid[0] != 0)
        return grid[0];

    if (grid[6] == grid[4] && grid[6] == grid[2] && grid[6] != 0)
        return grid[6];

    bool draw = true;

    for (int i = 0; i < 9; i++)
        if (grid[i] == 0)
            draw = false;
    if (draw == true)
        return 3;

    return 0;
}

void TicTacToe::set_player_point(const Vector2i& position)
{
    Texture x_texture;
    if (!x_texture.loadFromFile(_X_FILE_STRING))
        throw file_exception();
    Sprite x;
    x.setTexture(x_texture);
    x.setScale({ 1, 519 / 900 });

    if (grid[3 * (position.y / 173) + (position.x / 173)] == 0)
    {
        grid[3 * (position.y / 173) + (position.x / 173)] = 1;
        x.setPosition(static_cast<Vector2f>(position));
        sprites.push_back(x);
    }
}

Oltre all'algoritmo dovrei centrare la scritta di vittoria che varia per vincitore. In più non si mostrano gli sprite della X.

Comunque questa settimana sono quasi totalmente libero, palestra e amici permettendo, quindi posso provare questo algoritmo. Se non ho capito male è ricorsivo, guarda dove ottiene più punti e lo mette.
Ad esempio l’algoritmo, dopo che PLAYER ha occupato la casella 1 ad esempio, verifica per tutte le altre 8 cosa accade, simulando anche tutte le mosse di PLAYER possibili, no?
 
Ultima modifica:
Esatto. Simula la partita con le mosse di entrambi i giocatori sino ad uno stato terminale.
Tutta questa logica (guarda il file minimax_alphabeta.c del mio progetto) serve a determinare la mossa del computer. Il ciclo principale esegue tante iterazioni quante sono le possibili azioni (che nella pratica si tratta di tutte le caselle vuote).
 
Esatto. Simula la partita con le mosse di entrambi i giocatori sino ad uno stato terminale.
Tutta questa logica (guarda il file minimax_alphabeta.c del mio progetto) serve a determinare la mossa del computer. Il ciclo principale esegue tante iterazioni quante sono le possibili azioni (che nella pratica si tratta di tutte le caselle vuote).
C++:
#include <SFML\Graphics.hpp>
#include "file_exception.h"

#include <cstdlib>
#include <ctime>
#include <vector>

#define WINDOW_RESOLUTION 519
#define BLOCK_LENGTH (WINDOW_RESOLUTION / 3)
#define TITLE "Tic Tac Toe"

#define _ICON_FILE_STRING "icon.png"
#define _ICON_DIMENSION 225
#define _GRID_FILE_STRING "grid.jpg"
#define _FONT_FILE_STRING "Calibri.ttf"
#define _WINNER_TEXT_S 60
#define _WINNER_TEXT_C sf::Color::Black

#define VOID 0
#define PLAYER_P 1
#define PLAYER_C sf::Color::Blue
#define COMPUTER_P 2
#define COMPUTER_C sf::Color::Red

enum WINNER { DRAW = 1, PLAYER = 2, COMPUTER = 3};

class TicTacToe
{
public:
    TicTacToe();

private:
    void draw_things();
    void game_loop();
    int check_win();
    void set_point(const sf::Vector2i&, sf::Color);
    void logic();
    void get_winner();

    bool isFree(const sf::Vector2i position)
    {
        if (grid[3 * position.y / BLOCK_LENGTH + position.x / BLOCK_LENGTH] == VOID)
            return true;

        return false;
    }

    sf::Vector2i get_valid_position(const sf::Vector2i& position)
    {
        return { position.x / BLOCK_LENGTH * BLOCK_LENGTH, position.y / BLOCK_LENGTH * BLOCK_LENGTH };
    }

    int grid[9];
    WINNER winner;

    sf::RenderWindow window;
    std::vector<sf::Sprite> sprites;
    std::vector<sf::CircleShape> shapes;

};

C++:
#include "stdafx.h"
#include "TicTacToe.h"

#include <cstdlib>
#include <ctime>

using namespace std;
using namespace sf;

TicTacToe::TicTacToe()
    : winner(DRAW),
    sprites(0),
    shapes(0)
{
    srand(time(0));
    ContextSettings setting;
    setting.antialiasingLevel = 8;
    window.create(VideoMode(WINDOW_RESOLUTION, WINDOW_RESOLUTION), TITLE, Style::Close, setting);
    window.setVerticalSyncEnabled(true);

    for (int i = 0; i < 9; i++)
        grid[i] = VOID;

    Image icon;
    if (!icon.loadFromFile(_ICON_FILE_STRING))
        throw file_exception();
    window.setIcon(_ICON_DIMENSION, _ICON_DIMENSION, icon.getPixelsPtr());

    Texture grid_texture;
    if (!grid_texture.loadFromFile(_GRID_FILE_STRING))
        throw file_exception();
    Sprite grid;
    grid.setTexture(grid_texture);
    sprites.push_back(grid);

    game_loop();
}

void TicTacToe::draw_things()
{
    window.clear();

    for (size_t i = 0; i < sprites.size(); i++)
        window.draw(sprites[i]);
    for (size_t i = 0; i < shapes.size(); i++)
        window.draw(shapes[i]);

    window.display();
}

void TicTacToe::game_loop()
{
    draw_things();

    while (window.isOpen() && check_win() == 0)
    {
        Event player_event;

        do
        {
            window.pollEvent(player_event);
            draw_things();

            if (player_event.type == Event::Closed)
                exit(0);

        } while (player_event.type != Event::MouseButtonPressed || !isFree(Mouse::getPosition(window)));

        grid[3 * (Mouse::getPosition(window).y / BLOCK_LENGTH) + (Mouse::getPosition(window).x / BLOCK_LENGTH)] = PLAYER_P;
        set_point(get_valid_position(Mouse::getPosition(window)), PLAYER_C);

        do
        {
            window.pollEvent(player_event);

        } while (player_event.type != Event::MouseButtonReleased);


        draw_things();

        if (check_win() != 0)
            break;

        logic();

    }

    get_winner();
}

int TicTacToe::check_win()
{
    for (int i = 0; i < 6; i += 3)
        if (grid[i] == grid[i + 1] && grid[i] == grid[i + 2] && grid[i] != VOID)
            return grid[i];
    for (int i = 0; i < 3; i++)
        if (grid[i] == grid[i + 3] && grid[i] == grid[i + 6] && grid[i] != VOID)
            return grid[i];

    if (grid[0] == grid[4] && grid[0] == grid[8] && grid[0] != VOID)
        return grid[0];

    if (grid[6] == grid[4] && grid[6] == grid[2] && grid[6] != VOID)
        return grid[6];

    bool draw = true;

    for (int i = 0; i < 9; i++)
        if (grid[i] == VOID)
            draw = false;

    if (draw)
        return 3;

    return 0;

}

void TicTacToe::set_point(const Vector2i& pos, Color color)
{
    CircleShape point(BLOCK_LENGTH / 2 - 5);
    point.setPosition(static_cast<Vector2f>(pos));
    point.setFillColor(color);
    shapes.push_back(point);
}

//Minimax algorithm
void TicTacToe::logic()
{
    int x, y;
    do
    {
        x = rand() % 3;
        y = rand() % 3;
    } while (grid[3 * x + y] != VOID);

    grid[3 * x + y] = COMPUTER_P;

    Vector2i position;
    position.x = y * BLOCK_LENGTH;
    position.y = x * BLOCK_LENGTH;

    set_point(position, COMPUTER_C);
}

void TicTacToe::get_winner()
{
    switch (check_win())
    {
    case 1:
        winner = PLAYER;
        break;
    case 2:
        winner = COMPUTER;
        break;
    case 3:
        winner = DRAW;
        break;
    }

    Font winner_text_font;
    if (!winner_text_font.loadFromFile(_FONT_FILE_STRING))
        throw file_exception();
    Text winner_text;
    winner_text.setFont(winner_text_font);
    winner_text.setCharacterSize(_WINNER_TEXT_S);
    winner_text.setFillColor(_WINNER_TEXT_C);
    winner_text.setPosition({ WINDOW_RESOLUTION / 2 - 90 , WINDOW_RESOLUTION / 2 });

    switch (winner)
    {
    case PLAYER:
        winner_text.setString("Player wins!");
        break;
    case COMPUTER:
        winner_text.setString("Computer wins!");
        break;
    case DRAW:
        winner_text.setString("Draw!");
        break;
    }

    window.clear(Color::White);
    window.draw(winner_text);
    window.display();

    while (window.isOpen())
    {
        Event closing;
        window.pollEvent(closing);
        if (closing.type == Event::Closed)
            window.close();
    }

}

Ci sono vari impicci a livello di posizione del mouse per non so quale motivo, alcune aree non danno risposta. Poi non so bene gestire le posizioni delle scritte

Ora voglio provare a creare l'algoritmo. Quindi modifico l'array grid come vettore per usufruire del costruttore di copia.
 
@DispatchCode sai dirmi perché questo algoritmo semplice Minimax si limita a dare la prima casella disponibile invece della migliore? Grazie
C++:
int _minimax_algorithm(vector<int> copy)
{
    int max = INT_MIN;
    int x;

    for (int i = 0; i < 9; i++)
        if (copy[i] == 0)
        {
            copy[i] = 2;
            int temp = _minimax_algorithm_search(copy, 1);
            if (temp > max)
            {
                max = temp;
                x = i;
            }
            copy[i] = 0;
        }

    return x;
}

int _minimax_algorithm_search(vector<int> grid, int p_or_com)
{
    int min = INT_MAX;
    if (check_win(grid) == 1)
        return -10;
    if (check_win(grid) == 2)
        return 10;
    if (check_win(grid) == 3)
        return 0;

    if (p_or_com == 1)
    {
        for (int i = 0; i < 9; i++)
            if (grid[i] == 0)
            {
                grid[i] = 1;
                int temp = _minimax_algorithm_search(grid, 2);
                if (min > temp)
                    min = temp;
                grid[i] = 0;
            }
    }
    else
        for (int i = 0; i < 9; i++)
            if (grid[i] == 0)
            {
                grid[i] = 2;
                int temp = _minimax_algorithm_search(grid, 1);
                if (min > temp)
                    min = temp;
                grid[i] = 0;
            }

    return min;
}

int check_win(vector<int> grid)
{

    for (int i = 0; i <= 6; i++)
        if (grid[i] == grid[i + 1] && grid[i] == grid[i + 2] && grid[i] != 0)
            return grid[i];

    for (int i = 0; i < 3; i++)
        if (grid[i] == grid[i + 3] && grid[i] == grid[i + 6] && grid[i] != 0)
            return grid[i];

    if (grid[0] == grid[4] && grid[0] == grid[8] && grid[0] != 0)
        return grid[0];

    if (grid[6] == grid[4] && grid[6] == grid[2] && grid[6] != 0)
        return grid[6];

    bool draw = true;
    for (int i = 0; i < 0; i++)
        if (grid[i] == 0)
            draw = false;
    if (draw)
        return 3;

    return 0;
}
 
@_Achille cerco di risponderti il prima possibile, sono tornato poco fa dall'ufficio...

Comunque se è corretto come azioni disponibili, il problema sarà probabilmente la funzione di utilità che valuta lo stato terminale. ;)
Appena riesco guardo tutto quanto hai scritto comunque, magari ci sono proprio errori con l'algoritmo in sé.

Inviato da ONEPLUS A5000 tramite App ufficiale di Tom\'s Hardware Italia Forum
 
@_Achille cerco di risponderti il prima possibile, sono tornato poco fa dall'ufficio...

Comunque se è corretto come azioni disponibili, il problema sarà probabilmente la funzione di utilità che valuta lo stato terminale. ;)
Appena riesco guardo tutto quanto hai scritto comunque, magari ci sono proprio errori con l'algoritmo in sé.

Inviato da ONEPLUS A5000 tramite App ufficiale di Tom\'s Hardware Italia Forum
Grazie mille. Intento ti riporto una versione migliore ma che da lo stesso risultato
C++:
int _minimax_algorithm_search(vector<int> copy)
{
    int max = INT_MAX;
    int x;

    for(int i = 0; i < 9; i++)
        if (copy[i] == 0)
        {
            copy[i] = 2;
            int temp = _minimax_algorithm_min(copy);
            if (temp <= max)
            {
                max = temp;
                x = i;
            }
            copy[i] = 0;
        }

    return x;

}

int _minimax_algorithm_min(vector<int> grid)
{
    if (check_win(grid) == 1)
        return -10;
    if (check_win(grid) == 2)
        return 10;
    if (check_win(grid) == 3)
        return 0;

    int min = INT_MAX;
    for(int i = 0; i < 9; i++)
        if (grid[i] == 0)
        {
            grid[i] = 1;
            int temp = _minimax_algorithm_max(grid);
            if (temp <= min)
            {
                min = temp;
            }
            grid[i] = 0;
        }

    return min;
}

int _minimax_algorithm_max(vector<int> grid)
{
    if (check_win(grid) == 1)
        return -10;
    if (check_win(grid) == 2)
        return 10;
    if (check_win(grid) == 3)
        return 0;

    int max = INT_MIN;
    for (int i = 0; i < 9; i++)
        if (grid[i] == 0)
        {
            grid[i] = 2;
            int temp = _minimax_algorithm_min(grid);
            if (temp >= max)
            {
                max = temp;
            }
            grid[i] = 0;
        }

    return max;
}
 
Ultima modifica:
Hai modo di farmi avere una versione utilizzabile da CUI? Così posso provare su altri pc senza dover scaricare SFML. ;)

Il check_win() si può semplificare.

Non mi torna una cosa, ad un primo sguardo:

C++:
void TicTacToe::logic()
{
    int x, y;
    do
    {
        x = rand() % 3;
        y = rand() % 3;
    } while (grid[3 * x + y] != VOID);

    grid[3 * x + y] = COMPUTER_P;

    Vector2i position;
    position.x = y * BLOCK_LENGTH;
    position.y = x * BLOCK_LENGTH;

    set_point(position, COMPUTER_C);
}

Perchè fai questo?
 
Hai modo di farmi avere una versione utilizzabile da CUI? Così posso provare su altri pc senza dover scaricare SFML. ;)

Il check_win() si può semplificare.

Non mi torna una cosa, ad un primo sguardo:

C++:
void TicTacToe::logic()
{
    int x, y;
    do
    {
        x = rand() % 3;
        y = rand() % 3;
    } while (grid[3 * x + y] != VOID);

    grid[3 * x + y] = COMPUTER_P;

    Vector2i position;
    position.x = y * BLOCK_LENGTH;
    position.y = x * BLOCK_LENGTH;

    set_point(position, COMPUTER_C);
}

Perchè fai questo?
Ah no questo lo mette a caso.

Poi ti mando la versione senza grafica.
 
Hai modo di farmi avere una versione utilizzabile da CUI? Così posso provare su altri pc senza dover scaricare SFML. ;)

Il check_win() si può semplificare.

Non mi torna una cosa, ad un primo sguardo:

C++:
void TicTacToe::logic()
{
    int x, y;
    do
    {
        x = rand() % 3;
        y = rand() % 3;
    } while (grid[3 * x + y] != VOID);

    grid[3 * x + y] = COMPUTER_P;

    Vector2i position;
    position.x = y * BLOCK_LENGTH;
    position.y = x * BLOCK_LENGTH;

    set_point(position, COMPUTER_C);
}

Perchè fai questo?
Cavolo ho eliminato il progetto! Comunque si basa sullo stesso programma ma con funzione draw() ovviamente diversa e come input le cordinate nella griglia
 
Ho riguardato il codice che hai postato sopra, ma nel game_loop non ho visto la chiamata all'algoritmo MiniMax dopo la mossa dell'utente (umano). Quello è l' intero codice o mancano delle parti?
 
Rispetto al titolo mi pare che siate molto OT.

Comunque.. stiamo parlando di tic-tac-toe? È un gioco veramente stupido in cui chi inizia per primo vince sempre!

Quindi implementare una "logica" per questo gioco è un'espressione discutibile!

1) Le mosse da simulare sono un numero limitatissimo e sinceramente sempre le stesse (tra l'altro sono simmetriche per cui il numero di dimezza.
2) La conclusione è sempre di vittoria o pareggio a seconda di chi inizia.. quindi la scelta della mossa diventa sempre arbitraria...

ma avete mai visto il film "war games"?

Inviato dal mio Nexus 5 utilizzando Tapatalk
 
Ultima modifica:
Pubblicità
Pubblicità
Indietro
Top