Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdlib.h>
- #include <stdio.h>
- #include <ctype.h>
- #define INF 512
- #define MAX_DEPTH 4
- typedef struct node{
- char** board;
- int depth;
- int lastMove;
- int utility;
- char player;
- }node;
- // typedef struct nodeMont{
- // int num_plays;
- // int num_plays;
- // int depth;
- // node* n;
- // nodeMont* parent;
- // }nodeMont;
- node* newNode(char** board, int depth, int lastMove, char player){
- node *n = malloc(sizeof(node));
- n->board = (char**)malloc(7*sizeof(char*));
- for(int i = 0; i < 7; i++){
- n->board[i] = (char*)malloc(6*sizeof(char));
- }
- for(int i = 0; i < 7; i++){
- for(int j = 0; j < 6; j++){
- n->board[i][j] = board[i][j];
- }
- }
- n->depth = depth;
- n->lastMove = lastMove;
- n->player = player;
- return n;
- }
- // nodeMont* newNodeMont(char** board, int depth, int mdepth, int lastMove, char player, int np, int nw){
- //
- // nodeMont* n;
- // n->n=newNodenewNode(board, depth, lastMove, player);
- // n->num_plays=np;
- // n->num_wins=nw;
- // n->depth=mdepth;
- //
- // return n;
- // }
- int max(int a, int b){
- if(b > a){
- return b;
- }
- return a;
- }
- int min(int a, int b){
- if(b < a){
- return b;
- }
- return a;
- }
- char opponent(char player){
- if(player == 'O'){
- return 'X';
- }
- return 'O';
- }
- void printBoard(char** board){
- for(int i = 0; i < 6; i++){
- printf("|");
- for(int j = 0; j < 7; j++){
- printf("%c|", board[j][i]);
- }
- printf("\n");
- }
- }
- void makeMove(int move, char player, char** board){
- for(int i = 5; i >= 0; i--){
- if(board[move-1][i] == ' '){
- board[move-1][i] = player;
- return;
- }
- }
- return;
- }
- node* generateSuccessor(node* n, int move){
- node *new = newNode(n->board,n->depth+1,move,opponent(n->player));
- for(int i = 5; i >= 0; i--){
- if(new->board[move-1][i] == ' '){
- new->board[move-1][i] = n->player;
- break;
- }
- }
- return new;
- }
- int getHorizontalUtility(char ** board, int i, int j){
- int col = i;
- int row = j;
- int x = 0;
- int o = 0;
- for(col=i; col < i+4; col++){
- if(board[col][row] == 'X')
- x++;
- else if(board[col][row] == 'O')
- o++;
- }
- if(x==0){
- if(o==3)
- return -50;
- else if (o==2)
- return -10;
- else if (o==1)
- return -1;
- else if (o==4)
- return -INF;
- }
- if(o==0){
- if(x==1)
- return 1;
- else if(x==2)
- return 10;
- else if(x==3)
- return 50;
- else if(x==4)
- return INF;
- }
- return 0;
- }
- int getVerticalUtility(char ** board, int i, int j){
- int utilidade = 0;
- int col = i;
- int x=0;
- int o=0;
- // printf("Entramos en vertical con i=%i, j=%i\n",i,j);
- for(int row=j; row < j+4 ;row++){
- if(board[col][row] == 'X')
- x++;
- else if(board[col][row] == 'O')
- o++;
- }
- if(x==0){
- if(o==3)
- return -50;
- else if (o==2)
- return -10;
- else if (o==1)
- return -1;
- else if (o==4)
- return -INF;
- }
- if(o==0){
- if(x==1)
- return 1;
- else if(x==2)
- return 10;
- else if(x==3)
- return 50;
- else if(x==4)
- return INF;
- }
- return utilidade;
- }
- int getPrimaryDiagonalUtility(char ** board, int i, int j){
- int col = i;
- int row = j;
- int x = 0, o = 0;
- while(col < i+4){
- if(board[col][row] == 'X'){
- x++;
- }
- if(board[col][row] == 'O'){
- o++;
- }
- col++;
- row++;
- }
- if(o == 0){
- if(x == 1){
- return 1;
- }
- if(x == 2){
- return 10;
- }
- if(x == 3){
- return 50;
- }
- if(x == 4){
- return INF;
- }
- }
- if(x == 0){
- if(o == 1){
- return -1;
- }
- if(o == 2){
- return -10;
- }
- if(o == 3){
- return -50;
- }
- if(o == 4){
- return -INF;
- }
- }
- return 0;
- }
- int getSecondaryDiagonalUtility(char ** board, int i, int j){
- int col = i;
- int row = j;
- int x = 0, o = 0;
- while(col < i+4){
- if(board[col][row] == 'X'){
- x++;
- }
- if(board[col][row] == 'O'){
- o++;
- }
- col++;
- row--;
- }
- if(o == 0){
- if(x == 1){
- return 1;
- }
- if(x == 2){
- return 10;
- }
- if(x == 3){
- return 50;
- }
- if(x == 4){
- return INF;
- }
- }
- if(x == 0){
- if(o == 1){
- return -1;
- }
- if(o == 2){
- return -10;
- }
- if(o == 3){
- return -50;
- }
- if(o == 4){
- return -INF;
- }
- }
- return 0;
- }
- int utility(char** board){
- int utility, temp;
- utility = 0;
- for(int i = 0; i < 7; i++){
- for(int j = 0; j < 6; j++){
- if(i < 4){
- temp = getHorizontalUtility(board,i,j);
- if(temp >= INF || temp <= -INF){
- return temp;
- }
- utility += temp;
- if(j < 3){
- temp = getPrimaryDiagonalUtility(board,i,j);
- if(temp >= INF || temp <= -INF){
- return temp;
- }
- utility += temp;
- }
- else{
- temp = getSecondaryDiagonalUtility(board,i,j);
- if(temp >= INF || temp <= -INF){
- return temp;
- }
- utility += temp;
- }
- }
- if(j < 3){
- temp = getVerticalUtility(board,i,j);
- if(temp >= INF || temp <= -INF){
- return temp;
- }
- utility += temp;
- }
- }
- }
- return utility;
- }
- int isMoveValid(node* n,int movement){
- if (n->board[movement-1][0] == ' ') {
- return 1;
- }
- return 0;
- }
- int isBoardFull(char** board){
- for(int i = 0; i < 7; i++){
- for(int j = 0; j < 6; j++){
- if(board[i][j] == ' '){
- return 0;
- }
- }
- }
- return 1;
- }
- node* minValue(node* n);
- node* maxValue(node* n);
- int minimaxDecision(node* n){
- node* child;
- child = maxValue(n);
- return child->lastMove;
- }
- node* maxValue(node* n){
- node* child;
- node* maxChild;
- int maxV = -INF;
- int u = utility(n->board);
- if(u >= INF || u <= -INF || n->depth >= MAX_DEPTH){
- n->utility = u;
- return n;
- }
- if(isBoardFull(n->board)){
- n->utility = 0;
- return n;
- }
- for(int s = 1; s < 8; s++){
- if(isMoveValid(n, s)){
- //child = newNode(generateSuccessorBoard(n->board, s, n->player), n->depth+1, s, opponent(n->player));
- child = generateSuccessor(n,s);
- if(maxV < (minValue(child))->utility){
- maxV = child->utility;
- n->utility = maxV;
- maxChild = child;
- }
- }
- }
- return maxChild;
- }
- node* minValue(node* n){
- node* child;
- node* minChild;
- int minV = INF;
- int u = utility(n->board);
- if(u >= INF || u <= -INF || n->depth >= MAX_DEPTH){
- n->utility = u;
- return n;
- }
- if(isBoardFull(n->board)){
- n->utility = 0;
- return n;
- }
- for(int s = 1; s < 8; s++){
- if(isMoveValid(n, s)){
- //child = newNode(generateSuccessorBoard(n->board, s, n->player), n->depth+1, s, opponent(n->player));
- child = generateSuccessor(n,s);
- if(minV > (maxValue(child))->utility){
- minV = child->utility;
- n->utility = minV;
- minChild = child;
- }
- }
- }
- return minChild;
- }
- node* minAlphaValue(node* n, int alpha, int beta);
- node* maxAlphaValue(node* n, int alpha, int beta);
- int alphaBetaSearch(node* n){
- int alpha=-INF;
- int beta=INF;
- node* child = maxAlphaValue(n,alpha,beta);
- return child->lastMove;
- }
- node* maxAlphaValue(node* n, int alpha, int beta){
- node* child;
- node* maxChild;
- int maxV = -INF;
- int u = utility(n->board);
- if(u >= INF || u <= -INF || n->depth >= MAX_DEPTH){
- n->utility = u;
- return n;
- }
- for(int s = 1; s < 8; s++){
- child = generateSuccessor(n,s);
- if(maxV < (minAlphaValue(child,alpha,beta))->utility){
- maxV = child->utility;
- maxChild = child;
- }
- if(maxV>=beta)
- return maxChild;
- alpha=max(maxV,alpha);
- }
- return maxChild;
- }
- node* minAlphaValue(node* n, int alpha, int beta){
- node* child;
- node* minChild;
- int minV = INF;
- int u = utility(n->board);
- if(u >= INF || u <= -INF || n->depth >= MAX_DEPTH){
- n->utility = u;
- return n;
- }
- for(int s = 1; s < 8; s++){
- child = generateSuccessor(n,s);
- if(minV > (maxAlphaValue(child,alpha,beta))->utility){
- minV = child->utility;
- minChild = child;
- }
- if(minV<=alpha)
- return minChild;
- beta=max(minV,beta);
- }
- return minChild;
- }
- //returns a movement
- //a árvore é geral (tem que ser atualizada pelo back-propagate)
- //vector<nodeMont> tree;
- // int ucb(nodeMont child, nodeMont parent){
- // return ( (child->num_wins / child->num_plays) + sqrt(2)* sqrt(log(parent->num_plays)/child->num_plays));
- // }
- //
- // nodeMont selection(nodeMont* n){
- //
- // nodeMont selected;
- // int ucb = 0;
- // if(isMoveValid(n->nod->board, s)){
- //
- // /*//é precios implementar newNode para struct nodeMont
- // child = generateSuccessor(n,s);*/
- // if(){
- // ucb(child) > ucb;
- // ucb = ucb(child);
- // selected = child;
- // }
- // }
- //
- // return selected;
- //
- // }
- //
- // nodeMont* expand(nodeMont* n){
- //
- // nodeMont* child;
- // //o mov. que vamos tentar é porcolunas.
- //
- // int col = 0;
- //
- // for(i=tree.size()-1; i>tree.size()-8;i++){
- // if(tree.at(i)->mdepth== (n->mdepth + 1) ){
- // col++;
- // }
- // }
- //
- // if(isMoveValid(n->nod->board, col)){
- //
- // child->n=generateSuccessor(n,col);
- // child->num_plays=0;
- // child->num_wins=0;
- // tree.push_back(child);
- // };
- //
- // return child;
- // }
- //
- // int monteCarloTreeSearch(nodeMont* n){
- //
- // nodeMont* leaf;
- // nodeMont* child;
- // int result;
- // int i=0;
- // while(i<100){
- // i++;
- // leaf = Selection(tree);
- // child = Expand(leaf);
- // result = simulate(child);
- // backPropagate(result, child);
- // }
- //
- // return
- // }
- //
- // char simulate(nodeMont* n){
- //
- // char** board = (char**)malloc(7*sizeof(char*));
- //
- // for(int i = 0; i < 7; i++){
- // board[i] = (char*)malloc(6*sizeof(char));
- // }
- //
- // int eval = 0;
- // int m;
- // char player = n->n->player;
- //
- // board = n->n->board;
- //
- // node* startNode = newNode(board, 0, -1, player);
- // while(eval > -INF && eval < INF){
- // if(player == 'X'){
- // printf("CPU turn.\n");
- //
- // m = minimaxDecision(startNode);
- // makeMove(m, player, board);
- //
- //
- // }
- // else{
- // n = minimaxDecision(startNode);
- // makeMove(n, player, board);
- // }
- //
- // printBoard(board);
- // player = opponent(player);
- // printf("\n");
- // eval = utility(board);
- // startNode = newNode(board, 0, -1, player);
- // }
- //
- // //vamos retornar o oponente porque o while atualiçou o player depois de ganhar.
- // return opponent(player);
- // }
- //
- // void backPropagate(char result, nodeMont* n){
- //
- // nodeMont* current=n;
- // while(current->depth>0){
- //
- // current->num_plays +=1;
- //
- // if (current->n->player == result){
- // current->num_wins +=1;
- // }
- //
- // current=current->parent;
- // }
- //
- // //atualizamos o nó root
- // current->num_plays +=1;
- // if (current->n->player == result){
- // current->num_wins +=1;
- // }
- // }
- int main() {
- char** board = (char**)malloc(7*sizeof(char*));
- for(int i = 0; i < 7; i++) {
- board[i] = (char*)malloc(6*sizeof(char));
- }
- for(int i = 0; i < 7; i++){
- for(int j = 0; j < 6; j++){
- board[i][j] = ' ';
- }
- }
- //i coluna, j linha
- int optAlg = 0;
- int optTurn = 0;
- char player;
- while(optAlg != 1 && optAlg != 2){
- printf("Que algoritmo quer usar?\n1:Minimax\n2:Minimax com alfa-beta pruning\n");
- scanf("%d", &optAlg);
- }
- while(optTurn != 1 && optTurn != 2){
- printf("Quem joga primeiro:\n1:Humano 'O'\n2:Computador 'X'\n");
- scanf("%d", &optTurn);
- if(optTurn == 1){
- player = 'O';
- }
- if(optTurn == 2){
- player = 'X';
- }
- }
- int eval = 0;
- int m;
- node* startNode = newNode(board, 0, -1, player);
- while(eval > -INF && eval < INF){
- if(player == 'X'){
- printf("CPU turn.\n");
- if(optAlg == 1){
- m = minimaxDecision(startNode);
- }
- if(optAlg == 2){
- m = alphaBetaSearch(startNode);
- }
- }
- else{
- printf("Human to move: ");
- scanf("%d", &m);
- }
- makeMove(m, player, board);
- printBoard(board);
- player = opponent(player);
- printf("\n");
- eval = utility(board);
- startNode = newNode(board, 0, -1, player);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment