Task: Pig the dice game_Player


C++: #include <windows.h>
#include <iostream>
#include <string>


using namespace std;


const int PLAYERS = 4, MAX_POINTS = 100;


enum Moves { ROLL, HOLD };


class player
{
public:
    player()                     { current_score = round_score = 0; }
    void addCurrScore()          { current_score += round_score; }
    int getCurrScore()           { return current_score; }
    int getRoundScore()          { return round_score; }
    void addRoundScore( int rs ) { round_score += rs; }
    void zeroRoundScore()        { round_score = 0; }
    virtual int getMove() = 0;
    virtual ~player() {}

protected:
    int current_score, round_score;
};

class RAND_Player : public player
{
    virtual int getMove()
    {
	if( round_score + current_score >= MAX_POINTS ) return HOLD;

	if( rand() % 10 < 5 ) return ROLL;
	if( round_score > 0 ) return HOLD;
	return ROLL;
    }
};

class Q2WIN_Player : public player
{
    virtual int getMove()
    {
	if( round_score + current_score >= MAX_POINTS ) return HOLD;
		
	int q = MAX_POINTS - current_score;
	if( q < 6 ) return ROLL;
	q /= 4;
	if( round_score < q ) return ROLL;
	return HOLD;
    }
};

class AL20_Player : public player
{
    virtual int getMove()
    {
	if( round_score + current_score >= MAX_POINTS ) return HOLD;

	if( round_score < 20 ) return ROLL;
	return HOLD;
    }
};

class AL20T_Player : public player
{
    virtual int getMove()
    {
	if( round_score + current_score >= MAX_POINTS ) return HOLD;

	int d = ( 100 * round_score ) / 20;
	if( round_score < 20 && d < rand() % 100 ) return ROLL;
	return HOLD;
    }
};

class Auto_pigGame
{
public:
    Auto_pigGame() 
    {
	_players[0] = new RAND_Player();
	_players[1] = new Q2WIN_Player();
	_players[2] = new AL20_Player();
        _players[3] = new AL20T_Player();
    }

    ~Auto_pigGame()
    {
	delete _players[0];
	delete _players[1];
	delete _players[2];
        delete _players[3];
    }

    void play()
    {
	int die, p = 0;
	bool endGame = false;

	while( !endGame )
	{
	    switch( _players[p]->getMove() )
	    {
		case ROLL:
	    	    die = rand() % 6 + 1;
		    if( die == 1 )
		    {
			cout << "Player " << p + 1 << " rolled " << die << " - current score: " << _players[p]->getCurrScore() << endl << endl;
			nextTurn( p );
			continue;
		    }
		    _players[p]->addRoundScore( die );
		    cout << "Player " << p + 1 << " rolled " << die << " - round score: " << _players[p]->getRoundScore() << endl;
		break;
		case HOLD:
	    	    _players[p]->addCurrScore();
		    cout << "Player " << p + 1 << " holds - current score: " << _players[p]->getCurrScore() << endl << endl;
		    if( _players[p]->getCurrScore() >= MAX_POINTS )
			endGame = true;
		    else nextTurn( p );

	    }
	}
	showScore();
    }

private:
    void nextTurn( int& p )
    {
	_players[p]->zeroRoundScore();
	++p %= PLAYERS;
    }

    void showScore()
    {
	cout << endl;
	cout << "Player   I (RAND): "  << _players[0]->getCurrScore() << endl;
	cout << "Player  II (Q2WIN): " << _players[1]->getCurrScore() << endl;
        cout << "Player III (AL20): " << _players[2]->getCurrScore() << endl;
	cout << "Player  IV (AL20T): "  << _players[3]->getCurrScore() << endl << endl << endl;

	system( "pause" );
    }

    player*	_players[PLAYERS];
};

int main( int argc, char* argv[] )
{
    srand( GetTickCount() );
    Auto_pigGame pg;
    pg.play();
    return 0;
}




Go: package pig

import (
	"fmt"
	"math/rand"
	"time"
)

type (
	PlayerID   int
	MessageID  int
	StrategyID int

	PigGameData struct {
		player        PlayerID
		turnCount     int
		turnRollCount int
		turnScore     int
		lastRoll      int
		scores        [2]int
		verbose       bool
	}
)

const (
	
	gameOver = iota
	piggedOut
	rolls
	pointSpending
	holds
	turn
	gameOverSummary
	
	player1  = PlayerID(0)
	player2  = PlayerID(1)
	noPlayer = PlayerID(-1)
	
	maxScore = 100
	
	scoreChaseStrat = iota
	rollCountStrat
)


func pluralS(n int) string {
	if n != 1 {
		return "s"
	}
	return ""
}


func New() *PigGameData {
	return &PigGameData{0, 0, 0, 0, 0, [2]int{0, 0}, false}
}


func (pg *PigGameData) statusMessage(id MessageID) string {
	var msg string
	switch id {
	case gameOver:
		msg = fmt.Sprintf("Game is over after %d turns", pg.turnCount)
	case piggedOut:
		msg = fmt.Sprintf("    Pigged out after %d roll%s", pg.turnRollCount, pluralS(pg.turnRollCount))
	case rolls:
		msg = fmt.Sprintf("    Rolls %d", pg.lastRoll)
	case pointSpending:
		msg = fmt.Sprintf("    %d point%s pending", pg.turnScore, pluralS(pg.turnScore))
	case holds:
		msg = fmt.Sprintf("    Holds after %d turns, adding %d points for a total of %d", pg.turnRollCount, pg.turnScore, pg.PlayerScore(noPlayer))
	case turn:
		msg = fmt.Sprintf("Player %d's turn:", pg.player+1)
	case gameOverSummary:
		msg = fmt.Sprintf("Game over after %d turns\n player 1 %d\n player 2 %d\n", pg.turnCount, pg.PlayerScore(player1), pg.PlayerScore(player2))
	}
	return msg
}


func (pg *PigGameData) PrintStatus(id MessageID) {
	if pg.verbose {
		fmt.Println(pg.statusMessage(id))
	}
}


func (pg *PigGameData) Play(id StrategyID) (keepPlaying bool) {
	if pg.GameOver() {
		pg.PrintStatus(gameOver)
		return false
	}

	if pg.turnCount == 0 {
		pg.player = player2
		pg.NextPlayer()
	}

	pg.lastRoll = rand.Intn(6) + 1
	pg.PrintStatus(rolls)
	pg.turnRollCount++
	if pg.lastRoll == 1 {
		pg.PrintStatus(piggedOut)
		pg.NextPlayer()
	} else {
		pg.turnScore += pg.lastRoll
		pg.PrintStatus(pointSpending)
		success := false
		switch id {
		case scoreChaseStrat:
			success = pg.scoreChaseStrategy()
		case rollCountStrat:
			success = pg.rollCountStrategy()
		}
		if success {
			pg.Hold()
			pg.NextPlayer()
		}
	}
	return true
}


func (pg *PigGameData) PlayerScore(id PlayerID) int {
	if id == noPlayer {
		return pg.scores[pg.player]
	}
	return pg.scores[id]
}


func (pg *PigGameData) GameOver() bool {
	return pg.scores[player1] >= maxScore || pg.scores[player2] >= maxScore
}


func (pg *PigGameData) Winner() PlayerID {
	for index, score := range pg.scores {
		if score >= maxScore {
			return PlayerID(index)
		}
	}
	return noPlayer
}


func (pg *PigGameData) otherPlayer() PlayerID {
	
	return 1 - pg.player
}

func (pg *PigGameData) Hold() {
	pg.scores[pg.player] += pg.turnScore
	pg.PrintStatus(holds)
	pg.turnRollCount, pg.turnScore = 0, 0
}

func (pg *PigGameData) NextPlayer() {
	pg.turnCount++
	pg.turnRollCount, pg.turnScore = 0, 0
	pg.player = pg.otherPlayer()
	pg.PrintStatus(turn)
}

func (pg *PigGameData) rollCountStrategy() bool {
	return pg.turnRollCount >= 3
}

func (pg *PigGameData) scoreChaseStrategy() bool {
	myScore := pg.PlayerScore(pg.player)
	otherScore := pg.PlayerScore(pg.otherPlayer())
	myPendingScore := pg.turnScore + myScore
	return myPendingScore >= maxScore || myPendingScore > otherScore || pg.turnRollCount >= 5
}


func main() {
	
	rand.Seed(time.Now().UnixNano())

	
	pg := New()
	pg.verbose = true
	strategies := [2]StrategyID{scoreChaseStrat, rollCountStrat}

	
	for !pg.GameOver() {
		pg.Play(strategies[pg.player])
	}
	pg.PrintStatus(gameOverSummary)
}