
過去ログ 11
過去ログは下にいくほど新しい記事となっております。
※注意:このサイトにあるプログラムのソースコードや、その他の情報はすべて無保証です。やばいと思ったら実行しないでください。コンパイル、実行などによって生じた損害に対する責任は負いませんので、ご了承ください。
SDL_net 3
13-12-2009
2度あることは3度ある。
とりあえず、前回の数当てゲームを多人数プレイ可能にしてみた。これで、ネットプレイの意味が出てきた。
クライアントプログラムです。
#include <SDL/SDL.h>
#include <SDL/SDL_net.h>
#define REMOTE_HOST_IP "192.168.0.3"
#define REMOTE_HOST_PORT 5555
/* #define DEBUG */
#define SEND_FLAG_EMPTY 0
#define SEND_FLAG_SET 1
#define SEND_FLAG_SENT 2
#define SEND_FLAG_RECV 3
#define ZERO_MEMORY(x, y) memset(x, 0, y)
#define TIMEOUT 1000 /* タイムアウト */
/* 送信データセット */
typedef struct {
int flag; /* 送信状態のフラグ */
char send_data[1024]; /* 送信データ */
int len; /* 送信データの長さ */
unsigned int time; /* 時間カウント用 */
} t_send_data;
/* データタイプ */
typedef struct {
char type;
char value;
char value2;
char turnflag;
} t_data_type;
int copy_send_data(t_send_data*);
int set_send_data(char*, int);
int set_send_flag(int);
int set_send_time(unsigned int);
int check_timeout(int);
int g_s_thread_alive = 0; /* 送信スレッド生存フラグ */
int g_r_thread_alive = 0; /* 受信スレッド生存フラグ */
int g_comm_thread_alive = 0; /* 監視スレッド生存フラグ */
int g_finished_flag = 0; /* 終了フラグ(監視スレッド停止用) */
int g_input_thread_alive = 0; /* コンソール入力スレッド生存フラグ */
SDL_mutex *g_send_data_mutex;
t_send_data g_send_data;
/* 送信スレッド 引数はソケット */
int send_thread(void* pointer){
t_send_data data;
int result;
TCPsocket client_sock = (TCPsocket)pointer;
data.flag = SEND_FLAG_EMPTY;
while(1){
/* データがセットされるまで待機 */
while(data.flag != SEND_FLAG_SET){
SDL_Delay(20);
copy_send_data(&data);
}
/* printf("send!\n"); */
/* 送信処理 */
result = SDLNet_TCP_Send(client_sock, data.send_data, data.len);
if(result < data.len){
printf("送信に失敗しました。\n");
printf("プログラムを終了します。\n");
break;
}
data.flag = SEND_FLAG_SENT;
/* 送信したときの時間を記録 */
set_send_time(SDL_GetTicks());
/* 送信フラグを更新 */
set_send_flag(data.flag);
}
/* 生存フラグをOFFにしておく */
g_s_thread_alive = 0;
return 0;
}
/* 受信スレッド 引数はソケット */
int recv_thread(void* pointer){
char data[1024];
t_data_type data_type;
int result;
TCPsocket client_sock;
client_sock = (TCPsocket)pointer;
#ifdef DEBUG
printf("# receive thread start\n");
#endif
while(1){
/* 受信まで待機 */
result = SDLNet_TCP_Recv(client_sock, data, sizeof(data) - 1);
if(result <= 0){
printf("サーバーとの通信が切断されました。\n");
printf("プログラムを終了します。\n");
break;
}
data[result] = 0x00;
memcpy(&data_type, data, sizeof(data_type));
#ifdef DEBUG
printf("#R:t %d, v %d, v2 %d, f %d\n",
data_type.type,
data_type.value,
data_type.value2,
data_type.turnflag);
#endif
switch(data_type.type){
case 11: /* 開始依頼の応答/開始通知 */
printf("ゲーム開始です\n");
set_send_flag(SEND_FLAG_RECV);
if(data_type.turnflag == 1){
printf("あなたのターンです。\n");
set_send_flag(SEND_FLAG_EMPTY);
}
break;
case 12: /* 自分入力応答 */
set_send_flag(SEND_FLAG_RECV);
printf("あなたが入力した値に対し、サーバーはこう返しました。\n");
switch(data_type.value){
case 's':
printf("もっと小さい\n");
break;
case 'l':
printf("もっと大きい\n");
break;
case 'c':
printf("正解\n");
printf("あなたの勝ちです\n");
printf("ゲーム終了です\n");
set_send_flag(SEND_FLAG_EMPTY);
break;
default:
break;
}
break;
case 14: /* 他人入力 */
set_send_flag(SEND_FLAG_RECV);
printf("相手が入力した値%dに対し、サーバーはこう返しました。\n",data_type.value2);
switch(data_type.value){
case 's':
printf("もっと小さい\n");
break;
case 'l':
printf("もっと大きい\n");
break;
case 'c':
printf("正解\n");
printf("あなたの負けです\n");
printf("ゲーム終了です\n");
set_send_flag(SEND_FLAG_EMPTY);
break;
default:
break;
}
if(data_type.turnflag == 1){
set_send_flag(SEND_FLAG_EMPTY);
if(data_type.value != 'c'){
printf("あなたのターンです。\n");
}
}
break;
case 13: /* 終了通知 */
set_send_flag(SEND_FLAG_EMPTY);
printf("終了しました\n");
break;
case 15: /* 回線切断による終了 */
set_send_flag(SEND_FLAG_EMPTY);
printf("相手の回線切断により終了しました\n");
break;
break;
case 19: /* 拒否応答 */
set_send_flag(SEND_FLAG_RECV);
printf("コマンドは拒否されました\n");
if(data_type.turnflag == 1){
set_send_flag(SEND_FLAG_EMPTY);
}
break;
default:
break;
}
}
#ifdef DEBUG
printf("# receive thread end\n");
#endif
/* スレッド生存フラグをOFFにする */
g_r_thread_alive = 0;
return 0;
}
/* スレッド監視スレッド */
int comm_thread(void* pointer){
IPaddress client_ip;
TCPsocket client_sock;
SDL_Thread *s_thread;
SDL_Thread *r_thread;
g_comm_thread_alive = 1;
/* 通信の準備はこのスレッド内で行う */
SDLNet_ResolveHost(&client_ip, REMOTE_HOST_IP, REMOTE_HOST_PORT);
do {
/* ソケットオープン */
client_sock = SDLNet_TCP_Open(&client_ip);
if(client_sock != NULL){
printf("Open\n");
}
else {
printf("%s\n", SDLNet_GetError());
break;
}
/* ここに置くのはちょっと変かもしれないが・・・ */
g_s_thread_alive = 1;
g_r_thread_alive = 1;
/* 送受信スレッドの作成 */
s_thread = SDL_CreateThread(send_thread, client_sock);
r_thread = SDL_CreateThread(recv_thread, client_sock);
if(s_thread == NULL){
g_s_thread_alive = 0;
}
if(r_thread == NULL){
g_r_thread_alive = 0;
}
while(1){
/* スレッドが停止したら、もう片方のスレッドも停止させ、自身も終了に向かう */
if(g_r_thread_alive == 0){
#ifdef DEBUG
printf("r gone\n");
#endif
if(g_s_thread_alive == 1){
SDL_KillThread(s_thread);
}
break;
}
if(g_s_thread_alive == 0){
#ifdef DEBUG
printf("s gone\n");
#endif
if(g_r_thread_alive == 1){
SDL_KillThread(r_thread);
}
break;
}
/* タイムアウトチェック */
if(check_timeout(TIMEOUT) != 0){
/* タイムアウト とりあえず今回はスレッドを終了させる */
printf("timeout\n");
if(g_s_thread_alive == 1){
SDL_KillThread(s_thread);
}
if(g_r_thread_alive == 1){
SDL_KillThread(r_thread);
}
break;
}
/* メインスレッドからの停止依頼 */
if(g_finished_flag == 1){
#ifdef DEBUG
printf("quit\n");
#endif
if(g_s_thread_alive == 1){
SDL_KillThread(s_thread);
}
if(g_r_thread_alive == 1){
SDL_KillThread(r_thread);
}
break;
}
SDL_Delay(20);
}
/* ソケットクローズ */
SDLNet_TCP_Close(client_sock);
} while(0);
/* 生存フラグOFF */
g_comm_thread_alive = 0;
return 0;
}
/* 送信データにセットする処理 */
int set_send_data(char* data, int len){
int ret_value = 0;
SDL_mutexP(g_send_data_mutex);
do {
if(len < 1 || 1024 < len){
ret_value = -1;
break;
}
/* フラグチェック */
if(g_send_data.flag == SEND_FLAG_EMPTY){
/* SEND_FLAG_EMPTYであればセットする */
memcpy(g_send_data.send_data, data, len);
g_send_data.flag = SEND_FLAG_SET;
g_send_data.len = len;
}
else {
ret_value = g_send_data.flag;
break;
}
ret_value = 0;
} while(0);
SDL_mutexV(g_send_data_mutex);
return ret_value;
}
/* 送信フラグの初期化 */
int init_send_data(){
SDL_mutexP(g_send_data_mutex);
g_send_data.flag = SEND_FLAG_EMPTY;
SDL_mutexV(g_send_data_mutex);
return 0;
}
/* 送信データの取得 */
int copy_send_data(t_send_data* dst){
SDL_mutexP(g_send_data_mutex);
memcpy(dst, &g_send_data, sizeof(t_send_data));
SDL_mutexV(g_send_data_mutex);
return 0;
}
/* 送信フラグのセット */
int set_send_flag(int flag){
SDL_mutexP(g_send_data_mutex);
g_send_data.flag = flag;
SDL_mutexV(g_send_data_mutex);
return 0;
}
/* 送信時間のセット */
int set_send_time(unsigned int time){
SDL_mutexP(g_send_data_mutex);
g_send_data.time = time;
SDL_mutexV(g_send_data_mutex);
return 0;
}
/* タイムアウトチェック */
int check_timeout(int timeout){
unsigned int time;
unsigned int tick;
int diff;
int flag;
SDL_mutexP(g_send_data_mutex);
flag = g_send_data.flag;
if(flag == SEND_FLAG_SENT){
time = g_send_data.time;
}
tick = SDL_GetTicks();
SDL_mutexV(g_send_data_mutex);
/* フラグチェック */
if(flag != SEND_FLAG_SENT){
/* SEND_FLAG_SENT(送信済み)でなければ抜ける */
return 0;
}
/* タイムアウトの計算 */
diff = tick - time;
if(diff < 0){
diff = time - 0xFFFFFFFF + tick + 1;
}
if(diff >= timeout){
return -1;
}
return 0;
}
/* コンソール入出力スレッド */
int input_thread(void* pointer){
char buffer[10];
t_data_type data_type;
int ret_value;
int value;
while(1){
fgets(buffer, sizeof(buffer), stdin);
/* Eが入力されたら終了 */
if(buffer[0] == 'E'){
break;
}
value = atoi(buffer);
#ifdef DEBUG
printf("# value = %d\n",value);
#endif
if(value != 0){
if(value < 1){
printf("小さすぎます。\n");
}
else if(value > 100){
printf("大きすぎます。\n");
}
data_type.value = value;
data_type.type = 2;
}
else {
#ifdef DEBUG
printf("# send command :key = %c\n",buffer[0]);
#endif
switch(buffer[0]){
case 's': /* ゲームスタート依頼 */
data_type.type = 1;
data_type.value = 0;
break;
case 'c': /* ゲーム終了依頼 */
data_type.type = 3;
data_type.value = 0;
break;
default:
data_type.type = 0;
break;
}
}
if(data_type.type == 0){
continue;
}
/* 送信データにセット */
ret_value = set_send_data((char*)&data_type, sizeof(data_type));
if(ret_value != 0){
printf("今は入力できません(あなたの番ではありません)\n");
}
}
g_input_thread_alive = 0;
return 0;
}
/* メイン関数 */
int main(int argc, char* argv[]){
SDL_Thread *c_thread;
SDL_Thread *i_thread;
SDL_Init(SDL_INIT_EVERYTHING);
SDLNet_Init();
/* ミューテックスの作成 */
g_send_data_mutex = SDL_CreateMutex();
/* 送信フラグの初期化 */
init_send_data();
/* スレッド監視スレッドの作成 */
g_comm_thread_alive = 1;
c_thread = SDL_CreateThread(comm_thread, NULL);
/* コンソール入出力用スレッドの作成 */
g_input_thread_alive = 1;
i_thread = SDL_CreateThread(input_thread, NULL);
do {
if(c_thread == NULL){
break;
}
if(i_thread == NULL){
break;
}
while(1) {
if(g_comm_thread_alive == 0){
/* 監視スレッドが終了していたら終了 */
if(g_input_thread_alive == 1){
SDL_KillThread(i_thread);
}
break;
}
if(g_input_thread_alive == 0){
if(g_comm_thread_alive == 1){
g_finished_flag = 1;
SDL_WaitThread(c_thread, NULL);
}
}
SDL_Delay(20);
}
} while(0);
/* ミューテックス破棄 */
SDL_DestroyMutex(g_send_data_mutex);
printf("終了しました。\n");
SDLNet_Quit();
SDL_Quit();
return 0;
}
次にサーバープログラムです。
#include <SDL/SDL.h>
#include <SDL/SDL_net.h>
#include <time.h>
#define SERVER_HOST 5555
#define MAX_CONNECTION 2
#define ANSWER_NUMBER 54
#define SEND_FLAG_EMPTY 0
#define SEND_FLAG_SET 1
#define SEND_FLAG_SENT 2
#define SEND_FLAG_RECV 3
#define RECV_FLAG_DONE 0
#define RECV_FLAG_RECV 1
#define RECV_FLAG_READY 2
#define ZERO_MEMORY(x, y) memset(x, 0, y)
int g_answer = 1;
int g_turn = -1; /* どのコネクションの順番か */
typedef struct {
int flag;
char data[1024];
int len;
unsigned int time;
} t_rs_data;
typedef struct {
char type;
char value;
char value2;
char turnflag;
} t_data_type;
/* 通信統括スレッドで送受信スレッドを管理するための構造体 */
typedef struct {
int connection_no;
TCPsocket sock;
int send_thread_alive;
int recv_thread_alive;
int thread_fin;
} thread_arg;
/* メインスレッドで通信統括スレッドを管理するための構造体 */
typedef struct {
SDL_Thread *thread;
thread_arg arg;
} thread_set;
int set_send_data(void*, int, int);
int set_all_send_data(void*, int, int);
int g_fin_flag = 0;
t_rs_data g_recv_data[MAX_CONNECTION];
t_rs_data g_send_data[MAX_CONNECTION];
thread_set g_t_set[MAX_CONNECTION];
int send_thread(void* pointer){
TCPsocket accept_sock;
thread_arg *arg;
int result;
int con_no;
arg = (thread_arg*)pointer;
accept_sock = arg->sock;
con_no = arg->connection_no;
g_send_data[con_no].flag = SEND_FLAG_EMPTY;
while(1){
while(g_send_data[con_no].flag != SEND_FLAG_SET){
SDL_Delay(20);
}
result = SDLNet_TCP_Send(accept_sock, g_send_data[con_no].data, g_send_data[con_no].len);
if(result < g_send_data[con_no].len){
printf("send error\n");
break;
}
printf("#S to %d\n",con_no);
g_send_data[con_no].flag = SEND_FLAG_SENT;
}
arg->send_thread_alive = 0;
return 0;
}
int set_all_send_data(void* data, int len, int except){
int i;
for(i = 0; i < MAX_CONNECTION ; i++){
if(i != except){
set_send_data(data, len, i);
}
}
return 0;
}
int set_send_data(void* data, int len, int con_no){
if(g_t_set[con_no].arg.connection_no != -1){
memcpy(g_send_data[con_no].data, data, len);
g_send_data[con_no].flag = SEND_FLAG_SET;
g_send_data[con_no].len = len;
return 0;
}
return -1;
}
/* 拒否応答をセットする処理 */
int set_refuse_data(int con_no, int turnflag){
t_data_type data_type;
data_type.type = 19;
data_type.turnflag = turnflag;
return set_send_data(&data_type, sizeof(data_type), con_no);
}
int recv_thread(void* pointer){
TCPsocket accept_sock;
thread_arg *arg;
int con_no;
arg = (thread_arg*)pointer;
accept_sock = arg->sock;
con_no = arg->connection_no;
int result;
g_recv_data[con_no].flag = RECV_FLAG_DONE;
while(1){
while(g_recv_data[con_no].flag != RECV_FLAG_DONE){
SDL_Delay(20);
}
result = SDLNet_TCP_Recv(accept_sock, g_recv_data[con_no].data, sizeof(g_recv_data[con_no].data) - 1);
if(result <= 0){
printf("Host%d: DISCONNECT\n",arg->connection_no);
break;
}
printf("#R from %d\n", con_no);
g_recv_data[con_no].data[result] = 0x00;
g_recv_data[con_no].flag = RECV_FLAG_READY;
}
arg->recv_thread_alive = 0;
return 0;
}
/* アクションメイン */
int action_main(){
int i, j, k;
t_data_type r_data_type;
t_data_type s_data_type;
/* 受信データの確認 */
for(i = 0; i < MAX_CONNECTION; i++){
if(g_t_set[i].arg.connection_no != -1 &&
g_recv_data[i].flag == RECV_FLAG_READY){
if(i == g_turn || g_turn == -1){
/* 受信許可 */
ZERO_MEMORY(&s_data_type, sizeof(s_data_type));
memcpy(&r_data_type, g_recv_data[i].data, sizeof(r_data_type));
printf("#A %d : t %d v %d\n", i, r_data_type.type, r_data_type.value);
switch(r_data_type.type){
case 1: /* ゲーム開始依頼 */
if(g_turn != -1){
/* ゲーム開始前でなければ、拒否応答 */
set_refuse_data(i, 0);
}
else {
/* メンバーが揃っていなかったら拒否 */
k = 0;
for(j = 0; j < MAX_CONNECTION; j++){
if(g_t_set[j].arg.connection_no != -1){
k++;
}
}
if(k != MAX_CONNECTION){
set_refuse_data(i, 1);
break;
}
/* ゲーム開始前であれば、ゲームを開始する */
g_turn = rand() % MAX_CONNECTION;
g_answer = rand() % 100 + 1;
/* 開始通知の送信 */
s_data_type.type = 11;
s_data_type.turnflag = 1;
set_send_data(&s_data_type, sizeof(s_data_type), g_turn);
s_data_type.turnflag = 0;
set_all_send_data(&s_data_type, sizeof(s_data_type), g_turn);
}
break;
case 2: /* 値入力 */
if(g_turn == -1){
set_refuse_data(i, 1);
}
else {
if(r_data_type.value < g_answer){
s_data_type.value = 'l';
}
else if(r_data_type.value > g_answer){
s_data_type.value = 's';
}
else {
s_data_type.value = 'c';
g_turn = -1;
}
s_data_type.value2 = r_data_type.value;
s_data_type.type = 12;
set_send_data(&s_data_type, sizeof(s_data_type), i);
s_data_type.type = 14;
if(g_turn != -1){
g_turn++;
if(g_turn >= MAX_CONNECTION){
g_turn = 0;
}
}
for(j = 0; j < MAX_CONNECTION; j++){
if(j != i){
if(g_turn != j && g_turn != -1){
s_data_type.turnflag = 0;
}
else {
s_data_type.turnflag = 1;
}
set_send_data(&s_data_type, sizeof(s_data_type), j);
}
}
}
break;
case 3: /* 終了依頼 */
if(g_turn == -1){
set_refuse_data(i, 1);
break;
}
s_data_type.type = 13;
/* 全員に終了通知 */
set_all_send_data(&s_data_type, sizeof(s_data_type), -1);
g_turn = -1;
break;
default:
break;
}
}
else {
/* 受信拒否 */
set_refuse_data(i, 0);
}
g_recv_data[i].flag = RECV_FLAG_DONE;
}
}
return 0;
}
/* ゲーム強制終了 */
int send_game_terminate(){
int i;
t_data_type data_type;
data_type.type = 15;
for(i = 0; i < MAX_CONNECTION; i++){
if(g_t_set[i].arg.connection_no != -1){
set_send_data(&data_type, sizeof(data_type), i);
}
}
return 0;
}
int thread_func(void* pointer){
thread_arg *arg;
TCPsocket accept_sock;
SDL_Thread *s_thread;
SDL_Thread *r_thread;
arg = (thread_arg*)pointer;
accept_sock = arg->sock;
arg->send_thread_alive = 1;
arg->recv_thread_alive = 1;
s_thread = SDL_CreateThread(send_thread, pointer);
r_thread = SDL_CreateThread(recv_thread, pointer);
while(1){
if(arg->send_thread_alive == 0){
printf("## Con %d : send thread has gone. start closing \n", arg->connection_no);
if(arg->recv_thread_alive != 0){
SDL_KillThread(r_thread);
arg->recv_thread_alive = 0;
break;
}
}
if(arg->recv_thread_alive == 0){
printf("## Con %d : receive thread has gone. start closing \n", arg->connection_no);
if(arg->send_thread_alive != 0){
SDL_KillThread(s_thread);
arg->send_thread_alive = 0;
break;
}
}
if(arg->thread_fin == 1){
printf("## Con %d : closing\n", arg->connection_no);
if(arg->recv_thread_alive != 0){
SDL_KillThread(r_thread);
arg->recv_thread_alive = 0;
break;
}
if(arg->send_thread_alive != 0){
SDL_KillThread(s_thread);
arg->send_thread_alive = 0;
break;
}
break;
}
SDL_Delay(20);
}
SDLNet_TCP_Close(accept_sock);
printf("## Con %d : closed\n", arg->connection_no);
arg->connection_no = -1;
if(g_turn != -1){
g_turn = -1;
/* ゲーム強制終了を全ユーザーに送信する */
send_game_terminate();
}
return 0;
}
int net_main(void* pointer){
IPaddress server_ip;
TCPsocket server_sock;
int i;
for(i = 0; i < MAX_CONNECTION; i++){
g_t_set[i].arg.connection_no = -1;
}
SDLNet_ResolveHost(&server_ip, NULL, SERVER_HOST);
server_sock = SDLNet_TCP_Open(&server_ip);
do {
if(server_sock != NULL){
printf("OPEN\n");
}
else {
printf("%s\n", SDLNet_GetError());
break;
}
while(1){
for(i = 0; i < MAX_CONNECTION; i++){
if(g_t_set[i].arg.connection_no == -1 && g_turn == -1){
g_t_set[i].arg.sock = SDLNet_TCP_Accept(server_sock);
if(g_t_set[i].arg.sock != NULL){
printf("# ACCEPT Host %d\n", i);
g_t_set[i].arg.connection_no = i;
g_t_set[i].arg.thread_fin = 0;
g_t_set[i].thread = SDL_CreateThread(thread_func, &g_t_set[i].arg);
}
/*
else {
SDL_Delay(100);
i--;
}
*/
}
}
/* 受信後処理(もしあれば) */
action_main();
if(g_fin_flag == 1){
printf("# start quitting\n");
break;
}
SDL_Delay(100);
}
for(i = 0; i < MAX_CONNECTION; i++){
if(g_t_set[i].arg.connection_no != -1){
printf("# connection no %d : start closing\n", i);
g_t_set[i].arg.thread_fin = 1;
SDL_WaitThread(g_t_set[i].thread, NULL);
printf("# connection no %d : closed\n", i);
}
else {
printf("# connection no %d : no connection\n", i);
}
}
SDLNet_TCP_Close(server_sock);
} while(0);
return 0;
}
int main(int argc, char* argv[]){
char command[100];
SDL_Thread *thread;
int exitflag = 0;
srand(time(NULL));
SDL_Init(SDL_INIT_EVERYTHING);
SDLNet_Init();
thread = SDL_CreateThread(net_main, NULL);
g_fin_flag = 0;
while(exitflag == 0){
fgets(command, sizeof(command), stdin);
switch(command[0]){
case 'E':
g_fin_flag = 1;
SDL_WaitThread(thread, NULL);
exitflag = 1;
break;
}
}
SDLNet_Quit();
SDL_Quit();
return 0;
}
- 遊び方:
- クライアントキーコマンド
- s : ゲームスタート。ゲームが既に始まっている/人数が揃っていないと拒否されます。
- 数字 : 自分の考えた数字をサーバーに送信します。ゲームが始まっていない/自分の番でないと拒否されます。
- c : 終了します。ゲームが始まっていない/自分の番でないと拒否されます。
- E : プログラムを終了します。ゲーム中であれば、ゲームを終了します。
- サーバーキーコマンド
- E : プログラムを終了します。ゲーム中であれば、ゲームを終了します。
- クライアントキーコマンド
以下、内部情報
- 通信コマンド(1バイト目:type、2バイト目:value、3バイト目:value2、4バイト目:turnflag)
- 1 : ゲーム開始依頼
- 2 : 数字入力(value : 入力数字)
- 3 : ゲーム終了依頼
- 11 : ゲーム開始通知(turnflag : 入力許可(1: 許可、0: 不許可))
- 12 : 自分の入力結果(value : 結果(l,s,c))
- 13 : 相手の入力結果(value : 結果(l,s,c) , value2 : 相手の入力した数字 , turnflag : 入力許可(1: 許可、0: 不許可))
- 15 : 相手の回線切断によるゲーム終了
- 19 : 拒否応答(turnflag : 入力許可(1: 許可、0: 不許可))
ただの数当てゲームだけど結構複雑になってしまった。コマンド判定やターン制御とか結構いい加減になってしまいました。たかが数当てゲームなので許してちょうだい。
2~3回ぐらいしか遊んでいないので、バグは必ずあると思います。見つけたら勝手に直しちゃってください。
※メール、リンクは適当に。
Copyright (c) 2009 greencap

