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

📄 checkers.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
字号:
/* Copyright (C) Peter Dalton, 2001. 
 * All rights reserved worldwide.
 *
 * This software is provided "as is" without express or implied
 * warranties. You may freely copy and compile this source into
 * applications you distribute provided that the copyright text
 * below is included in the resulting source code, for example:
 * "Portions Copyright (C) Peter Dalton, 2001"
 */
/***
 * File:   Checkers.cpp - Implements Checkers.h
 *         -----------------------------------------------------
 * Author: Peter Dalton
 * Date:   4/9/2001 3:33:00 PM
 *
 * Description:

 *
 */

#include <time.h>

#include "MemoryManager.h"
#include "Checkers.h"

/*******************************************************************************************/
/*******************************************************************************************/
// ***** Implementation of the Checkers Class

/**
 * Checkers::Checkers():
 *  Constructor.
 * 
 *  Return Type : 
 *  Arguments   : NONE
 */
Checkers::Checkers( void )
{
	m_board = new Board( false );
	m_redsTurn = true;

	m_redsEvalFunc   = BasicEvaluation;
	m_whitesEvalFunc = BasicEvaluation;

	m_redsAlgor   = PRUNNING;
	m_whitesAlgor = PRUNNING;

	m_redsPly   = 4;
	m_whitesPly = 4;

	for (int ii = 0; ii < 10; ++ii) {
		m_RedsLastMove[ii] = m_WhitesLastMove[ii] = 0;
	}
}

/*******************************************************************************************/

/**
 * Checkers::~Checkers():
 *  Destructor.
 * 
 *  Return Type : 
 *  Arguments   : NONE
 */
Checkers::~Checkers( void ) 
{
	delete m_board;
	PathList::releaseCacheMemory();
}

/*******************************************************************************************/

/**
 * Checkers::computerMove():
 *  This method instructs the computer to make a move.  Based upon the set heristics this
 *  method will call the appropriate routines to determine the best move to be made.  TRUE
 *  is returned if the computer made a move, otherwise FALSE is returned.  FALSE is only
 *  returned if the game is over or there is a stale mate condition.
 * 
 *  Return Type : bool 
 *  Arguments   : NONE
 */
bool Checkers::computerMove( void )
{
  if (gameOver() || staleMate()) { // generate all of the possible moves for red
		return false;      // No moves left to be made, stale mate or game over!!
	}

	pathValue path[MAX_PATHLEN];       // Used to hold the best path
	int value;                         // The value of the best path

	if (m_redsTurn) {
		if (m_redsAlgor == ITERATIVE) value = Iterative( m_board, path );
		else                          value = AlphaBeta( m_board, true, 0, m_redsPly, -99999, 99999, path );
	
		for (int ii = 0; ii <= path[0]; ++ii) {
			m_RedsLastMove[ii] = path[ii];
		}
	}
	else {
		if (m_redsAlgor == ITERATIVE) value = Iterative( m_board, path );
		else                          value = AlphaBeta( m_board, true, 0, m_whitesPly, -99999, 99999, path );

		for (int ii = 0; ii <= path[0]; ++ii) {
			m_WhitesLastMove[ii] = path[ii];
		}
	}

	int done = m_board->makeMove( path, m_redsTurn );  // Make the computer's move

	m_redsTurn = !m_redsTurn;
	return true;
} 

/*******************************************************************************************/
// ***** Private Member Methods

/**
 * Checkers::AlphaBeta():
 *  This method performs alpha beta search routines to determine the best move for the 
 *  computer to make.
 * 
 *  Return Type : int -> The value of the best path found throughout the search.
 *  Arguments   : 
 *  	Board* board  	 : The current game board.
 *  	bool myTurn	     : Whether or not it is my time, maximize the score.
 *  	int curPly	     : The current search ply.
 *  	int maxPly	     : The maximum search ply.
 *  	int alpha	       : The best move found so far.
 *  	int beta	       : The best move found so far for my oponent.
 *  	pathValue *path	 : A buffer to hold the best move found.
 *    double startTime : The time at which the process began, used for Iterative searches.
 */
int Checkers::AlphaBeta( Board* board, bool myTurn, int curPly, int maxPly, int alpha, 
												 int beta, pathValue *path, double startTime )
{
	Board tempBoard;
	PathList possibleStates;
	int value;

	ALGORITHM alg = m_redsTurn ? m_redsAlgor : m_whitesAlgor;

	if (alg == ITERATIVE) {
		if ((clock() - startTime)/CLOCKS_PER_SEC >= 59.0) {
			if (m_redsTurn) return -99999; 
			else            return -99999; 
		}
	}

	if (myTurn) {
		value = alpha;     // Can't do worse than alpha
		board->generateMoves( m_redsTurn, possibleStates );
		if (possibleStates.getLength() == 0) {
			if (m_redsTurn) return (*m_redsEvalFunc)( board, m_redsTurn ); 
			else            return (*m_whitesEvalFunc)( board, m_redsTurn ); 
		}

		if (alg == PLAUSIBLE || alg == ITERATIVE) {
//			Plausible_Ordering( board, &possibleStates, true );
		}

		for (int ii = 0; ii < possibleStates.getLength(); ++ii) {

			if (curPly == 0 && possibleStates.getLength() > 1) {
				pathValue *p = possibleStates.getPath( ii );

				// Avoid making the same move over and over again.
				if (m_redsTurn) {
					if (p[0] == 2 && p[1] == m_RedsLastMove[2] && p[2] == m_RedsLastMove[1]) continue;
				}
				else {
					if (p[0] == 2 && p[1] == m_WhitesLastMove[2] && p[2] == m_WhitesLastMove[1]) continue;
				}
			}

			tempBoard = *board;
			tempBoard.makeMove( possibleStates.getPath( ii ), m_redsTurn );
			int A;
			if (curPly == maxPly-1) {
				if (m_redsTurn) A = (*m_redsEvalFunc)( &tempBoard, m_redsTurn ); 
				else            A = (*m_whitesEvalFunc)( &tempBoard, m_redsTurn );
			}
			else {
				A = AlphaBeta( &tempBoard, false, curPly+1, maxPly, value, beta, NULL );
			}
			if (A > value) {
				value = A;
				if (path) {
					pathValue *p = possibleStates.getPath( ii );
					for (int jj = 0; jj <= p[0]; ++jj) {
						path[jj] = p[jj];
					}
				}
			}

			if (alg != MINMAX && value >= beta) {
				return value;
			}
		}
	}
	else {
		value = beta;      // Can't do better than beta
		board->generateMoves( !m_redsTurn, possibleStates );
		if (possibleStates.getLength() == 0) {
			if (m_redsTurn) return (*m_redsEvalFunc)( board, m_redsTurn ); 
			else            return (*m_whitesEvalFunc)( board, m_redsTurn ); 
		}

		if (alg == PLAUSIBLE || alg == ITERATIVE) {
//			Plausible_Ordering( board, &possibleStates, false );
		}

		for (int ii = 0; ii < possibleStates.getLength(); ++ii) {
			tempBoard = *board;
			tempBoard.makeMove( possibleStates.getPath( ii ), !m_redsTurn );
			int B;
			if (curPly == maxPly-1) {
				if (m_redsTurn) B = (*m_redsEvalFunc)( &tempBoard, m_redsTurn ); 
				else            B = (*m_whitesEvalFunc)( &tempBoard, m_redsTurn );
			}
			else {
				B = AlphaBeta( &tempBoard, true, curPly+1, maxPly, alpha, value, NULL );
			}
			if (B < value) {
				value = B;
			}

			if (alg != MINMAX && value <= alpha) {
				return value;
			}
		}
	}

	return value;
}

/*******************************************************************************************/

/**
 * Checkers::Iterative():
 *  Performs iterative deepening to determine the best move to be made.
 * 
 *  Return Type : int -> The best path value found throughout the search.
 *  Arguments   : 
 *  	Board *board	  : The current game board.
 *  	pathValue *path : Used to hold the best move path upon return.
 */
int Checkers::Iterative( Board *board, pathValue *path )
{
  int bestMove;
	pathValue path2[12];

  int depth = 5; // At least a depth of 5 can be reached.  Starting the search at
                 // a lower level is simply a waste of time and resources.

  double timer = clock();
  do 
  {
		int v = AlphaBeta( board, true, 0, depth++, -99999, 99999, path2, timer );
		if (v != -99999) {
			bestMove = v;
			for (int ii = 0; ii <= path2[0]; ++ii) {
				path[ii] = path2[ii];
			}
		}

  }while((clock() - timer)/CLOCKS_PER_SEC < 59.8 );

	cout << "Reached Depth: " << --depth << endl;
  return bestMove;
} 

/*******************************************************************************************/

/**
 * Checkers::Plausible_Ordering():
 *  Given a list of moves this method is responsible for reordering the moves by sorting 
 *  them.  If MaxNode == true then the list is sorted in decending order, otherwise they
 *  are sorted in accending order.
 * 
 *  Return Type : void 
 *  Arguments   : 
 *  	Board *board	  : The current game board.
 *  	PathList *moves	: The list of moves to be sorted.
 *  	bool MaxNode	  : Whether to sort in accending or decending order.
 */
void Checkers::Plausible_Ordering( Board *board, PathList *moves, bool MaxNode )
{
	if (moves->getLength() <= 1) return;   // No need to sort the list
  
	int value[MAX_MOVES];
  Board tempBoard;

  // Grab the value of the board if each of the possible moves where made
  for (int ii = 0; ii < moves->getLength(); ++ii) {
		tempBoard = *board;
    tempBoard.makeMove( moves->getPath( ii ), m_redsTurn );

		if (m_redsTurn) value[ii] = (*m_redsEvalFunc)( &tempBoard, m_redsTurn );
		else            value[ii] = (*m_whitesEvalFunc)( &tempBoard, m_redsTurn );
  }	

	if (MaxNode) moves->sortListDecending( value );
	else         moves->sortListAccending( value );
} 

/*******************************************************************************************/

/**
 * Checkers::BasicEvaluation():
 *  The default evaluation routine.  Direct comparison to the number of pieces each player
 *  has.
 * 
 *  Return Type : int 
 *  Arguments   : 
 *  	Board *board	: The board to be evaluated.
 *  	bool redsTurn	: Whether or not it is red's turn.
 */
int Checkers::BasicEvaluation( Board *board, bool redsTurn )
{
  if (redsTurn) return (board->NumRedPieces() - board->NumWhitePieces());
  else	        return (board->NumWhitePieces() - board->NumRedPieces());
} 

// ***** End of Checkers.cpp
/*******************************************************************************************/
/*******************************************************************************************/

⌨️ 快捷键说明

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