/*****************************************************************************\ * FILE: board.cpp * * PURPOSE: Implementation of the board class * * Created by Eric Akers, 23 Dec 2003 * * ChangeLog: * ELA - - Initial Working Version * * * * * Copyright (C) 2003 Eric Akers * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \*****************************************************************************/ // Header Files ############################################################# #include #include #include #include #include "Board.h" // Macros ################################################################### // Directions #define NORTH 0 #define SOUTH 1 #define EAST 2 #define WEST 3 #define NORTH_WEST 4 #define SOUTH_EAST 5 #define SOUTH_WEST 6 #define NORTH_EAST 7 // Winning combo #define CONNECT_WIN 5 // Structures ############################################################### // Class Function Definitions ############################################### Board::Board() { // Initialize the board for( int row=0; row<19; row++ ) { for( int col=0; col<19; col++ ) { board[col][row] = BLANK; } } // We are not a winner yet winner = false; } Board* Board::getNextBoard( int row, int column, int player ) const { // Create the new board Board * newBoard = new Board(); if( newBoard == NULL ) { printf( "No memory\n" ); exit( -1 ); } // Copy the old board memcpy( newBoard->board, board, 19*19 ); // Copy the old adjacent moves list pos = getOpenAdjacentPositions(); for( list::iterator iter=pos.begin(); iter != pos.end(); iter++ ) { newBoard->openPositions.addPosition( (*iter).row, (*iter).col ); } // Set the new move newBoard->setPlayerMove( row, column, player ); // Determine if the new board is a winner newBoard->determineWinner( row, column ); return newBoard; } void Board::setPlayerMove( int row, int column, int player ) { // printf( "\n\nBoard: Set Player Move: (%d,%d)\n", row, column ); board[column][row] = player; // Add new open adjacent positions setOpenAdjacentPositions( row, column ); // Remove the old adjacent positions openPositions.removePosition( row, column ); // Determine if a win happened determineWinner( row, column ); } bool Board::isWinningState() const { return winner; } bool Board::determineWinner( int row, int col ) { // Check each direction and around the chosen location for a winner // printf( "Board::determineWinner\n" ); for( int i=0; i<8; i+=2 ) { // Each direction is next to the opposite direction. So add the two // together int open, count = 1, fullCount, tmpCount; // printf( "**** DIRECTION: %d\n", i ); getNumAdjacentPieces( row, col, i, tmpCount, open, fullCount ); count += tmpCount; getNumAdjacentPieces( row, col, i + 1, tmpCount, open, fullCount ); count += tmpCount; // printf( "Count: %d\n", count ); // A winner is CONNECT_WIN in a row if( count >= CONNECT_WIN ) { winner = true; // Very important return true; } } // We did not make it return false; } int Board::getPlayerAt( int row, int column ) const { return board[column][row]; } void Board::getNumAdjacentPieces( int row, int col, int direction, int & continuousLength, int & openSize, int & fullLength ) const { int deltaX, deltaY; getDirectionDelta( direction, deltaX, deltaY ); // printf( "getNumAdjacent: direction %d, delta x: %d, y: %d\n", // direction, deltaX, deltaY ); // Set when there is room to continue int openCount = 0; // Set when the continuousness has ended bool isFinished = false; // Get the player checking this for int player = board[col][row]; assert( player != BLANK ); int count = 0, continuousCount = 0; int curX = row, curY = col; for( int i=0; i<5; i++ ) { curX += deltaX; curY += deltaY; // Make sure the new location is in bounds if( curX > 18 || curX < 0 || curY > 18 || curY < 0 ) { break; } // printf( "(%d,%d) = %d\t", curX, curY, board[curY][curX] ); // See if the string continues if( board[curY][curX] != player ) { isFinished = true; if( board[curY][curX] != BLANK ) { break; } else { openCount++; } } else { count++; openCount++; if( isFinished == false ) { // the continuous count continues continuousCount++; } } } // printf( "\ngetNumAdjacent:: count = %d (%d,%d)\n", count,row,col ); openSize = openCount; continuousLength = continuousCount; fullLength = count; // The whole length, even if there are breaks } void Board::getDirectionDelta( int direction, int & row, int & col ) const { switch( direction ) { case NORTH: row = 1; col = 0; break; case SOUTH: row = -1; col = 0; break; case EAST: row = 0; col = 1; break; case WEST: row = 0; col = -1; break; case NORTH_WEST: row = 1; col = -1; break; case NORTH_EAST: row = 1; col = 1; break; case SOUTH_WEST: row = -1; col = -1; break; case SOUTH_EAST: row = -1; col = 1; break; default: printf( "INVALID DIRECTION\n" ); exit( -1 ); } } void Board::setOpenAdjacentPositions( int row, int col ) { int rowDelta[] = { 1, -1, 0, 0, 1, 1, -1, -1 }; int colDelta[] = { 0, 0, 1, -1, -1, 1, -1, 1 }; for( int i=0; i<8; i++ ) { int curRow = row + rowDelta[i]; int curCol = col + colDelta[i]; if( curRow < 0 || curRow > 18 || curCol < 0 || curCol > 18 ) { // Not an actual position continue; } else { if( board[curCol][curRow] == BLANK ) { openPositions.addPosition( curRow, curCol ); } } } }