クライアント側のカードの値が変化してしまう
解決したいこと
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