#include // vastavalt opsüsteemile defineerime kas WIN või UNIX #define UNIX // konstandid const true = -1; const false = 0; const TableSize = 8; // andmetüübid enum TBoxes {bWhite, bBlack, bFree, bFull, bAction}; enum ErrorNr {enNone, enGeneral, enIllegalMove, enReverseStep, enMustTake, enTooLong}; struct TButtonPosition{ int Ch; int Nr; }; // globaalsed muutujad int Table[8][8]; int Score[2]; /* Puhastab ekraani, kasutades selleks süsteemset käsku - mistõttu vajalikud ka vastavad direktiivid */ void ClearScreen(void){ #ifdef UNIX system("clear"); #else system("cls"); #endif return; } /* Joonistab kabelaua ekraanile */ int DrawTable() { int i, j; // ülemised veerutähised printf(" A B C D E F G H \n"); for(i=0; i<\033[0m"); #else printf("><"); #endif break; case bAction: printf("++"); break; } } // parempoolne reanumber printf(" %d ", TableSize-i); printf("\n"); } // alumised veerutähised printf(" A B C D E F G H \n"); return true; } /* Algväärtustab kabelaua. Märgib kus asuvad mustad ja kus valged ruudud. Samuti kus asuvad mustad ja kus valged nupud. */ int InitTable(){ int i,j; // Sisestame ruudustiku for(i=0; i0) && (j%2>0)) { Table[i][j] = bFull; } else { Table[i][j] = bFree; } } } } // Sisestame mustad nupud for(i=0; i<3; i++){ for(j=0; j ja tähemärgile vastava positsiooni ja tagastab selle. NB! Ei kontrolli, kas punkt asub üldse kabelaual */ struct TButtonPosition GetPosition(int InputInt, char InputChar){ struct TButtonPosition OutputPos; OutputPos.Nr = TableSize - InputInt; if((int)InputChar >= 97) { OutputPos.Ch = (int)InputChar - 97; // väiketähtede puhul } else { OutputPos.Ch = (int)InputChar - 65; // suurtähtede puhul } return OutputPos; } /* Reverse GetPosition (ainult suurtähed) */ int RGetPosition(struct TButtonPosition Pos, int *OutputInt, char *OutputChar){ *OutputInt = TableSize - Pos.Nr; *OutputChar = 65 + Pos.Ch; return true; } /* Kui positsioon Pos asub kabelaual, siis tagastab true, vastasel juhul false */ int IsOnTheTable(struct TButtonPosition Pos){ if ( (Pos.Nr>=0 && Pos.Nr=0 && Pos.Ch väärtuseks kabelaual on bFree siis tagastab true, vastasel juhul false */ int IsFree(struct TButtonPosition Pos){ if (Table[Pos.Nr][Pos.Ch] == bFree){ return true; } else { return false; } } /* Kui positsiooni väärtuseks kabelaual on siis tagastab true, vastasel juhul false */ int IsWithButton(struct TButtonPosition Pos, int Color){ if (Table[Pos.Nr][Pos.Ch] == Color){ return true; } else { return false; } } /* Arvutab ja väljastab sooritatud käigu pikkuse. Kui käik pole sooritatud diagonaalsuunas, siis tagastab false */ int StepLength(struct TButtonPosition Pos1, struct TButtonPosition Pos2){ struct TButtonPosition move; // arvutame käigu pikkuse Nr suunal ning Ch suunal move.Nr = abs(Pos1.Nr-Pos2.Nr); move.Ch = abs(Pos1.Ch-Pos2.Ch); // kui käigu pikkus mõlemas suunas on sama // siis tagastame pikkuse. if(move.Ch==move.Nr){ return move.Ch; } else { return false; } } /* Väljastab hetke mänguskoori kujul "Seis: XX - YY n.n. juhib" */ void PrintScore(){ printf("Seis: %d - %d ", Score[bWhite], Score[bBlack]); if(Score[bWhite] > Score[bBlack]){ printf("Valge juhib.\n"); } else { if(Score[bWhite] < Score[bBlack]){ printf("Must juhib.\n"); } else { printf("Viik.\n"); } } return; } /* Trükib ekraanile käigu */ void PrintMove(struct TButtonPosition Pos1, struct TButtonPosition Pos2){ int Int1, Int2; char Char1, Char2; RGetPosition(Pos1, &Int1, &Char1); RGetPosition(Pos2, &Int2, &Char2); #ifdef UNIX printf("\033[32m%c%d -> %c%d \n\033[0m", Char1, Int1, Char2, Int2); #else printf("%c%d -> %c%d \n", Char1, Int1, Char2, Int2); #endif return; } /* Kui Positsioonilt saab sooritada võtmisega käigu, siis tagastatakse true ning läbi -i tagastatakse positsioon, kuhukohta nupp peale võtmist maandub. Kui võtta ei saa, tagastatakse false. Kui = true siis prindib välja, millistest kohtadest saab võtta. */ int CanTake(struct TButtonPosition Pos, struct TButtonPosition *TargetPos, int Print){ int i,j, ii,jj; int Found=false; // tsükkel Pos.Nr-1 -> Pos.Nr+1 for(i=Pos.Nr-1;i Pos.Ch+1 for(j=Pos.Ch-1;j=0 && j=0){ // kui punktis (i;j) on vastupidist värvi nupp if( Table[Pos.Nr][Pos.Ch] == OppositeColor(Table[i][j]) ){ // arvutame punkti (ii;jj) asukoha // Aluspunkt -> VastaseVärvigaPunkt -> SihtPunkt (ii;jj) ii = (i-Pos.Nr)*2 + Pos.Nr; jj = (j-Pos.Ch)*2 + Pos.Ch; // kui punkt (ii;jj) asub kabelaual if(ii=0 && jj=0){ // kui see punkt on vaba if(Table[ii][jj] == bFree){ TargetPos->Nr = ii; TargetPos->Ch = jj; // kui printimine on määratud, siis trükime ekraanile if(Print){ PrintMove(Pos, *TargetPos); Found = true; } else { return true; } } } } } } } return Found; } /* Käib läbi kogu kabelaua ja otsib, kas vastavat värvi nupuga saab sooritada võtmise käiku. Kui saab siis tagastab true. Kui = true, siis trükib välja millised võtmisekäigud on võimalikud */ int ScanCanTake(int Color, int Print){ struct TButtonPosition Pos, TargetPos; int Can=false; // käime läbi kogu kabelaua for(Pos.Nr=0;Pos.Nr< k2ik.\n"); } return; } /* loeb kasutajalt mängukäsu. "q"-ga algava käsu korral false, muidu true */ int GetInput(struct TButtonPosition *Pos1, struct TButtonPosition *Pos2){ int Int1, Int2; char Char1, Char2; char Tyhik, Enter; printf("Sisesta k2ik (XX-YY): "); scanf("%c%d%c%c%d%c", &Char1, &Int1, &Tyhik, &Char2, &Int2, &Enter); // Kui sisestati Q, siis tagastame false if (Char1 == 'q' || Char1 == 'Q'){ return false; } // Andmete töötlemine *Pos1 = GetPosition(Int1, Char1); *Pos2 = GetPosition(Int2, Char2); return true; } /* Kui käiku on võimalik sooritada siis true, vastasel juhul false */ int IsValidMove(struct TButtonPosition Pos1, struct TButtonPosition Pos2, int ActiveColor){ if(IsOnTheTable(Pos1) && IsOnTheTable(Pos2)){ if(IsWithButton(Pos1, ActiveColor) && IsFree(Pos2)){ return true; } } return false; } /* Trükib ekraanile veakoodile vastava teate */ void TranslateError(int Error){ #ifdef UNIX printf("\033[31m"); #endif switch(Error){ case enGeneral: printf("Yldine viga\n"); break; case enIllegalMove: printf("Seda k2iku ei saa sooritada!\n"); break; case enReverseStep: printf("Tagurpidi ei saa k2jja!\n"); break; case enMustTake: printf("Sa pead v6tma!\n"); break; case enTooLong: printf("Liiga pikk k2ik!\n"); break; } #ifdef UNIX printf("\033[0m"); #endif } /* Kontrollib, kas üks mängijatest on juba mõngu võitnud. Kui on, siis tagastab true, vastasel juhul false */ int SomeOneWon(int ScoreWhite, int ScoreBlack){ char Enter; if(ScoreWhite==12 || ScoreBlack==12){ if(ScoreWhite==12){ printf("Valge v6itis!!!\n"); } else { if(ScoreBlack==12){ printf("Must v6itis!!!\n"); } } printf("L6petamiseks vajuta ENTER"); scanf("%c", &Enter); return true; } return false; } /* Kontrollib, kas käik Pos1 -> Pos2 on lubatud ja kui on, siis sooritab selle käigu. Kui käik pole lubatud, siis tagastab vastava veateate. */ int TestMove(struct TButtonPosition Pos1, struct TButtonPosition Pos2, int *ActiveColor, int Can){ int AttackSquare; if(IsValidMove(Pos1, Pos2, *ActiveColor)){ switch(StepLength(Pos1, Pos2)) { case 0: // Ebasobiv käik return enIllegalMove; break; case 1: // Harilik käik // kui ei saa võtta if(!Can){ // kui käiakse ettepoole if(*ActiveColor==bWhite && Pos2.Nr-Pos1.Nr<0 || *ActiveColor==bBlack && Pos2.Nr-Pos1.Nr>0){ Table[Pos1.Nr][Pos1.Ch] = bFree; Table[Pos2.Nr][Pos2.Ch] = *ActiveColor; *ActiveColor = OppositeColor(*ActiveColor); } else { return enReverseStep; } } else { return enMustTake; } break; case 2: // Harilik Võtmine // Leiame ruudu, kus asub võetav nupp AttackSquare = Table[Pos1.Nr + (int)((Pos2.Nr - Pos1.Nr)/2)][Pos1.Ch + (int)((Pos2.Ch - Pos1.Ch)/2)]; // kui sellel ruudul asub vastase nupp if(AttackSquare==OppositeColor(*ActiveColor)) { // kustutame nupu algpositsioonilt Table[Pos1.Nr][Pos1.Ch] = bFree; // kustutame vastase nupu Table[Pos1.Nr + (int)((Pos2.Nr - Pos1.Nr)/2)][Pos1.Ch + (int)((Pos2.Ch - Pos1.Ch)/2)] = bFree; // paneme nupu uuele positsioonile Table[Pos2.Nr][Pos2.Ch] = *ActiveColor; // suurendame skoori Score[*ActiveColor]++; // kui rohkem võtta ei saa, siis anname mängujärje vastasele if(!CanTake(Pos2, &Pos1, false)){ *ActiveColor = OppositeColor(*ActiveColor); } } else { return enIllegalMove; } break; default: // Siia peaks tulema tammide asi... return enTooLong; } } else { return enIllegalMove; } return enNone; } void Intro(void){ char Enter; ClearScreen(); #ifdef UNIX printf("\033[32m"); #endif printf(" <==< KB >==>\n"); printf("\n"); printf("Suurep2rane kabem2ng nii noortele kui vanadele.\n"); printf("\n"); printf("K2igud sisestatakse kujul: 'XX-YY'\n"); printf("\n"); printf(" 'XX' ja 'YY' on ruudu tähised kujul \n"); printf(" nagu n2iteks 'A1', 'D4' või 'H7'\n"); printf(" '-' t2histab suvalist t2hem2rki\n"); printf("\n"); printf("M2ngu l6petamiseks sisestage k2igu asemel 'quit!' \n"); printf("\n"); printf("Nyyd aga vajutage ENTER, et alustada m2ngu.\n"); scanf("%c", &Enter); #ifdef UNIX printf("\033[0m"); #endif return; } int main(int argc, char *argv[]) { struct TButtonPosition Pos1, Pos2; // Tehtud käigu kaks positsiooni Pos1->Pos2 int ActiveColor = bWhite; // Aktiivne nupuvärv int Can; // Märgib seda, kas võtmine on võimalik int Error = enNone; // Veakood // lähtestamine Score[0] = 0; Score[1] = 0; InitTable(); // Sissejuhatav tekst Intro(); while(true){ // joonistame ekraanile igasugu infot ClearScreen(); DrawTable(); if(Error){ // Trükime kasutaja sisestatud käigu uuesti ekraanile PrintMove(Pos1, Pos2); TranslateError(Error); } PrintScore(); PrintNextMove(ActiveColor); // kontrollime, kas saab võtta // väljastame vastavad võimalused ekraanile Can = ScanCanTake(ActiveColor, true); // kontrollime, kas keegi on juba võitnud if(SomeOneWon(Score[0],Score[1])){ break; } // Sisend kasutajalt if(!GetInput(&Pos1,&Pos2)){ printf("L6pp...\n"); break; } // Proovime käiku sooritada Error = TestMove(Pos1,Pos2,&ActiveColor,Can); } return 0; }