トップ 差分 一覧 ソース 検索 ヘルプ PDF RSS ログイン

Tag

 鬼ごっこゲーム

非同期通信の実験

  作業環境

  • Cygwinのホームディレクトリ以下に
ホーム/soc/

あるいは

ホーム/soc/tag/

のようなディレクトリを作成し、そこで作業を行う。

  ソース

tag.h

/*********************************************/
/*       File name:  tag.h                   */
/*    Project name:  socket/tag              */
/*      Month/Year:  Jan/2003                */
/*          Author:  Shuichi YUKITA          */
/*********************************************/

#include  <sys/types.h>
#include "mylib.h"
#define PORT  50001
#define HOSTNAME_LENGTH 64

session.h

/*********************************************/
/*       File name:  session.h               */
/*    Project name:  socket/tag              */
/*      Month/Year:  Jan/2003                */
/*          Author:  Shuichi YUKITA          */
/*********************************************/

extern void session_init(int soc, 
			 char mc, int mx, int my,
			 char pc, int px, int py);
extern void session_loop();

session.c

/*********************************************/
/*       File name:  session.c               */
/*    Project name:  socket/tag              */
/*      Month/Year:  Jan/2003                */
/*          Author:  Shuichi YUKITA          */
/*********************************************/

#include <sys/types.h>
#include <curses.h>
#include <signal.h>

#define BUF_LEN 20
#define MIN_X	1
#define MIN_Y	1
#define MAX_X	60
#define MAX_Y	20

#define NORTH 'k'
#define SOUTH 'j'
#define EAST  'l'
#define WEST  'h'
#define QUIT  'q'

static	int	session_soc;     /* socket  */
static	fd_set	mask;            /* fd mask */
static	int	width;           /* width of the mask */
static	char	my_char, peer_char; /* character */

typedef	struct{
  int	x,y; /* current position */
  char	look;  /* character */
} PLAYER;

static	PLAYER	me, peer;    /* 自分と相手の状態を保持する変数  */

static	char	buf[BUF_LEN];  /* 送受信兼用バッファ */

static	WINDOW	*win;	     /* 表示用ウィンドウ */

/*  session モジュールにプライベートな関数  */
static void hide(PLAYER *who);
static void show(PLAYER *who);
static int update(PLAYER *who, int c);
static int interpret(PLAYER *who);
static void die();

/*  session モジュールの初期化  */
void session_init(int soc, 
		  char mc, int mx, int my,
		  char pc, int px, int py)
{
  session_soc = soc;
  width = soc + 1;
  FD_ZERO(&mask);
  FD_SET(0, &mask);
  FD_SET(session_soc, &mask);
  me.look = mc;
  peer.look = pc;

  me.x = mx;  me.y = my;
  peer.x = px;  peer.y = py;

  /* curses initialization */
  initscr();
  signal(SIGINT, die);

  /* window border */
  win = newwin(MAX_Y + 2, MAX_X + 2, 0, 0);
  box(win, '|', '-');

  /* terminal settings */
  cbreak();
  noecho();
}


/*  session メインループ  */
void session_loop()
{
  int	c,flag;
  fd_set readOk;
	
  show(&me);

  flag = 1;
  while(1){
    /*  select の前に毎回 readOk を初期化する。 */
    readOk = mask;
    select(width,(fd_set *)&readOk,NULL,NULL,NULL);

    /*  キーボードからの入力ありか? */
    if ( FD_ISSET(0, &readOk ) ){
      c = getchar();
      hide(&me);
      flag = update(&me, c);
      show(&me);
      write(session_soc,buf,BUF_LEN);
      if(flag == 0) break;
    }


    /*  ソケットにデータありか? */
    if ( FD_ISSET(session_soc, &readOk ) ){
      read(session_soc,buf,BUF_LEN);
      hide(&peer);
      flag = interpret(&peer);
      show(&peer);
      if(flag == 0) break;
    }

  }
  /* 端末属性を復旧して終わる */
  die();
}


static void show(PLAYER *who)
{
  wmove(win, who->y, who->x);
  waddch(win, who->look);
  wmove(win, who->y, who->x);
  wrefresh(win);
}
		
		
static void hide(PLAYER *who)
{
  wmove(win, who->y, who->x);
  waddch(win, ' ');
}
	

static int update(PLAYER *who, int c)
{
  switch(c){
  case WEST:
    if ( who->x > MIN_X )
      who->x--;
    break;
  case SOUTH:
    if ( who->y < MAX_Y )
      who->y++;
    break;
  case NORTH:
    if ( who->y > MIN_X )
      who->y--;
    break;
  case EAST:
    if ( who->x < MAX_X )
      who->x++;
    break;
  case QUIT:
    buf[0]=QUIT;
    return 0;
  default:
    break;
  }

  /* 更新された位置データを送信用文字列に変換する。 */ 
  sprintf(buf, "%d %d\n", who->x, who->y);
  return 1;
}


static int interpret(PLAYER *who)
{
  /* もし相手が終了を希望したら */
  if (buf[0] == 'q')
    return 0;

	/* 受信文字列から位置データに変換する。 */
  sscanf(buf, "%d %d", &who->x, &who->y);
  return 1;
}

static void die()
{
  endwin();  /* 端末属性の復旧 */
  exit();
}

server.c

/*********************************************/
/*       File name:  server.c                */
/*    Project name:  socket/tag              */
/*      Month/Year:  Jan/2003                */
/*          Author:  Shuichi YUKITA          */
/*********************************************/

#include "session.h" 
#include "tag.h"

main()
{
	int	soc;    /*  socket  */

	if( (soc = setup_server(PORT) ) == -1){
	  exit(1);
	}

	session_init(soc, 'o', 1,1, 'x',10, 10);
	session_loop();
}

client.c

/*********************************************/
/*       File name:  client.c                */
/*    Project name:  socket/tag              */
/*      Month/Year:  Jan/2003                */
/*          Author:  Shuichi YUKITA          */
/*********************************************/

#include "session.h" 
#include "tag.h"

main()
{
  int	soc;    /*  socket  */
  char	hostname[HOSTNAME_LENGTH];

  printf("input  server's  hostname: ");
  fgets(hostname, HOSTNAME_LENGTH, stdin);
  chop_newline(hostname, HOSTNAME_LENGTH);

  if( (soc = setup_client(hostname,PORT) ) == -1){
    exit(1);
  }

  session_init(soc, 'x', 10,10, 'o',1, 1);
  session_loop();
}

  ビルド Makefile

#*********************************************/
#*       File name:  Makefile                */
#*    Project name:  socket/tag              */
#*      Month/Year:  Jan/2003                */
#*          Author:  Shuichi YUKITA          */
#*********************************************/
#
#  "root.o" target is implicitly built by
#  $(COMPILE.c) -o root.o root.c

MYLIBDIR=../mylib
CFLAGS=-I$(MYLIBDIR)
RM=rm -f

all:	s  c

s:	server.o  session.o
	$(LINK.c) -o s server.o session.o $(MYLIBDIR)/mylib.a -lcurses

c:	client.o  session.o
	$(LINK.c) -o c client.o session.o $(MYLIBDIR)/mylib.a -lcurses 

server.o:	server.c tag.h session.h

client.o:	client.c tag.h session.h

clean:
	$(RM)  s  c  *.o *~

  実行

初めの一歩 と同じ。