Written some cool source code? Upload it to Programmer's Heaven.

View Battleship\src\User.cpp

GPL'ed Battleship clone Win32/Linux 1.2.1

Submitted By: i_like_cpp
Rating: (Not rated) (Rate It)


/*
Free Battleship clone for Win32/Linux Console.
Copyright (C) 2005  Dennis Gertitschke

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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "../inc/User.h"
#include "../inc/Ship.h"
#include "../inc/Screen.h"
#include "../inc/Error.h"
#include "../inc/Common.h"

#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#include <windows.h>
#endif

User::User(){
        for(int i=0;i<100;i++){
                m_barrValidEnd[i]=false;
        }
        m_cStartX=m_cEndX=m_cDirection=0;
        m_iStartY=m_iEndY=0;
        m_pScreen->setMode(GAMETYPE_PLAYER_VS_COMPUTER);
}

User::~User(){
}

void User::registerCallback(void *pObj,F pFunc){
        m_pObj=pObj;
        m_pFunc=pFunc;
}

void User::reset(){

       
        m_bDefeat=false;
        m_iShipCount=4;

        for(int i=0;i<100;i++){
                m_arrBoard[i]=NULL;
                m_barrValidStart[i]=true;
                m_barrValidEnd[i]=false;
                m_barrValidShot[i]=true;
        }

        m_cStartX=m_cEndX=m_cDirection=0;
        m_iStartY=m_iEndY=m_iIndex=0;
        m_pFrigate->reset();
        m_pDestroyer->reset();
        m_pCruiser->reset();
        m_pBattleship->reset();
}

void User::shoot(){

        char cShotX;
        int  iShotY;

        do{
                m_pScreen->getUserCoordinate(cShotX,iShotY);
                if(!validateCoordinate(cShotX,iShotY)){
                        Error myerror("Invalid coordinate");
                        m_pScreen->printErrorMsg(myerror);
                }
                else{
                        m_iIndex=transformToBoardIndex(cShotX,iShotY);
                        if(!m_barrValidShot[m_iIndex]){
                                Error myerror("You already shot that field");
                                m_pScreen->printErrorMsg(myerror);
                        }
                }
        }while(!validateCoordinate(cShotX,iShotY)||!m_barrValidShot[m_iIndex]);

        m_barrValidShot[m_iIndex]=false;

        // call back the computer
        m_pFunc(m_pObj,cShotX,iShotY);
}

void User::validateCompShotCallback(void *pObj,char cX,int iY,bool& bRefHit,int& iRefHitCount){
        User *self=static_cast<User*>(pObj);
        self->validateCompShot(cX,iY,bRefHit,iRefHitCount);
}

void User::validateCompShot(char cX,int iY,bool& bRefHit,int& iRefHitCount){

        int iShot=transformToBoardIndex(cX,iY);
        char cTmpX=cX;
        int  iTmpY=iY;
       
        if(m_arrBoard[iShot]!=NULL){
                bRefHit=true;
                iRefHitCount++;
                m_arrBoard[iShot]->hit();
                if(m_arrBoard[iShot]->getStatus()){
                        m_iShipCount--;
                        iRefHitCount=0;
                        if(!m_iShipCount)
                                m_bDefeat=true;
                }
                m_pScreen->printUserStatus(bRefHit,m_arrBoard[iShot]->getId(),m_arrBoard[iShot]->getStatus());
                transformToUserScreen(cTmpX,iTmpY);
                m_pScreen->displayHit(cTmpX,iTmpY);
        }
        else{
                bRefHit=false;
                m_pScreen->printUserStatus(bRefHit,NULL,false);
                transformToUserScreen(cTmpX,iTmpY);
                m_pScreen->displayMiss(cTmpX,iTmpY);
        }
}

bool User::validateDirection(char cDirection){

        if(cDirection!='H'&&cDirection!='V')
                return false;
        else
                return true;
}

void User::transformToUserScreen(char& cRefX,int& iRefY){

        cRefX=static_cast<char>((cRefX-65)+2*(cRefX-40));
        iRefY=iRefY+4;
}

void User::placeShip(Ship *pShip){

        int i=0;
        char cTmpX;
        int iTmpY;

        while(i<pShip->getLength()){

                switch(m_cDirection){

                case 'H':       if(m_cStartX<m_cEndX){
                                                cTmpX=m_cStartX;
                                                iTmpY=m_iStartY;
                                                markNeighboursInvalid(m_cStartX,m_iStartY);
                                                m_iIndex=transformToBoardIndex(m_cStartX,m_iStartY);
                                                m_arrBoard[m_iIndex]=pShip;
                                                m_barrValidStart[m_iIndex]=false;
                                                m_cStartX++;
                                                transformToUserScreen(cTmpX,iTmpY);
                                                m_pScreen->displayShip(cTmpX,iTmpY);
                                        }
                                        else{
                                                cTmpX=m_cStartX;
                                                iTmpY=m_iStartY;
                                                markNeighboursInvalid(m_cStartX,m_iStartY);
                                                m_iIndex=transformToBoardIndex(m_cStartX,m_iStartY);
                                                m_arrBoard[m_iIndex]=pShip;
                                                m_barrValidStart[m_iIndex]=false;
                                                m_cStartX--;
                                                transformToUserScreen(cTmpX,iTmpY);
                                                m_pScreen->displayShip(cTmpX,iTmpY);
                                        }
                                        break;


                case 'V':       if(m_iStartY<m_iEndY){
                                                cTmpX=m_cStartX;
                                                iTmpY=m_iStartY;
                                                markNeighboursInvalid(m_cStartX,m_iStartY);
                                                m_iIndex=transformToBoardIndex(m_cStartX,m_iStartY);
                                                m_arrBoard[m_iIndex]=pShip;
                                                m_barrValidStart[m_iIndex]=false;
                                                m_iStartY++;
                                                transformToUserScreen(cTmpX,iTmpY);
                                                m_pScreen->displayShip(cTmpX,iTmpY);
                                        }
                                        else{
                                                cTmpX=m_cStartX;
                                                iTmpY=m_iStartY;
                                                markNeighboursInvalid(m_cStartX,m_iStartY);
                                                m_iIndex=transformToBoardIndex(m_cStartX,m_iStartY);
                                                m_arrBoard[m_iIndex]=pShip;
                                                m_barrValidStart[m_iIndex]=false;
                                                m_iStartY--;
                                                transformToUserScreen(cTmpX,iTmpY);
                                                m_pScreen->displayShip(cTmpX,iTmpY);
                                        }
                                        break;

                }
                i++;
        }
}

void User::resetEndpoints(){

        for(int i=0;i<100;i++)
                m_barrValidEnd[i]=false;
}

bool User::readValidStartEnd(Ship *pShip){

        int iOffset;

        iOffset=pShip->getLength()-1;
        m_pScreen->promptUserToHide(pShip->getId(),pShip->getLength());

        do{
                m_pScreen->getDirection(m_cDirection);
                if(!validateDirection(m_cDirection)){
                        Error myerror("Please enter 'h' or 'v'");
                        m_pScreen->printErrorMsg(myerror);
                }
        }while(!validateDirection(m_cDirection));

        m_pScreen->clearErrorMsg();

        do{
                m_pScreen->getUserCoordinate(m_cStartX,m_iStartY);
                if(!validateCoordinate(m_cStartX,m_iStartY)){
                        Error myerror("Invalid coordinate");
                        m_pScreen->printErrorMsg(myerror);
                }
                else{
                        m_iIndex=transformToBoardIndex(m_cStartX,m_iStartY);
                        if(!m_barrValidStart[m_iIndex]){
                                Error myerror("Coordinate already in use");
                                m_pScreen->printErrorMsg(myerror);
                        }
                }
        }while(!validateCoordinate(m_cStartX,m_iStartY)||!m_barrValidStart[m_iIndex]);

        m_pScreen->clearErrorMsg();

        switch(m_cDirection){

        case 'H':       if(validateCoordinate(static_cast<char>(m_cStartX+iOffset),m_iStartY)){
                                        if(checkStartEnd(m_cStartX,m_iStartY,pShip->getLength(),1)){
                                                m_iIndex=transformToBoardIndex(static_cast<char>(m_cStartX+iOffset),m_iStartY);
                                                m_barrValidEnd[m_iIndex]=true;
                                        }
                                }
                                if(validateCoordinate(static_cast<char>(m_cStartX-iOffset),m_iStartY)){
                                        if(checkStartEnd(m_cStartX,m_iStartY,pShip->getLength(),2)){
                                                m_iIndex=transformToBoardIndex(static_cast<char>(m_cStartX-iOffset),m_iStartY);
                                                m_barrValidEnd[m_iIndex]=true;
                                        }
                                }
                                break;

        case 'V':       if(validateCoordinate(m_cStartX,m_iStartY+iOffset)){
                                        if(checkStartEnd(m_cStartX,m_iStartY,pShip->getLength(),3)){
                                                m_iIndex=transformToBoardIndex(m_cStartX,m_iStartY+iOffset);
                                                m_barrValidEnd[m_iIndex]=true;
                                        }
                                }
                                if(validateCoordinate(m_cStartX,m_iStartY-iOffset)){
                                        if(checkStartEnd(m_cStartX,m_iStartY,pShip->getLength(),4)){
                                                m_iIndex=transformToBoardIndex(m_cStartX,m_iStartY-iOffset);
                                                m_barrValidEnd[m_iIndex]=true;
                                        }
                                }
                                break;
        }

        do{
                m_pScreen->getUserCoordinate(m_cEndX,m_iEndY);
                if(!validateCoordinate(m_cEndX,m_iEndY)){
                        Error myerror("Invalid coordinate");
                        m_pScreen->printErrorMsg(myerror);
                }
                else{
                        m_iIndex=transformToBoardIndex(m_cEndX,m_iEndY);
                        if(!m_barrValidEnd[m_iIndex]){
                                Error myerror("The endpoint entered is invalid");
                                m_pScreen->printErrorMsg(myerror);
                                resetEndpoints();
                                return false;
                        }
                }
        }while(!validateCoordinate(m_cEndX,m_iEndY)||!m_barrValidEnd[m_iIndex]);
        m_pScreen->clearErrorMsg();
        resetEndpoints();
        return true;
}

void User::deployFleet(){

#ifdef WIN32
        PlaySound("..\\sound\\alarm.wav",NULL,SND_SYNC);
#else
        ::playWave("../sound/alarm.wav",8,1,8000);
#endif
        while(!readValidStartEnd(m_pFrigate));
        placeShip(m_pFrigate);
        while(!readValidStartEnd(m_pDestroyer));
        placeShip(m_pDestroyer);
        while(!readValidStartEnd(m_pCruiser));
        placeShip(m_pCruiser);
        while(!readValidStartEnd(m_pBattleship));
        placeShip(m_pBattleship);
        m_pScreen->printUserSucessfullyPlaced();
}

bool User::checkStartEnd(char cStartX,int iStartY,int iLength,int iDirection){
        bool bResult=true;
        int i=0;

        while(i<iLength){
                switch(iDirection){
                        case 1: m_iIndex=transformToBoardIndex(cStartX,iStartY);
                                        if(!m_barrValidStart[m_iIndex])
                                                return false;
                                        cStartX++;
                                        break;

                        case 2: m_iIndex=transformToBoardIndex(cStartX,iStartY);
                                        if(!m_barrValidStart[m_iIndex])
                                                return false;
                                        cStartX--;
                                        break;

                        case 3: m_iIndex=transformToBoardIndex(cStartX,iStartY);
                                        if(!m_barrValidStart[m_iIndex])
                                                return false;
                                        iStartY++;
                                        break;

                        case 4: m_iIndex=transformToBoardIndex(cStartX,iStartY);
                                        if(!m_barrValidStart[m_iIndex])
                                                return false;
                                        iStartY--;
                                        break;
                }
                i++;
        }
        return bResult;
}
 
corner
© 1996-2008. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
Publisher: Lars Hagelin.
bootstrapLabs Logo A bootstrapLabs project.