質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.99%

サーバとクライアントの三目並べ

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,443

Asahi_1115

score 11

サーバとクライアント間で接続を行って、三目並べ(勝敗判定なし)を実行するプログラムを作ってます。接続まではできたのですが、二次元配列の使い方がわからず、下記のような実行結果までたどり着けません。どのように書き足せばよいのでしょうか。

<サーバ側>
クライアントからの接続待ち
123
1---
2---
3---
クライアントへデータを送信してください
行ナンバー:1
列ナンバー:1 

123
1s--
2---
3---
クライアントからのデータ待ち
[1]クライアントからのデータ(行) = 2
[1]クライアントからのデータ(列) = 2 

<クライアント側> 

123
1---
2---
3--- 

サーバからの受信待ち
[1]サーバからのデータ(行) = 1
[1]サーバからのデータ(列) = 2 

123
1s--
2---
3---
サーバへデータを送信してください
行ナンバー:2
列ナンバー:2 

123
1s--
2-c-
3--- 

※石を置くたびshow_plane()関数を実行して盤の内容を表示する

  • サーバ側
include <stdio.h>
include <winsock2.h>
define BUF_LEN 2//入出力バッファサイズ

void show_plane(void);
 char plane[4][5] = {" 123","1---","2---","3---"};
int main()
 {
 WSADATA wsaData;
 SOCKET sock0;
 struct sockaddr_in addr;
 struct sockaddr_in client;
 int len;
 SOCKET sock; 

//char buf[BUF_LEN];//入出力バッファ
int buf[BUF_LEN];//入出力バッファ 

// winsock2の初期化
WSAStartup(MAKEWORD(2, 0), &wsaData); 

// ソケットの作成
sock0 = socket(AF_INET, SOCK_STREAM, 0); 

// ソケットの設定(アドレス構造体の設定)
addr.sin_family = AF_INET;//インターネットを使用する
addr.sin_port = htons(12345);//サーバ(自分自身)のポート番号
addr.sin_addr.S_un.S_addr = INADDR_ANY;//IPアドレスすべての値指定 

//ソケットのディスクリプタとアドレス構造体を結びつける
bind(sock0, (struct sockaddr *)&addr, sizeof(addr)); 

// TCPクライアントからの接続要求を待てる状態にする(待ちクライアント数指定)
listen(sock0,1); 

// TCPクライアントからの接続要求を受け付ける
printf("クライアントからの接続待ち\n");
 len = sizeof(client);
 sock = accept(sock0, (struct sockaddr *)&client, &len); 

//送受信処理
int cnt = 1;
 char inputdata[4];
 do{
 printf("クライアントへデータを送信してください\n");
 memset(buf, 0, sizeof(buf));//送受信バッファ0クリア 

//キーボードから行列を入力
printf("行ナンバー:");
gets(inputdata);
 buf[0] = atoi(inputdata);
 printf("列ナンバー:");
gets(inputdata);
 buf[1] = atoi(inputdata);
 send(sock, (char*)buf, sizeof(buf), 0);//送信 データint型配列だが通信はchar型で
//(数値型はサイズがシステムで異なるので) 

printf("クライアントからのデータ待ち\n");
 memset(buf, 0, sizeof(buf));
 recv(sock, (char*)buf, sizeof(buf), 0);//受信 データint型配列だが通信はchar型で
printf("[%d]クライアントからのデータ(行)= %d\n", cnt, buf[0]);
 printf("[%d]クライアントからのデータ(列)= %d\n", cnt, buf[1]); 

cnt++;
 } while (buf[0]!= 99);//クライアントから行99受信したら終了 

// TCPセッションの終了
closesocket(sock); 

// winsock2の終了処理
WSACleanup();
 return 0;
 }
 void show_plane(void){
 printf("\n");
 for(int i = 0; j < 4; i++){ 

printf("%c",plane[i][j]);
 }
 printf("\n"); 

} 
  • クライアント側
define _WINSOCK_DEPRECATED_NO_WARNINGS
include <stdio.h>
include <winsock2.h>
define BUF_LEN 2//入出力バッファサイズ

void show_plane(void);
 char plane[4][5] = {" 123","1---","2---","3---"};
int main()
 {
 WSADATA wsaData;
 struct sockaddr_in server;
 SOCKET sock;
 //char buf[BUF_LEN];//入出力バッファ
int buf[BUF_LEN];//入出力バッファ 

// winsock2の初期化
WSAStartup(MAKEWORD(2, 0), &wsaData); 

// ソケットの作成
sock = socket(AF_INET, SOCK_STREAM, 0); 

// 接続先指定用アドレス構造体の準備
server.sin_family = AF_INET;//インターネット使用
server.sin_port = htons(12345);//接続先ポート番号
server.sin_addr.S_un.S_addr = inet_addr("*.*.*.*");//接続先IPアドレス 

// サーバに接続
connect(sock, (struct sockaddr *)&server, sizeof(server)); 

//受信送信処理
int cnt=1;
 char inputdata[4];
 do{
 memset(buf, 0, sizeof(buf));//送受信バッファ0クリア
printf("サーバからのデータ受信待ち\n");
 recv(sock, (char*)buf, sizeof(buf), 0);//受信 データint型配列だが通信はchar型で
printf("[%d]サーバからのデータ(行)= %d\n", cnt,buf[0]);
 printf("[%d]サーバからのデータ(列)= %d\n", cnt, buf[1]); 

printf("サーバへデータを送信してください\n");
 memset(buf, 0, sizeof(buf));//送受信バッファ0クリア 

//キーボードから行列を入力
printf("行ナンバー:");
gets(inputdata);
 buf[0] = atoi(inputdata);
 printf("列ナンバー:");
gets(inputdata);
 buf[1] = atoi(inputdata);
 send(sock, (char*)buf, sizeof(buf), 0);;//送信 データint型配列だが通信はchar型で
cnt++;
 } while (buf[0] != 99);//行99送信した場合、終了
// TCPセッションの終了
closesocket(sock); 

// winsock2の終了処理
WSACleanup();
 return 0;
 }
 void show_plane(void){
 printf("\n");
 for(int i = 0; j < 4; i++){ 

printf("%c",plane[i][j]);
 }
 printf("\n");
 } 
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • fuzzball

    2017/06/19 16:08

    タグを修正して下さい。また、コードが正しく囲えていないので修正して下さい。

    キャンセル

  • 退会済みユーザー

    2017/06/23 17:23

    複数のユーザーから「問題・課題が含まれていない質問」という意見がありました
    teratailでは、漠然とした興味から票を募るような質問や、意見の主張をすることを目的とした投稿は推奨していません。
    「編集」ボタンから編集を行い、質問の意図や解決したい課題を明確に記述していただくと回答が得られやすくなります。

回答 2

checkベストアンサー

0

うーん…学校の課題か何かかい?
不明点のコードのレベルが低すぎて教えることにあまり気乗りしませんが…
まあ個人的なプログラムかもしれませんしね。

int row = buf[0];
int col = buf[1];

plane[row][col] = 's'; // 又は 'c'。
show_plane();

あえて最小のコードにしています。
これを送受信前後に挟めばいいでしょう。

show_planeにも不具合があるし、入力内容のエラー処理がないという致命的な問題があります。
が、とりあえず二次元配列の取り扱いというならこれだけでいいでしょうかね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

send前にplane配列へ格納すれば良いでしょうかね。
あとsend前、recv後にshow_planeも呼ばないとだめかもですね。

plane[buf[0]][buf[1]] = 'S';
show_plane();
send(sock, (char*)buf, sizeof(buf), 0);
~
recv(sock, (char*)buf, sizeof(buf), 0);
show_plane();

それからshow_planeの処理がよろしくないですね。
plane配列の各行はNUL文字で終わっているので、文字ではなく文字列として出力した方が効率良いでしょう。

void show_plane(void){
    printf("\n");
    for(int i = 0; j < 4; i++){ 
        printf("%s\n",plane[i]);
    }
    printf("\n"); 
} 

他にも指摘すべき点は多々あるかもしれませんが、とりあえず気づいたところです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる