yakage0524
@yakage0524

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

クライアント側のカードの値が変化してしまう

解決したいこと

Visual StudioでC++の通信機能付き神経衰弱を作成しています。
カードをクリック(めくる)際、サーバ側が操作するとクライアント側のカードの値が変化してしまいます。
また、めくったカードが両方に表示されるようにしたいです。
解決方法を教えてください。

発生している問題・エラー

カードをクリック(めくる)際、サーバ側が操作するとクライアント側のカードの値が変化する。

該当するソースコード

言語名C++
#define _CRT_SECURE_NO_WARNINGS // sprintfの警告を無効化
#include <Windows.h>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <vector>      // std::vector
#include <utility>     // std::pair
#include <algorithm>   // std::shuffle
#include <random>      // std::default_random_engine
#include <WinSock.h>
#include <stdio.h>
#pragma comment(lib,"wsock32.lib")

////////////////////////////////////////////////////////////////////////////////
//
// 使用ライブラリ
//
#pragma comment(lib,"wsock32.lib")


////////////////////////////////////////////////////////////////////////////////
//
//  定数定義
//
#define WM_SOCKET       (WM_USER+1)     // ソケット用メッセージ
#define PORT            10000           // 通信ポート番号

#define IDB_CONNECT     1000            // [接続]ボタン
#define IDB_ACCEPT      1001            // [接続待ち]ボタン
#define IDB_REJECT      1002            // [切断]ボタン
#define IDB_REJECTREQUEST 1003          // [切断要請]ボタン

#define IDF_HOSTNAME    2000                // ホスト名入力エディットボックス

#define IDE_RECVMSG     3000            // メッセージ受信イベント

#define WINDOW_W        840         // ウィンドウの幅
#define WINDOW_H        750         // ウィンドウの高さ

#define MAX_MESSAGE     128         // 配列の最大要素数

#define MAX_ARRAY     10000             // 配列の最大要素数


#define BUFSIZE 9     //座標が入る配列の最大要素数

#define REJECTNUMBER  123456789  //切断要請かどうかの判定用

////////////////////////////////////////////////////////////////////////////////
//
//  グローバル変数
//
LPCTSTR lpClassName = "SimpleGraphicalChat";        // ウィンドウクラス名
LPCTSTR lpWindowName = "SimpleGraphicalChat";        // タイトルバーにつく名前

HPEN hPenBlack;                     // 黒ペン
HPEN hPenRed;                       //赤ペン

const RECT d = { 10, 100, 810, 700 };                  // 描画領域(左上隅のx座標, 左上隅のy座標, 右下隅のx座標, 右下隅のy座標)

SOCKET sock = INVALID_SOCKET;            // ソケット
SOCKET sv_sock = INVALID_SOCKET;            // サーバ用ソケット
HOSTENT* phe;                       // HOSTENT構造体

int n = 0;                                              // カウンタ(自分用)
int flag[MAX_ARRAY];                                // ペンダウンフラグ(自分用)
POINT pos[MAX_ARRAY];                               // 座標を格納(自分用)

int n_rev = 0;                                          //カウンタ(受信した用)
int flag_rev[MAX_ARRAY];                                // ペンダウンフラグ(受信した用)
POINT pos_rev[MAX_ARRAY];                               // 座標を格納(受信した用)

bool canvas = false;        //キャンバスに書き込めるならtrue、書き込めないならfalse

static BOOL firstMessageReceived = FALSE; // 最初のメッセージを受信したかどうか
static BOOL isSynced = FALSE; // 配列同期が完了したかどうか
static BOOL isHost = FALSE;   // ホストかどうか
///////

const int ROWS = 4;
const int COLS = 5;
const int CARD_WIDTH = 100;
const int CARD_HEIGHT = 150;
const int WINDOW_WIDTH = COLS * CARD_WIDTH;
const int WINDOW_HEIGHT = ROWS * CARD_HEIGHT + 50; // スコア表示分の余白

int board[ROWS][COLS]; // カードの数字を格納する2次元配列
bool revealed[ROWS][COLS]; // 表向きかどうかを管理する配列
int player1Score = 0;
int player2Score = 0;
bool isPlayer1Turn = true;

// 選択されたカードの座標
std::pair<int, int> firstCard = { -1, -1 };
std::pair<int, int> secondCard = { -1, -1 };
bool isWaiting = false; // 2枚のカードを待機中かどうかを表すフラグ

////////////////////////////////////////////////////////////////////////////////
//
//  プロトタイプ宣言
//
LRESULT CALLBACK WindowParamroc(HWND, UINT, WPARAM, LPARAM);   // ウィンドウ関数
LRESULT CALLBACK OnPaint(HWND, UINT, WPARAM, LPARAM);  // 描画関数
BOOL SockInit(HWND hWnd);                               // ソケット初期化
BOOL SockAccept(HWND hWnd);                             // ソケット接続待ち
BOOL SockConnect(HWND hWnd, LPCSTR host);               // ソケット接続
void WindowInit(HWND hWnd);                             // ウィンドウ初期化
void setData(int f, int x, int y);                   // 描画情報を入れる
void setData_rev(int f, int x, int y);                   // 描画情報(受信したもの用)を入れる
BOOL checkMousePos(int x, int y);           // マウスの位置がキャンパスの中かどうか判定する


LRESULT CALLBACK WindowParamroc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

void initializeBoard() {
    std::vector<int> numbers;
    for (int i = 1; i <= 10; ++i) {
        numbers.push_back(i);
        numbers.push_back(i);
    }

    std::random_device rd;
    std::mt19937 rng(rd());
    std::shuffle(numbers.begin(), numbers.end(), rng);

    int index = 0;
    for (int i = 0; i < ROWS; ++i) {
        for (int j = 0; j < COLS; ++j) {
            board[i][j] = numbers[index++];
            revealed[i][j] = false;
        }
    }
}

// 配列の同期を行う関数
void synchronizeArray() {
    // 配列データを送信 (行列をバイト列として送信)
    send(sock, (char*)board, sizeof(board), 0);
}

void drawBoard(HDC hdc) {
    for (int i = 0; i < ROWS; ++i) {
        for (int j = 0; j < COLS; ++j) {
            HBRUSH brush = revealed[i][j] ? CreateSolidBrush(RGB(255, 255, 255)) : CreateSolidBrush(RGB(0, 0, 255));
            RECT rect = { j * CARD_WIDTH, i * CARD_HEIGHT + 50, (j + 1) * CARD_WIDTH, (i + 1) * CARD_HEIGHT + 50 };
            FillRect(hdc, &rect, brush);
            DeleteObject(brush);

            if (revealed[i][j]) {
                char text[10];
                sprintf(text, "%d", board[i][j]);
                SetTextColor(hdc, RGB(0, 0, 0));
                SetBkMode(hdc, TRANSPARENT);
                DrawTextA(hdc, text, -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
            }
        }
    }
}

void handleMouseClick(HWND hWnd, int x, int y) {
    if (isWaiting) return; // 2枚のカードが処理中ならクリック無効化

    int col = x / CARD_WIDTH;
    int row = (y - 50) / CARD_HEIGHT;

    if (row >= 0 && row < ROWS && col >= 0 && col < COLS && !revealed[row][col]) {
        revealed[row][col] = true;
        InvalidateRect(hWnd, nullptr, TRUE); // カードの状態をすぐに更新

        if (firstCard.first == -1) {
            firstCard = { row, col };
        }
        else if (secondCard.first == -1) {
            secondCard = { row, col };

            if (board[firstCard.first][firstCard.second] == board[secondCard.first][secondCard.second]) {
                if (isPlayer1Turn) {
                    player1Score++;
                }
                else {
                    player2Score++;
                }
                firstCard = { -1, -1 };
                secondCard = { -1, -1 };
            }
            else {
                isWaiting = true;
                SetTimer(hWnd, 1, 1000, nullptr); // 1秒後にWM_TIMERを送信
            }
        }
    }
}

void resetCards() {
    revealed[firstCard.first][firstCard.second] = false;
    revealed[secondCard.first][secondCard.second] = false;
    firstCard = { -1, -1 };
    secondCard = { -1, -1 };
}

void drawScores(HDC hdc) {
    // 1プレイヤーのスコア (左上)
    RECT player1Rect = { 10, 10, 110, 40 }; // 1プレイヤーのスコアの表示エリア
    HBRUSH brush = CreateSolidBrush(RGB(255, 255, 255)); // 白色の背景
    FillRect(hdc, &player1Rect, brush); // 1プレイヤーのスコアの背景をクリア
    DeleteObject(brush);

    char player1ScoreText[16]; // スコアのテキスト (最大 "Score: 999" くらい想定)
    sprintf(player1ScoreText, "P1: %d", player1Score);
    SetTextColor(hdc, RGB(0, 0, 0)); // 黒色のテキスト
    SetBkMode(hdc, TRANSPARENT); // 背景は透明
    DrawTextA(hdc, player1ScoreText, -1, &player1Rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE); // 1プレイヤーのスコア描画

    // 2プレイヤーのスコア (右上)
    RECT player2Rect = { WINDOW_WIDTH - 120, 10, WINDOW_WIDTH - 20, 40 }; // 2プレイヤーのスコアの表示エリア
    brush = CreateSolidBrush(RGB(255, 255, 255)); // 白色の背景
    FillRect(hdc, &player2Rect, brush); // 2プレイヤーのスコアの背景をクリア
    DeleteObject(brush);

    char player2ScoreText[16];
    sprintf(player2ScoreText, "P2: %d", player2Score);
    SetTextColor(hdc, RGB(0, 0, 0));
    SetBkMode(hdc, TRANSPARENT);
    DrawTextA(hdc, player2ScoreText, -1, &player2Rect, DT_RIGHT | DT_VCENTER | DT_SINGLELINE); // 2プレイヤーのスコア描画
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    initializeBoard();

    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowParamroc;
    wc.hInstance = hInstance;
    wc.lpszClassName = TEXT("MemoryGameWindow");

    RegisterClass(&wc);

    HWND hWnd = CreateWindowEx(0, TEXT("MemoryGameWindow"), TEXT("Memory Game"), WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT,
        nullptr, nullptr, hInstance, nullptr);

    ShowWindow(hWnd, nCmdShow);

    MSG msg = {};
    while (GetMessage(&msg, nullptr, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

LRESULT CALLBACK WindowParamroc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    static HWND hWndHost;                       // ホスト名入力用エディットボックス
    static HWND hWndConnect, hWndAccept;        // [接続]ボタンと[接続待ち]ボタン
    static HWND hWndReject;                     // [切断]ボタン
    static HWND hWndRejectRequest;              // [切断要請]ボタン
    static BOOL mouseFlg = FALSE;               // 前回の状態 TRUE:描画した、FALSE:描画していない

    switch (uMsg) {

    case WM_CREATE:     // ウィンドウが生成された
        hPenBlack = (HPEN)CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
        hPenRed = (HPEN)CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
        // 文字列表示
        CreateWindow("static", "Host Name",
            WS_CHILD | WS_VISIBLE, 10, 10, 100, 18,
            hWnd, NULL, NULL, NULL);

        // ホスト名入力用エディットボックス
        hWndHost = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",
            WS_CHILD | WS_VISIBLE, 10, 30, 200, 25,
            hWnd, (HMENU)IDF_HOSTNAME, NULL, NULL);
        // [接続]ボタン
        hWndConnect = CreateWindow("button", "接続",
            WS_CHILD | WS_VISIBLE, 220, 30, 90, 25,
            hWnd, (HMENU)IDB_CONNECT, NULL, NULL);
        // [接続待ち]ボタン
        hWndAccept = CreateWindow("button", "接続待ち",
            WS_CHILD | WS_VISIBLE, 325, 30, 90, 25,
            hWnd, (HMENU)IDB_ACCEPT, NULL, NULL);
        // [切断]ボタン
        hWndReject = CreateWindow("button", "切断",
            WS_CHILD | WS_VISIBLE | WS_DISABLED, 325, 60, 90, 25,
            hWnd, (HMENU)IDB_REJECT, NULL, NULL);
        // [切断要請]ボタン
        hWndRejectRequest = CreateWindow("button", "切断要請",
            WS_CHILD | WS_VISIBLE | WS_DISABLED, 220, 60, 90, 25,
            hWnd, (HMENU)IDB_REJECTREQUEST, NULL, NULL);

        SetFocus(hWndHost);     //フォーカス指定
        SockInit(hWnd);         // ソケット初期化

        return 0L;

    case WM_COMMAND:    // ボタンが押された
        switch (LOWORD(wParam)) {
        case IDB_ACCEPT:    // [接続待ち]ボタン押下(サーバー)
            if (SockAccept(hWnd)) {  // 接続待ち要求
                return 0L;      // 接続待ち失敗
            }
            EnableWindow(hWndHost, FALSE);              // [HostName]   無効
            EnableWindow(hWndConnect, FALSE);           // [接続]       無効
            EnableWindow(hWndAccept, FALSE);            // [接続待ち]   無効
            EnableWindow(hWndRejectRequest, TRUE);      // [切断要請]   有効
            EnableWindow(hWndReject, TRUE);             // [切断]       有効
            return 0L;

        case IDB_CONNECT:   // [接続]ボタン押下(クライアント)
            char host[100];
            GetWindowText(hWndHost, host, sizeof(host));

            if (SockConnect(hWnd, host)) {   // 接続要求
                SetFocus(hWndHost);     // 接続失敗
                return 0L;
            }
            EnableWindow(hWndHost, FALSE);              // [HostName]   無効
            EnableWindow(hWndConnect, FALSE);           // [接続]       無効
            EnableWindow(hWndAccept, FALSE);            // [接続待ち]   無効
            EnableWindow(hWndRejectRequest, TRUE);      // [切断要請]   有効
            EnableWindow(hWndReject, TRUE);             // [切断]       有効
            return 0L;

        case IDB_REJECT:    // [切断]ボタン押下
            if (sock != INVALID_SOCKET) {    // 自分がクライアント側なら
                // ソケットを閉じる
                closesocket(sock);
                sock = INVALID_SOCKET;
            }
            if (sv_sock != INVALID_SOCKET) { // 自分がサーバ側なら
                // サーバ用ソケットを閉じる
                closesocket(sv_sock);
                sv_sock = INVALID_SOCKET;
            }
            SendMessage(hWnd, WM_DESTROY, 0, 0); // 切断処理発行
            return 0L;

        case IDB_REJECTREQUEST:    // [切断要請]ボタン押下
            switch (MessageBox(hWnd, TEXT("切断を要請しますか?"), "information", MB_OKCANCEL | MB_ICONEXCLAMATION)) {
            case IDOK:
                char buf[10];
                sprintf_s(buf, sizeof(buf), "%d", REJECTNUMBER);
                if (send(sock, buf, strlen(buf) + 1, 0) == SOCKET_ERROR) {    // 送信処理
                    // 送信に失敗したらエラーを表示
                    MessageBox(hWnd, TEXT("Error for reject request"), TEXT("Error"),
                        MB_OK | MB_ICONEXCLAMATION);
                }
                return 0L;
            case IDCANCEL:
                return 0L;
            }
        } /* end of switch (LOWORD(wParam)) */

    case WM_SOCKET:          // 非同期処理メッセージ
        if (WSAGETSELECTERROR(lParam) != 0) { return 0L; }

        switch (WSAGETSELECTEVENT(lParam)) {
        case FD_ACCEPT:     // 接続待ち完了通知
        {
            SOCKADDR_IN cl_sin;
            int len = sizeof(cl_sin);
            sock = accept(sv_sock, (LPSOCKADDR)&cl_sin, &len);

            if (sock == INVALID_SOCKET) {
                MessageBox(hWnd, "Accepting connection failed",
                    "Error", MB_OK | MB_ICONEXCLAMATION);
                closesocket(sv_sock);
                sv_sock = INVALID_SOCKET;
                EnableWindow(hWndHost, TRUE);              // [HostName]    有効
                EnableWindow(hWndConnect, TRUE);           // [接続]        有効
                EnableWindow(hWndAccept, TRUE);            // [接続待ち]    有効
                EnableWindow(hWndRejectRequest, FALSE);    // [切断要請]    無効
                EnableWindow(hWndReject, FALSE);           // [切断]        無効

                SetFocus(hWndHost);         // フォーカス指定
                return 0L;
            }

#ifndef NO_DNS
            // ホスト名取得
            phe = gethostbyaddr((char*)&cl_sin.sin_addr, 4, AF_INET);
            if (phe) { SetWindowText(hWndHost, phe->h_name); }
#endif  NO_DNS
            // 非同期モード (受信&切断)
            if (WSAAsyncSelect(sock, hWnd, WM_SOCKET, FD_READ | FD_CLOSE)
                == SOCKET_ERROR) {
                // 接続に失敗したら初期状態に戻す
                MessageBox(hWnd, "WSAAsyncSelect() failed",
                    "Error", MB_OK | MB_ICONEXCLAMATION);
                EnableWindow(hWndHost, TRUE);              // [HostName]    有効
                EnableWindow(hWndConnect, TRUE);           // [接続]        有効
                EnableWindow(hWndAccept, TRUE);            // [接続待ち]    有効
                EnableWindow(hWndRejectRequest, FALSE);    // [切断要請]    無効
                EnableWindow(hWndReject, FALSE);           // [切断]        無効
                SetFocus(hWndHost);         // フォーカス指定
                return 0L;
            }
            return 0L;
        }/* end of case FD_ACCEPT: */

        case FD_CONNECT: {// 接続完了通知

            // 非同期モード (受信&切断)
            if (WSAAsyncSelect(sock, hWnd, WM_SOCKET, FD_READ | FD_CLOSE)
                == SOCKET_ERROR) {
                // 接続に失敗したら初期状態に戻す
                MessageBox(hWnd, "WSAAsyncSelect() failed",
                    "Error", MB_OK | MB_ICONEXCLAMATION);
                EnableWindow(hWndHost, TRUE);              // [HostName]    有効
                EnableWindow(hWndConnect, TRUE);           // [接続]        有効
                EnableWindow(hWndAccept, TRUE);            // [接続待ち]    有効
                EnableWindow(hWndRejectRequest, FALSE);    // [切断要請]    無効
                EnableWindow(hWndReject, FALSE);           // [切断]        無効
                SetFocus(hWndHost);         // フォーカス指定  
                return 0L;
            }

            // クライアント側のみ配列同期を行う
            if (!isHost && !isSynced) {
                isSynced = TRUE;
                synchronizeArray(); // 配列の同期を行う関数を呼び出す
            }

        }break;

        case FD_READ: {// メッセージ受信

            static BOOL firstMessageReceived = FALSE; // 最初のメッセージを受信したかどうか
            int f2, x2, y2;
            char buf[MAX_MESSAGE]; // 受信内容を一時的に格納するバッファ
            if (recv(sock, buf, sizeof(buf), 0) != SOCKET_ERROR) { // 受信できたなら
                if (atoi(buf) == REJECTNUMBER) { // メッセージの内容が切断要請コマンド:REJECTだった場合
                    MessageBox(hWnd, "切断要請が来ました。[切断]ボタンを押してください。",
                        "Information", MB_OK | MB_ICONINFORMATION);
                }
                else if (!isHost && !firstMessageReceived) { // 最初のメッセージなら配列データとして扱う
                    firstMessageReceived = TRUE;
                    //memmove(board, buf, sizeof(board));
                    int* bufPtr = (int*)buf; // buf を int 型として扱う
                    for (int i = 0; i < ROWS; i++) {
                        for (int j = 0; j < COLS; j++) {
                            board[i][j] = *bufPtr++; // ポインタを進めながら値を格納
                        }
                    }
                }
                else { // メッセージの内容がマウス移動通知コマンド:FXYだった場合
                    sscanf_s(buf, "%1d%3d%3d", &f2, &x2, &y2);
                    n_rev++;
                    setData_rev(f2, x2, y2);
                    InvalidateRect(hWnd, &d, FALSE);

                    // 受信した座標をテキストとして表示(消していい)
                    char recvBuf[50];
                    HDC hdc = GetDC(hWnd);
                    sprintf_s(recvBuf, sizeof(recvBuf), "Received: (%d, %d)", x2, y2);
                    TextOut(hdc, 300, 70, recvBuf, strlen(recvBuf)); // ウィンドウ上部中央に座標を描画
                    ReleaseDC(hWnd, hdc);
                }
            }
        }break;


        case FD_CLOSE:      // 切断された
            MessageBox(hWnd, "切断されました。",
                "Information", MB_OK | MB_ICONINFORMATION);
            SendMessage(hWnd, WM_COMMAND, IDB_REJECT, 0); // 切断処理発行
            return 0L;
        }/* end of switch (WSAGETSELECTEVENT(lParam)) */
        return 0L;

    case WM_LBUTTONDOWN: {// マウス左ボタンが押された
        if (checkMousePos(LOWORD(lParam), HIWORD(lParam)) && canvas == true) { // 描画領域の中かつキャンバスが有効なら
            setData(0, LOWORD(lParam), HIWORD(lParam)); // 線の始点として座標を記録
            n++;
            InvalidateRect(hWnd, &d, FALSE);
            mouseFlg = TRUE;

        }
        else {
            mouseFlg = FALSE;
        }
        int x = LOWORD(lParam);
        int y = HIWORD(lParam);
        handleMouseClick(hWnd, x, y);
    } break;

    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        drawBoard(hdc);
        drawScores(hdc);
        EndPaint(hWnd, &ps);
    } break;

    case WM_TIMER: {
        KillTimer(hWnd, 1);
        resetCards();
        isWaiting = false;
        InvalidateRect(hWnd, nullptr, TRUE);
        isPlayer1Turn = !isPlayer1Turn; // ターンを切り替える
    } break;

    case WM_DESTROY: {
        PostQuitMessage(0);
    } break;

    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}


////////////////////////////////////////////////////////////////////////////////
//
//  ソケット初期化処理
//
BOOL SockInit(HWND hWnd)
{
    WSADATA wsa;
    int ret;
    char ret_buf[80];

    ret = WSAStartup(MAKEWORD(1, 1), &wsa);

    if (ret != 0) {
        wsprintf(ret_buf, "%d is the err", ret);
        MessageBox(hWnd, ret_buf, "Error", MB_OK | MB_ICONSTOP);
        exit(-1);
    }
    return FALSE;
}

////////////////////////////////////////////////////////////////////////////////
//
//  ソケット接続 (クライアント側)
//
BOOL SockConnect(HWND hWnd, LPCSTR host)
{
    SOCKADDR_IN cl_sin; // SOCKADDR_IN構造体

    // ソケットを開く
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == INVALID_SOCKET) {        // ソケット作成失敗
        MessageBox(hWnd, "Socket() failed", "Error", MB_OK | MB_ICONEXCLAMATION);
        return TRUE;
    }

    memset(&cl_sin, 0x00, sizeof(cl_sin)); // 構造体初期化
    cl_sin.sin_family = AF_INET;           // インターネット
    cl_sin.sin_port = htons(PORT);       // ポート番号指定

    phe = gethostbyname(host); // アドレス取得

    if (phe == NULL) {
        MessageBox(hWnd, "gethostbyname() failed.",
            "Error", MB_OK | MB_ICONEXCLAMATION);
        return TRUE;
    }
    memcpy(&cl_sin.sin_addr, phe->h_addr, phe->h_length);

    // 非同期モード (接続)
    if (WSAAsyncSelect(sock, hWnd, WM_SOCKET, FD_CONNECT) == SOCKET_ERROR) {
        closesocket(sock);
        sock = INVALID_SOCKET;
        MessageBox(hWnd, "WSAAsyncSelect() failed",
            "Error", MB_OK | MB_ICONEXCLAMATION);
        return TRUE;
    }

    // 接続処理
    if (connect(sock, (LPSOCKADDR)&cl_sin, sizeof(cl_sin)) == SOCKET_ERROR) {
        if (WSAGetLastError() != WSAEWOULDBLOCK) {
            closesocket(sock);
            sock = INVALID_SOCKET;
            MessageBox(hWnd, "connect() failed", "Error", MB_OK | MB_ICONEXCLAMATION);
            return TRUE;
        }
    }
    canvas = true;  //キャンバス 有効
    return FALSE;
}


////////////////////////////////////////////////////////////////////////////////
//
//  接続待ち (サーバ側)
//
BOOL SockAccept(HWND hWnd)
{
    SOCKADDR_IN sv_sin;         // SOCKADDR_IN構造体

    // サーバ用ソケット
    sv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sv_sock == INVALID_SOCKET) { // ソケット作成失敗
        MessageBox(hWnd, "Socket() failed", "Error", MB_OK | MB_ICONEXCLAMATION);
        return TRUE;
    }

    memset(&sv_sin, 0x00, sizeof(sv_sin));      // 構造体初期化
    sv_sin.sin_family = AF_INET;           // インターネット
    sv_sin.sin_port = htons(PORT);       // ポート番号指定
    sv_sin.sin_addr.s_addr = htonl(INADDR_ANY); // アドレス指定

    if (bind(sv_sock, (LPSOCKADDR)&sv_sin, sizeof(sv_sin)) == SOCKET_ERROR) {
        closesocket(sv_sock);
        sv_sock = INVALID_SOCKET;
        MessageBox(hWnd, "bind() failed", "Error", MB_OK | MB_ICONEXCLAMATION);
        return TRUE;
    }

    if (listen(sv_sock, 5) == SOCKET_ERROR) {
        // 接続待ち失敗
        closesocket(sv_sock);
        sv_sock = INVALID_SOCKET;
        MessageBox(hWnd, "listen() failed", "Error", MB_OK | MB_ICONEXCLAMATION);
        return TRUE;
    }

    // 非同期処理モード (接続待ち)
    if (WSAAsyncSelect(sv_sock, hWnd, WM_SOCKET, FD_ACCEPT) == SOCKET_ERROR) {
        closesocket(sv_sock);
        sv_sock = INVALID_SOCKET;
        MessageBox(hWnd, "WSAAsyncSelect() failed",
            "Error", MB_OK | MB_ICONEXCLAMATION);
        return TRUE;
    }
    canvas = true;  //キャンバス 有効
    return FALSE;
}

////////////////////////////////////////////////////////////////////////////////
//
//  描画情報を格納
//
void setData(int f, int x, int y)
{
    char buf[15];
    flag[n] = f;
    pos[n].x = x;
    pos[n].y = y;
    sprintf_s(buf, sizeof(buf), "%1d%03d%03d", f, x, y); //bufに座標が入っている
    send(sock, buf, strlen(buf) + 1, 0);
}

////////////////////////////////////////////////////////////////////////////////
//
//  描画情報(受信したもの)を格納
//

void setData_rev(int f, int x, int y)
{
    flag_rev[n_rev] = f;
    pos_rev[n_rev].x = x;
    pos_rev[n_rev].y = y;
}

////////////////////////////////////////////////////////////////////////////////
//
//  マウスの位置がキャンパスの中かどうか判定する
//
BOOL checkMousePos(int x, int y)
{
    if (x >= d.left && x <= d.right
        && y >= d.top && y <= d.bottom) {
        return TRUE;
    }
    return FALSE;
}

自分で試したこと

サーバ側が操作する前にクライアント側が操作してもカードの値に変化はありませんでした。

0

No Answers yet.

Your answer might help someone💌