分享
 
 
 

井字过三关(算法分析)

王朝other·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

井字过三关算法分析

思路分析:

1。游戏解析:算法轮流画X和O,知道有一方出现横竖斜的3个X或O,或者全部摆满都没有分出胜负。那么如何判断胜负呢?我们就设置一个IsWinner的函数吧。在#define EX 1 #define OH 2 而把所有网格状态存储在一个数组m_nGameGrid,初始化为0,而有画X时就记录为EX,画O时就记录为EO。这样使用下面的函数就可以判断胜负了。

int IsWinner ()

{

static int nPattern[8][3] = {

0, 1, 2,

3, 4, 5,

6, 7, 8,

0, 3, 6,

1, 4, 7,

2, 5, 8,

0, 4, 8,

2, 4, 6

};

for (int i=0; i<8; i++) {

if ((m_nGameGrid[nPattern[i][0]] == EX) &&

(m_nGameGrid[nPattern[i][1]] == EX) &&

(m_nGameGrid[nPattern[i][2]] == EX))

return EX;

if ((m_nGameGrid[nPattern[i][0]] == OH) &&

(m_nGameGrid[nPattern[i][1]] == OH) &&

(m_nGameGrid[nPattern[i][2]] == OH))

return OH;

}

return 0;

}

2。使用左键点击出现X,右键点击出现O。在每次点击的时候都要判断是出现结局了,是否可以画,是应该画哪个?

这样就应该记录下一个应该画的符合,使用变量m_nNextChar,因此,点击右键的时候,就把EO和m_nNextChar对比,同时判断m_nGameGrid[i]是否为0(是否已经画过)

3。为了知道点击的位置在那个区域,应该保存其中的9个区域,如

const CRect m_rcSquares[9] = {

CRect ( 16, 16, 112, 112),

CRect (128, 16, 224, 112),

CRect (240, 16, 336, 112),

CRect ( 16, 128, 112, 224),

CRect (128, 128, 224, 224),

CRect (240, 128, 336, 224),

CRect ( 16, 240, 112, 336),

CRect (128, 240, 224, 336),

CRect (240, 240, 336, 336)

};

这样就可以使用GetRectID (CPoint point)来取得点所在的网格。可以使用PtInRect函数,如

for (int i=0; i<9; i++) {

if (m_rcSquares[i].PtInRect (point))

return i;

}

这样就可以知道是在0~8中的哪个网格。

4。思路应该挺清楚的吧!再来看看:程序初始化->点击(左键或者右键)->判断在哪个网格->是否可以画(是否已画?没画但是画错?)->画图->判断是否结束->如果没结束,继续点击。。。。

5。完整的代码(不是完美的代码!):

头文件:TicTac.h

#define EX 1

#define OH 2

class CMyApp : public CWinApp

{

public:

virtual BOOL InitInstance ();

};

class CMainWindow : public CWnd

{

protected:

static const CRect m_rcSquares[9]; // Grid coordinates

int m_nGameGrid[9]; // Grid contents

int m_nNextChar; // Next character (EX or OH)

int GetRectID (CPoint point);

void DrawBoard (CDC* pDC);

void DrawX (CDC* pDC, int nPos);

void DrawO (CDC* pDC, int nPos);

void ResetGame ();

void CheckForGameOver ();

int IsWinner ();

BOOL IsDraw ();

public:

CMainWindow ();

protected:

virtual void PostNcDestroy ();

afx_msg void OnPaint ();

afx_msg void OnLButtonDown (UINT nFlags, CPoint point);

afx_msg void OnLButtonDblClk (UINT nFlags, CPoint point);

afx_msg void OnRButtonDown (UINT nFlags, CPoint point);

DECLARE_MESSAGE_MAP ()

};

源文件:TicTac.cpp

#include <afxwin.h>

#include "TicTac.h"

CMyApp myApp;

/////////////////////////////////////////////////////////////////////////

// CMyApp member functions

BOOL CMyApp::InitInstance ()

{

m_pMainWnd = new CMainWindow;

m_pMainWnd->ShowWindow (m_nCmdShow);

m_pMainWnd->UpdateWindow ();

return TRUE;

}

/////////////////////////////////////////////////////////////////////////

// CMainWindow message map and member functions

BEGIN_MESSAGE_MAP (CMainWindow, CWnd)

ON_WM_PAINT ()

ON_WM_LBUTTONDOWN ()

ON_WM_LBUTTONDBLCLK ()

ON_WM_RBUTTONDOWN ()

END_MESSAGE_MAP ()

const CRect CMainWindow::m_rcSquares[9] = {

CRect ( 16, 16, 112, 112),

CRect (128, 16, 224, 112),

CRect (240, 16, 336, 112),

CRect ( 16, 128, 112, 224),

CRect (128, 128, 224, 224),

CRect (240, 128, 336, 224),

CRect ( 16, 240, 112, 336),

CRect (128, 240, 224, 336),

CRect (240, 240, 336, 336)

};

CMainWindow::CMainWindow ()

{

m_nNextChar = EX;

::ZeroMemory (m_nGameGrid, 9 * sizeof (int));

//

// Register a WNDCLASS.

//

CString strWndClass = AfxRegisterWndClass (

CS_DBLCLKS, // Class style

AfxGetApp ()->LoadStandardCursor (IDC_ARROW), // Class cursor

(HBRUSH) (COLOR_3DFACE + 1), // Background brush

AfxGetApp ()->LoadStandardIcon (IDI_WINLOGO) // Class icon

);

//

// Create a window.

//

CreateEx (0, strWndClass, _T ("Tic-Tac-Toe"),

WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,

CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL);

//

// Size the window.

//

CRect rect (0, 0, 352, 352);

CalcWindowRect (&rect);

SetWindowPos (NULL, 0, 0, rect.Width (), rect.Height (),

SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);

}

void CMainWindow::PostNcDestroy ()

{

delete this;

}

void CMainWindow::OnPaint ()

{

CPaintDC dc (this);

DrawBoard (&dc);

}

void CMainWindow::OnLButtonDown (UINT nFlags, CPoint point)

{

//

// Do nothing if it's O's turn, if the click occurred outside the

// tic-tac-toe grid, or if a nonempty square was clicked.

//

if (m_nNextChar != EX)

return;

int nPos = GetRectID (point);

if ((nPos == -1) || (m_nGameGrid[nPos] != 0))

return;

//

// Add an X to the game grid and toggle m_nNextChar.

//

m_nGameGrid[nPos] = EX;

m_nNextChar = OH;

//

// Draw an X on the screen and see if either player has won.

//

CClientDC dc (this);

DrawX (&dc, nPos);

CheckForGameOver ();

}

void CMainWindow::OnRButtonDown (UINT nFlags, CPoint point)

{

//

// Do nothing if it's X's turn, if the click occurred outside the

// tic-tac-toe grid, or if a nonempty square was clicked.

//

if (m_nNextChar != OH)

return;

int nPos = GetRectID (point);

if ((nPos == -1) || (m_nGameGrid[nPos] != 0))

return;

//

// Add an O to the game grid and toggle m_nNextChar.

//

m_nGameGrid[nPos] = OH;

m_nNextChar = EX;

//

// Draw an O on the screen and see if either player has won.

//

CClientDC dc (this);

DrawO (&dc, nPos);

CheckForGameOver ();

}

void CMainWindow::OnLButtonDblClk (UINT nFlags, CPoint point)

{

//

// Reset the game if one of the thick black lines defining the game

// grid is double-clicked with the left mouse button.

//

CClientDC dc (this);

if (dc.GetPixel (point) == RGB (0, 0, 0))

ResetGame ();

}

int CMainWindow::GetRectID (CPoint point)

{

//

// Hit-test each of the grid's nine squares and return a rectangle ID

// (0-8) if (point.x, point.y) lies inside a square.

//

for (int i=0; i<9; i++) {

if (m_rcSquares[i].PtInRect (point))

return i;

}

return -1;

}

void CMainWindow::DrawBoard (CDC* pDC)

{

//

// Draw the lines that define the tic-tac-toe grid.

//

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

CPen* pOldPen = pDC->SelectObject (&pen);

pDC->MoveTo (120, 16);

pDC->LineTo (120, 336);

pDC->MoveTo (232, 16);

pDC->LineTo (232, 336);

pDC->MoveTo (16, 120);

pDC->LineTo (336, 120);

pDC->MoveTo (16, 232);

pDC->LineTo (336, 232);

//

// Draw the Xs and Os.

//

for (int i=0; i<9; i++) {

if (m_nGameGrid[i] == EX)

DrawX (pDC, i);

else if (m_nGameGrid[i] == OH)

DrawO (pDC, i);

}

pDC->SelectObject (pOldPen);

}

void CMainWindow::DrawX (CDC* pDC, int nPos)

{

CPen pen (PS_SOLID, 16, RGB (255, 0, 0));

CPen* pOldPen = pDC->SelectObject (&pen);

CRect rect = m_rcSquares[nPos];

rect.DeflateRect (16, 16);

pDC->MoveTo (rect.left, rect.top);

pDC->LineTo (rect.right, rect.bottom);

pDC->MoveTo (rect.left, rect.bottom);

pDC->LineTo (rect.right, rect.top);

pDC->SelectObject (pOldPen);

}

void CMainWindow::DrawO (CDC* pDC, int nPos)

{

CPen pen (PS_SOLID, 16, RGB (0, 0, 255));

CPen* pOldPen = pDC->SelectObject (&pen);

pDC->SelectStockObject (NULL_BRUSH);

CRect rect = m_rcSquares[nPos];

rect.DeflateRect (16, 16);

pDC->Ellipse (rect);

pDC->SelectObject (pOldPen);

}

void CMainWindow::CheckForGameOver ()

{

int nWinner;

//

// If the grid contains three consecutive Xs or Os, declare a winner

// and start a new game.

//

if (nWinner = IsWinner ()) {

CString string = (nWinner == EX) ?

_T ("X wins!") : _T ("O wins!");

MessageBox (string, _T ("Game Over"), MB_ICONEXCLAMATION | MB_OK);

ResetGame ();

}

//

// If the grid is full, declare a draw and start a new game.

//

else if (IsDraw ()) {

MessageBox (_T ("It's a draw!"), _T ("Game Over"),

MB_ICONEXCLAMATION | MB_OK);

ResetGame ();

}

}

int CMainWindow::IsWinner ()

{

static int nPattern[8][3] = {

0, 1, 2,

3, 4, 5,

6, 7, 8,

0, 3, 6,

1, 4, 7,

2, 5, 8,

0, 4, 8,

2, 4, 6

};

for (int i=0; i<8; i++) {

if ((m_nGameGrid[nPattern[i][0]] == EX) &&

(m_nGameGrid[nPattern[i][1]] == EX) &&

(m_nGameGrid[nPattern[i][2]] == EX))

return EX;

if ((m_nGameGrid[nPattern[i][0]] == OH) &&

(m_nGameGrid[nPattern[i][1]] == OH) &&

(m_nGameGrid[nPattern[i][2]] == OH))

return OH;

}

return 0;

}

BOOL CMainWindow::IsDraw ()

{

for (int i=0; i<9; i++) {

if (m_nGameGrid[i] == 0)

return FALSE;

}

return TRUE;

}

void CMainWindow::ResetGame ()

{

m_nNextChar = EX;

::ZeroMemory (m_nGameGrid, 9 * sizeof (int));

Invalidate ();

}

6。呵呵,是不是很爽呢?

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有