Projekt gry kółko i krzyżyk (ang. Tic Tac Toe) wykonany w C++ przy użyciu funkcji. Projekt dla I roku studiów Informatycznych.

Gra oferuje:
- możliwość gry z komputerem lub dla dwóch graczy
- możliwość wyboru czy gramy kółkiem czy krzyżykiem
- komunikat o wygranej jednego z graczy z podświetleniem jego trzech znaków w jednej linii
- w przypadku gry z komputerem możemy wybrać kto zaczyna lub zdecydować się na losowy wybór
- autorski algorytm gry komputera (komputer jest nie do pokonania, przynajmniej tak wykazały liczne testy programu)
- algorytm komputera umożliwia mu wygranie z graczem jeśli ten popełni błędy strategiczne (komputer stosuje kilka strategi zaobserwowanych przy normalnej grze w kółko i krzyżyk)

Projekt uruchamiany pod Visual Studio 2008.

/*

The MIT License

Copyright (c) 2009 Webook.pl

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// kolko_i_krzyzyk.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
//#include <cmath>
#include <string>
#include <ctime> // time(NULL)
#include <cctype> //
#include <Windows.h> // zawiera funkcje Sleep()
//#include<stdio.h> // zawiera funkcje getchar()
using namespace std; // otwarcie przestrzeni nazw

// funkcje uzyte w programie
void start_game(int komunikat);
void menu_glowne();
void clear_screen();
void menu_1(int komunikat_m1);
void run_game(int opcja);
void pokaz_plansze();
void run_game_start(int kto_zaczyna, int ustaw_preferencje_g1, int ustaw_preferencje_g2, int dwoch_graczy, int pole_zajete=0);
int wstaw_znaczek(char nr_pola_char, string znaczek);
void spr_wygrana();
void ruch_komputera();
int rk_spr_przeciwnika(int p1, int p2, int p3, string znaczek);
int rk_obrona(string znaczek);
int rk_wstaw_znaczek(int nr_pola, string znaczek, int do_pola);
int rk_wstaw_znaczek_jesli_dwa_pola_zajete(int nr_pola1, int nr_pola2, string znaczek, int do_pola);
int rk_wstaw_znaczek_jesli_3wolne_2komputera(int p1, int p2, int p3, int pk1, int pk2, int do_pola);

// zmienne globalne w programie
string tablica[] = {"0","1","2","3","4","5","6","7","8","9"}; // zawiera nr pol do ktorych mozna wstawic X lub O
string tablica_gry[10] = {"OFF"," "," "," "," "," "," "," "," "," "}; // bedzie zawierac wstawione X, O, pierwsze pole dajemy OFF poniewaz nie bedziemy uzywac elementu tablicy o indexie 0
string imie_g1; // imie gracza 1
string imie_g2 = "KOMPUTER"; // jesli drugi gracz nie gra to domyslnie przeciwnikiem jest komputer wiec jako imie wstawiamy komputer
string znaczek_g1; // znak X lub O dla gracza 1
string znaczek_g2;
string wygral; // zawiera znaczek ktory wygral, na jego podstawie okreslimy do kogo nezley ten znaczek i wyswietlimy imie gracza ktory wygra (wszystko w funkcji spr_wygrana)
int koniec_gry=0; // zawiera informacje czy gra zostala zakonczona, 1 - tak, 0 - nie
int rk_nr_ruchu=0; // zawiera nr ruchu komputera
int tablica_wygranych_znakow[10]; // zawiera w danych indexa wartosc 1 jesli dane pole nalezy do linii wygranej np. xxx wtedy taki znak x bedzie mial czerwony kolor

int _tmain(int argc, _TCHAR* argv[])
{
start_game(0);
//system("pause");
return 0;
}

/**********************************************************************************************/
/**********************************************************************************************/

void start_game(int komunikat) {

char m_opcja; // zawiera wybor zakladki z glownego menu
//komunikat - zawiera informacje o tym czy wybrano niepoprawna opcje z menu, jesli 1 to wyswietla komunikat o zlym wyborze opcji z menu

menu_glowne();

// komunikaty o blednym wyborze z menu
if(komunikat == 1) {
cout<<"+ Nie poprawny wybor! Podaj nr jeszcze raz.nn";
}


cin>>m_opcja;
cin.ignore(1000, 'n'); // kasuje ostatnie 1000 znakow z bufora aby zabezpieczyc sie przed niepoprawnym podaniem wyboru z menu

if(m_opcja == '1') { // porownuje typ char, 1 musi byc w apostrofach podczas porownania ciagu
// gra gracz vs komputer
menu_1(0);
//system("pause");

} else if(m_opcja == '2') {
// gra dla dwoch graczy
run_game(3);
//system("pause");
} else if(m_opcja == '3') { // wyjscie

} else {
start_game(1); // wyswietla na nowo menu + komunikat o zlym wyborze z menu

}

}

/**********************************************************************************************/

void menu_glowne()
{
clear_screen();

cout<<"MENU:nWybierz numer i nacisnij enter.nn"
<< "1. Nowa gra z komputeremn"
<< "2. Nowa gra dla dwoch osob (losowy gracz rozpoczyna)n" // run_game(3);
<< "3. Wyjscienn";

}

/**********************************************************************************************/

void clear_screen() { // czyscimy ekran i pozostawiamy tylko linie z nazwa programu
system("cls");
cout<<"====== Kolko i krzyzyk v1.05 19.11.2009 Webook.pl ======nn";
}

/**********************************************************************************************/

void menu_1(int komunikat_m1) {
clear_screen();
cout<<"1. Nowa gra (wybierz literke a, b lub c i nacisnij enter)n"
<<" a) zaczyna graczn" // 0
<<" b) zaczyna komputern" // 1
<<" c) losuj do kogo nalezy pierwszy ruchn" // 2
<<" e) wyjscie do menu glownegonn";

if(komunikat_m1 == 1) {
cout<<"Nie poprawny wybor opcji!n";
} else if(komunikat_m1 == 2) {
cout<<"Nie poprawna opcja uruchomienia nowej gry!n";
}

char m1;
cin>>m1;
cin.ignore(1000, 'n');

if(m1 == 'a') { // zaczyna gracz
run_game(0);
} else if(m1 == 'b') { // zaczyna komputer
run_game(1);
} else if(m1 == 'c') { // losuj do kogo nalezy pierwszy ruch
run_game(2);
} else if(m1 == 'e') {
start_game(0);
} else {
menu_1(1);
}

}

/**********************************************************************************************/

void run_game(int opcja)
{
// opcja zawiera informacje o tym kto zaczyna pierwszy ruch
/*
0 - zaczyna gracz
1 - zaczyna komputer
2 - losowo zaczyna gracz
3 - gra dla dwoch osob
*/

pokaz_plansze();

switch(opcja) {
case 0:
run_game_start(0, 1, 0, 0);
break;
case 1:
run_game_start(1, 1, 0, 0);
break;
case 2:
run_game_start(2, 1, 0, 0);
break;
case 3:
run_game_start(2, 1, 1, 1);
break;
default:
menu_1(2);
break;
}

//system("pause");
}

/**********************************************************************************************/

void pokaz_plansze() {

clear_screen();

cout<<" | | n"
<<" ";
if(tablica_wygranych_znakow[1]==1) { // jesli znak w polu jeden nalezy do 3 znakow zwycieskich to go kolorujemy na czerwono
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
cout<<tablica_gry[1];
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
} else {
cout<<tablica_gry[1];
}
cout<<" | ";
if(tablica_wygranych_znakow[2]==1) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
cout<<tablica_gry[2];
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
} else {
cout<<tablica_gry[2];
}
cout<<" | ";
if(tablica_wygranych_znakow[3]==1) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
cout<<tablica_gry[3];
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
} else {
cout<<tablica_gry[3];
}
cout<<" n"
<<" "<<tablica[1]<<"| "<<tablica[2]<<"| "<<tablica[3]<<"n"
<<"----- ----- -----n"
<<" | | n"
<<" ";
if(tablica_wygranych_znakow[4]==1) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
cout<<tablica_gry[4];
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
} else {
cout<<tablica_gry[4];
}
cout<<" | ";
if(tablica_wygranych_znakow[5]==1) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
cout<<tablica_gry[5];
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
} else {
cout<<tablica_gry[5];
}
cout<<" | ";
if(tablica_wygranych_znakow[6]==1) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
cout<<tablica_gry[6];
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
} else {
cout<<tablica_gry[6];
}
cout<<" n"
<<" "<<tablica[4]<<"| "<<tablica[5]<<"| "<<tablica[6]<<"n"
<<"----- ----- -----n"
<<" | | n"
<<" ";
if(tablica_wygranych_znakow[7]==1) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
cout<<tablica_gry[7];
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
} else {
cout<<tablica_gry[7];
}
cout<<" | ";
if(tablica_wygranych_znakow[8]==1) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
cout<<tablica_gry[8];
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
} else {
cout<<tablica_gry[8];
}
cout<<" | ";
if(tablica_wygranych_znakow[9]==1) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
cout<<tablica_gry[9];
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
} else {
cout<<tablica_gry[9];
}
cout<<" n"
<<" "<<tablica[7]<<"| "<<tablica[8]<<"| "<<tablica[9]<<"nnn";

}

/**********************************************************************************************/

void run_game_start(int kto_zaczyna, int ustaw_preferencje_g1, int ustaw_preferencje_g2, int dwoch_graczy, int pole_zajete) {

if(ustaw_preferencje_g1) { // podaj dane gracza 1
koniec_gry = 0; // podczas pierwszego uruchomienia gry kasujemy zapis informacji o koncu gry ktory moglbyc utworzony w czasie poprzedniej gry
cout<<"GRACZ 1, prosze podaj swoje imie: ";
cin>>imie_g1;

cout<<"nA teraz "<<imie_g1<<" wybierz czym chcesz grac:n1) O - kolkon2) X - krzyzykn";
char znaczek_g1_wybor;
cin>>znaczek_g1_wybor;
cin.ignore(1000, 'n');

if(znaczek_g1_wybor == '1') {
znaczek_g1 = "O";
znaczek_g2 = "X"; // automatycznie przypisujemy przeciwny znaczek dla drugiego gracza, przyda sie jesli wybrano gre na dwoch graczy lub jako znaczek przypisany dla komputera
} else if(znaczek_g1_wybor == '2') {
znaczek_g1 = "X";
znaczek_g2 = "O";
} else {
znaczek_g1 = "X";
znaczek_g2 = "O";
cout<<"Blednie wybrales znak! Dlatego przydzielono Ci domyslny znak X!n";
Sleep(1500);
}
//cout<<"n";
cout<<"Do pierwszego gracza zostal przypisany znak: "<<znaczek_g1;
cout<<"nczekaj...nn";
Sleep(1500);
}

if(ustaw_preferencje_g2) { // podaj dane gracza 2 jesli wybrano gre dla dwoch graczy
cout<<"GRACZ 2, prosze podaj swoje imie: ";
cin>>imie_g2;
//cout<<"n";
cout<<"Do drugiego gracza zostal przypisany znak: "<<znaczek_g2<<"nczekaj...nn";
Sleep(3000);
}


int los; // zawiera 0 lub 1, decyduje kto rozpoczyna pierwszy ruch gracz1 czy (komputer lub gracz 2 [w zaleznosci czy wlaczono tryb dwoch graczy])
if(kto_zaczyna == 2) { // jesli losujemy ruch to generujemy dla kogo
srand(time(NULL));
los = rand() %2;
}


// wyswietl plansze
pokaz_plansze();

spr_wygrana();

if(koniec_gry == 0) { // jesli jeszcze nikt nie wygral to gra toczy sie dalej
// jesli pole w ktore cos wstawiamy jest zajete to wyswietl komunikat
if(pole_zajete) {
cout<<"Wybrane pole jest zajete lub podales niepoprawny jego numer (zakres od 1 do 9)!nn";
}

char nr_pola = 0; // bedzie zawierac pobrany nr pola do ktorego nalezy wstawic dany znak przekazany do funkcji wstaw_znaczek()
if(kto_zaczyna == 0) { // ruch gracz1

cout<<imie_g1<<" wybierz nr pola w ktorym chcesz wstawic "<<znaczek_g1<<": ";
//cin>>nr_pola;
nr_pola = getchar();
cin.ignore(1000, 'n');

if(wstaw_znaczek(nr_pola, znaczek_g1)) { // zwraca 1 jesli wstawiono poprawnie znaczek, wtedy ruch dla przeciwnika
run_game_start(1,0,0,dwoch_graczy); // teraz wywolujemy ruch dla komputera lub gracza2 w zaleznosci czy wlaczony jest tryb dwoch graczy
} else { // nie wstawiono znaczka poniewaz pole jest zajete, wywolamy od nowa ta funkcje z komunikatem o zajetym polu
run_game_start(0,0,0,dwoch_graczy,1);
}

} else if(kto_zaczyna == 1 && dwoch_graczy == 0) { // ruch komputera, tryb dwoch graczy wylaczony
cout<<"ruch komputera...n";
Sleep(1000);
ruch_komputera();
run_game_start(0,0,0,dwoch_graczy); // przekazujemy ruch do gracza 1

} else if(kto_zaczyna == 1 && dwoch_graczy == 1) { // ruch gracza2, tryb dwoch graczy wlaczony

cout<<imie_g2<<" wybierz nr pola w ktorym chcesz wstawic "<<znaczek_g2<<": ";
//cin>>nr_pola;
nr_pola = getchar();
cin.ignore(1000, 'n');

if(wstaw_znaczek(nr_pola, znaczek_g2)) { // zwraca 1 jesli wstawiono poprawnie znaczek, wtedy ruch dla przeciwnika
run_game_start(0,0,0,dwoch_graczy); // teraz wywolujemy ruch dla komputera lub gracza2 w zaleznosci czy wlaczony jest tryb dwoch graczy
} else { // nie wstawiono znaczka poniewaz pole jest zajete, wywolamy od nowa ta funkcje z komunikatem o zajetym polu
run_game_start(1,0,0,dwoch_graczy,1);
}

} else if(kto_zaczyna == 2 && ustaw_preferencje_g2 == 0) { // losowo zaczyna gre miedzy gracz1 a komputer
run_game_start(los,0,0,0);
} else if(kto_zaczyna == 2 && ustaw_preferencje_g2 == 1) { // losowa gra miedzy gracz1 a gracz2
run_game_start(los,0,0,1);
} else {
cout<<"Nie oczekiwana konfiguracja gry!";
system("pause");
}
}
}


/**********************************************************************************************/

int wstaw_znaczek(char nr_pola_char, string znaczek) {

int wstawiono=0; // 1- tak, 0 - nie (pole jest zajete)
int nr_pola = static_cast<int>(nr_pola_char); // zamiana typu char na int
nr_pola = nr_pola-48; // odejmujemy 48 aby w przypadku gdy wybierzemy pole 1 (zapis ACII 49 odjac 48 daje nam liczbe 1)
if(nr_pola < 1 || nr_pola > 9) {
wstawiono = 0; // jesli nr pola jest niewlasciwy to odrazu blokujemy wybor takiego pola
} else if(tablica_gry[nr_pola] == " ") {
tablica[nr_pola] = " "; // kasujemy wyswietlanie nr pola do ktorego mozna wstawiac znaczki
tablica_gry[nr_pola] = znaczek; // wstawiamy odpowiedni znak w dane pole
wstawiono = 1;
} else { // w to pole jest juz wstawiony znaczek
wstawiono = 0;
}

return wstawiono;
}

/**********************************************************************************************/

void spr_wygrana() {

// poziome sprawdzenie czy wystepuja 3 znaczki obok siebie
if((tablica_gry[1] == tablica_gry[2] && tablica_gry[2] == tablica_gry[3]) && tablica_gry[1] != " ") {
wygral = tablica_gry[1];
koniec_gry = 1;
tablica_wygranych_znakow[1]=1;
tablica_wygranych_znakow[2]=1;
tablica_wygranych_znakow[3]=1;
} else if((tablica_gry[4] == tablica_gry[5] && tablica_gry[5] == tablica_gry[6]) && tablica_gry[4] != " ") {
wygral = tablica_gry[4];
koniec_gry = 1;
tablica_wygranych_znakow[4]=1;
tablica_wygranych_znakow[5]=1;
tablica_wygranych_znakow[6]=1;
} else if((tablica_gry[7] == tablica_gry[8] && tablica_gry[8] == tablica_gry[9]) && tablica_gry[7] != " ") {
wygral = tablica_gry[7];
koniec_gry = 1;
tablica_wygranych_znakow[7]=1;
tablica_wygranych_znakow[8]=1;
tablica_wygranych_znakow[9]=1;

// pionowe sprawdzenie
} else if((tablica_gry[1] == tablica_gry[4] && tablica_gry[4] == tablica_gry[7]) && tablica_gry[1] != " ") {
wygral = tablica_gry[1];
koniec_gry = 1;
tablica_wygranych_znakow[1]=1;
tablica_wygranych_znakow[4]=1;
tablica_wygranych_znakow[7]=1;
} else if((tablica_gry[2] == tablica_gry[5] && tablica_gry[5] == tablica_gry[8]) && tablica_gry[2] != " ") {
wygral = tablica_gry[2];
koniec_gry = 1;
tablica_wygranych_znakow[2]=1;
tablica_wygranych_znakow[5]=1;
tablica_wygranych_znakow[8]=1;
} else if((tablica_gry[3] == tablica_gry[6] && tablica_gry[6] == tablica_gry[9]) && tablica_gry[3] != " ") {
wygral = tablica_gry[3];
koniec_gry = 1;
tablica_wygranych_znakow[3]=1;
tablica_wygranych_znakow[6]=1;
tablica_wygranych_znakow[9]=1;

// sprawdzenie po skosie
} else if((tablica_gry[1] == tablica_gry[5] && tablica_gry[5] == tablica_gry[9]) && tablica_gry[1] != " ") {
wygral = tablica_gry[1];
koniec_gry = 1;
tablica_wygranych_znakow[1]=1;
tablica_wygranych_znakow[5]=1;
tablica_wygranych_znakow[9]=1;
} else if((tablica_gry[3] == tablica_gry[5] && tablica_gry[5] == tablica_gry[7]) && tablica_gry[3] != " ") {
wygral = tablica_gry[3];
koniec_gry = 1;
tablica_wygranych_znakow[3]=1;
tablica_wygranych_znakow[5]=1;
tablica_wygranych_znakow[7]=1;
}

// sprawdzamy czy sa jeszcze puste pola aby moc kontynuowac gre lub zakonczyc ja remisem
int znaleziono_puste_pola = 0;
for(int a=1;a<=9;a++) {
if(tablica_gry[a] == " ") { // znaleziono puste pola wiec gra moze toczyc sie dalej
znaleziono_puste_pola = 1;
break;
}
}

if(koniec_gry) { // ktos wygral to wyswietlamy wynik
string imie_wygranego;
if(wygral == znaczek_g1) { // jesli znaczek np. X nalezal do gracza1 to wygral gracz1 w przeciwnym wypadku znaczek X musial nalezec do gracza2
imie_wygranego = imie_g1;
} else {
imie_wygranego = imie_g2;
}

for(int i=0;i<=5;i++) {
pokaz_plansze();
Sleep(500); // nazwa funkcji z duzej litery, wyswietlamy napis po 500ms
cout<<"Wygral "<<imie_wygranego<<"! ("<<5-i<<")n";
if(imie_wygranego == "KOMPUTER") {
cout<<"Komputer pokonal Cie w "<<rk_nr_ruchu<<" ruchach.";
}
cout<<"nn";
Sleep(1000);
}
}

if(znaleziono_puste_pola == 0 && koniec_gry == 0) { // nieznaleziono pustych pol i nikt nie zdobyl 3 znaczkow obok siebie wiec gra konczy sie remisem

for(int j=0;j<=5;j++) {
pokaz_plansze();
Sleep(500); // nazwa funkcji z duzej litery, wyswietlamy napis po 500ms
cout<<"Remis pomiedzy graczami "<<imie_g1<<" vs "<<imie_g2<<"! ("<<5-j<<")nn";
Sleep(1000);
}

koniec_gry = 1; // ustalamy wartosc na koniec_gry=1 aby zablokowac pytanie sie o dalszy ruch ktoregos z graczy, inicjujemy ta wartosc na samym koncu poniewaz wczesniej mogla miec wartosc 0 gdy byl remis co umozliwilo wykonanie tego if'a
}

if(koniec_gry) {
cout<<"nnCzy chcesz rozpoczac nowa gre?n1) tak - wybierz tryb z menu glownegon2) nie - wyjscie z programunn";
int nowa_gra;
cin>>nowa_gra;
if(nowa_gra == 1) {
// resetujemy pola tablicy na domyslne wartosci
//tablica[10] = {"0","1","2","3","4","5","6","7","8","9"}; // zawiera nr pol do ktorych mozna wstawic X lub O
//tablica_gry[10] = {"OFF"," "," "," "," "," "," "," "," "," "};

tablica[1] = "1";
tablica[2] = "2";
tablica[3] = "3";
tablica[4] = "4";
tablica[5] = "5";
tablica[6] = "6";
tablica[7] = "7";
tablica[8] = "8";
tablica[9] = "9";
for(int b=0;b<=9;b++) {
tablica_gry[b] = " ";
tablica_wygranych_znakow[b]=0; // resetujemy info o polach ktore nalezaly do wygranej linii, dzieki temu przy kolejnej rozgrywce nie beda juz kolorowane te same pola tylko te ktore wygraja druga rozgrywke
}

rk_nr_ruchu = 0; // resetujemy zapamietana liczbe ruchow komputera

start_game(0); // uruchamiamy glowne menu gry
}
}

}

/**********************************************************************************************/

void ruch_komputera() {

// sprawdzenie czy komputer jako pierwszy podejmuje ruch
int pierwszy_ruch = 1;
for(int b=1;b<=9;b++) {
if(tablica_gry[b] != " ") {
pierwszy_ruch = 0; // jesli ktorekolwiek pole jest zajete to znaczy ze komputer wykonuje drugi ruch
}
}

if(pierwszy_ruch) { // komputer stawia jako pierwszy znak

srand(time(NULL));
int los = rand() %4;

switch(los) {
case 0:
tablica[1] = " ";
tablica_gry[1] = znaczek_g2;
break;
case 1:
tablica[3] = " ";
tablica_gry[3] = znaczek_g2;
break;
case 2:
tablica[7] = " ";
tablica_gry[7] = znaczek_g2;
break;
default:
tablica[9] = " ";
tablica_gry[9] = znaczek_g2;
break;
}

} else { // komputer wykonuje ruch po graczu

if(rk_obrona(znaczek_g2) == 0) { // jesli zero to znaczy ze komputer nie znalazl sytuacji w ktorej moglby wygrac jednym ruchem

if(rk_obrona(znaczek_g1) == 0) { // jesli zwroci 0 to znaczy ze komputer nie wykonal ruchu blokujacego przeciwnika i moze probowac atakowac


if(rk_nr_ruchu==0) { // to jest pierwszy ruch komputera, wykonywany po ruchu gracza1

if(wstaw_znaczek('5', znaczek_g2)) { // jesli wolny srodek to wstaw

// stawiamy znak naprzeciw
} else if(rk_wstaw_znaczek(1,znaczek_g1,9)) {
} else if(rk_wstaw_znaczek(3,znaczek_g1,7)) {
} else if(rk_wstaw_znaczek(7,znaczek_g1,3)) {
} else if(rk_wstaw_znaczek(9,znaczek_g1,1)) {

// stawiamy znak obok pola jesli przeciwnik dal znak w narozniku
} else if(rk_wstaw_znaczek(1,znaczek_g1,2)) {
} else if(rk_wstaw_znaczek(3,znaczek_g1,6)) {
} else if(rk_wstaw_znaczek(7,znaczek_g1,4)) {
} else if(rk_wstaw_znaczek(9,znaczek_g1,8)) {

// stawiamy znak na wzor L
} else if(rk_wstaw_znaczek(1,znaczek_g1,8)) {
} else if(rk_wstaw_znaczek(3,znaczek_g1,4)) {
} else if(rk_wstaw_znaczek(7,znaczek_g1,6)) {
} else if(rk_wstaw_znaczek(9,znaczek_g1,2)) {

// stawiamy znak obok znaku przeciwnika
} else if(rk_wstaw_znaczek(1,znaczek_g1,2)) {
} else if(rk_wstaw_znaczek(3,znaczek_g1,6)) {
} else if(rk_wstaw_znaczek(7,znaczek_g1,4)) {
} else if(rk_wstaw_znaczek(9,znaczek_g1,8)) {


// 17.10.2009
} else if(rk_wstaw_znaczek(8,znaczek_g1,6)) {
} else if(rk_wstaw_znaczek(8,znaczek_g1,4)) {
} else if(rk_wstaw_znaczek(6,znaczek_g1,8)) {
} else if(rk_wstaw_znaczek(6,znaczek_g1,2)) {
} else if(rk_wstaw_znaczek(2,znaczek_g1,6)) {
} else if(rk_wstaw_znaczek(2,znaczek_g1,4)) {
} else if(rk_wstaw_znaczek(4,znaczek_g1,2)) {
} else if(rk_wstaw_znaczek(4,znaczek_g1,8)) {

// blokowanie strategii x w 4,8 wstawiamy do 7
} else if(rk_wstaw_znaczek_jesli_dwa_pola_zajete(4,8,znaczek_g1,7)) {
} else if(rk_wstaw_znaczek_jesli_dwa_pola_zajete(6,8,znaczek_g1,9)) {
} else if(rk_wstaw_znaczek_jesli_dwa_pola_zajete(2,6,znaczek_g1,3)) {
} else if(rk_wstaw_znaczek_jesli_dwa_pola_zajete(4,2,znaczek_g1,1)) {

// jesli znak przeciwnika w innym polu niz na rogach planszy
} else {

// wstawiamy znaczek do pierwszego wolnego pola
for(int i=1;i<=9;i++) {
if(tablica_gry[i] == " ") {
tablica_gry[i] = znaczek_g2;
tablica[i] = " ";
break;
}
}

}
} else {

/*if(wstaw_znaczek('5', znaczek_g2)) {
} else*/

if(rk_nr_ruchu == 1 && wstaw_znaczek('5', znaczek_g2)) { // jesli rk_nr_ruchu == 1 bedzie falszywe to juz nie wykonuje sie drugi czlon po && poniewaz wartosc koniunkcji bedzie i tak falszywa


// jesli srodek zajety przez komputer i sa wolne w kolo pola
//} else if(tablica_gry[5] == znaczek_g2 && (tablica_gry[1]==" " || tablica_gry[2]==" " || tablica_gry[3]==" " || tablica_gry[4]==" " || tablica_gry[6]==" " || tablica_gry[7]==" " || tablica_gry[8]==" " || tablica_gry[9]==" ")) { // jesli srodek zajety przez komp


// 19.11.2009 - proba zagrania strategia ktora sprawi ze przeciwnik nie bedzie mogl zablokowac ruchu komputera
} else if(rk_wstaw_znaczek_jesli_3wolne_2komputera(1,4,9, 5,7, 1)) {
} else if(rk_wstaw_znaczek_jesli_3wolne_2komputera(1,8,9, 5,7, 9)) {
} else if(rk_wstaw_znaczek_jesli_3wolne_2komputera(3,4,6, 5,9, 3)) {
} else if(rk_wstaw_znaczek_jesli_3wolne_2komputera(3,7,8, 5,9, 7)) {
} else if(rk_wstaw_znaczek_jesli_3wolne_2komputera(1,6,9, 5,3, 9)) {
} else if(rk_wstaw_znaczek_jesli_3wolne_2komputera(1,2,9, 5,3, 1)) {
} else if(rk_wstaw_znaczek_jesli_3wolne_2komputera(3,7,8, 5,1, 7)) {
} else if(rk_wstaw_znaczek_jesli_3wolne_2komputera(2,3,7, 5,1, 3)) {

// 17.11.2009
// skuteczna metoda na to aby komputer nie przegrywal
// nalezy doprowadzic do sytuacji w ktorej wymusimy na graczu koniecznosc blokady komputera,
// tymsamym nie bedzie on mogl grac wedlug swojej strategii lecz bedzie zajety blokowaniem komputera
// co w efekcie doprowadza do remisu, chyba ze gracz popelni blad to wtedy komputer to wykorzysta i wygra ;)
} else if(tablica_gry[5] == znaczek_g2 && rk_wstaw_znaczek(2," ",8)) {
} else if(tablica_gry[5] == znaczek_g2 && rk_wstaw_znaczek(8," ",2)) {
} else if(tablica_gry[5] == znaczek_g2 && rk_wstaw_znaczek(4," ",6)) {
} else if(tablica_gry[5] == znaczek_g2 && rk_wstaw_znaczek(6," ",4)) {
} else if(tablica_gry[5] == znaczek_g2 && rk_wstaw_znaczek(1," ",9)) {
} else if(tablica_gry[5] == znaczek_g2 && rk_wstaw_znaczek(9," ",1)) {
} else if(tablica_gry[5] == znaczek_g2 && rk_wstaw_znaczek(3," ",7)) {
} else if(tablica_gry[5] == znaczek_g2 && rk_wstaw_znaczek(7," ",3)) {

// blokowanie strategii x w 4,8 wstawiamy do 7
} else if(rk_wstaw_znaczek_jesli_dwa_pola_zajete(4,8,znaczek_g1,7)) {
} else if(rk_wstaw_znaczek_jesli_dwa_pola_zajete(6,8,znaczek_g1,9)) {
} else if(rk_wstaw_znaczek_jesli_dwa_pola_zajete(2,6,znaczek_g1,3)) {
} else if(rk_wstaw_znaczek_jesli_dwa_pola_zajete(4,2,znaczek_g1,1)) {

// 17.10.2009
} else if(rk_wstaw_znaczek(8,znaczek_g1,6)) {
} else if(rk_wstaw_znaczek(8,znaczek_g1,4)) {
} else if(rk_wstaw_znaczek(6,znaczek_g1,8)) {
} else if(rk_wstaw_znaczek(6,znaczek_g1,2)) {
} else if(rk_wstaw_znaczek(2,znaczek_g1,6)) {
} else if(rk_wstaw_znaczek(2,znaczek_g1,4)) {
} else if(rk_wstaw_znaczek(4,znaczek_g1,2)) {
} else if(rk_wstaw_znaczek(4,znaczek_g1,8)) {


} else if(rk_wstaw_znaczek(1,znaczek_g2,9)) { // jesli pole 1 zajmuje znak komputera to wstaw znak komputera do pola 9
} else if(rk_wstaw_znaczek(3,znaczek_g2,7)) {
} else if(rk_wstaw_znaczek(7,znaczek_g2,3)) {
} else if(rk_wstaw_znaczek(9,znaczek_g2,1)) {

//jesli srodkowe pole zajete przez komputer i ktorys z naroznikow jest wolny to wykonaj cialo
} else if(tablica_gry[5] == znaczek_g2 && (tablica_gry[1]==" " || tablica_gry[3]==" " || tablica_gry[7]==" " || tablica_gry[9]==" ")) {


srand(time(NULL));
int los = rand() %4;
int nr_p; // nr naroznika do ktorego wstawic znak komputera
switch(los) {
case 0:
nr_p = 1;
break;
case 1:
nr_p = 3;
break;
case 2:
nr_p = 7;
break;
default:
nr_p = 9;
}
if(rk_wstaw_znaczek(5,znaczek_g2,nr_p)) {
} else if(rk_wstaw_znaczek(5,znaczek_g2,1)) {
} else if(rk_wstaw_znaczek(5,znaczek_g2,3)) {
} else if(rk_wstaw_znaczek(5,znaczek_g2,7)) {
} else if(rk_wstaw_znaczek(5,znaczek_g2,9)) {
}

// tworzenie trojkata dla komputera [dziala to tak jak w opisie ponizej dla blokowania gracza X]
} else if(rk_spr_przeciwnika(5,7,9,znaczek_g2)) {
} else if(rk_spr_przeciwnika(1,3,5,znaczek_g2)) {
} else if(rk_spr_przeciwnika(1,5,7,znaczek_g2)) {
} else if(rk_spr_przeciwnika(3,5,9,znaczek_g2)) {

/* blokowanie strategi gracza X
[O _ _]
[_ X _]
[T _ X]
w miejsce T nalezy wstawic O, wstawiamy w tej kominacji jak i w podobnych znak komputera
*/
} else if(rk_spr_przeciwnika(5,7,9,znaczek_g1)) {
} else if(rk_spr_przeciwnika(1,3,5,znaczek_g1)) {
} else if(rk_spr_przeciwnika(1,5,7,znaczek_g1)) {
} else if(rk_spr_przeciwnika(3,5,9,znaczek_g1)) {


} else if(wstaw_znaczek('5', znaczek_g2)) { // jesli srodek pusty to wstaw znak

// nie zastosowano zadnej z powyzszych strategii wiec losowo wstawiamy znak komputera do wolnego pola
} else {

// wstawiamy znaczek do pierwszego wolnego pola
for(int f=1;f<=9;f++) {
if(tablica_gry[f] == " ") {
tablica_gry[f] = znaczek_g2;
tablica[f] = " ";
break;
}
}

}
}

}
}
}

rk_nr_ruchu++; // zwieksza licznik ruchow jakie wykonal komputer
}

/**********************************************************************************************/

// funkcja sprawdza czy w danych trzech polach sa dwa takie same znaki, jesli tak to w trzecim wolnym polu wstawia znak komputera
// oznacza to ze w przypadku dwoch znakow przeciwnika np. [x x] zostanie zablokowany jego ruch [xox],
// natomiast w przypadku dwoch znakow komputera [o o] zostanie wstawiony trzeci znak ktory spowoduje wygrana [ooo]
// parametr znaczek okresla czy sprawdzamy znaczki gracza 1 lub komputera
int rk_spr_przeciwnika(int p1, int p2, int p3, string znaczek) {
int zablokowano_ruch = 0; // zawiera informacje o zablokowaniu ruchu. Jesli znaleziono dwa X lub O obok siebie i wstawiono O to zmienna przyjmie wartosc 1 co oznacza ze zablokowano ruch przeciwnika lub wstawiono 3 znak komputera ktory powoduje wygranie gry. Wartosc 0 oznacza ze nie ma koniecznosci w danym wierszu lub kolumnie wstawiac znaku by blokowac przeciwnika

if(tablica_gry[p1]==tablica_gry[p2] && tablica_gry[p1]==znaczek && tablica_gry[p3] == " ") { //[xx ] jesli pierwsze i drugie pole jest zajete przez przeciwnika a trzecie pole jest wolne to wstawiamy znaczek_g2 (znak komputera) w wolne pole p3 aby zablokowac gracza1 lub uzupelnic 3 znak komputera aby wygral (zalezne od parametru znaczek)
tablica_gry[p3] = znaczek_g2;
tablica[p3] = " "; // wymazanie nr pola po wstawieniu do niego znaczka
zablokowano_ruch = 1;
} else if(tablica_gry[p1]==tablica_gry[p3] && tablica_gry[p1]==znaczek && tablica_gry[p2] == " ") { //[x x]
tablica_gry[p2] = znaczek_g2;
tablica[p2] = " ";
zablokowano_ruch = 1;
} else if(tablica_gry[p2]==tablica_gry[p3] && tablica_gry[p2]==znaczek && tablica_gry[p1] == " ") { //[ xx]
tablica_gry[p1] = znaczek_g2;
tablica[p1] = " ";
zablokowano_ruch = 1;
}

return zablokowano_ruch;
}

/**********************************************************************************************/

// znaczek przekazuje informacje dla jakich znakow sprawdzamy czy w danym np. wieresuz wystepuja dwa znaki obok siebie a trzecie pole jest puste
// funkcje wykorzystamy aby najpierw sprawdzic czy komputer moze wygrac, pozniej wywolamy funkcje z znaczkiem przeciwnika aby sprawdzic czy mozna go zablokowac
int rk_obrona(string znaczek) {
int rk_obrona_return=0; // zawiera informacje czy komputer sie obronil czy nie, jesli zwraca 0 to komputer nie musi sie bronic i moze przejsc do ataku, jesli wynosi 1 to komputer wykonal ruch obronny i wtedy nie atakujejemy gracza

if(rk_spr_przeciwnika(1,2,3,znaczek)) { // sprawdzamy czy w polach 1,2,3 moze przeciwnik wygrac, jesli tak to go blokujemy
rk_obrona_return=1; // wykonano ruch obronny
} else if(rk_spr_przeciwnika(4,5,6,znaczek)) {
rk_obrona_return=1;
} else if(rk_spr_przeciwnika(7,8,9,znaczek)) {
rk_obrona_return=1;
} else if(rk_spr_przeciwnika(1,4,7,znaczek)) {
rk_obrona_return=1;
} else if(rk_spr_przeciwnika(2,5,8,znaczek)) {
rk_obrona_return=1;
} else if(rk_spr_przeciwnika(3,6,9,znaczek)) {
rk_obrona_return=1;
} else if(rk_spr_przeciwnika(1,5,9,znaczek)) {
rk_obrona_return=1;
} else if(rk_spr_przeciwnika(3,5,7,znaczek)) {
rk_obrona_return=1;
}


return rk_obrona_return;
}

/**********************************************************************************************/

// funkcja wstawia do odpowiedniego pola znaczek g2, jesli pole do ktorego chcemy cos wstawic jest zajete to zwraca int 0
// jesli dane pole ma dany znaczek to wstaw znaczek komputera do pola o int do_pola
int rk_wstaw_znaczek(int nr_pola, string znaczek, int do_pola) {
int wstawiono=0;

if(tablica_gry[nr_pola] == znaczek && tablica_gry[do_pola] == " ") {
tablica_gry[do_pola] = znaczek_g2; // wstawia znaczek komputera do pola
tablica[do_pola] = " ";
wstawiono = 1;
}

return wstawiono;
}

/**********************************************************************************************/

// jesli dwa pola zajete przez przeciwnika to wstaw swoj znak
int rk_wstaw_znaczek_jesli_dwa_pola_zajete(int nr_pola1, int nr_pola2, string znaczek, int do_pola) {
int wstawiono=0;

if(tablica_gry[nr_pola1] == znaczek && tablica_gry[nr_pola2] == znaczek && tablica_gry[do_pola] == " ") {
tablica_gry[do_pola] = znaczek_g2; // wstawia znaczek komputera do pola
tablica[do_pola] = " ";
wstawiono = 1;
}

return wstawiono;
}

/**********************************************************************************************/

// 19.11.2009
int rk_wstaw_znaczek_jesli_3wolne_2komputera(int p1, int p2, int p3, int pk1, int pk2, int do_pola) {
int wstawiono=0;

// jesli trzy pierwsze argumenty czyli nr tych pol sa wolne to oraz dwa kolejne argumenty czyli nr pol zajetych przez komputer to wstaw do_pola znak komputera
if(tablica_gry[p1] == " " && tablica_gry[p2] == " " && tablica_gry[p3] == " " && tablica_gry[pk1] == znaczek_g2 && tablica_gry[pk2] == znaczek_g2) {
tablica_gry[do_pola] = znaczek_g2; // wstawia znaczek komputera do pola
tablica[do_pola] = " ";
wstawiono = 1;
}

return wstawiono;
}