#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
/*Stała - odpowiada za maksymalną liczbę elementów w tablicy*/
#define MAXSTAN 3
/*DEKLARACJE FUNKCJI*/
int walidacjazmiennych(int a, int b);
void czyszczenietablicy(short int tab[MAXSTAN][MAXSTAN]);
void wyswietlplansze(short int tab[MAXSTAN][MAXSTAN]);
short int rozleglewyrazenie(short int a, short int b, short int tab[MAXSTAN][MAXSTAN]);
bool czymozesz_zapis(short int klawisz, short int wybor, short int tab[MAXSTAN][MAXSTAN]);
void wyswietlnapis(char i[]);
short int sprawdzczywygral(short int tab[MAXSTAN][MAXSTAN]);
short int sprawdzczyremis(short int tab[MAXSTAN][MAXSTAN]);
short int rekurencja(char znak[9],short int ktogra, short int glebokosc);
bool zakonczeniegry(short int tab[MAXSTAN][MAXSTAN]);
/*KONIEC DEKLARACJI FUNKJCI*/
void usunac(short int tab[MAXSTAN][MAXSTAN], short int wyborgracza)
{
int i,j;
printf("\n"); printf("%d",wyborgracza); printf("\n");
printf("\n"); for(i=0; i<3; i++){for(j=0; j<3; j++) printf("%d",tab[i][j]); printf("\n");} printf("\n");
}
int main(void)
{
/*stan- przechowuje informacje o znakach na planszy, wyborgracza- czym gra uzytkownik? 1 - kolko 2 - krzyzyk, klawisz- co uzytkownik wcisnal?*/
/*kogoruch- kto gra? 1- komp, 0- gracz*/
/*
NIEZIMPLEMENTOWANY KOGORUCH
*/
short int stan[MAXSTAN][MAXSTAN]; short int wyborgracza; short int klawisz; bool kogoruch;
wyswietlnapis("***\n");
do
{
/*czyszczenie tablicy na wartosci poczatkowe*/
czyszczenietablicy(stan);
wyswietlnapis("Gra w kolko i krzyzyk\nCzym grasz?\n1 - Kolko \n2 - Krzyzyk\nMoj wybor to: ");
wyborgracza=walidacjazmiennych(49,50); /*wyborgracza - definiuje czym będzie grał użytkownik 1- kolko, 2 - krzyzyk*/
wyswietlnapis("\033[2J\033[0;0f");
do
{
usunac(stan,wyborgracza);
wyswietlplansze(stan); /*wyświetla aktualny stan planszy*/
if(zakonczeniegry(stan)) break;
wyswietlnapis("0 -Wyjscie, 1..9 - Klawisze do postawienia znaku. Wybrales: ");
do /*Do-WHILE pętla sprawdza czy dany znak może być zapisany w tablicy, jesli tak, zapisuje, jesli nie użytkownik ponownie wpisuje znak*/
{
klawisz=walidacjazmiennych(48,57);
if(klawisz==48) break; /*jeśli 0, pętla jest przerywana i następuje wyjście z programu*/
}while(czymozesz_zapis(klawisz,wyborgracza,stan));
if((klawisz==48)||(zakonczeniegry(stan))) break;
czymozesz_zapis(minmax(stan,(wyborgracza==1)?2:1),wyborgracza,stan);
if(zakonczeniegry(stan)) break;
}while(1);
wyswietlnapis("Skonczona gra.\nCzy chcesz grac dalej?\nJesli tak nacisnij klawisz 0.\nJesli nie klawisz 1.\nInne klawisze - bledny klawisz, ponowne wczytanie\n");
}while((walidacjazmiennych(48,49)==48)?1:0);
return 0;
}
void wyswietlnapis(char i[]) { printf("%s",i);}
bool czymozesz_zapis(short int klawisz, short int wybor, short int tab[MAXSTAN][MAXSTAN])
{
/*Komentarz kodującego Wolalem, miec na sumieniu uzycie, tylu intrukcji goto niż, 18 wyjść z jednej fukcji. Swiadomie pominelem, koncowy break przy uzyciu intrukcji case, ponieważ przynajmniej tak mi się wydaje, tok wykonywanych instrukcji przechwytuje go to*/
switch(klawisz)
{
case 55: if(tab[0][0]==0) { tab[0][0]=(wybor==49)?1:2; goto prawda; } else goto falsz;
case 56: if(tab[0][1]==0) { tab[0][1]=(wybor==49)?1:2; goto prawda; } else goto falsz;
case 57: if(tab[0][2]==0) { tab[0][2]=(wybor==49)?1:2; goto prawda; } else goto falsz;
case 52: if(tab[1][0]==0) { tab[1][0]=(wybor==49)?1:2; goto prawda; } else goto falsz;
case 53: if(tab[1][1]==0) { tab[1][1]=(wybor==49)?1:2; goto prawda; } else goto falsz;
case 54: if(tab[1][2]==0) { tab[1][2]=(wybor==49)?1:2; goto prawda; } else goto falsz;
case 49: if(tab[2][0]==0) { tab[2][0]=(wybor==49)?1:2; goto prawda; } else goto falsz;
case 50: if(tab[2][1]==0) { tab[2][1]=(wybor==49)?1:2; goto prawda; } else goto falsz;
case 51: if(tab[2][2]==0) { tab[2][2]=(wybor==49)?1:2; goto prawda; } else goto falsz;
default: goto falsz;
}
falsz: return 1; prawda: return 0;
}
short int rozleglewyrazenie(short int a, short int b,short int tab[MAXSTAN][MAXSTAN])
{
const char spacja=' '; const char kolko='O'; const char krzyzyk='X';
return (tab[a][b]==0)?spacja:(tab[a][b]==1?kolko:krzyzyk);
}
void wyswietlplansze(short int tab[MAXSTAN][MAXSTAN])
{
const char j[8]="-----\n"; int i;
for(i=0; i<MAXSTAN; i++)
{
printf("\n%c|%c|%c\n",rozleglewyrazenie(i,0,tab),rozleglewyrazenie(i,1,tab),rozleglewyrazenie(i,2,tab));
if(i!=2) printf("%s",j);
}
}
void czyszczenietablicy(short int tab[MAXSTAN][MAXSTAN])
{
short int i,j;
for (i=0; i<MAXSTAN; i++) for(j=0; j<MAXSTAN; j++) tab[i][j]=0;
}
int walidacjazmiennych(int a, int b)
{
int i,c;
do
{
i=getchar();
}while(((i>=a)&&(i<=b))?0:1);
while ((c=getchar()) !='\n'&& c!=EOF); /*CZYSZCZENIE BUFFORA KLAWIATURY*/
return i;
}
short int sprawdzczywygral(short int tab[MAXSTAN][MAXSTAN])
/*sprawdza czy 1- kolko wygralo, jesli tak zwraca wartosc ujemna, jesli wygralo 2- krzyzyk, zwraca wartosc dodatnia*/
{
int i,j;
for(i=0; i<(MAXSTAN); i++)
for(j=1; j<(MAXSTAN); j++)
{
if((tab[i][0]==j)&&(tab[i][1]==j)&&(tab[i][2]==j)) goto wygrana; /*Sprawdzenie po wierszach i kolumnach, czy ktos wygral*/
if((tab[0][i]==j)&&(tab[1][i]==j)&&(tab[2][i]==j)) goto wygrana;
}
if((tab[0][0]==j)&&(tab[1][1]==j)&&(tab[2][2]==j)) goto wygrana; /*Sprawdzenie po przekatnych, czy ktos wygral*/
if((tab[2][0]==j)&&(tab[1][1]==j)&&(tab[0][2]==j)) goto wygrana;
return 0; /*Jesli nikt nie wygral zwroc 0*/
wygrana: return (j==1)?-1:1;
}
short int sprawdzczyremis(short int tab[MAXSTAN][MAXSTAN])
{
short int i=0; short int j=0;
while(j<(MAXSTAN+1)) /*jeśli licznik, wyszedł poza największą liczbę kolumn+1 pętla ma się przerwać ponieważ, została już sprawdzona cała tablica*/
{
if(tab[i][j]==0) return 1; /*pętla sprawdza, po wierszach, czy jest 0 w tablicy*/
++i;
if(i==MAXSTAN) {i=0; ++j;} /*jeśli licznik wyszedł poza największą liczbę wierszy+1, licznik ma się wyzerować i dodać do liczby kolumn*/
}
return 0; /*funkcja zwróci 0, wyłącznie wtedy kiedy w tablicy już nie ma wartości zero. Czyli miejsca gdzie można postawić figurę lub liczbę*/
}
short int rekurencja(char znak[9],short int ktogra, short int glebokosc)
{
short int i,j,k,l,suma,licznik,stan[MAXSTAN][MAXSTAN],wygral; char znak1[9]; int wyniki[MAXSTAN*MAXSTAN];
j=licznik=suma=0;
for(i=(MAXSTAN-1); i>-1; i--)
for(j=0; j<MAXSTAN; j++)
{
znak[licznik]=='0'?stan[i][j]=0:(znak[licznik]=='1'?stan[i][j]=1:(stan[i][j]=2));
++licznik; /*potrzebny żeby można było dekodowac chara od 1-9*/
}
wygral=sprawdzczywygral(stan); if(wygral!=0) return wygral;
if(sprawdzczyremis(stan)!=1) return 0;
j=32000; k=-32000; l=-1;
for(i=0; i<(MAXSTAN*MAXSTAN); i++)
{
if(znak[i]=='0')
{
strcpy(znak1,znak); /*kopiowanie lancucha charowego*/
ktogra==1?znak1[i]='1':(znak1[i]='2'); /*tworzenie nowej mozliwosci z wielu, np 000 000 000 > 100 000 000*/
wyniki[i]=rekurencja(znak1,(ktogra==1?2:1)*-1,glebokosc+1); /*rekurencyjne odwolania do samej siebie, zeby poznac wyniki*/
if(ktogra!=2) { if(wyniki[i]>=k) { k=wyniki[i]; l=i;}}
else if(wyniki[i]<=j) { j=wyniki[i]; l=i;}
}
else wyniki[i]=0;
}
for(i=0; i<(MAXSTAN*MAXSTAN); i++) suma+=wyniki[i];
if(glebokosc!=0) return suma*-1; else return(l+48); /*tablica jest numerowana od 0*/
}
short int minmax(short int tab[MAXSTAN][MAXSTAN], short int ktogra)
{
short int i,j; char znak[9]; short int licznik=0;
for(i=(MAXSTAN-1); i>-1; i--)
for(j=0; j<MAXSTAN; j++) /*for przechodzi przez tablice, licznik zapisuje to jak rzada rekurencja*/
{
tab[i][j]==0?znak[licznik]='0':(tab[i][j]==1?znak[licznik]='1':(znak[licznik]='2'));
++licznik;
}
znak[9]='\0';
return rekurencja(znak,ktogra,0);
}
bool zakonczeniegry(short int tab[MAXSTAN][MAXSTAN])
{
if(sprawdzczywygral(tab)!=0) {wyswietlplansze(tab); wyswietlnapis("\nWykryto wygrane, przerwanie gry...\n"); goto label;} /*WYGRANA*/
if(sprawdzczyremis(tab)!=1) {wyswietlplansze(tab); wyswietlnapis("\nWykryto remis, przerwanie gry...\n"); goto label;} /*REMIS*/
return 0;
label: return 1;
}
Dlatego wydaje się zamieszczanie całego kodu jest zbędne.