连连看算法,我的一种实现
来源:互联网 发布:android读取串口数据 编辑:程序博客网 时间:2024/05/22 05:33
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <sys/time.h>
using namespace std;
struct Point
{
int iX;
int iY;
int iKind;
Point( ) : iX( 0 ), iY( 0 ),iKind( 0 )
{
}
Point( int x, int y ) : iX( x ), iY( y ),iKind( 0 )
{
}
};
bool canConnectDirect( const Point& p1, const Point& p2,
int iMaxCol, int iMaxRow, Point * pstArr )
{
bool bFound = false;
if ( p2.iX == p1.iX )
{
// 横坐标相同,看iY
// 向上
int i = p1.iY - 1;
int iP1X = p1.iX;
for ( ; i >= 1 ; --i )
{
if ( pstArr[ iP1X + i * ( iMaxCol + 2 ) ].iKind > 0 )
{
if ( i == p2.iY )
{
bFound = true;
}
break;
}
}
if ( !bFound )
{
// 向下
i = p1.iY + 1;
int iP1X = p1.iX;
for ( ; i <= iMaxRow ; ++i )
{
if ( pstArr[ iP1X + i * ( iMaxCol + 2 ) ].iKind > 0 )
{
if ( i == p2.iY )
{
bFound = true;
}
break;
}
}
}
}
else if ( p2.iY == p1.iY )
{
// 纵坐标相同,看iX
// 向左
int j = p1.iX - 1 ;
int iP1Y = p1.iY;
for ( ; j >= 1 ; --j )
{
if ( pstArr[ j + iP1Y * ( iMaxCol + 2 ) ].iKind > 0 )
{
if ( j == p2.iX )
{
bFound = true;
}
break;
}
}
if ( !bFound )
{
// 向右
j = p1.iX + 1 ;
for ( ; j <= iMaxCol ; ++j )
{
if ( pstArr[ j + iP1Y * ( iMaxCol + 2 ) ].iKind > 0 )
{
if ( j == p2.iX )
{
bFound = true;
}
break;
}
}
}
}
return bFound;
}
int getAllConnectPoint( const Point& p1, int iMaxCol,
int iMaxRow, Point * pstArr, set<int>& setDirect,
const set<int>& setDetected )
{
// 向左
int j = p1.iX - 1 ;
int iP1Y = p1.iY;
for ( ; j >= 0 ; --j )
{
if ( pstArr[ j + iP1Y * ( iMaxCol + 2 ) ].iKind > 0 )
{
break;
}
else
{
int iSetPos = j * 10000 + iP1Y;
if ( setDetected.empty()
|| setDetected.find( iSetPos ) == setDetected.end() )
{
setDirect.insert( iSetPos );
}
}
}
// 向右
j = p1.iX + 1 ;
for ( ; j <= iMaxCol + 1 ; ++j )
{
if ( pstArr[ j + iP1Y * ( iMaxCol + 2 ) ].iKind > 0 )
{
break;
}
else
{
int iSetPos = j * 10000 + iP1Y;
if ( setDetected.empty()
|| setDetected.find( iSetPos ) == setDetected.end() )
{
setDirect.insert( iSetPos );
}
}
}
// 向上
int i = p1.iY - 1;
int iP1X = p1.iX;
for ( ; i >= 0 ; --i )
{
if ( pstArr[ iP1X + i * ( iMaxCol + 2 ) ].iKind > 0 )
{
break;
}
else
{
int iSetPos = iP1X * 10000 + i;
if ( setDetected.empty()
|| setDetected.find( iSetPos ) == setDetected.end() )
{
setDirect.insert( iSetPos );
}
}
}
// 向下
i = p1.iY + 1;
iP1X = p1.iX;
for ( ; i <= iMaxRow + 1 ; ++i )
{
if ( pstArr[ iP1X + i * ( iMaxCol + 2 ) ].iKind > 0 )
{
break;
}
else
{
int iSetPos = iP1X * 10000 + i;
if ( setDetected.empty()
|| setDetected.find( iSetPos ) == setDetected.end() )
{
setDirect.insert( iSetPos );
}
}
}
}
void printSet( const set<int>& curSet )
{
set<int>::const_iterator itr = curSet.begin();
for ( ; itr != curSet.end(); ++itr )
{
cout << "(" << *itr / 10000 << "," << *itr % 10000 << ")"<< "\t";
}
cout << endl;
}
bool canConnect( const Point& p1, const Point& p2,
int iMaxCol, int iMaxRow, Point * pstArr )
{
// 直接连通的情况
bool bCan = canConnectDirect( p1, p2, iMaxCol, iMaxRow, pstArr );
if ( bCan )
{
return bCan;
}
// 看拐一个弯,1级连通的情况
set<int> setDetected;
set<int> setP1Direct;
getAllConnectPoint( p1, iMaxCol, iMaxRow,
pstArr, setP1Direct, setDetected );
if ( setP1Direct.empty() )
{
return false;
}
//cout << "P1 : ( " << p1.iX << "," << p1.iY << " )'s set is "<< endl;
//printSet( setP1Direct );
set<int> setP2Direct;
getAllConnectPoint( p2, iMaxCol, iMaxRow,
pstArr, setP2Direct, setDetected );
if ( setP2Direct.empty() )
{
return false;
}
//cout << "P2: ( " << p2.iX << "," << p2.iY << " )'s set is "<< endl;
//printSet( setP2Direct );
// 取交集
set<int> interSet;
set<int>::iterator itr = interSet.begin();
set_intersection( setP1Direct.begin(), setP1Direct.end(),
setP2Direct.begin(), setP2Direct.end(), inserter( interSet, itr ) );
if ( ! interSet.empty() )
{
return true;
}
setDetected = setP1Direct;
// 1级连不同,看拐两个弯,2级连通的情况
set<int>::iterator itr1 = setP1Direct.begin();
set<int> setTmp;
for ( ; itr1 != setP1Direct.end(); ++itr1 )
{
setTmp.clear();
getAllConnectPoint( Point( *itr1 / 10000, *itr1 % 10000 ) , iMaxCol, iMaxRow,
pstArr, setTmp, setDetected );
if ( setTmp.empty() )
{
continue;
}
//cout << "itr1: ( " << *itr1 / 10000 << "," << *itr1 % 10000 << " )'s set is "<< endl;
//printSet( setTmp );
itr = interSet.begin();
set_intersection( setTmp.begin(), setTmp.end(),
setP2Direct.begin(), setP2Direct.end(), inserter( interSet, itr ) );
if ( ! interSet.empty() )
{
return true;
}
setDetected.insert( setTmp.begin(), setTmp.end() );
}
return false;
}
bool printArr( int iWidth, int iHeight, Point * pstArr )
{
int iCol = 1;
int iRow = 1;
for ( iRow = 1; iRow <= iHeight; ++iRow )
{
for ( iCol = 1; iCol <= iWidth; ++iCol )
{
cout << pstArr[ iCol + iRow * ( iWidth + 2 ) ].iKind << "\t";
}
cout << endl;
}
}
int main( int argc , char **argv )
{
int iWidth = 10;
int iHeight = 10;
int i = 0;
Point * pstArr = new Point[ ( iWidth + 2 ) * ( iHeight + 2 ) ];
map<int, Point*> mapPt;
int iMaxKind = 15;
int iCol = 0;
int iRow = 0;
int iKind = 0;
srand( time( NULL ) );
struct timeval tvStart, tvEnd;
gettimeofday( &tvStart, NULL );
for ( int iRunCount = 0; i < atoi( argv[1] ) ; ++i )
{
// 随机生成一个连连看棋局
// 1 - width 为col的取值范围 1 - height 为 row的取值范围
for ( iCol = 1; iCol <= iWidth ; ++iCol )
{
for ( iRow = 1; iRow <= iHeight ; ++iRow )
{
int iCurPos = iCol + iRow * ( iWidth + 2 );
if ( pstArr[ iCurPos ].iKind > 0 )
{
continue;
}
iKind = rand() % iMaxKind + 1;
pstArr[ iCurPos ].iX = iCol;
pstArr[ iCurPos ].iY = iRow;
pstArr[ iCurPos ].iKind = iKind;
int iResultCol = rand() % iWidth + 1 ;
int iResultRow = rand() % iHeight + 1 ;
while ( pstArr[ iResultCol + iResultRow * ( iWidth + 2 ) ].iKind != 0 )
{
iResultCol = rand() % iWidth + 1 ;
iResultRow = rand() % iHeight + 1 ;
}
int iArrPos = 0;
iArrPos = iResultCol + iResultRow * ( iWidth + 2 );
pstArr[ iArrPos ].iX = iResultCol;
pstArr[ iArrPos ].iY = iResultRow;
pstArr[ iArrPos ].iKind = iKind;
//cout << "iPos is " << iCol << "," << iRow << ", result is " << iResultCol << "," << iResultRow << endl;
}
}
//printArr( iWidth, iHeight, pstArr );
//cout << "===========================================" << endl;
int iEraseCount = 1;
map<int, set<Point*> > mapKind;
// 将所有的同花色的位置,保存到一个map中,为的是下面匹配的时候只在同花色之间进行匹配
for ( iRow = 1; iRow <= iHeight; ++iRow )
{
for ( iCol = 1; iCol <= iWidth; ++iCol )
{
//cout << " iCol + iRow * ( iWidth + 2 ) is " << iCol + iRow * ( iWidth + 2 ) << endl;
int iArrPos = iCol + iRow * ( iWidth + 2 );
int iKind = pstArr[ iArrPos ].iKind;
if ( iKind > 0 )
{
//cout << "map Kind:" << iKind << " insert ( " << iCol << "," << iRow << ")" << endl;
mapKind[ iKind ].insert( &( pstArr[ iArrPos ] ) );
}
}
}
Point stEmpty;
// 循环匹配,直到没有可以匹配的花色为止,如果此时仍然有不为0的为止,则表示死锁了
for ( ; iEraseCount > 0 ; )
{
iEraseCount = 0;
for ( iCol = 1; iCol <= iWidth; ++iCol )
{
for ( iRow = 1; iRow <= iHeight; ++iRow )
{
//cout << " iCol + iRow * ( iWidth + 2 ) is " << iCol + iRow * ( iWidth + 2 ) << endl;
int iArrPos = iCol + iRow * ( iWidth + 2 );
int iCurKind = pstArr[ iArrPos ].iKind;
if ( iCurKind > 0 )
{
// 找到同花色的为止链表
set<Point*>& curSet = mapKind[ iCurKind ];
if ( curSet.size() > 1 )
{
set<Point*>::iterator itr = curSet.begin();
bool bErased = false;
// 和当前位置iArrPos看能否连上,每次只连一个
for ( ; itr != curSet.end() ; )
{
if ( *itr == &pstArr[ iArrPos ] )
{
++itr;
continue;
}
bool bConnect = canConnect( pstArr[ iArrPos ],
*( *itr ), iWidth, iHeight, pstArr );
if ( bConnect )
{
bErased = true;
++iEraseCount;
/*
cout << "Point ( " << iCol << "," << iRow << ") and Point ( "
<< (*itr)->iX << ","
<< (*itr)->iY << ") can connect " << endl;
*/
*( *itr ) = stEmpty;
// 每次只清除和当前位置对应的1个位置
curSet.erase( itr );
break;
}
else
{
itr++;
}
}
if ( bErased )
{
// 删除了对应的pos
pstArr[ iArrPos ] = stEmpty;
curSet.erase( &pstArr[ iArrPos ] );
}
}
}
}
}
//cout << "after one loop" << endl;
}
}
//printArr( iWidth, iHeight, pstArr );
gettimeofday( &tvEnd, NULL );
int iCost = ( tvEnd.tv_sec - tvStart.tv_sec ) * 1000 + ( tvEnd.tv_usec - tvStart.tv_usec ) / 1000;
cout << argv[1] << " times cost " << iCost << " ms " << endl;
delete [] pstArr;
return 0;
}
./a.out 3000
gdb ./a.out core
- 连连看算法,我的一种实现
- j2me 实现连连看的算法
- java 实现 连连看的算法
- 对连连看一种算法的分析与思考
- 《连连看》的算法!
- 【游戏算法之连连看】我最开始想到的连连看的 消除算法。。。。。
- 【游戏算法之连连看】我最开始想到的连连看的 消除算法。。。。。【补充】
- 连连看的实现
- 连连看算法(控制台实现)
- Android 连连看的算法
- 连连看消除算法的C++代码实现
- 连连看 代码的实现
- 连连看游戏的实现
- android游戏开发之我的小小游戏2——连连看游戏3连连看算法1
- android游戏开发之我的小小游戏2——连连看游戏4连连看算法2
- android游戏开发之我的小小游戏2——连连看游戏5连连看算法3
- 简单的连连看的算法
- 连连看算法的一个思路
- Guid
- Pro Android学习笔记(五四):调试和分析(2):View层次结构
- 关于request.getHeader("Referer")的说明
- MongoDB阅读精要分析
- 第十周上机实践项目——乘法口诀表。
- 连连看算法,我的一种实现
- x264 自适应量化模式 (AQ Adaptive Quantization) 初探
- Java7 安全机制和自签名证书的使用
- 引用动态库libxxx.so中的func的方法
- loaded the "BlueView" nib but the view outlet was not set 错误的解决办法。
- linux 输出正确或错误信息到文件 1> 或 2>>
- hierarchyviewer 用法
- clientabortexception:IOException
- c#中public private protected internal 的区别