Files
TicTacToe/main.cpp
vadim.bochkov 8268e14e8a Крестики-нолики против бота с примитивным рандомайзером в роли ИИ.
Реализация через двумерный массив и объекты-классы (насколько я их понял).
Можно играть первым и вторым номером, игра ведёт счёт.
2024-11-01 15:52:41 +05:00

215 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <chrono>
#include <thread>
#include <windows.h>
#include <string>
using namespace std;
typedef unsigned int unint;
int main() {
//
//ПЕРЕМЕННЫЕ
//
//МЭЙН
const int LINES = 3, COLUMNS = 3;
bool newgame=true, firstnumber;
int turn, humanwin=0, botwin=0;
string wannaplay="y";
const string INCORRECT="INCORRECT VALUE, TRY AGAIN: ", ENDGAME="\nGame says: ''The game ends here.''";
const string XWON="Game says: ''X wins!''", OWON="O wins!", DRAW="Game says: ''Nobody wins - DRAW!''";
const string BOTLOST="Bot says: ''Shee u beat me, I'm worry.''", HUMANLOST="Bot says: ''nahahaha lamer, look how I beat u!''";
const string SEP(15, '-');
const string BOTTHINK="Bot says: ''Wait, I'm thinking.''";
//
//КЛАССЫ
//Класс, отвечающий за формирование и вывод поля
class Board {
public:
bool Xwonflag=false;
bool Owonflag=false;
//ИГРОВОЕ ПОЛЕ
//первое число LINES характеризует строку
//второе число COLUMNS характеризует столбик
string board[LINES][COLUMNS] = {
{"e", "e", "e"},
{"e", "e", "e"},
{"e", "e", "e"}
};
//Функция вывода поля.
//Пустая клетка ("е") выводится координатами, а занятая - своим знаком.
void BoardShow() {
for (int countlines = 0; countlines < LINES; ++countlines) {
for (int countcolumns = 0; countcolumns < COLUMNS; ++countcolumns) {
if (board[countlines][countcolumns]=="e") {
cout << countlines << countcolumns << " ";
}
else {
cout << board[countlines][countcolumns] << " ";
}
}
cout << endl;
}
}
void XWon() {
if ((board[0][0])=="'X'") {
if ((board[0][1])=="'X'" and (board[0][2])=="'X'") {Xwonflag=true;}
else if ((board[1][1])=="'X'" and (board[2][2])=="'X'") {Xwonflag=true;}
else if ((board[1][0])=="'X'" and (board[2][0])=="'X'") {Xwonflag=true;}
}
if (((board[1][0])=="'X'") and ((board[1][1])=="'X'") and ((board[1][2]))=="'X'") {Xwonflag=true;}
if (((board[0][1])=="'X'") and ((board[1][1])=="'X'") and ((board[2][1]))=="'X'") {Xwonflag=true;}
if (((board[0][2])=="'X'") and ((board[1][2])=="'X'") and ((board[2][2]))=="'X'") {Xwonflag=true;}
if ((board[2][0])=="'X'") {
if ((board[2][1])=="'X'" and (board[2][2])=="'X'") {Xwonflag=true;}
else if ((board[1][1])=="'X'" and (board[0][2])=="'X'") {Xwonflag=true;}
}
}
void OWon() {
if ((board[0][0])=="'O'") {
if ((board[0][1])=="'O'" and (board[0][2])=="'O'") {Owonflag=true;}
else if ((board[1][1])=="'O'" and (board[2][2])=="'O'") {Owonflag=true;}
else if ((board[1][0])=="'O'" and (board[2][0])=="'O'") {Owonflag=true;}
}
if (((board[1][0])=="'O'") and ((board[1][1])=="'O'") and ((board[1][2]))=="'O'") {Owonflag=true;}
if (((board[0][1])=="'O'") and ((board[1][1])=="'O'") and ((board[2][1]))=="'O'") {Owonflag=true;}
if (((board[0][2])=="'O'") and ((board[1][2])=="'O'") and ((board[2][2]))=="'O'") {Owonflag=true;}
if ((board[2][0])=="'O'") {
if ((board[2][1])=="'O'" and (board[2][2])=="'O'") {Owonflag=true;}
else if ((board[1][1])=="'O'" and (board[0][2])=="'O'") {Owonflag=true;}
}
}
};
//Ходы игрока и бота
class Turn {
public:
int turnLINEint, turnCOLint;
string Humancount, turnline, turncol;
void HumanTurn() {
//ХОД ИГРОКА
//алгоритм на вычленение первого и второго значений координат
//получает строку вида "XY", первый символ кидает через at в строку для Х,
//второй символ также символ кидает в строку для Y,
//затем переводит обе строки в числа, с которыми можно вести вычисления.
cin >> Humancount;
turnline=Humancount.at(0);
turncol=Humancount.at(1);
turnLINEint=stoi(turnline);
turnCOLint=stoi(turncol);
//cout << "\nlineHUMAN: " << turnLINEint << " colHUMAN: " << turnCOLint << endl;
}
void BotTurn() {
//ХОД БОТА
//рандомит первое значение (строку), засыпает,
//рандомит второе значение (столбец)
srand((time(0)));
turnLINEint=(rand()%3);
Sleep((rand()/3));
srand((time(0)));
turnCOLint=(rand()%3);
//cout << "lineBOT: " << turnLINEint << " colBOT: " << turnCOLint << endl;
}
};
//Объявление объектов
Turn Game;
Board BoardObj;
//
//
//
//
//Заглавие игры. Инструкции для игрока. Выводится только при первом запуске.
cout << "Bot says:" << endl;
cout << "''Wolcome to TicTacToe choom." << endl;
cout << "Look at the clear board." << endl;
BoardObj.BoardShow();
cout << "When u wanna do ur turn - u should type coordinates of the any empty cell." << endl;
cout << "(For example '22' or '10')" << endl;
cout << "I afford I shouldn't explain u rules of the TicTacToe. So let's play brodie.''" << endl;
//
//Основной цикл игры
while (wannaplay=="y") {
//Объявление переменных при старте новой игры на основе булевого флага newgame.
//Флаг newgame становится TRUE на стадии "Заглавие игры",
//становится FALSE в начале цикла после присвоения переменных,
//и снова становится TRUE при окончании цикла (т.е. при чьей-то победе или ничье).
if (newgame) {
//
//Запрос на то, кто первый. 1=игрок, 0=бот.
//Выводит соответствующее сообщение после выбора.
//Обнуляет общие переменные.
//Также снимает флаг newgame, который возвращается в конце игры.
cout << "Bot asks: Wanna be an X? (1/0):";
cin >> firstnumber;
if (firstnumber) {cout << "Bot says: ''Well, u'll be an X.''" << endl;}
else {cout << "Bot says: ''OK, I'll be an X.''\n" << endl;}
turn=1;
newgame=false;
}
cout << SEP << endl;
cout << "Game says: ''Now it's " << turn << " turn.''" << endl;
turn++;
Game.turnLINEint=3;
Game.turnCOLint=3;
//Если первым номером (Х) выступает игрок
if (firstnumber) {
cout << "Enter ur coords:";
while ((BoardObj.board[Game.turnLINEint][Game.turnCOLint]!="e")) {
Game.HumanTurn();
if ((BoardObj.board[Game.turnLINEint][Game.turnCOLint]!="e")) {cout << INCORRECT;}
}
BoardObj.board[Game.turnLINEint][Game.turnCOLint] = "'X'";
Game.turnLINEint=3;
Game.turnCOLint=3;
cout << BOTTHINK << endl;
while ((BoardObj.board[Game.turnLINEint][Game.turnCOLint]!="e")) {Game.BotTurn();}
BoardObj.board[Game.turnLINEint][Game.turnCOLint] = "'O'";
BoardObj.BoardShow();
}
//Если игрок выступает вторым номером (O)
else {
cout << BOTTHINK << endl;
while ((BoardObj.board[Game.turnLINEint][Game.turnCOLint]!="e")) {Game.BotTurn();}
BoardObj.board[Game.turnLINEint][Game.turnCOLint] = "'X'";
BoardObj.BoardShow();
cout << "Enter ur coords:";
Game.turnLINEint=3;
Game.turnCOLint=3;
while ((BoardObj.board[Game.turnLINEint][Game.turnCOLint]!="e")) {
Game.HumanTurn();
if ((BoardObj.board[Game.turnLINEint][Game.turnCOLint]!="e")) {cout << INCORRECT;}
}
BoardObj.board[Game.turnLINEint][Game.turnCOLint] = "'O'";
}
BoardObj.XWon();
BoardObj.OWon();
if ((BoardObj.Xwonflag) or (BoardObj.Owonflag) or (turn>=9)) {
cout << ENDGAME << endl;
newgame=true;
if (BoardObj.Xwonflag) {cout << XWON << endl;}
else if (BoardObj.Owonflag) {cout << OWON << endl;}
else if ((turn>=9) and (!BoardObj.Xwonflag) and (!BoardObj.Owonflag)) {cout << DRAW << endl;}
if ((firstnumber) and (BoardObj.Xwonflag)) {cout << BOTLOST << endl; humanwin=+1;}
else if ((!firstnumber) and (BoardObj.Owonflag)) {cout << BOTLOST << endl; humanwin=+1;}
else {cout << HUMANLOST << endl; botwin=+1;}
cout << SEP << endl;
cout << SEP << endl;
cout << "Wanna play another time?(y/n): ";
cin >> wannaplay;
}
}
//
//СТАТИСТИКА ПРИ ЗАВЕРШЕНИИ ИГРЫ
cout << SEP << endl;
cout << "SOME STATS OF SESSION:" << endl;
cout << "Bot says: ''Hell u won me " << humanwin << " times.\nAnd I won u " << botwin << " times.''" << endl;
//
//компьютер респектует или лошит игрока
if (humanwin<botwin) {cout << "Bot says: ''fuckyeah go back home lamer, u need some training.''" << endl;}
else if (botwin<humanwin) {cout << "Bot says: ''well, dat was not bad how u beat me.''" << endl;}
else if (botwin==humanwin) {cout << "Bot says: ''yeah dat was fairplay.''" << endl;}
return 1488;
}