日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MFC随机博弈黑白棋

發(fā)布時(shí)間:2024/7/19 编程问答 69 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MFC随机博弈黑白棋 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

隨機(jī)博弈黑白棋

隨機(jī)博弈黑白棋

TxyITxs | 隨機(jī)博弈黑白棋 | 2019.04.21

摘要

通過隨機(jī)落子,實(shí)現(xiàn)黑白棋的博弈。無任何落子規(guī)則,棋子死活與圍棋中棋子的死活一致,即存在至少一口氣。動(dòng)態(tài)模擬雙方博弈,但棋盤無落子位置時(shí)停止。

設(shè)計(jì)思路

主要基于時(shí)鐘來實(shí)現(xiàn)動(dòng)態(tài)博弈,考慮博弈的持續(xù)性數(shù)據(jù)修改,黑白雙方需要互斥訪問數(shù)據(jù)以及正確界面繪制,通過設(shè)置兩個(gè)時(shí)鐘,一個(gè)時(shí)鐘主要負(fù)責(zé)界面背景,棋盤網(wǎng)格,黑白棋子繪制,繪制完后,釋放數(shù)據(jù)使用權(quán);另一個(gè)時(shí)鐘主要負(fù)責(zé)博弈落子(即修改數(shù)據(jù)),通過在可落子位置隨機(jī)選擇一個(gè),然后釋放數(shù)據(jù)使用權(quán)。

棋盤數(shù)據(jù)使用N*N大小的一維數(shù)組Tdata存儲(chǔ),棋子坐標(biāo)(x,y)對(duì)應(yīng)的數(shù)組通過x*N+y計(jì)算。棋盤所用可落子位置通過向量vector<CPoint>Tpos來存儲(chǔ),通過隨機(jī)產(chǎn)生一個(gè)索引來得到一個(gè)落子位置,然后將該索引對(duì)應(yīng)Tpos的位置刪除,修改Tdata中對(duì)應(yīng)位置的值。

1. UI設(shè)計(jì)

1.1 利用基于對(duì)環(huán)框的MFC程序框架來搭建UI界面,主要涉及到界面背景色繪制,棋盤網(wǎng)格繪制,以及通過訪問數(shù)據(jù)繪制棋子。

1.2 棋盤背景繪制

void TChessBgUI(CClientDC *dc)

{

CPen pen(PS_SOLID, 1, RGB(0, 0, 0));

CBrush *pbrush = CBrush::FromHandle((HBRUSH)GetStockObject(GRAY_BRUSH));

dc->SelectObject(&pen);

dc->SelectObject(pbrush);

CRect bg;

GetClientRect(bg);

dc->FillRect(bg, pbrush);

}

1.3 棋盤網(wǎng)格繪制,繪制的起始位置CPoint Tst,繪制的結(jié)束位置CpointTed,網(wǎng)格間距Tchline,網(wǎng)格的大小N*N。

void TChessUI(CClientDC *dc)

{

CPen pen(PS_SOLID, 1, RGB(0, 0, 0));

dc->SelectObject(&pen);

for (int i = Tst.x; i <= Ted.x; i += Tchline)

{

dc->MoveTo(i, Tst.y);

dc->LineTo(i, Ted.y);

}?????????????

for (int j = Tst.y; j <= Ted.y; j += Tchline)

{

dc->MoveTo(Tst.x, j);

dc->LineTo(Ted.x, j);

}

}

?

1.4 繪制棋子

void TshowLayout(CClientDC *dc)

{

CPen pen(PS_SOLID, 1, RGB(0, 0, 0));

CBrush *pbrush = NULL;

dc->SelectObject(&pen);

int PieceSize = 10;

for (int i = 0; i < Tcount; i++)

{

for (int j = 0; j < Tcount; j++)

{

??????? if (Tdata[i*Tcount + j] ==1)

??????? {

?????????????? pbrush = CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH));

??????? dc->SelectObject(pbrush);

??????? dc->Ellipse(Tst.x+Tchline*i-PieceSize, Tst.y+Tchline *j- PieceSize, Tst.x + Tchline*i + PieceSize, Tst.y + Tchline *j + PieceSize);

??????? }

??????? if (Tdata[i*Tcount + j] == -1)

??????? {

?????????????? pbrush = CBrush::FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH));

??????? dc->SelectObject(pbrush);

??????? dc->Ellipse(Tst.x + Tchline*i - PieceSize, Tst.y + Tchline *j - PieceSize, Tst.x + Tchline*i + PieceSize, Tst.y + Tchline *j + PieceSize);

??????? }

}

}

}

2.數(shù)據(jù)存儲(chǔ)

? 2.1 全局變量,需要初始化。

vector<int> Tdata;數(shù)值0、1、-1,0代表該位置為空,1代表白棋,-1代表黑棋

?????? vector<CPoint> Tpos;棋盤可落子位置

?????? int Tcount =19;棋盤大小

?????? int Tchline = 30;網(wǎng)格間距

?????? CPoint? Tst;棋盤起始位置

?????? CPoint Ted;1棋盤結(jié)束位置

?????? int Twhite = -1;先手指示器

?????? bool Ttime = false;時(shí)鐘調(diào)度指示器

3.博弈算法

3.1 隨機(jī)落子模擬

void SimulationData()

{

default_random_engine dre;//隨機(jī)數(shù)引擎

dre.seed((unsigned)time(NULL));

int pos = -1;

if(!Tpos.empty())

{

pos = dre() % Tpos.size();

if (Twhite==1)

{

??????? Tdata[Tpos[pos].x*Tcount + Tpos[pos].y] = 1;

??????? Twhite = -Twhite;//此時(shí)指示需提子的棋子顏色,以及下次落子的顏色

}

else if(Twhite == -1)

{

??????? Tdata[Tpos[pos].x*Tcount + Tpos[pos].y] = -1;

??????? Twhite = -Twhite;

}

Tpos.erase(Tpos.begin() + pos);

}

}

?

隨機(jī)索引位置的產(chǎn)生,利用C++ 11新特性,使用隨機(jī)數(shù)random類來產(chǎn)生,頭文件#include<random>。

?

?

?

3.2 ?提子過程,將棋盤上Twhite指示的棋子的死子提出,增加棋盤落子可用位置;

?

void grape()

{

if (Twhite == 0)return;

else

{

vector<CPoint> grap;

vector<bool> visi;

visi.resize(Tcount*Tcount, false);

grap.clear();

for (int i = 0; i < Tcount; i++)

{

??????? for (int j = 0; j < Tcount; j++)

??????? {

?????????????? if (Tdata[i*Tcount + j] == Twhite)

?????????????? {

???????????????????visi.resize(Tcount*Tcount, false);??

? ? ? ? ? ? ? ? ? ? if (TisLive(i, j,visi) == false)

????????????????????? ?????? grap.push_back(CPoint(i, j));

?????????????? }

??????? }

}

while (!grap.empty())

{

??????? CPoint p=grap.front();

??????? Tdata[p.x*Tcount+p.y] = 0;

??????? Tpos.push_back(p);

??????? grap.erase(grap.begin());

}

}

?}

?

3.3 提子過程需要判斷棋子的死活,利用深度搜索算法,判斷棋子s(x,y)的死活,則需判斷其四鄰接棋子的死活,若s,為活棋,無需提子,返回ture,若s為死棋,則返回false;通過遞歸來實(shí)現(xiàn)。

bool TisLive(unsigned int i, unsigned int j, vector<bool>& visi)

{

if (i<0 || i>Tcount || j<0 || j>Tcount)

?????? ?????? return false;

?????? else if (Tdata[i*Tcount + j] == -Twhite)

?????? {

????????????? return false;

?????? }

?????? else if (Tdata[i*Tcount + j] == 0)

?????? {

????????????? return true;

?????? }

?????? else if(Tdata[i*Tcount+j]==Twhite&&visi[i*Tcount + j]==false)

?????? {

????????????? visi[i*Tcount + j] = true;

????????????? if (TisLive(i - 1, j,visi))

return true;

????????????? if(TisLive(i, j - 1, visi))

?return true;

????????????? if(TisLive(i+1, j, visi))??

return true;

????????????? if(TisLive(i , j+ 1, visi))

?return true;

?????? }

??????

?? ??? ?else return false;
?? ??? ?return false;

????? }

3.4 onTimer函數(shù)

? ? ? ?在初始化函數(shù)中設(shè)置兩個(gè)時(shí)鐘;

???? ?SetTimer(0, 1000, NULL);
? ? ? SetTimer(1, 10, NULL);

? ? ? ?兩個(gè)時(shí)鐘總用一個(gè)onTimer,通過nIDEvent來識(shí)別執(zhí)行此函數(shù)的時(shí)鐘。一個(gè)時(shí)鐘負(fù)責(zé)UI繪制,一個(gè)時(shí)鐘模擬數(shù)據(jù)變化。

void CWhiteBlackChessDlg::OnTimer(UINT_PTR nIDEvent)
{

?? ?CClientDC dc(this);
?? ?switch (nIDEvent)
?? ?{
?? ?case 0:
?? ?{
?? ??? ?if (Ttime)
?? ??? ?{?? ?
?? ??? ??? ??? ?SimulationData();
?? ??? ??? ??? ?grape();
?? ??? ??? ??? ?Ttime = false;
?? ??? ?}
?? ?}
?? ??? ?break;
?? ?case 1:
?? ?{?? ?
?? ??? ?
?? ??? ?if (!Ttime)
?? ??? ?{?? ??? ?
?? ??? ??? ?TChessBgUI(&dc);
?? ??? ??? ?TChessUI(&dc);
?? ??? ??? ?TshowLayout(&dc);
?? ??? ??? ?Ttime = true;?? ??? ?
?? ??? ??? ?if (Tpos.empty())
?? ??? ??? ?{
?? ??? ??? ??? ?KillTimer(0);?? ?
?? ??? ??? ??? ?KillTimer(1);
?? ??? ??? ?}
?? ??? ?}
?? ?}break;
?? ?default:break;
?? ?}
?? ?CDialogEx::OnTimer(nIDEvent);
}

?

3.5 初始化函數(shù)

void TInit()
?? ?{
?? ??? ?Tdata.resize(Tcount*Tcount,0);
?? ??? ?Tpos.resize(Tcount*Tcount);
?? ??? ?Tst.SetPoint(30, 30);
?? ??? ?Ted.SetPoint(Tchline * Tcount, Tchline * Tcount);
?? ??? ?for (int i = 0; i < Tcount; i++)
?? ??? ?{
?? ??? ??? ?for (int j = 0; j < Tcount; j++)
?? ??? ??? ??? ?Tpos[i*Tcount + j] = CPoint(i, j);
?? ??? ?}
?? ?}

總結(jié)

  • 在實(shí)踐過程中,動(dòng)態(tài)模擬的持續(xù)性,采用面向過程的算法設(shè)計(jì)思路,常常導(dǎo)致程序阻塞,因?yàn)閯?dòng)態(tài)模擬需要使用循環(huán),這可能導(dǎo)致數(shù)據(jù)一直動(dòng)態(tài)修改,由于循環(huán),導(dǎo)致無法執(zhí)行到界面繪制代碼,界面的控制信息無法捕捉和執(zhí)行,鑒于這種情況,可以采用時(shí)鐘或者多線程來實(shí)現(xiàn)。
  • UI界面采用了模塊化設(shè)計(jì)思路,對(duì)程序的復(fù)用提供了可能;
  • 可以利用該框架,重寫提子或落子函數(shù),模擬自然界中的動(dòng)態(tài)變化現(xiàn)象,可以通過直觀UI看到變化情況。
  • 目前程序尚不完善。
  • ?

    總結(jié)

    以上是生活随笔為你收集整理的MFC随机博弈黑白棋的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。