📄 computegame.cpp
字号:
// ComputeGame.cpp : implementation file
//
#include "stdafx.h"
#include "Game.h"
#include "ComputeGame.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CComputeGame dialog
//构造函数
CComputeGame::CComputeGame(CWnd* pParent /*=NULL*/)
: CDialog(CComputeGame::IDD, pParent)
{
//{{AFX_DATA_INIT(CComputeGame)
m_aPolicyNum = 0;
m_bPolicyNum = 0;
//}}AFX_DATA_INIT
// 双方博弈策略数目中间值
m_aMidPolicyNum = 0;
m_bMidPolicyNum = 0;
// 博弈均衡解的个数
m_gameResNum1 = 0;
m_gameResNum2 = 0;
}
void CComputeGame::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CComputeGame)
DDX_Control(pDX, IDC_AB_OPENCONFIG, m_abOpenConfig);
DDX_Text(pDX, IDC_A_POLICYNUM, m_aPolicyNum);
DDV_MinMaxInt(pDX, m_aPolicyNum, 1, 30);
DDX_Text(pDX, IDC_B_POLICYNUM, m_bPolicyNum);
DDV_MinMaxInt(pDX, m_bPolicyNum, 1, 30);
DDX_Control(pDX, IDC_GAMERESULT, m_gameResult);
DDX_Control(pDX, IDC_GAMEINPUT, m_gameInput);
DDX_Control(pDX,IDC_GameResult2,m_gameResult2);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CComputeGame, CDialog)
//{{AFX_MSG_MAP(CComputeGame)
ON_BN_CLICKED(IDC_AB_OPENCONFIG, OnAbOpenconfig)
ON_BN_CLICKED(IDC_CoputerCom, OnCoputerCom)
ON_BN_CLICKED(IDC_AB_COMPUTE, OnAbCompute)
ON_BN_CLICKED(IDC_Save, OnSave)
ON_BN_CLICKED(IDC_Set, OnSet)
ON_BN_CLICKED(IDC_AB_CLEAR, OnAbClear)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CComputeGame message handlers
//通过打开对话框,选择一个博弈文件,将博弈矩阵显示在博弈矩阵列表控制中
void CComputeGame::OnAbOpenconfig()
{
// TODO: Add your control notification handler code here
CString sourceFileName, gameSrc, gameItemText, gameLineStr;
int i, j, gameReadedBytes;
CFile gameFile;
// 定义打开对话框
CFileDialog openDlg(TRUE,"",NULL,OFN_HIDEREADONLY|
OFN_OVERWRITEPROMPT,
"NFG(*.nfg)|*.nfg|(All Files(*.*)|*.*||",NULL);
if(openDlg.DoModal() == IDOK)
{
// 获取选择的文件名
sourceFileName = openDlg.GetPathName();
// 打开的文件格是否正确
if(openDlg.GetFileExt().Compare("nfg") != 0)
AfxMessageBox("博弈矩阵文件格式不正确!");
else
{
//打开博弈文件
gameFile.Open(sourceFileName, CFile::modeRead);
gameReadedBytes = 0;
// 获取我方/敌方的策略数目
gameFile.SeekToBegin();
CFileReadLine(&gameFile, &gameLineStr);
//获得我方策略数
gameSrc = gameLineStr.Left(gameLineStr.Find("x"));
gameSrc = gameSrc.Right(gameSrc.GetLength() - gameSrc.ReverseFind(' ') - 1);
m_aPolicyNum = atoi(gameSrc.GetBuffer(gameSrc.GetLength()));
//获得敌方策略数
gameSrc = gameLineStr.Right(gameLineStr.GetLength() -
gameLineStr.Find("x") - 1);
gameSrc = gameSrc.Left(gameSrc.Find(" "));
m_bPolicyNum = atoi(gameSrc.GetBuffer(gameSrc.GetLength()));
UpdateData(FALSE);
// 根据我方/敌方的策略数目设置初始博弈矩阵
OnABConfig();
// 文件指针指向第二行数据
gameReadedBytes += gameLineStr.GetLength();
gameFile.Seek(gameReadedBytes, CFile::begin);
// 文件指针定位到博弈数据
while(CFileReadLine(&gameFile, &gameLineStr))
{
if(gameLineStr.Find(",") >= 0)
break;
else
{
gameReadedBytes += gameLineStr.GetLength();
gameFile.Seek(gameReadedBytes, CFile::begin);
}
}
// 读取博弈数据显示在LISTCTRL中
for(j = 1; j < m_bPolicyNum + 1; j++)
{
for(i = 0; i < m_aPolicyNum; i++)
{
if(CFileReadLine(&gameFile, &gameLineStr))
{
gameSrc = "";
gameItemText = "";
gameSrc = gameLineStr.Left(gameLineStr.Find(","));
gameSrc = gameSrc.Right(gameSrc.GetLength() - 5); //博弈数据1
gameItemText.Insert(gameItemText.GetLength(), gameSrc);
gameItemText.Insert(gameItemText.GetLength(), ",");
gameSrc = gameLineStr.Right(gameLineStr.GetLength() -
gameLineStr.Find(",") - 2);
gameSrc = gameSrc.Left(gameSrc.GetLength() - 3); //博弈数据2
gameItemText.Insert(gameItemText.GetLength(), gameSrc);
m_gameInput.SetItemText(i, j, gameItemText);
gameReadedBytes += gameLineStr.GetLength();
gameFile.Seek(gameReadedBytes, CFile::begin);
}
}
}
// 关闭博弈数据文件
gameFile.Close();
}
}
}
BOOL CComputeGame::OnInitDialog()
{
CDialog::OnInitDialog();
// 设置博弈输入为全行选择
m_gameInput.SetExtendedStyle(LVS_EX_FULLROWSELECT);
// 设置博弈输入LISTCTRL的单元格包含多个数据
m_gameInput.SetOneValueInEdit(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
// 读取博弈文件的一行数据
int CComputeGame::CFileReadLine(CFile* file, CString* string)
{
char tempBuf[15];
CString readStr;
int readNum, readedBytes, curPos;
char enterStr[2];
enterStr[0] = 0x0a;
enterStr[1] = '\0';
curPos = (int)file->GetPosition();
*string = "";
readedBytes = 0;
while((readNum = file->Read(tempBuf, 30)) >= 1)
{
readStr = "";
readStr.Insert(0, tempBuf);
if(readStr.Find(enterStr) < 0)
{
*string = *string + readStr;
readedBytes += readNum;
}
else
{
readStr = readStr.Left(readStr.Find(enterStr) + 1);
*string = *string + readStr;
break;
}
file->Seek(curPos + readedBytes, CFile::begin);
tempBuf[0] = '\0';
}
file->Seek(curPos, CFile::begin);
if(readStr.GetLength() >= 1)
return readStr.GetLength();
return 0;
}
// 删除博弈输入矩阵,即清除博弈矩阵控制列表中的内容
void CComputeGame::ClearGameInput()
{
UpdateData();
int i, j, delRowEnable, delColEnable;
CHeaderCtrl* pHeaderCtrl = m_gameInput.GetHeaderCtrl();
delRowEnable = 0;
delColEnable = 0;
if(m_aMidPolicyNum > 0) delRowEnable = 1;
if(m_bMidPolicyNum > 0) delColEnable = 1;
if(pHeaderCtrl != NULL)
{
if(pHeaderCtrl->GetItemCount() > 0)
delColEnable = 1;
}
// 删除博弈输入的所有行
if(delRowEnable > 0)
{
for(i = 0; i < m_aMidPolicyNum; i++)
{
m_gameInput.DeleteItem(m_gameInput.GetItemCount() - 1);
}
}
// 删除博弈输入的所有列
if(delColEnable > 0)
{
for(j = 0; j < m_bMidPolicyNum + 1; j++)
{
m_gameInput.DeleteColumn(m_bMidPolicyNum - j);
}
}
}
// 根据我方及敌方的策略数设置初始的博弈矩阵
void CComputeGame::OnABConfig()
{
UpdateData();
// 清除已有的博弈输入
ClearGameInput();
int i, j;
CString colName, rowName, num, lines;
BOOL bRowColValid;
bRowColValid = FALSE;
//判断我方策略数和敌方策略数须是否越界(此处限制在30以内的正整数)
if((m_aPolicyNum >0 && m_aPolicyNum <= 30) &&
(m_bPolicyNum >0 && m_bPolicyNum <= 30))
bRowColValid = TRUE;
// 根据双方策略数设置博弈列表
if(bRowColValid)
{
// 增加行和列交叉项
m_gameInput.InsertColumn(0, _T("我方/敌方"), LVCFMT_CENTER, 75);
// 增加列
for(j = 1; j < m_bPolicyNum + 1; j++)
{
num.Format("%d", j);
colName = "策略" + num;
m_gameInput.InsertColumn(j, colName, LVCFMT_CENTER, 100);
}
// 增加行
for(i = 0; i < m_aPolicyNum; i++)
{
num.Format("%d", i + 1);
rowName = "策略" + num;
m_gameInput.InsertItem(i, rowName);
for(j = 1; j < m_bPolicyNum + 1; j++)
m_gameInput.SetItemText(i, j, "0,0");
}
// 设置博弈策略控件列表可在位编辑的列集合
for(j = 1; j < m_bPolicyNum + 1; j++)
{
num.Format("%d", j);
lines += num + ",";
}
m_gameInput.SetEditLines(lines);
// 记录本次设置的行和列值,用于下次完全删除所有的行和列
m_aMidPolicyNum = m_aPolicyNum;
m_bMidPolicyNum = m_bPolicyNum;
UpdateData();
}
}
//通过对敌我双方收益的比较,求解纳什均衡解
void CComputeGame::OnCoputerCom()
{
// TODO: Add your control notification handler code here
bool equ1,equ2;//判断是否是均衡解,两者都为真时为均衡解
double max;
EquNum=0;
CString num,colName;
GetCtrlListData();
//进行敌方双方的收益大小比较
for(int i=0;i<m_aPolicyNum;i++)
for(int j=0;j<m_bPolicyNum;j++)
{
equ1=true;
equ2=true;
//我方策略固定时,敌方采用不同策略时的收益大小比较
max=GameData[i][j][1];
for(int k=0;k<m_bPolicyNum;k++)
if(max<GameData[i][k][1])
{
equ1=false;
break ;
}
if(!equ1)
continue;
//敌方策略固定时,我方采用不同策略时的收益大小比较
max=GameData[i][j][0];
for(int l=0;l<m_aPolicyNum;l++)
if(max<GameData[l][j][0])
{
equ2=false;
break;
}
//某一局势为纳什均衡解时,保存我方策略号、敌方策略号
if((equ1 && equ2))
{
Equ[EquNum][0]=i+1;
Equ[EquNum][1]=j+1;
EquNum++;
}
}
//在比较方法纳什均衡解控制列表框中显示纳什均衡解
if(EquNum>0)
{
int i,j;
if(m_gameResNum1 > 0)
ClearGameResult();
// 增加博弈结果序号
m_gameResult.InsertColumn(0, _T("序号"), LVCFMT_CENTER, 60);
// 增加我方列集合
for(j = 0; j < m_aPolicyNum; j++)
{
num.Format("%d", j + 1);
colName = "我方策略" + num;
m_gameResult.InsertColumn(j + 1, colName, LVCFMT_CENTER, 100);
}
// 增加敌方列集合
for(j = 0; j < m_bPolicyNum; j++)
{
num.Format("%d", j + 1);
colName = "敌方策略" + num;
m_gameResult.InsertColumn(j + m_aPolicyNum + 1, colName, LVCFMT_CENTER, 100);
}
//显示纳什均衡解对应的敌我双方策略号(纳什均衡解对应的策略号其值为1,其他的为0)
for(i=0;i<EquNum;i++)
{
CString str;
str.Format("%d",i+1);
str="均衡"+str;
m_gameResult.InsertItem(i,str);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -