sapporocpp / 4moku

4目並べ
MIT License
0 stars 0 forks source link

雑魚AI置き場 #3

Open ignisan opened 8 years ago

ignisan commented 8 years ago
#include "4moku.hpp"
std::tuple<int,int> AI_FUNCTION(const Board& board,int player) {
    int nx,ny;
    std::tie(nx,ny) = board.size();
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_int_distribution<> rndx(0,nx);
    std::uniform_int_distribution<> rndy(0,ny);

    for(int x=0;x<nx;++x) {
        for(int y=0;y<ny;++y) {
            // 2つ連続する自分の石を探す
            if(player_id(player)==board(x,y)
                && player_id(player)==board(x+1,y)) {
                if(placeable(board,x+2,y)) {
                    return std::make_tuple(x+2,y);
                }
                if(placeable(board,x-1,y)) {
                    return std::make_tuple(x-1,y);
                }
            }
            if(player_id(player)==board(x,y)
                && player_id(player)==board(x,y-1)) {
                if(placeable(board,x,y-2)) {
                    return std::make_tuple(x,y-2);
                }
                if(placeable(board,x,y+1)) {
                    return std::make_tuple(x,y+1);
                }
            }
            if(player_id(player)==board(x,y)
                && player_id(player)==board(x+1,y-1)) {
                if(placeable(board,x+2,y-2)) {
                    return std::make_tuple(x+2,y-2);
                }
                if(placeable(board,x-1,y+1)) {
                    return std::make_tuple(x-1,y+1);
                }
            }
            if(player_id(player)==board(x,y)
                && player_id(player)==board(x+1,y+1)) {
                if(placeable(board,x+2,y+2)) {
                    return std::make_tuple(x+2,y+2);
                }
                if(placeable(board,x-1,y-1)) {
                    return std::make_tuple(x-1,y-1);
                }
            }
        }
    }

    for(int x=0;x<nx;++x) {
        for(int y=0;y<ny;++y) {
            // 自分の石を探す
            if(player_id(player)==board(x,y)) {
                // 周囲におけるかチェック
                for(int ix=x-1;ix<x+2;++ix) {
                    for(int iy=y-1;iy<y+2;++iy) {
                        if(placeable(board,ix,iy)) {
                            return std::make_pair(ix,iy);
                        }
                    }
                }
            }
        }
    }

    std::tuple<int,int> random_choice = std::make_tuple(-1,-1);

    for(int i=0;i<300;++i) {
        int x=rndx(mt), y=rndy(mt);
        if(placeable(board, x, y)){
            // 置けるなら
            Board board_tmp(board);
            board_tmp(x,y) = player_id(player);

            if(finished(board_tmp)){
                // そこに置いて勝つなら
                return std::make_tuple(x,y);
            }else{
                // そうでないなら
                if(std::get<0>(random_choice) == -1){
                    random_choice = std::make_tuple(x,y);
                }
            }
        }
    }
    return random_choice;
}
maraigue commented 8 years ago
#include "4moku.hpp"

std::tuple<int,int> AI_FUNCTION(const Board& board,int player) {
    // ・自分が勝つことが確定するような置き場所があるならそこに置く。
    // ・自分が置くことで、次に相手が勝つことが確定する置き場所があるならそこは置かない。
    // ・そうでなければ、置ける場所に置く。

    int nx,ny;
    std::tie(nx,ny) = board.size();
    std::tuple<int,int> random_choice, tmp_choice;

    std::mt19937 mt(std::time(0));
    std::uniform_real_distribution<> rnd(0, 1);

    int candidates = 0;
    for(int i = 0; i < nx; ++i){
        for(int j = 0; j < ny; ++j){

            if(placeable(board, i, j)){
                Board board_tmp(board);
                board_tmp(i, j) = player_id(player);

                tmp_choice = std::make_tuple(i, j);
                // 自分の勝ちが確定できるならそこに置く
                if(finished(board_tmp)) return tmp_choice;

                // 相手の勝ちが確定できるならそこに置かない
                for(int p = 0; p < nx; ++p){
                    for(int q = 0; q < ny; ++q){
                        if(placeable(board_tmp, p, q)){
                            Board board_tmp2(board_tmp);
                            board_tmp2(p, q) = player_id((player+1) % 2);
                            if(finished(board_tmp2)){
                                tmp_choice = std::make_tuple(-1, -1);
                                std::cerr << "Placing at (" << i << ", " << j << ") lets the opponent win!" << std::endl;
                                break;
                            }
                        }
                    }
                }

                // もしどちらの勝ちも確定しないなら、ランダム選択
                if(std::get<0>(tmp_choice) != -1){
                    ++candidates;
                    if(rnd(mt) < 1.0/candidates) random_choice = tmp_choice;
                }
            }
        }
    }

    return random_choice;
}