⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stonehandler.cpp

📁 qgo-1.5.4-r3.tar.gz linux下一个很好玩的游戏
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/** stonehandler.cpp*/#include "stonehandler.h"#include "boardhandler.h"#include "group.h"#include "board.h"#include "imagehandler.h"#include <stdlib.h>StoneHandler::StoneHandler(BoardHandler *bh): boardHandler(bh){	CHECK_PTR(boardHandler);		stones = new QIntDict<Stone>(367);  // prime number larger than 361 (19*19)	// TODO: Dynamic for different board size?	stones->setAutoDelete(TRUE);		groups = new QPtrList<Group>;	groups->setAutoDelete(TRUE);		workingOnNewMove = false;}StoneHandler::~StoneHandler(){	clearData();	delete stones;	delete groups;}void StoneHandler::clearData(){	workingOnNewMove = false;	stones->clear();	groups->clear();}bool StoneHandler::addStone(Stone *stone, bool toAdd, bool doCheck, Matrix *m, bool koStone){//	CHECK_PTR(stone);//	CHECK_PTR(m);  	if (toAdd)		stones->insert(Matrix::coordsToKey(stone->posX(), stone->posY()), stone);		if (doCheck)		return checkPosition(stone, m, koStone);		return true;}bool StoneHandler::removeStone(int x, int y, bool hide){	if (!hasStone(x, y))		return false;		if (!hide)	{    // We delete the killed stones only if we want to update the board (i.e. : not if we are browsing the game)    if (boardHandler->getDisplay_incoming_move())             //SL added eb 9      if (!stones->remove(Matrix::coordsToKey(x, y)))	    {			   qWarning("   ***   Key for stone %d, %d not found!   ***", x, y);			   return false;		   }	}	else	{		Stone *s;		if ((s = stones->find(Matrix::coordsToKey(x, y))) == NULL)		{			qWarning("   ***   Key for stone %d, %d not found!   ***", x, y);			return false;		}		s->hide();	}		return true;}//  0 : no stone// -1 : hidden//  1 : shownint StoneHandler::hasStone(int x, int y){	Stone *s;		if ((s = stones->find(Matrix::coordsToKey(x, y))) == NULL)		return 0;		if (s->visible())		return 1;		return -1;}//bool StoneHandler::checkPosition(Stone *stone)bool StoneHandler::checkPosition(Stone *stone, Matrix *m, bool koStone){	//CHECK_PTR(stone); // CHECK_PTR(m); // SL added eb 8 	if (!stone->visible())		return true;		Group *active = NULL;		// No groups existing? Create one.	if (groups->isEmpty())	{		Group *g = assembleGroup(stone,m);		CHECK_PTR(g);		groups->append(g);		active = g;	}	// We already have one or more groups.	else	{		bool flag = false;		Group *tmp;				for (unsigned int i=0; i<groups->count(); i++)		{			tmp = groups->at(i);			//CHECK_PTR(tmp);						// Check if the added stone is attached to an existing group.			// If yes, update this group and replace the old one.			// If the stone is attached to two groups, remove the second group.			// This happens if the added stone connects two groups.			if (tmp->isAttachedTo(stone))			{				// Group attached to stone				if (!flag)				{					if (!groups->remove(i))						qFatal("StoneHandler::checkPosition(Stone *stone):"						"Oops, removing an attached group failed.");					active = assembleGroup(stone,m);					groups->insert(i, active);					flag = true;				}				// Groups connected, remove one				else				{					if (active != NULL && active == groups->at(i))						active = tmp;					if (!groups->remove(i))						qFatal("StoneHandler::checkPosition(Stone *stone): "						"Oops, removing a connected group failed.");					i--;				}			}		}				// The added stone isnt attached to an existing group. Create a new group.		if (!flag)		{			Group *g = assembleGroup(stone,m);			CHECK_PTR(g);			groups->append(g);			active = g;		}	}		// active->debug();			// Now we have to sort the active group as last in the groups QPtrList,	// so if this one is out of liberties, we beep and abort the operation.	// This prevents suicide moves.	groups->append(groups->take(groups->findRef(active)));		// Check the liberties of every group. If a group has zero liberties, remove it.	for (unsigned int i=0; i<groups->count(); i++)	{		Group *tmp = groups->at(i);		//CHECK_PTR(tmp); 		tmp->setLiberties(countLiberties(tmp, m));          //SL added eb 8    		// qDebug("Group #%d with %d liberties:", i, tmp->getLiberties());		// tmp->debug();				// Oops, zero liberties. 		if (tmp->getLiberties() == 0)		{			// Suicide move?			if (tmp == active)			{				if (active->count() == 1)				{					groups->remove(i);					removeStone(stone->posX(), stone->posY(), false);				}				return false;			}						//was it a forbidden ko move ?			if ((tmp->count() == 1) && koStone && ((countLiberties(active, m) == 0)))			{				active->debug();				groups->remove(groups->findRef(active));				removeStone(stone->posX(), stone->posY(), false);				return false ;			}			int stoneCounter = 0;						// Erase the stones of this group from the stones table.			QListIterator<Stone> it(*tmp);			for (; it.current(); ++it)			{				Stone *s = it.current();				CHECK_PTR(s);				if (workingOnNewMove)					boardHandler->updateCurrentMatrix(stoneNone, s->posX(), s->posY());				removeStone(s->posX(), s->posY());				stoneCounter ++;			}						// Remove the group from the groups list.			// qDebug("Oops, a group got killed. Removing killed group #%d", i);			if (tmp == active)				active = NULL;			if (!groups->remove(i))				qFatal("StoneHandler::checkPosition(Stone *stone): "				"Oops, removing a killed group failed.");			i--;						// Tell the boardhandler about the captures			boardHandler->setCaptures(stone->getColor(), stoneCounter);		}	}		return true;}Group* StoneHandler::assembleGroup(Stone *stone, Matrix *m){	if (stones->isEmpty())		qFatal("StoneHandler::assembleGroup(Stone *stone): No stones on the board!");		Group *group = new Group();	CHECK_PTR(group);	//	CHECK_PTR(stone);//  CHECK_PTR(m);                   //SL added eb 8	group->append(stone);		unsigned int mark = 0;		// Walk through the horizontal and vertical directions and assemble the	// attached stones to this group.	while (mark < group->count())	{		stone = group->at(mark);		// we use preferably the matrix		if ((m==NULL && stone->visible())|| (m!= NULL || m->at(stone->posX() - 1, stone->posY() - 1) != stoneNone ))		{			int stoneX = stone->posX(),				stoneY = stone->posY();			StoneColor col = stone->getColor();						// North			group = checkNeighbour(stoneX, stoneY-1, col, group,m);      //SL added eb 8						// West			group = checkNeighbour(stoneX-1, stoneY, col, group,m);       //SL added eb 8						// South			group = checkNeighbour(stoneX, stoneY+1, col, group,m);       //SL added eb 8						// East			group = checkNeighbour(stoneX+1, stoneY, col, group,m);        //SL added eb 8		}		mark ++;	}		return group;}Group* StoneHandler::checkNeighbour(int x, int y, StoneColor color, Group *group, Matrix *m) //SL added eb 8{//	CHECK_PTR(group);//	CHECK_PTR(m); //added eb 8  bool visible = false ;  int size = boardHandler->board->getBoardSize();     //end add eb 8  Stone *tmp = stones->find(Matrix::coordsToKey(x, y));    // Okay, this is dirty and synthetic :  // Because we use this function where the matrix can be NULL, we need to check this  // Furthermore, since this has been added after the first code, we keep the 'stone->visible' test where one should only use the 'matrix' code  if (m != NULL && x-1 >= 0 && x-1 < size && y-1 >= 0 && y-1 < size) //SL added eb 8   visible = (m->at(x - 1, y - 1) != stoneNone); //SL added eb 9 We do this in order not to pass a null matrix to the matrix->at function (seen in handicap games)  // again we priviledge matrix over stone visibility (we might be browsing a game)	if (tmp != NULL && tmp->getColor() == color && (tmp->visible()|| visible)) //SL added eb 8	{		if (!group->contains(tmp))		{			group->append(tmp);			tmp->checked = true;		}	}	return group;}int StoneHandler::countLiberties(Group *group, Matrix *m)     //SL added eb 8{//	CHECK_PTR(group);//	CHECK_PTR(m); // SL added eb 8  	int liberties = 0;	QValueList<int> libCounted;		// Walk through the horizontal and vertial directions, counting the	// liberties of this group.	for (unsigned int i=0; i<group->count(); i++)	{		Stone *tmp = group->at(i);		//CHECK_PTR(tmp);				int x = tmp->posX(),			y = tmp->posY();				// North		checkNeighbourLiberty(x, y-1, libCounted, liberties,m);        //SL added eb 8				// West		checkNeighbourLiberty(x-1, y, libCounted, liberties,m);         //SL added eb 8				// South		checkNeighbourLiberty(x, y+1, libCounted, liberties,m);          //SL added eb 8				// East		checkNeighbourLiberty(x+1, y, libCounted, liberties,m);         //SL added eb 8	}	return liberties;}void StoneHandler::checkNeighbourLiberty(int x, int y, QValueList<int> &libCounted, int &liberties, Matrix *m)    //SL added eb 8{	if (!x || !y)		return;		Stone *s;//  CHECK_PTR(m); // SL added eb 8  if (m==NULL) //added eb 8 -> we don't have a matrix passed here, so we check on the board  {	  if (x <= boardHandler->board->getBoardSize() && y <= boardHandler->board->getBoardSize() && x >= 0 && y >= 0 &&		  !libCounted.contains(100*x + y) &&  		((s = stones->find(Matrix::coordsToKey(x, y))) == NULL ||	  	!s->visible()))	  {		  libCounted.append(100*x + y);		  liberties ++;	  }  }    else                                        {    if (x <= boardHandler->board->getBoardSize() && y <= boardHandler->board->getBoardSize() && x >= 0 && y >= 0 &&	    !libCounted.contains(100*x + y) &&	    (m->at(x - 1, y - 1) == stoneNone ))         // ?? check stoneErase ?	  {		  libCounted.append(100*x + y);		  liberties ++;	  }            // end add eb 8  }}int StoneHandler::countLibertiesOnMatrix(Group *group, Matrix *m)    {	CHECK_PTR(group);	CHECK_PTR(m);		int liberties = 0;	QValueList<int> libCounted;		// Walk through the horizontal and vertial directions, counting the	// liberties of this group.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -