2021-02-43.cpp

これは、確率から統計的な確率を生成するプログラムですのソースコードです。

確率通りになるまでの試行回数、パチンコ・パチスロ・投資の統計的確率」で使用しています。

 



/*
実行には、別途メルセンヌ・ツイスタ ライブラリが必要です。
次のファイル必須
	SFMT-alti.h
	SFMT-common.h
	SFMT-neon.h
	SFMT-params.h
	SFMT-params11213.h
	SFMT-params1279.h
	SFMT-params132049.h
	SFMT-params19937.h
	SFMT-params216091.h
	SFMT-params2281.h
	SFMT-params4253.h
	SFMT-params44497.h
	SFMT-params607.h
	SFMT-params86243.h
	SFMT-sse2-msc.h
	SFMT-sse2.h
	SFMT.c
	SFMT.h

*/
#include 

#include "SFMT.h"

HINSTANCE	s_hInstanceHandle	=NULL;
LPSTR		s_lpWindowClassName	="SimpleWindow2020";

// 1/300で195が出たらBIGに当選。
LPSTR		s_lpBigDenominator="300";
// 1/200で188が出たらREGに当選。
LPSTR		s_lpRegDenominator="200";
// 試行回数
LPSTR		s_lpNumTry="10000";

typedef struct __BONUS{
	DWORD	dwNumBonus;
	DWORD	dwDenominator, dwMolecules;
}BONUS, *LPBONUS;

#define	ID_ADD		100
#define	ID_CLEAR	101
#define	ID_COPY		102
#define	ID_BIG		103
#define	ID_REG		104
#define	ID_TRY		105
#define	ID_EDIT		106

// dwDenominator:	分母
// dwMolecules:		分子
inline void InitBonus(LPBONUS lpBonus, DWORD dwDenominator, DWORD dwMolecules)
{
	lpBonus->dwNumBonus			=0;
	lpBonus->dwDenominator		=dwDenominator;
	lpBonus->dwMolecules		=dwMolecules;
}
inline BOOL LoteryBonus(LPBONUS lpBonus, DWORD dwLottery)
{
	if((dwLottery%
		lpBonus->dwDenominator)==lpBonus->dwMolecules)
	{
		lpBonus->dwNumBonus++;
		return TRUE;	// 当選
	}
	return FALSE;
}




typedef struct __DATA{
	BONUS	big;
	BONUS	reg;
}DATA, *LPDATA;

typedef struct __SIMPLEWINDOWINFO{
	HWND	hWnd;
	HWND	hAdd;
	HWND	hCopy;
	HWND	hClear;
	HWND	hBig;
	HWND	hReg;
	HWND	hTry;
	HWND	hEdit;

	LPDATA	lpData;
	DWORD	dwNumData;
	LPSTR	lpTextBuffer;
	LPBYTE	lpBuffer;
}SIMPLEWINDOWINFO, *LPSIMPLEWINDOWINFO;
#define	MAXDATA			1000
#define	MAXTEXTBUFFER	MAXDATA*200


HRESULT	AllocAllData(LPSIMPLEWINDOWINFO lpInfo)
{
	DWORD	dwDataSize;

	dwDataSize=MAXDATA*sizeof(DATA);
	lpInfo->lpBuffer=new BYTE[dwDataSize+MAXTEXTBUFFER];
	if(lpInfo->lpBuffer==NULL)
		return E_OUTOFMEMORY;

	LPBYTE	lpBuffer;
	lpBuffer=lpInfo->lpBuffer;

	lpInfo->lpData		=(LPDATA)lpBuffer;
	lpBuffer+=dwDataSize;

	lpInfo->lpTextBuffer=(LPSTR)lpBuffer;

	return S_OK;
}

HRESULT	FreeAllData(LPSIMPLEWINDOWINFO lpInfo)
{
	if(lpInfo->lpBuffer!=NULL)
	{
		delete lpInfo->lpBuffer;
		lpInfo->lpBuffer=NULL;
	}
	lpInfo->lpData			=NULL;
	lpInfo->lpTextBuffer	=NULL;
	return S_OK;
}

HRESULT	DestroyClientWindows(LPSIMPLEWINDOWINFO lpInfo)
{
	if(lpInfo->hAdd!=NULL)
	{
		DestroyWindow(lpInfo->hAdd);
	}
	if(lpInfo->hCopy!=NULL)
	{
		DestroyWindow(lpInfo->hCopy);
	}
	if(lpInfo->hClear!=NULL)
	{
		DestroyWindow(lpInfo->hClear);
	}
	if(lpInfo->hBig!=NULL)
	{
		DestroyWindow(lpInfo->hBig);
	}
	if(lpInfo->hReg!=NULL)
	{
		DestroyWindow(lpInfo->hReg);
	}
	if(lpInfo->hTry!=NULL)
	{
		DestroyWindow(lpInfo->hTry);
	}
	if(lpInfo->hEdit!=NULL)
	{
		DestroyWindow(lpInfo->hEdit);
	}

	ZeroMemory(lpInfo, sizeof(*lpInfo));
	return S_OK;
}

HRESULT AddData(HWND hWnd, LPSIMPLEWINDOWINFO lpInfo)
{
	if(lpInfo->dwNumData>=MAXDATA)
	{
		return E_FAIL;
	}

	LONG	lBig, lReg, lTry;
	lBig=GetDlgItemInt(hWnd, ID_BIG, NULL, NULL);
	lReg=GetDlgItemInt(hWnd, ID_REG, NULL, NULL);
	lTry=GetDlgItemInt(hWnd, ID_TRY, NULL, NULL);
	if(lBig<1)
		lBig=1;
	if(lReg<1)
		lReg=1;
	if(lTry<1)
		lTry=1;

	sfmt_t	sfmt;
	sfmt_init_gen_rand(&sfmt, GetTickCount());

	LONG	i;
	DWORD	lottery;
	BONUS	big, reg;

	InitBonus(&big, lBig, lBig*2/7);
	InitBonus(&reg, lReg, lReg*3/4);

	for(i=0; i<lTry; i++) { lottery=(DWORD)sfmt_genrand_uint32(&sfmt); if(LoteryBonus(&big, lottery) || LoteryBonus(&reg, lottery)) {// ボーナスを同時に当選しない continue; } } CopyMemory(&lpInfo->lpData[lpInfo->dwNumData].big, &big, sizeof(big));
	CopyMemory(&lpInfo->lpData[lpInfo->dwNumData].reg, &reg, sizeof(reg));
	lpInfo->dwNumData++;

	// ----- reset
	LPSTR	lpTextBuffer;
	DWORD	dwNumData, dwNumBigs, dwNumRegs;
	LPDATA	lpData;

	lpTextBuffer=lpInfo->lpTextBuffer;
	dwNumData	=lpInfo->dwNumData;
	lpData		=lpInfo->lpData;

	wsprintf(lpTextBuffer
				, "回数 %d\r\n"
				"総試行回数 %d\r\n"
				, dwNumData
				, lTry*dwNumData
				);
	lpTextBuffer+=strlen(lpTextBuffer);

	dwNumBigs	=0;
	dwNumRegs	=0;
	strcpy(lpTextBuffer, "----- 各当選数 -----\r\n"
						"BIG=");
	lpTextBuffer+=strlen(lpTextBuffer);
	for(i=0; i<(LONG)dwNumData; i++)
	{
		dwNumBigs	+=lpData[i].big.dwNumBonus;
		if(i)
			wsprintf(lpTextBuffer, ", %d", lpData[i].big.dwNumBonus);
		else
			wsprintf(lpTextBuffer, "%d", lpData[i].big.dwNumBonus);
		lpTextBuffer+=strlen(lpTextBuffer);
	}

	strcpy(lpTextBuffer, "\r\nREG=");
	lpTextBuffer+=strlen(lpTextBuffer);
	for(i=0; i<(LONG)dwNumData; i++) { dwNumRegs +=lpData[i].reg.dwNumBonus; if(i) wsprintf(lpTextBuffer, ", %d", lpData[i].reg.dwNumBonus); else wsprintf(lpTextBuffer, "%d", lpData[i].reg.dwNumBonus); lpTextBuffer+=strlen(lpTextBuffer); } strcpy(lpTextBuffer, "\r\n"); lpTextBuffer+=strlen(lpTextBuffer); DWORD dwBigDenominator, dwRegDenominator; DWORD dwBigMolecules, dwRegMolecules; if(dwNumBigs>0)
	{
		dwBigDenominator	=lTry*dwNumData/dwNumBigs;
		dwBigMolecules		=1;
	}
	else
	{
		dwBigDenominator	=lTry;
		dwBigMolecules		=0;
	}
	if(dwNumRegs>0)
	{
		dwRegDenominator	=lTry*dwNumData/dwNumRegs;
		dwRegMolecules		=1;
	}
	else
	{
		dwRegDenominator	=lTry;
		dwRegMolecules		=0;
	}
	wsprintf(lpTextBuffer
					, "----- 合計 -----\r\n"
					"BIG=%d\r\n"
					"REG=%d\r\n"
					"----- 試行による統計的確率 -----\r\n"
					"BIG=%d/%d\r\n"
					"REG=%d/%d\r\n"
					, dwNumBigs
					, dwNumRegs
					, dwBigMolecules
					, dwBigDenominator
					, dwRegMolecules
					, dwRegDenominator
					);
	lpTextBuffer+=strlen(lpTextBuffer);


	::SetWindowText(lpInfo->hEdit, lpInfo->lpTextBuffer);
	return S_OK;
}


void ClearData(LPSIMPLEWINDOWINFO lpInfo)
{
	lpInfo->dwNumData=0;
	if(lpInfo->hEdit!=NULL)
		::SetWindowText(lpInfo->hEdit,"");
}



//	ウィンドウプロシージャ
LRESULT	CALLBACK LoterryWndProc(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
	LPSIMPLEWINDOWINFO	lpInfo;
	lpInfo=(LPSIMPLEWINDOWINFO)GetWindowLongPtr(hWnd, 0);
	if(lpInfo==NULL
		|| lpInfo->hWnd==NULL)
	{
		switch(nMessage){
		case WM_CREATE:
			{
				LPCREATESTRUCT	lpcs=(LPCREATESTRUCT)lParam;

				lpInfo=(LPSIMPLEWINDOWINFO)lpcs->lpCreateParams;
				if(lpInfo==NULL)
					return -1;
				SetWindowLongPtr(hWnd, 0, (LONG_PTR)lpInfo);	// こちらの方が将来的に安全
				lpInfo->hWnd=hWnd;
				if(DefWindowProc(hWnd, nMessage, wParam, lParam)!=0)
				{
					DestroyClientWindows(lpInfo);
					return -1;
				}

				RECT	rClient;
				GetClientRect(hWnd, &rClient);

				lpInfo->hAdd=CreateWindowEx(
									0, "BUTTON", "Add"
									, WS_VISIBLE|WS_CHILD| BS_PUSHBUTTON
									, 0, 0, 100, 32, hWnd
									, (HMENU)ID_ADD, s_hInstanceHandle, NULL);
				lpInfo->hCopy=CreateWindowEx(
									0, "BUTTON", "Copy"
									, WS_VISIBLE|WS_CHILD| BS_PUSHBUTTON
									, 100, 0, 100, 32, hWnd
									, (HMENU)ID_COPY, s_hInstanceHandle, NULL);
				lpInfo->hClear=CreateWindowEx(
									0, "BUTTON", "Clear"
									, WS_VISIBLE|WS_CHILD| BS_PUSHBUTTON
									, 200, 0, 100, 32, hWnd
									, (HMENU)ID_CLEAR, s_hInstanceHandle, NULL);

				lpInfo->hBig=CreateWindowEx(
									WS_EX_CLIENTEDGE, "EDIT", s_lpBigDenominator
									, WS_VISIBLE|WS_CHILD| ES_NUMBER
									, 300, 0, 100, 32, hWnd
									, (HMENU)ID_BIG, s_hInstanceHandle, NULL);
				lpInfo->hReg=CreateWindowEx(
									WS_EX_CLIENTEDGE, "EDIT", s_lpRegDenominator
									, WS_VISIBLE|WS_CHILD| ES_NUMBER
									, 400, 0, 100, 32, hWnd
									, (HMENU)ID_REG, s_hInstanceHandle, NULL);
				lpInfo->hTry=CreateWindowEx(
									WS_EX_CLIENTEDGE, "EDIT", s_lpNumTry
									, WS_VISIBLE|WS_CHILD| ES_NUMBER
									, 500, 0, 100, 32, hWnd
									, (HMENU)ID_TRY, s_hInstanceHandle, NULL);


				rClient.top+=32;
				lpInfo->hEdit=CreateWindowEx(
									WS_EX_CLIENTEDGE, "EDIT", NULL
									, WS_VISIBLE|WS_CHILD| ES_MULTILINE| ES_WANTRETURN| ES_AUTOHSCROLL| ES_AUTOVSCROLL| WS_HSCROLL| WS_VSCROLL
									, rClient.left, rClient.top, rClient.right-rClient.left, rClient.bottom-rClient.top, hWnd
									, (HMENU)ID_EDIT, s_hInstanceHandle, NULL);


				RECT	rWindow;
				LONG	cx, cy;
				GetWindowRect(hWnd, &rWindow);
				cx=rWindow.right-rWindow.left;
				cy=rWindow.bottom-rWindow.top;
				::SetWindowPos(hWnd, NULL
								, GetSystemMetrics(SM_CXSCREEN)/2-cx/2
								, GetSystemMetrics(SM_CYSCREEN)/2-cy/2
								, cx, cy
								, 0
								);

				return 0L;
			}
		};
		return DefWindowProc(hWnd, nMessage, wParam, lParam);
	}
	else
	{
		switch(nMessage){
		case WM_DESTROY:
			{
       			LRESULT returncode;
				DestroyClientWindows(lpInfo);
				returncode=DefWindowProc(hWnd, nMessage, wParam, lParam);
       			lpInfo->hWnd=NULL;
				PostQuitMessage(0);
				return returncode;
			}
		case WM_COMMAND:
			switch(LOWORD(wParam)){
			case ID_ADD:
				if(HIWORD(wParam)==BN_CLICKED)
				{
					AddData(hWnd, lpInfo);
				}
				break;
			case ID_COPY:
				::SendMessage(lpInfo->hEdit, EM_SETSEL, 0L, -1);
				::SendMessage(lpInfo->hEdit, WM_COPY, 0L, 0L);
				break;
			case ID_CLEAR:
				if(HIWORD(wParam)==BN_CLICKED)
				{
					ClearData(lpInfo);
				}
				break;
			};
			return DefWindowProc(hWnd, nMessage, wParam, lParam);

		case WM_SIZE:
			switch(wParam){
			case SIZE_MINIMIZED:
				break;
			default:
				{
					RECT	rClient;
					GetClientRect(hWnd, &rClient);

					::SetWindowPos(lpInfo->hAdd, NULL
									, 0, 0, 100, 32, 0);
					::SetWindowPos(lpInfo->hCopy, NULL
									, 100, 0, 100, 32, 0);
					::SetWindowPos(lpInfo->hClear, NULL
									, 200, 0, 100, 32, 0);
					::SetWindowPos(lpInfo->hBig, NULL
									, 300, 0, 100, 32, 0);
					::SetWindowPos(lpInfo->hReg, NULL
									, 400, 0, 100, 32, 0);
					::SetWindowPos(lpInfo->hTry, NULL
									, 500, 0, 100, 32, 0);

					rClient.top+=32;
					::SetWindowPos(lpInfo->hEdit, NULL
									, rClient.left, rClient.top
									, rClient.right-rClient.left
									, rClient.bottom-rClient.top
									, 0);

				}
				break;
			};
			return 0L;

		};
		return DefWindowProc(hWnd, nMessage, wParam, lParam);
	}

}




BOOL RegisterWindowClass(HINSTANCE hInstance)
{
	s_hInstanceHandle=hInstance;
	//	-------- ウィンドウクラスの登録 ---------
	WNDCLASSEX	wc;					// ウィンドウクラス構造体
	ZeroMemory(&wc, sizeof(wc));
	wc.cbSize		=sizeof(wc);
	wc.cbClsExtra	=0;
	wc.cbWndExtra	=sizeof(SIMPLEWINDOWINFO*);	// 補足ウィンドウメモリ
	wc.hInstance	=hInstance;
	wc.hIcon		=NULL;
	wc.hCursor		=NULL;
	wc.lpszMenuName	=NULL;					// メニューリソース名
	wc.hIconSm		=NULL;

	// ------- 通常のウィンドウ(ネズミ色) -------
	wc.style		=CS_HREDRAW|CS_VREDRAW;
	wc.lpszClassName=s_lpWindowClassName;
	wc.lpfnWndProc	=LoterryWndProc;
	wc.hbrBackground=(HBRUSH)GetStockObject(LTGRAY_BRUSH);
	if(!RegisterClassEx(&wc))
		return FALSE;

	return TRUE;
}
void UnregisterWindowClass()
{
	UnregisterClass(s_lpWindowClassName, s_hInstanceHandle);
}


HRESULT	MessageLoop(HINSTANCE hInstance)
{
	SIMPLEWINDOWINFO	s_SimpleWindow;
	ZeroMemory(&s_SimpleWindow, sizeof(s_SimpleWindow));
	AllocAllData(&s_SimpleWindow);


	// ----- initialize
	if(!RegisterWindowClass(hInstance))
	{
		FreeAllData(&s_SimpleWindow);
		return 0;
	}


	if(::CreateWindowEx(0, s_lpWindowClassName, "Simple Window"
						, WS_OVERLAPPEDWINDOW| WS_CLIPCHILDREN| WS_VISIBLE|WS_POPUP,
						0, 0, 600, 400, NULL,
						NULL, s_hInstanceHandle, &s_SimpleWindow)==NULL)
	{
		UnregisterWindowClass();
		FreeAllData(&s_SimpleWindow);
		return E_OUTOFMEMORY;
	}

	MSG	msg;
	while(::GetMessage(&msg, NULL,NULL,NULL))
	{
		::TranslateMessage(&msg);
		::DispatchMessage(&msg);
	}
	::TranslateMessage(&msg);
	::DispatchMessage(&msg);


	// ----- release
	UnregisterWindowClass();

	FreeAllData(&s_SimpleWindow);
	return S_OK;
}



int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
					LPSTR lpszCommandLine, int nCmdShow)
{

	MessageLoop(hInstance);

	return 0;
}