Система сохранений и ходов компьютера в консольных крестиках-ноликах - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Вчера вечером решил продолжить изучать С++, что бы вспомнить основы начал с СИ и собрался написать игру крестики нолики. Игра практически готова и даже работает для режима "2 игрока", но я пока не знаю, как реализовать систему ходов компьютера и систему сохранений. Подкиньте идею, как можно реализовать такие системы. P.S. Вот исходник:
/////////////////////////////////
// Program : крестики - нолики //
// Autor : Бесчастных Денис    //
/////////////////////////////////
 
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <locale.h>
#include <time.h>
 
#define MAX_SAVES 3
 
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); //Получаение дескриптора устройства стандартного вывода
static int hightMenu = 1;
/*
    1 - Начать игру
    2 - Загрузить игру
    3 - Как играть?
    4 - Выход
*/
static int lowMenu = 1;
/*
    1 - 2 игрока
    2 - Против компьютера
    3 - Назад
*/
static int inGameMenu = 1;
/*
    1 - Продолжить игру
    2 - Сохранить игру
    3 - Как играть?
    4 - К главному меню
    5 - Выход
*/
static int turn;
/*
    чья очередь ходить
    1 - 1-ый игрок
    2 - 2-ой игрок
*/
static int loadMenu = 1;
static int win = 0;
static int numberMoves = 0;
static int gamemode = -1;
/*
    0 - 2 игрока
    1 - против компьютера
*/
static char gamer1 = (turn == 1) ? 'X' : 'O';
static char gamer2 = (turn == 2) ? 'X' : 'O';
static int coordX = 1;
static int coordY = 1;
static int gameMatrix[3][3];
static char form[14][15];
static int saveNumber = 0;
static int EXIT = 0;
static int saves[MAX_SAVES][11];
char bufRus[256];
FILE* FORM;
FILE* SAVES;
 
///Список прототипов
void paintComponent();       //делает отрисовку после загрузки
void setGame(int);           //устанавливает игру по сохранению
void saveGame();             //сохраняет текущую игру
void isWin();                //функция определения победы
char *Rus(const char *text); //функция вывода русских букв
void readForm();             //читает форму
void generateForm();         //создает форму, если ее нет
void printForm();            //выводит форму
void setForm(int, int, int); //устанавливает в форму новое значение
void readSaves();            //читает сохранения
void fileSystem();           //открывает/создает системные файлы
void printHelp();            //выводит справку
void printHightMenu();       //выводит главное меню
void printLowMenu();         //выводит меню новой игры
void printGame();            //выводит игровое окно
void printInGameMenu();      //выводит меню во время игры
void printLoadMenu();        //выводит меню загрузки
void printWin();             //вывод победы
void hightMenuCycle();       //цикл главного меню
void lowMenuCycle();         //цикл меню новой игры
void gameCycle();            //цикл игры
void inGameCycle();          //цикл меню во время игры
void loadMenuCycle();        //цикл меню загрузки
 
void paintComponent()
{
    for(int x = 1; x < 4; x++)
        for(int y = 1; y < 4; y++)
            if (gameMatrix[x - 1][y - 1]) setForm(gameMatrix[x - 1][y - 1], x, y);
}
 
void setGame(int n)
{
    numberMoves = 0;
    for(int i = 0; i < 3; i++)
        for(int j = 0; j < 3; j++)
        {
            gameMatrix[i][j] = saves[n][i * 3 + j];
            if (gameMatrix[i][j]) numberMoves++;
        }
    turn = saves[n][9];
    gamemode = saves[n][10];
    win = 0;
    if (numberMoves % 2)
    {
        gamer1 = (turn == 2) ? 'O' : 'X';
        gamer2 = (turn == 2) ? 'X' : 'O';
    }
    else
    {
        gamer1 = (turn == 1) ? 'O' : 'X';
        gamer2 = (turn == 1) ? 'X' : 'O';
    }
}
 
void saveGame()
{
    SAVES = fopen("saves.txt", "w");
    if (saveNumber < MAX_SAVES)
    {
        saveNumber++;
        fprintf(SAVES, "%d ", saveNumber);
        for(int i = 0; i < saveNumber - 1; i++)
                for(int j = 0; j < 10; j++)
                fprintf(SAVES, "%d ", saves[i][j]);
        for(int i = 0; i < 3; i++)
            for(int j = 0; j < 3; j++)
            {
                fprintf(SAVES, "%d ", gameMatrix[i][j]);
                saves[saveNumber - 1][i * 3 + j] = gameMatrix[i][j];
            }
        fprintf(SAVES, "%d %d", turn, gamemode);
        saves[saveNumber - 1][9] = turn;
        saves[saveNumber - 1][10] = gamemode;
        fclose(SAVES);
        system("cls");
        printf(Rus("Игра сохранена!\n"));
        system("pause");
    }
    else
    {
        system("cls");
        printf(Rus("Нет места для сохранения!\n"));
        system("pause");
    }
}
 
void isWin()
{
    for(int j = 0; j < 3; j++)
    {
        if (gameMatrix[j][0] == gameMatrix[j][1] && gameMatrix[j][1] == gameMatrix[j][2]) win = gameMatrix[j][0];
        if (win) break;
        if (gameMatrix[0][j] == gameMatrix[1][j] && gameMatrix[1][j] == gameMatrix[2][j]) win = gameMatrix[0][j];
        if (win) break;
    }
    if (win) return;
    if ((gameMatrix[0][0] == gameMatrix[1][1] && gameMatrix[1][1] == gameMatrix[2][2]) || (gameMatrix[2][0] == gameMatrix[1][1] && gameMatrix[1][1] == gameMatrix[0][2])) win = gameMatrix[1][1];
}
 
char *Rus(const char *text)
{
    CharToOem(text,bufRus);
    return bufRus;
}
 
void readForm()
{
    for(int i = 0; i < 14; i++) fgets(form[i], 15, FORM);
}
 
void generateForm()
{
    char c01 = (char)201; //левый вырхний угол
    char c02 = (char)187; //правый верхний угол
    char c03 = (char)200; //нижний левый угол
    char c04 = (char)188; //нижний правый угол
    char c05 = (char)205; //равно горизонтальное
    char c06 = (char)186; //равно вертикальное
    char c07 = (char)203; //верхний тристоронник
    char c08 = (char)202; //нижний тристоронник
    char c09 = (char)204; //левый тристоронник
    char c10 = (char)185; //правый тристоронник
    char c11 = (char)206; //четверосторонник
    char s00[14] = {c01, c05, c05, c05, c07, c05, c05, c05, c07, c05, c05, c05, c02, '\0'};
    char s01[14] = {c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, '\0'};
    char s02[14] = {c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, '\0'};
    char s03[14] = {c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, '\0'};
    char s04[14] = {c09, c05, c05, c05, c11, c05, c05, c05, c11, c05, c05, c05, c10, '\0'};
    char s05[14] = {c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, '\0'};
    char s06[14] = {c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, '\0'};
    char s07[14] = {c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, '\0'};
    char s08[14] = {c09, c05, c05, c05, c11, c05, c05, c05, c11, c05, c05, c05, c10, '\0'};
    char s09[14] = {c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, '\0'};
    char s10[14] = {c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, '\0'};
    char s11[14] = {c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, ' ', ' ', ' ', c06, '\0'};
    char s12[14] = {c03, c05, c05, c05, c08, c05, c05, c05, c08, c05, c05, c05, c04, '\0'};
    fprintf(FORM, "%s\n", s00);
    fprintf(FORM, "%s\n", s01);
    fprintf(FORM, "%s\n", s02);
    fprintf(FORM, "%s\n", s03);
    fprintf(FORM, "%s\n", s04);
    fprintf(FORM, "%s\n", s05);
    fprintf(FORM, "%s\n", s06);
    fprintf(FORM, "%s\n", s07);
    fprintf(FORM, "%s\n", s08);
    fprintf(FORM, "%s\n", s09);
    fprintf(FORM, "%s\n", s10);
    fprintf(FORM, "%s\n", s11);
    fprintf(FORM, "%s\n", s12);
}

Решение задачи: «Система сохранений и ходов компьютера в консольных крестиках-ноликах»

textual
Листинг программы
void printLoadMenu()
{
    system("cls");
    SetConsoleTextAttribute(hConsole, (WORD) ((12) | 10));
    printf(Rus("################################################################################"));
    printf(Rus("#                                                                              #"));
    printf(Rus("#                               Крестики-Нолики                                #"));
    printf(Rus("#                                                                              #"));
    printf(Rus("################################################################################"));
    printf(Rus("\n\nЗагрузка сохранения:\n\n"));
    char s1[] = "Сохранений нет\n";
    char s2[] = "Назад\n";
    if (!saveNumber) printf(Rus(s1));
    for(int i = 0; i < saveNumber + 1; i++)
        if (loadMenu == i + 1)
        {
            SetConsoleTextAttribute(hConsole, (WORD) ((15 << 5) | 0));
            if (i == saveNumber) printf("%s", Rus(s2));
            else printf("%s%d%d\n", Rus("Сохранение"), i / 10, i % 10);
            SetConsoleTextAttribute(hConsole, (WORD) ((12) | 10));
        }
        else
            if (i == saveNumber) printf("%s", Rus(s2));
            else printf("%s%d%d\n", Rus("Сохранение"), i / 10, i % 10);
}
 
void printWin()
{
    system("cls");
    printf(Rus("################################################################################"));
    printf(Rus("#                                                                              #"));
    printf(Rus("#                               Крестики-Нолики                                #"));
    printf(Rus("#                                                                              #"));
    printf(Rus("################################################################################"));
    printf("\n\n");
    printf(Rus("\t\t\t\tИГРА ОКОНЧЕНА\n"));
    if (!win) printf(Rus("Ничья!!!\n"));
    else if ((turn == 1 && gamer2 == 'X') || (turn == 2 && gamer2 == 'O'))
        if (gamemode) printf(Rus("Победил компьютер!!!\n"));
        else printf(Rus("Победил 2-ой игрок!!!\n"));
    else if (gamemode) printf(Rus("Вы победили!!!\n"));
    else printf(Rus("Победил 1-ый игрок!!!\n"));
    printf("\n\n\n");
    system("pause");
}
 
void hightMenuCycle()
{
    for(int i = 0; i < 3; i++)
        for(int j = 0; j < 3; j++)
            gameMatrix[i][j] = 0;
    srand(time(NULL));
    turn = rand() % 2 + 1;
    gamer1 = (turn == 1) ? 'X' : 'O';
    gamer2 = (turn == 2) ? 'X' : 'O';
    gamemode = -1;
    numberMoves = 0;
    turn = 1;
    coordX = 1;
    coordY = 1;
    fileSystem();
    win = 0;
    for(int number = 0; gamemode == -1;)
    {
        printHightMenu();
        number = getch();
        if (number == 224) number = getch(); //служебная клавища состоит из 2 символов 224 + еще чет
        switch (number)
        {
            case 13: // если ENTER
                    switch(hightMenu)
                    {
                        case 1:
                            lowMenuCycle();
                            break;
                        case 2:
                            loadMenuCycle();
                            break;
                        case 3:
                            printHelp();
                            break;
                        case 4:
                            EXIT = 1;
                            return;
                    }
                break;
            case 80: // если ВНИЗ
                    hightMenu = hightMenu % 4 + 1;
                break;
            case 72: // если ВВЕРХ
                    hightMenu = hightMenu - 1 + (hightMenu - 1 == 0) * 4;
                break;
        }
    }
    if (gamemode > -1) gameCycle();
}
 
void lowMenuCycle()
{
    for(int number = 0;;)
    {
        printLowMenu();
        number = getch();
        if (number == 224) number = getch(); //служебная клавища состоит из 2 символов 224 + еще чет
        switch (number)
        {
            case 13: // если ENTER
                    switch(lowMenu)
                    {
                        case 1:
                            gamemode = 0;
                            return;
                        case 2:
                            gamemode = 1;
                            return;
                        case 3:
                            return;
                    }
            case 80: // если ВНИЗ
                    lowMenu = lowMenu % 3 + 1;
                break;
            case 72: // если ВВЕРХ
                    lowMenu = lowMenu - 1 + (lowMenu - 1 == 0) * 3;
                break;
        }
    }
}
 
void gameCycle()
{
    for(int number = 0; numberMoves < 10;)
    {
        printGame();
        if (numberMoves == 9)
        {
            numberMoves++;
            continue;
        }
        if (win) break;
        number = getch();
        if (number == 224) number = getch(); //служебная клавища состоит из 2 символов 224 + еще чет
        switch (number)
        {
            case 27: // если ESC
                inGameCycle();
                break;
            case 13: // если ENTER
                if (!gameMatrix[coordX - 1][coordY - 1])
                {
                    gameMatrix[coordX - 1][coordY - 1] = turn;
                    isWin();
                    numberMoves++;
                    setForm(numberMoves, coordX, coordY);
                    if (win) break;
                    turn++;
                    turn = turn % 3 + (turn % 3 == 0);
                }
                break;
            case 75: //если ВЛЕВО
                if (coordY != 1) coordY--;
                break;
            case 77: //если ВПРАВО
                if (coordY != 3) coordY++;
                break;
            case 80: // если ВНИЗ
                if (coordX != 3) coordX++;
                break;
            case 72: // если ВВЕРХ
                if (coordX != 1) coordX--;
                break;
        }
    }
    printWin();
}
 
void inGameCycle()
{
    for(int number = 0; numberMoves < 10;)
    {
        printInGameMenu();
        number = getch();
        if (number == 224) number = getch(); //служебная клавища состоит из 2 символов 224 + еще чет
        switch (number)
        {
            case 27: // если ESC
                return;
            case 13: // если ENTER
                switch(inGameMenu)
                {
                    case 1:
                        return;
                    case 2:
                        saveGame();
                        break;
                    case 3:
                        printHelp();
                        break;
                    case 5:
                        EXIT = 1;
                    case 4:
                        numberMoves = 10;
 
                }
                break;
            case 80: // если ВНИЗ
                    inGameMenu = inGameMenu % 5 + 1;
                break;
            case 72: // если ВВЕРХ
                    inGameMenu = inGameMenu - 1 + (inGameMenu - 1 == 0) * 5;
                break;
        }
    }
}
 
void loadMenuCycle()
{
    for(int number = 0;;)
    {
        printLoadMenu();
        number = getch();
        if (number == 224) number = getch(); //служебная клавища состоит из 2 символов 224 + еще чет
        switch (number)
        {
            case 27: // если ESC
                return;
            case 13: // если ENTER
                if (loadMenu == saveNumber + 1) return;
                else setGame(loadMenu);
                paintComponent();
                system("cls");
                for(int i = 0; i < 3; i++)
                {
                    for(int j = 0; j < 3; j++)
                        printf("%d ", gameMatrix[i][j]);
                    printf("\n");
                }
                system("pause");
                return;
            case 80: // если ВНИЗ
                    loadMenu = loadMenu % (saveNumber + 1) + 1;
                break;
            case 72: // если ВВЕРХ
                    loadMenu = loadMenu - 1 + (loadMenu - 1 == 0) * (saveNumber + 1);
                break;
        }
    }
}
 
int main()
{
    system("chcp 866");
    for(; !EXIT;) hightMenuCycle();
    return 0;
}

Оцени полезность:

6   голосов , оценка 3.833 из 5
Похожие ответы