Додаток Б. Текст програми

 

#include <stdio.h>

#include <ctype.h>

#include <conio.h>

 

#define String_Length 80

 

#define Squares 9

typedef char Square_Type;

typedef Square_Type Board_Type[Squares];

const Square_Type Empty = ' ';

 

/* Максимальна величина оцінки ходу */

const int Infinity = 10;

 

/* Максимальна кількість ходів у грі */

const int Maximum_Moves = Squares;

 

int Total_Nodes;

 

/* Масив‚ що описує всім виграшних комбінацій */

#define Possible_Wins 8

const int Three_in_a_Row[Possible_Wins][3] = {

{ 0, 1, 2 },

{ 3, 4, 5 },

{ 6, 7, 8 },

{ 0, 3, 6 },

{ 1, 4, 7 },

{ 2, 5, 8 },

{ 0, 4, 8 },

{ 2, 4, 6 }

};

 

/* Масив, який використовується в евристичній формулі для кожного ходу */

const int Heuristic_Array[4][4] = {

{ 0, -10, -100, -1000 },

{ 10, 0, 0, 0 },

{ 100, 0, 0, 0 },

{ 1000, 0, 0, 0 }

};

 

/* Структура, що отримує хід та визначає його евристику */

typedef struct {

int Square;

int Heuristic;

} Move_Heuristic_Type;

 

/* Очистка ігрового поля */

void Initialize(Board_Type Board) {

int I;

for (I = 0; I < Squares; I++)

    Board[I] = Empty;

}

/* Якщо гравець переміг, виводить переможця. Якщо гра нічийна, повертає 'C'. Якщо гра ще не завершена‚ повертає Empty. */

 

Square_Type Winner(Board_Type Board) {

int I;

for (I = 0; I < Possible_Wins; I++) {

    Square_Type Possible_Winner = Board[Three_in_a_Row[I][0]];

    if (Possible_Winner!= Empty &&

    Possible_Winner == Board[Three_in_a_Row[I][1]] &&

    Possible_Winner == Board[Three_in_a_Row[I][2]])

    return Possible_Winner;

}

 

for (I = 0; I < Squares; I++)

    if (Board[I] == Empty)

    return Empty;

 

return 'C';

}

 

Square_Type Other(Square_Type Player) {

return Player == 'X'? 'O': 'X';

}

 

/* Виконання ходу на ігровому полі */

 

void Play(Board_Type Board, int Square, Square_Type Player) {

Board[Square] = Player;

}

 

/* Вивід ігрового поля */

 

void Print(Board_Type Board) {

int I;

clrscr();

for (I = 0; I < Squares; I += 3) {

    if (I > 0)

    printf("\t---+---+---\n");

    printf("\t %c | %c | %c \n", Board[I], Board[I + 1], Board[I + 2]);

}

printf("\n");

}

 

/* Повертає використану евристику, щоб визначити команду, в якій розшукується підпорядкована вершина */

 

int Evaluate(Board_Type Board, Square_Type Player) {

int I;

int Heuristic = 0;

for (I = 0; I < Possible_Wins; I++) {

    int J;

    int Players = 0, Others = 0;

    for (J = 0; J < 3; J++) {

    Square_Type Piece = Board[Three_in_a_Row[I][J]];

    if (Piece == Player)

              Players++;

    else if (Piece == Other(Player))

              Others++;

    }

    Heuristic += Heuristic_Array[Players][Others];

}

return Heuristic;

}

/* Визначає ціну найкращого ходу‚ яка повертається в змінній *Square */

int Best_Move(Board_Type Board, Square_Type Player, int *Square, int Move_Nbr,

    int Alpha, int Beta) {

int Best_Square = -1;

int Moves = 0;

int I;

Move_Heuristic_Type Move_Heuristic[Squares];

 

Total_Nodes++;

 

/* Знаходить евристику всіх ходів і сортує ходи по спаданню ціни */

 

for (I = 0; I < Squares; I++) {

    if (Board[I] == Empty) {

    int Heuristic;

    int J;

    Play(Board, I, Player);

    Heuristic = Evaluate(Board, Player);

    Play(Board, I, Empty);

    for (J = Moves-1; J >= 0 &&

                       Move_Heuristic[J].Heuristic < Heuristic; J--) {

              Move_Heuristic[J + 1].Heuristic = Move_Heuristic[J].Heuristic;

              Move_Heuristic[J + 1].Square = Move_Heuristic[J].Square;

    }

    Move_Heuristic[J + 1].Heuristic = Heuristic;

    Move_Heuristic[J + 1].Square = I;

    Moves++;

    }

}

for (I = 0; I < Moves; I++) {

    int Score;

    int Sq = Move_Heuristic[I].Square;

    Square_Type W;

 

/* Виконання ходу та визначення його ціни */

 

    Play(Board, Sq, Player);

    W = Winner(Board);

    if (W == 'X')

    Score = (Maximum_Moves + 1) - Move_Nbr;

    else if (W == 'O')

    Score = Move_Nbr - (Maximum_Moves + 1);

    else if (W == 'C')

    Score = 0;

    else

    Score = Best_Move(Board, Other(Player), Square, Move_Nbr + 1,

                       Alpha, Beta);

 

    Play(Board, Sq, Empty);

 

    if (Player == 'X') {

    if (Score >= Beta) {

              *Square = Sq;

              return Score;

    } else if (Score > Alpha) {

              Alpha = Score;

              Best_Square = Sq;

    }

    } else {

    if (Score <= Alpha) {

              *Square = Sq;

              return Score;

    } else if (Score < Beta) {

              Beta = Score;

              Best_Square = Sq;

    }

    }

}

*Square = Best_Square;

if (Player == 'X')

    return Alpha;

else

    return Beta;

}

 

/* Виводить текст повідомлення за ціною ходу‚ яка повертається Best_Move */

 

void Describe(int Score) {

if (Score < 0)

    printf("\tВи маєте гарантований виграш.\n");

else if (Score == 0)

    printf("\tЯ можу гарантувати Вам нічию.\n");

else

    printf("\tВиграш гарантує хід %d.\n",

     Maximum_Moves - Score + 1);

}

/* Визначає хід людини або комп’ютера */


void Move(Board_Type Board, Square_Type Player, int Move_Nbr) {

int Square;

 

if (Player == 'X') {

    Total_Nodes = 0;

    Describe(Best_Move(Board, 'X', &Square, Move_Nbr, -Infinity, Infinity));

    printf("\t%d вершина перевірена.\n", Total_Nodes);

    Play(Board, Square, 'X');

    printf("\tХўд #%d - X ходить на %d\n", Move_Nbr, Square + 1);

} else {

    do {

    printf("\tХўд #%d - Куди ходить O? ", Move_Nbr);

    scanf("%d", &Square);

    Square--;

    } while (Board[Square]!= ' ');

    Play(Board, Square, 'O');

}

}

 

/* Реалізація гри */

 

void Game() {

Square_Type Player;

char Answer[String_Length];

Board_Type Board;

int Move_Nbr = 1;

 

Initialize(Board);


printf("\n\tХочете ходити першим? ");

scanf("%s", Answer);

if (toupper(Answer[0]) == 'Y')

    Player = 'O';

else

    Player = 'X';

 

while(Winner(Board) == ' ') {

    Print(Board);

    Move(Board, Player, Move_Nbr);

    Player = Other(Player);

    Move_Nbr++;

}

Print(Board);

 

if (Winner(Board)!= 'C')

    printf("\t%c виграли!\n", Winner(Board));

else

    printf("\tНiчия.\n");

}

 

int main() {

char Answer[String_Length];

clrscr();

printf("\tГра у хрестики - нулики!\n\n");

printf("\tОзнайомтесь з нумерацією ігрового поля:\n");

printf("\t 1 | 2 | 3\n");

printf("\t---+---+---\n");

printf("\t 4 | 5 | 6\n");

printf("\t---+---+---\n");

printf("\t 7 | 8 | 9\n");

printf("\n");

printf("\tКомп'ютер грає X, ви граєте O.\n");

 

do {

    Game();

    printf("\n\tХочете продовжувати? ");

    scanf("%s", Answer);

} while (toupper(Answer[0]) == 'Y');

}






Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: