Внешняя спецификация и алгоритм
Приветствие. Вывод игрового поля и легенды.
Ход первого игрока.
Проверка правильности хода и условий победы. Начисление очка.
false(нет победы)
Ход второго игрока.
Проверка правильности хода и условий победы. Начисление очка.
true(есть победа)
Вывод сообщения о выигрыше %username% и вывод %rates%.
Структура программы
Главная функция main
main
ma
Upd_disp
Win_mesg
Disp_init
Check_res
«upd_disp» - вывод текущего состояния поля
«disp_init» - инициализация графического поля, вывод приветствия, игрового поля и легенды
«check_res» - проверка условия выигрыша
«win_mesg» - сообщение о выигрыше, работа с рейтингом.
«main» - главная функция, основной цикл игры.
Код программы
#include<cstdio>
#include<cstdlib>
#include<conio.h>
#include<graphics.h>
#include<iostream.h>
#include<fstream>
using namespace std;
char disp[101][101]; //картинка
void upd_disp(int x,int y){
int poly[8];
char t[2]={0};
int ax,ay;
register int i,j; // так похоже хоть чут-чуть но быстрее =)
for(i=(x-12);i<(x+13);i++){
if(i>=-1 && i<=100){
for(j=(y-12);j<(y+13);j++){
if((i==x)&&(j==y)){ // для этого случая координаты всегда однии и те же
poly[0]=216;
poly[1]=245; //Подробнее о координатах.
poly[2]=234; // пример:
poly[3]=245; // 17*(y-j+12)+(y-j+12)
poly[4]=234; // 30+17*(x-i+12)+(x-i+12)-1
poly[5]=263; // (y-j+12) и (x-i+12) - номер ячейки на экране, а заодно
poly[6]=216; // поправка на пикселы, занимаемые линиями
poly[7]=263; // 17 - сторона ячейки в пикселах
if(disp[i][j]==' '){ // 30 - поправка на текст, находящийся над таблицей
setfillstyle(1,10); // +1 и -1 поправка, необходимая для того, что б заливка
fillpoly(4,poly); // сработала точно
}else{ // +18 - иногда нужна ещё поправка, зачем не помню,
t[0]=disp[i][j]; // но в этих местах в оригинале было (y-j+13) или (x-i+13)
// поправка появилась в результате введения ax и ay
setfillstyle(1,12); // ниже есть ещё одна поправка "+6" , необходимая для
fillpoly(4,poly); // вывода символа ровно по середине ячейки.
setbkcolor(12);
outtextxy(222,246,t);
setbkcolor(0);
}
}else{
ax=18*(x-i+12); // кажется, один раз посчитать будет быстрее =)
ay=18*(y-j+12);
if((j==-1)||(j==100)||(i==-1)||(i==100)){
poly[0]=ay;
poly[1]=29+ax;
poly[2]=ay+18;
poly[3]=29+ax;
poly[4]=ay+18;
poly[5]=47+ax;
poly[6]=ay;
poly[7]=47+ax;
setfillstyle(1,14);
fillpoly(4,poly);
}else if(j>-1 && j<100) {
t[0]=disp[i][j];
poly[0]=ay;
poly[1]=29+ax;
poly[2]=ay+18;
poly[3]=29+ax;
poly[4]=ay+18;
poly[5]=47+ax;
poly[6]=ay;
poly[7]=47+ax;
setfillstyle(1,0);
fillpoly(4,poly);
if (t[0]!=' '){
outtextxy(ay+6,30+ax,t);
}
}
}
}
}
}
}
void disp_init(void){
int poly[8];
int i;
for(i=0; i<100;i++){
for(int j=0;j<100;j++){
disp[i][j]=' ';
}
}
int gdriver = DETECT, gmode, errorcode;
initgraph(&gdriver, &gmode, "c:\\turboc30\\bgi");
errorcode = graphresult();
if (errorcode != grOk){
printf("Не удалась графика : %s\n", grapherrormsg(errorcode));
system("PAUSE");
exit(1);
}
outtextxy(0,-2,"Крестики-нолики 100x100\n");
for(i=0;i<26;i++){ // рисуем поле
line(0,i*18+29,450,i*18+29);
}
for(i=0;i<26;i++){
line(i*18,29,i*18,479);
}
outtextxy(455,28,"W - вверх"); // выводим легенду =)
outtextxy(455,48,"S - вниз");
outtextxy(455,68,"A - влево");
outtextxy(455,88,"D - вправо");
outtextxy(455,108,"Q - выход");
outtextxy(455,128,"пробел - поставить знак");
outtextxy(455,148,"x - крестик");
outtextxy(455,168,"0 - нолик");
setcolor(0);
poly[0]=455;
poly[1]=188;
poly[2]=472;
poly[3]=188;
poly[4]=472;
poly[5]=205;
poly[6]=455;
poly[7]=205;
setfillstyle(1,12);
fillpoly(4,poly);
setcolor(15);
outtextxy(473,188," - текущая клетка,");
outtextxy(473,208," в которую нельзя");
outtextxy(473,228," поставить знак");
setcolor(0);
poly[0]=455;
poly[1]=248;
poly[2]=472;
poly[3]=248;
poly[4]=472;
poly[5]=265;
poly[6]=455;
poly[7]=265;
setfillstyle(1,10);
fillpoly(4,poly);
setcolor(15);
outtextxy(473,248," - текущая клетка,");
outtextxy(473,268," в которую можно");
outtextxy(473,288," поставить знак");
setcolor(0);
poly[0]=455;
poly[1]=308;
poly[2]=472;
poly[3]=308;
poly[4]=472;
poly[5]=325;
poly[6]=455;
poly[7]=325;
setfillstyle(1,14);
fillpoly(4,poly);
setcolor(15);
outtextxy(473,308," - клетка, в ");
outtextxy(473,328," которую нельзя");
outtextxy(473,348," поставить знак");
outtextxy(473,368," (границы поля)");
outtextxy(0,13,"Ход крестиков");
upd_disp(50,50);
}
bool check_res(int x, int y){ // проверка условия выигрыша
char sym=disp[x][y]; // смотрим во все стороны и считаем
int i,j; // пять по одной прямой есть - выиграли =)
i=1;
j=1;
while(disp[x+i][y]==sym && j<5){
j++;
i++;
}
i=-1;
while(disp[x+i][y]==sym && j<5){
j++;
i--;
}
if (j==5){
return true;
}
i=1;
j=1;
while(disp[x][y+i]==sym && j<5){
j++;
i++;
}
i=-1;
while(disp[x][y+i]==sym && j<5){
j++;
i--;
}
if(j==5){
return true;
}
i=1;
j=1;
while(disp[x+i][y+i]==sym && j<5){
j++;
i++;
}
i=-1;
while(disp[x+i][y+i]==sym && j<5){
j++;
i--;
}
if(j==5){
return true;
}
i=1;
j=1;
while(disp[x+i][y-i]==sym && j<5){
j++;
i++;
}
i=-1;
while(disp[x+i][y-i]==sym && j<5){
j++;
i--;
}
if (j==5){
return true;
}
return false;
}
void win_mesg(bool flag, int hod){ // инфа и выигрыше
fstream hs("hs.dat",ios_base::in);
int poly[8];
int x,y,i;
char c[2];
char name[22]={0};
char hsname[5][22]={0};
int hsscr[5]={0};
setcolor(0); // очищаем экран
poly[0]=0;
poly[1]=0;
poly[2]=0;
poly[3]=479;
poly[4]=639;
poly[5]=479;
poly[6]=639;
poly[7]=0;
setfillstyle(1,0);
fillpoly(4,poly);
setcolor(15);
poly[0]=145; // красивости
poly[1]=171;
poly[2]=145;
poly[3]=255;
poly[4]=449;
poly[5]=255;
poly[6]=449;
poly[7]=171;
setfillstyle(1,0);
fillpoly(4,poly);
if(flag){
outtextxy(185,175," Крестики Выиграли.");
hod=1+(hod/2);
}else{
outtextxy(195,175," Нолики Выиграли.");
hod=hod/2;
}
outtextxy(150,195,"Введите имя");
x=150;
y=215;
c[0]=getch();
c[1]='\0';
i=0;
while(c[0]!=13){
if(c[0]!=8){
if(x<360){
outtextxy(x,y,c);
x+=10;
name[i]=c[0];
i++;
}
}else if(x>150){
name[i]='\0';
i--;
x-=10;
outtextxy(x,y," ");
}
c[0]=getch();
}
i=0;
while(!hs.eof()){
hs>>hsname[i];
if(hs.eof()){
break;
}
hs>>hsscr[i];
i++;
}
for(x=0;x<=i;x++)
if(hsscr[x]>hod)
break;
cout<<name<<endl;
cout<<i<<endl;
if(x<=i || i<5){
for(y=i-1;y>x-1;y--){
strcpy(hsname[y],hsname[y-1]);
hsscr[y]=hsscr[y-1];
}
cout<<name<<endl;
if(i<5)
i++;
strcpy(hsname[x],name);
hsscr[x]=hod;
hs.close();
fstream hs("hs.dat",ios_base::out | ios_base::trunc);
for(x=0;x<i;x++){
hs<<hsname[x]<<endl<<hsscr[x]<<endl;
}
hs.close();
}
setcolor(0); // очищаем экран
poly[0]=0;
poly[1]=0;
poly[2]=0;
poly[3]=479;
poly[4]=639;
poly[5]=479;
poly[6]=639;
poly[7]=0;
setfillstyle(1,0);
fillpoly(4,poly);
setcolor(15);
poly[0]=145; // красивости
poly[1]=171;
poly[2]=145;
poly[3]=314;
poly[4]=449;
poly[5]=314;
poly[6]=449;
poly[7]=171;
setfillstyle(1,0);
fillpoly(4,poly);
if(flag){
outtextxy(245,175,"Крестики Выиграли.");
hod=1+(hod/2);
}else{
outtextxy(195,175,"Нолики Выиграли.");
hod=hod/2;
}
outtextxy(150,195,"Лучший счёт");
y=215;
for(x=0;x<i && x<5;x++){
outtextxy(150,y+x*20,hsname[x]);
sprintf(name,"%d",hsscr[x]);
outtextxy(370,y+x*20,name);
}
return;
}
int main(void){
int x=50;
int y=50;
disp_init();
int ch='\0';
bool flag=false;
int hod=0;
ch=getch();
while((ch!='q')&&(ch!='Q')){
if (((ch=='W')||(ch=='w'))&&(x!=99)){ // с WASD'ом что-то странное
x++; // инверсия, блин =)
upd_disp(x,y);
}
if (((ch=='S')||(ch=='s'))&&(x!=0)){
x--;
upd_disp(x,y);
}
if (((ch=='a')||(ch=='A'))&&(y!=99)){
y++;
upd_disp(x,y);
}
if (((ch=='d')||(ch=='D'))&&(y!=0)){
y--;
upd_disp(x,y);
}
if (ch==' '){
hod++;
if(flag && disp[x][y]==' '){ // флаг расскажет кто сейчас - крестики или нолики =)
disp[x][y]='0';
flag=!flag;
}else if(!flag && disp[x][y]==' '){
disp[x][y]='x';
flag=!flag;
}
upd_disp(x,y);
if(check_res(x,y)){
win_mesg(flag,hod);
ch='q';
}else{
ch=getch();
if (flag){
outtextxy(0,13,"Ход ноликов "); // пробелы для того, что б затереть
}else{ // остатки надписи про крестики.
outtextxy(0,13,"Ход крестиков"); // два пробела примерно один знак.
}
}
}else{
ch=getch();
}
}
// outtextxy(149,235," Что бы выйти нажмите любую клавишу");
getch();
closegraph();
return 0;
}