Система сохранений и ходов компьютера в консольных крестиках-ноликах - 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;
}