- •Задание на курсовую работу.
- •Правила игры.
- •Описание протокола.
- •Общая схема работы клиента.
- •Общая схема работы сервера.
- •Разбор опций командной строки.
- •Описание реализации протокола на сервере.
- •Описание реализации протокола на клиенте.
- •Описание пользовательского интерфейса клиента.
- •Исходный код board.H
- •Исходный код board.C
- •Исходный код client.C
- •Исходный код server.C
Описание реализации протокола на клиенте.
При соединении с сервером клиенту отправляется список клиентов ожидающих второго игрока. Далее по выбору клиента либо создается новая игра, либо происходит присоединение к уже созданной. После чего в цикле с неблокируемым вводом, происходит обмен запросов по протоколу. Взаимодействие с пользовательским интерфейсом происходит через “переменную состояния”, безопасность взаимодействия обеспечивается за счет мьютексов.
Внутри цикла происходит обработка всех сообщений и ошибок, согласно протоколу.
Описание пользовательского интерфейса клиента.
Управление отрисовкой интерфейса и терминалом происходит при помощи функций библиотек myTerm и myBigChars.
В частности myTerm используется для установки режима терминалов, для управления курсором, установки цвета, рисование рамок, вывод символов в определенной позиции на экране и т.д. MyBigChars содержит функции для вывода на экран т. н. «bigchar'ов» т.е. изображений размером 8х8 символов, записанных в файле. В данном случае — изображения крестика и нолика.
Управление интерфейсом организуется в потоке main, состоит из цикла, производящего чтение. Но в данном случае — чтение со стандартного потока ввода, т.е. с клавиатуры.
В зависимости от нажатой клавиши и текущего состояния выполняются те или иные действия по отрисовке интерфейса.
Исходный код board.H
#include "myBigChars.h"
#include "myTerm.h"
#include <fcntl.h>
#define max_row 32
#define max_col 50
#define BG White
#define FG Black
#define FGV Red
#define FBG Blue
#define MAXLINE 128
#define MAX_CH_IP 25
struct menu_type
{
int id;
char ip[MAX_CH_IP];
};
typedef enum { EMPTY, CROSS, ZERO } tPosSign;
typedef tPosSign board[3][3];
bigchar zero,cross,nul;
extern int initic();
extern int printBoard (board,int,int);
extern void setBoardPos(board, int, int, tPosSign);
extern void getBoardPos (board, int, int, tPosSign *);
extern int editBoard (board *, int *, int *);
extern int menu (struct menu_type *, int, int, int, int);
extern int victory(board,tPosSign *,int *,int *);
extern void win_printBoard (tPosSign,int,int);
Исходный код board.C
#include "board.h"
#include "error.h"
int initic()
{
int f,n;
nul.a=nul.b=0;
error_1_return(f=open("zero", O_RDONLY),"Ошибка при открытие файла zero",-1);
error_1_return(bigcharread(f, &zero, 1, &n),"Ошибка при считывание символа zero",-1);
close(f);
error_1_return(f=open("cross", O_RDONLY),"Ошибка при открытие файла cross",-1);
error_1_return(bigcharread(f, &cross, 1, &n),"Ошибка при считывание символа cross",-1);
close(f);
return 0;
}
int printBoard (board cletka,int x,int y)
{
int i,j;
bigchar bc;
getscreensize(&i,&j);
if (i<max_row || j<max_col)
{
printf("Ошибка: недостаточный размер экрана\n");
return -1;
}
setfgcolor(FG);
setbgcolor(BG);
box(1,1,30,30);
for (i=0;i<3;i++)
for (j=0;j<3;j++)
{
if (x==j&&y==i)
{
setfgcolor(FGV);
setbgcolor(BG);
}
else
{
setfgcolor(FG);
setbgcolor(BG);
}
box(2+j*10,2+i*10,8,8);
switch (cletka[i][j])
{
case ZERO:
bc=zero;
break;
case CROSS:
bc=cross;
break;
case EMPTY:
bc=nul;
break;
}
printbigchar(&bc,3+j*10,3+i*10,FG,BG);
}
return 0;
}
void setBoardPos(board cletka, int x, int y, tPosSign sign)
{
cletka[y][x] = sign;
bigchar bc;
switch (sign)
{
case ZERO:
bc=zero;
break;
case CROSS:
bc=cross;
break;
case EMPTY:
bc=nul;
break;
}
}
void getBoardPos(board cletka, int x, int y, tPosSign *sign)
{
*sign = cletka[y][x];
}
void edit_str(char str[], int x, int y,int wid)
{
int i;
gotoXY(x,y);
mywrite("%s",str);
for (i=strlen(str);i<wid;i++)
mywrite(" ");
}
int menu (struct menu_type *lst, int x, int y, int str,int wid)
{
int ed=0,i;
keys key;
clrscr();
setfgcolor(FGV);
setbgcolor(BG);
box(x,y,wid,str);
setfgcolor(FGV);
setbgcolor(FBG);
edit_str(lst[0].ip,x+1,y+1,wid);
setfgcolor(FG);
setbgcolor(BG);
for (i=1;i<str;i++)
edit_str(lst[i].ip,x+1,y+1+i,wid);
while (key!=K_ENTER && key!=K_ESC)
{
readkey(&key);
switch (key)
{
case K_DOWN:
setfgcolor(FG);
setbgcolor(BG);
edit_str(lst[ed].ip,x+1,y+1+ed,wid);
if (ed==str-1)
ed=0;
else
ed++;
setfgcolor(FGV);
setbgcolor(FBG);
edit_str(lst[ed].ip,x+1,y+1+ed,wid);
break;
case K_UP:
setfgcolor(FG);
setbgcolor(BG);
edit_str(lst[ed].ip,x+1,y+1+ed,wid);
if (ed==0)
ed=str-1;
else
ed--;
setfgcolor(FGV);
setbgcolor(FBG);
edit_str(lst[ed].ip,x+1,y+1+ed,wid);
break;
default:
break;
}
}
setfgcolor(FG);
setbgcolor(BG);
if (key==K_ESC)
return -1;
else
return ed;
}
int victory(board cletka,tPosSign *sign,int *napr,int *nom)
{
int i,j,k;
for (i=0;i<3;i++)
{
k=0;
for (j=1;j<3;j++)
if (cletka[i][j]==cletka[i][j-1]) k++;
if (k==2&&cletka[i][0]!=EMPTY)
{
*sign=cletka[i][0];
*napr=0;
*nom=i;
return 1;
}
}
for (j=0;j<3;j++)
{
k=0;
for (i=1;i<3;i++)
if (cletka[i][j]==cletka[i-1][j]) k++;
if (k==2&&cletka[0][j]!=EMPTY)
{
*sign=cletka[0][j];
*napr=1;
*nom=j;
return 1;
}
}
k=0;
for (i=1;i<3;i++)
if (cletka[i][i]==cletka[i-1][i-1]) k++;
if (k==2&&cletka[0][0]!=EMPTY)
{
*sign=cletka[0][0];
*napr=2;
*nom=0;
return 1;
}
k=0;
for (i=1;i<3;i++)
if (cletka[i][2-i]==cletka[i-1][3-i]) k++;
if (k==2&&cletka[0][2]!=EMPTY)
{
*sign=cletka[0][2];
*napr=2;
*nom=1;
return 1;
}
return 0;
}
void win_printBoard (tPosSign sign,int napr,int nom)
{
int i;
setfgcolor(FGV);
setbgcolor(BG);
switch (napr)
{
case 0:
for (i=0;i<3;i++)
box(2+i*10,2+nom*10,8,8);
break;
case 1:
for (i=0;i<3;i++)
box(2+nom*10,2+i*10,8,8);
break;
case 2:
if (nom)
{
box(2+2*10,2+0*10,8,8);
box(2+1*10,2+1*10,8,8);
box(2+0*10,2+2*10,8,8);
}
else
{
box(2+0*10,2+0*10,8,8);
box(2+1*10,2+1*10,8,8);
box(2+2*10,2+2*10,8,8);
}
break;
}
gotoXY(40,2);
if (sign==CROSS)
printf("CROSS WIN");
else
printf("ZERO WIN");
}