isohex10_4.cpp

来自「一個遊戲教程」· C++ 代码 · 共 1,096 行 · 第 1/2 页

CPP
1,096
字号
	//place corner markers
	//upper left
	Board[1][1].iTileNum=1;
	Board[2][1].iTileNum=2;
	Board[1][2].iTileNum=3;
	Board[2][2].iTileNum=4;
	//upper right
	Board[5][1].iTileNum=1;
	Board[6][1].iTileNum=2;
	Board[5][2].iTileNum=3;
	Board[6][2].iTileNum=4;
	//lower left
	Board[1][5].iTileNum=1;
	Board[2][5].iTileNum=2;
	Board[1][6].iTileNum=3;
	Board[2][6].iTileNum=4;
	//lower right
	Board[5][5].iTileNum=1;
	Board[6][5].iTileNum=2;
	Board[5][6].iTileNum=3;
	Board[6][6].iTileNum=4;

	//save board
	SaveBoard();
}

void ShowBoard()
{
	int iTile=0;
	int TileX=0;
	int TileY=0;
	//retrieve tile width and height(assuming all tiles are as wide/high as tile 0)
	int iTileWidth=tsReversi.GetTileList()[0].rcSrc.right-tsReversi.GetTileList()[0].rcSrc.left;
	int iTileHeight=tsReversi.GetTileList()[0].rcSrc.bottom-tsReversi.GetTileList()[0].rcSrc.top;
	//loop through board squares
	for(int y=0;y<8;y++)
	{
		//tile y position
		TileY=y*iTileHeight+(600-iTileHeight*8)/2;
		for(int x=0;x<8;x++)
		{
			//tile x position
			TileX=x*iTileWidth+(800-iTileWidth*8)/2;

			//show background
			//base tile
			iTile=Board[x][y].iTileNum;
			//modify for hilite
			if(Board[x][y].bHilite)
			{
				iTile+=5;
			}
			tsReversi.PutTile(lpddsBack,TileX,TileY,iTile);

			//show piece
			iTile=Board[x][y].iPiece;
			switch(iTile)
			{
			case PIECEEMPTY:
				{
					//do nothing
				}break;
			case PIECEWHITE:
				{
					//put white piece
					tsReversi.PutTile(lpddsBack,TileX,TileY,10);
				}break;
			case PIECEBLACK:
				{
					//put white piece
					tsReversi.PutTile(lpddsBack,TileX,TileY,24);
				}break;
			case PIECETRANSIT:
				{
					//put transition piece
					tsReversi.PutTile(lpddsBack,TileX,TileY,iAnimation+10);
				}break;
			}
			//hilite last move
			if(Board[x][y].bLastMove)
			{
				tsReversi.PutTile(lpddsBack,TileX,TileY,25);
			}
		}
	}
}


void ScanForMoves(int plyr)
{
	//loop through board
	for(int x=0;x<8;x++)
	{
		for(int y=0;y<8;y++)
		{
			//check for a valid move
			Board[x][y].bHilite=ValidMove(plyr,x,y);
		}
	}
}

bool AnyValidMoves(int plyr)
{
	//scan the board
	for(int x=0;x<8;x++)
	{
		for(int y=0;y<8;y++)
		{
			//a single valid move will return true
			if(ValidMove(plyr,x,y))
			{
				return(true);
			}
		}
	}
	return(false);//didnt find a move, return false
}

bool ValidMove(int plyr,int x,int y)
{
	//loop through directions
	for(int dir=DIR_NORTH;dir<DIR_COUNT;dir++)
	{
		//check for a valid run
		if(ValidRun(plyr,x,y,dir))
		{
			//at least one valid run means the move is valid
			return(true);
		}
	}

	//default to false
	return(false);
}

bool ValidRun(int plyr,int x,int y,int dir)
{
	//set distance to zero
	int dist=0;
	int piece=0;
	for(;;)
	{
		//retrieve the piece
		piece=Board[x][y].iPiece;

		switch(dist)
		{
		case 0:
			{
				//if square is not empty, it is not a valid run
				if(piece!=PIECEEMPTY)
				{
					return(false);
				}
			}break;
		case 1:
			{
				//check for bounds
				if(x<0) return(false);
				if(y<0) return(false);
				if(x>7) return(false);
				if(y>7) return(false);

				//must have a piece of the opposing side
				if(piece!=(1-plyr))
				{
					return(false);
				}
			}break;
		default:
			{
				//check for bounds
				if(x<0) return(false);
				if(y<0) return(false);
				if(x>7) return(false);
				if(y>7) return(false);

				//piece cannot be empty
				if(piece==PIECEEMPTY)
				{
					return(false);
				}

				//if piece is of the players color, it is a valid run
				if(piece==plyr)
				{
					return(true);
				}

			}break;
		}
		//move the x,y
		x+=DeltaX(dir);
		y+=DeltaY(dir);
		dist++;
	}
}

int DeltaX(int dir)
{
	//switch on direction
	switch(dir)
	{
		//directions that require leftward movememnt
	case DIR_NORTHWEST:
	case DIR_WEST:
	case DIR_SOUTHWEST:
		{
			return(-1);
		}break;
		//directions that require rightward movement
	case DIR_NORTHEAST:
	case DIR_EAST:
	case DIR_SOUTHEAST:
		{
			return(1);
		}break;
	}
	return(0);//default to no movement
}

int DeltaY(int dir)
{
	//switch on direction
	switch(dir)
	{
	case DIR_NORTHWEST:
	case DIR_NORTH:
	case DIR_NORTHEAST:
		{
			//upward
			return(-1);
		}break;
	case DIR_SOUTHWEST:
	case DIR_SOUTH:
	case DIR_SOUTHEAST:
		{
			//downward
			return(1);
		}break;
	}
	return(0);//default to no movement
}

void MakeMove(int plyr,int x,int y)
{

	//store valid runs
	bool Run[DIR_COUNT];
	int dir=0;
	for(dir=DIR_NORTH;dir<DIR_COUNT;dir++)
	{
		Run[dir]=ValidRun(plyr,x,y,dir);
	}

	//set pieces to transitory state
	int tx;//tx is a temporary x coordinate
	int ty;
	for(dir=DIR_NORTH;dir<DIR_COUNT;dir++)
	{
		//must be a valid run
		if(Run[dir])
		{
			//set first position
			tx=x+DeltaX(dir);
			ty=y+DeltaY(dir);

			//while still on an opposing piece
			while(Board[tx][ty].iPiece==(1-plyr))
			{
				//set piece to transit
				Board[tx][ty].iPiece=PIECETRANSIT;
				//update x,y position
				tx+=DeltaX(dir);
				ty+=DeltaY(dir);
			}
		}
	}

	//set the appropriate animation value
	switch(plyr)
	{
	case PLAYERTWO:
		{
			//animation value of 14
			iAnimation=14;
		}break;
	case PLAYERONE:
		{
			//animation value of 0
			iAnimation=0;
		}break;
	}

	//set initial piece
	Board[x][y].iPiece=plyr;

}

void FinishMove(int plyr)
{
	//scan board
	for(int x=0;x<8;x++)
	{
		for(int y=0;y<8;y++)
		{
			//if a transit piece
			if(Board[x][y].iPiece==PIECETRANSIT)
			{
				//set to player's piece
				Board[x][y].iPiece=plyr;
			}
		}
	}
}

void MakeRandomMove(int plyr)
{
	int x;
	int y;
	//pick a valid, random move
	for(;;)
	{
		//pick random square
		x=rand()%8;
		y=rand()%8;
		//if a valid move, break out of the loop
		if(ValidMove(plyr,x,y)) break;
	}
	//make the move
	MakeMove(plyr,x,y);
	iGameState=GS_FLIP;
	SetLastMove(x,y);
}

void MakeGreedyMove(int plyr)
{
	//loop vars
	int x;
	int y;
	//backup the board
	SaveBoard();
	//make an ai array for judging moves
	int AI[8][8];
	int hival=0;
	//loop through board squares
	for(x=0;x<8;x++)
	{
		for(y=0;y<8;y++)
		{
			//restore the board
			RestoreBoard();
			//check for valid move
			if(ValidMove(plyr,x,y))
			{
				//valid move
				MakeMove(plyr,x,y);
				FinishMove(plyr);
				AI[x][y]=GetScore(plyr);
			}
			else
			{
				//non-valid move
				AI[x][y]=0;
			}
			//new high value
			if(AI[x][y]>hival)
			{
				hival=AI[x][y];
			}
		}
	}
	//restore the board
	RestoreBoard();
	//find a square
	for(;;)
	{
		//pick random square
		x=rand()%8;
		y=rand()%8;
		//check against hival
		if(AI[x][y]==hival) break;
	}
	MakeMove(plyr,x,y);
	iGameState=GS_FLIP;
	SetLastMove(x,y);
}

void MakeMiserMove(int plyr)
{
	//loop vars
	int x;
	int y;
	//temp x and y
	int tx;
	int ty;
	//backup the board
	SaveBoard();
	//make an ai array for judging moves
	int AI[8][8];
	int loval=0x7FFFFFFF;
	//loop through board squares
	for(x=0;x<8;x++)
	{
		for(y=0;y<8;y++)
		{
			AI[x][y]=0;
			//restore the board
			RestoreBoard();
			//check for valid move
			if(ValidMove(plyr,x,y))
			{
				//weight the moves
				//edges
				if(x==0) AI[x][y]-=2;
				if(x==7) AI[x][y]-=2;
				if(y==0) AI[x][y]-=2;
				if(y==7) AI[x][y]-=2;
				//corners
				if((x==0) && (y==0)) AI[x][y]-=6;
				if((x==7) && (y==0)) AI[x][y]-=6;
				if((x==0) && (y==7)) AI[x][y]-=6;
				if((x==7) && (y==7)) AI[x][y]-=6;

				//valid move
				MakeMove(plyr,x,y);
				FinishMove(plyr);
				//loop to count valid moves for opposing player
				for(tx=0;tx<8;tx++)
				{
					for(ty=0;ty<8;ty++)
					{
						//count valid moves
						if(ValidMove(1-plyr,tx,ty))
						{
							AI[x][y]++;
							//edges
							if(tx==0) AI[x][y]+=1;
							if(tx==7) AI[x][y]+=1;
							if(ty==0) AI[x][y]+=1;
							if(ty==7) AI[x][y]+=1;
							//corners
							if((tx==0) && (ty==0)) AI[x][y]+=3;
							if((tx==7) && (ty==0)) AI[x][y]+=3;
							if((tx==0) && (ty==7)) AI[x][y]+=3;
							if((tx==7) && (ty==7)) AI[x][y]+=3;
						}
					}
				}
			}
			else
			{
				//not a valid move
				AI[x][y]=0x7FFFFFFF;
			}
			//new high value
			if(AI[x][y]<loval)
			{
				loval=AI[x][y];
			}
		}
	}
	//restore the board
	RestoreBoard();
	//find a square
	for(;;)
	{
		//pick random square
		x=rand()%8;
		y=rand()%8;
		//check against hival
		if(AI[x][y]==loval) break;
	}
	MakeMove(plyr,x,y);
	iGameState=GS_FLIP;
	SetLastMove(x,y);
}

int GetScore(int plyr)
{
	int score=0;
	//loop through board
	for(int x=0;x<8;x++)
	{
		for(int y=0;y<8;y++)
		{
			//if piece belongs to plr, add to score
			if(Board[x][y].iPiece==plyr) score++;
		}
	}
	return(score);
}

void ShowScores()
{
	//score and counter
	int score;
	int counter;
	//player one score
	score=GetScore(PLAYERONE);
	//show a column of player one's pieces
	for(counter=0;counter<score;counter++)
	{
		tsReversi.PutTile(lpddsBack,0,4*counter,24);
	}
	//player two score
	score=GetScore(PLAYERTWO);
	//show columns of player two's pieces
	for(counter=0;counter<score;counter++)
	{
		tsReversi.PutTile(lpddsBack,(tsReversi.GetTileList()[0].rcSrc.right-tsReversi.GetTileList()[0].rcSrc.left),4*counter,10);
	}
}

void SetLastMove(int x, int y)
{
	//temp x and y for loops
	for(int tx=0;tx<8;tx++)
	{
		for(int ty=0;ty<8;ty++)
		{
			//clear the lastmove
			Board[tx][ty].bLastMove=false;
		}
	}
	//set new last move
	Board[x][y].bLastMove=true;
}

void ShowPlayers()
{
	//grab tile width
	int iTileWidth=tsReversi.GetTileList()[0].rcSrc.right-tsReversi.GetTileList()[0].rcSrc.left;
	//grab tile height
	int iTileHeight=tsReversi.GetTileList()[0].rcSrc.bottom-tsReversi.GetTileList()[0].rcSrc.top;

	//show player 1
	tsReversi.PutTile(lpddsBack,0,600-iTileHeight,24);
	//show AI level
	tsReversi.PutTile(lpddsBack,0,600-iTileHeight,26+iAILevel[PLAYERONE]);
	//show player 2
	tsReversi.PutTile(lpddsBack,iTileWidth,600-iTileHeight,10);
	//show AI level
	tsReversi.PutTile(lpddsBack,iTileWidth,600-iTileHeight,26+iAILevel[PLAYERTWO]);
	//show current player
	tsReversi.PutTile(lpddsBack,iTileWidth*iPlayer,600-iTileHeight,25);
}

⌨️ 快捷键说明

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