isohex10_4.cpp
来自「一個遊戲教程」· C++ 代码 · 共 1,096 行 · 第 1/2 页
CPP
1,096 行
/*****************************************************************************
IsoHex10_4.cpp
Ernest S. Pazera
27JUN2000
Start a WIN32 Application Workspace, add in this file
Needs ddraw.lib, and dxguid.lib
Needs GDICanvas.h/cpp
Needs DDFuncs.h/cpp
Needs tileset.h/cpp
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
//INCLUDES
//////////////////////////////////////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "GDICanvas.h"
#include "ddraw.h"
#include "DDFuncs.h"
#include "mmsystem.h"
#include "TileSet.h"
//////////////////////////////////////////////////////////////////////////////
//DEFINES
//////////////////////////////////////////////////////////////////////////////
//name for our window class
#define WINDOWCLASS "ISOHEX10"
//title of the application
#define WINDOWTITLE "IsoHex 10-4: Reversi"
const int PLAYERONE=0;//black player
const int PLAYERTWO=1;//white player
const int PIECEEMPTY=-1;//empty square
const int PIECEBLACK=0;//black piece
const int PIECEWHITE=1;//white piece
const int PIECETRANSIT=2;//animated flip
//game states
const int GS_NONE=-1;
const int GS_WAITFORINPUT=0;
const int GS_NEWGAME=1;
const int GS_NEXTPLAYER=2;
const int GS_FLIP=3;
//directions
const int DIR_NORTH=0;
const int DIR_NORTHEAST=1;
const int DIR_EAST=2;
const int DIR_SOUTHEAST=3;
const int DIR_SOUTH=4;
const int DIR_SOUTHWEST=5;
const int DIR_WEST=6;
const int DIR_NORTHWEST=7;
const int DIR_COUNT=8;
//ai levels
const int AI_HUMAN=0;
const int AI_RANDOM=1;
const int AI_GREEDY=2;
const int AI_MISER=3;
const int AI_COUNT=4;
//////////////////////////////////////////////////////////////////////////////
//PROTOTYPES
//////////////////////////////////////////////////////////////////////////////
bool Prog_Init();//game data initalizer
void Prog_Loop();//main game loop
void Prog_Done();//game clean up
//save/restore board to backup board
void SaveBoard();
void RestoreBoard();
//game manipulation
void SetUpBoard();
void ShowBoard();
//move
void ScanForMoves(int plyr);
bool AnyValidMoves(int plyr);
bool ValidMove(int plyr,int x,int y);
bool ValidRun(int plyr,int x,int y,int dir);
//move x and y in direction
int DeltaX(int dir);
int DeltaY(int dir);
//make a move
void MakeMove(int plyr,int x, int y);
void FinishMove(int plyr);
//ai move functions
void MakeRandomMove(int plyr);
void MakeGreedyMove(int plyr);
void MakeMiserMove(int plyr);
//score evaulation
int GetScore(int plyr);
void ShowScores();
//last move
void SetLastMove(int x, int y);
//show players
void ShowPlayers();
//////////////////////////////////////////////////////////////////////////////
//GLOBALS
//////////////////////////////////////////////////////////////////////////////
HINSTANCE hInstMain=NULL;//main application handle
HWND hWndMain=NULL;//handle to our main window
//IDirectDraw7 Pointer
LPDIRECTDRAW7 lpdd=NULL;
//surfaces
LPDIRECTDRAWSURFACE7 lpddsMain=NULL;
LPDIRECTDRAWSURFACE7 lpddsBack=NULL;
//tileset
CTileSet tsReversi;
//tile information structure
struct REVERSITILE
{
int iTileNum;//base tile number for square
bool bHilite;//hilited, or not hilited
int iPiece;//piece occupying square
bool bLastMove;//last move made
};
//the board
REVERSITILE Board[8][8];
//backup board
REVERSITILE BackUpBoard[8][8];
//current player
int iPlayer=0;
//counter for animated "flipping" of pieces
int iAnimation=0;
//ai level for the players
int iAILevel[2];
//gamestate
int iGameState=GS_NONE;
//////////////////////////////////////////////////////////////////////////////
//WINDOWPROC
//////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK TheWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
//which message did we get?
switch(uMsg)
{
case WM_LBUTTONUP:
{
//grab mouse position
POINT ptMouse;
ptMouse.x=LOWORD(lParam);
ptMouse.y=HIWORD(lParam);
//test rectangle
RECT rcTest;
//get tile width and height
int iTileWidth=tsReversi.GetTileList()[0].rcSrc.right-tsReversi.GetTileList()[0].rcSrc.left;
int iTileHeight=tsReversi.GetTileList()[0].rcSrc.bottom-tsReversi.GetTileList()[0].rcSrc.top;
//calc board rect
SetRect(&rcTest,(400-iTileWidth*4),(300-iTileHeight*4),(400+iTileWidth*4),(300+iTileHeight*4));
//point on board?
if(PtInRect(&rcTest,ptMouse))
{
//if we are waiting for input and the ai is "human", check for inside the board
if((iGameState==GS_WAITFORINPUT) && (iAILevel[iPlayer]==AI_HUMAN))
{
//find board position
int BoardX=(ptMouse.x-rcTest.left)/iTileWidth;
int BoardY=(ptMouse.y-rcTest.top)/iTileHeight;
//check for a valid square
if(ValidMove(iPlayer,BoardX,BoardY))
{
//make the move
MakeMove(iPlayer,BoardX,BoardY);
SetLastMove(BoardX,BoardY);
iGameState=GS_FLIP;
}
}
//if a game is over, start a new game by clicking on the board
if(iGameState==GS_NONE)
{
iGameState=GS_NEWGAME;
}
}
//check for the AI indicators
//player one
SetRect(&rcTest,0,600-iTileHeight,iTileWidth,600);
//check for mouse in rect
if(PtInRect(&rcTest,ptMouse))
{
iAILevel[PLAYERONE]++;
iAILevel[PLAYERONE]%=AI_COUNT;
}
//player two
SetRect(&rcTest,iTileWidth,600-iTileHeight,iTileWidth*2,600);
//check for mouse in rect
if(PtInRect(&rcTest,ptMouse))
{
iAILevel[PLAYERTWO]++;
iAILevel[PLAYERTWO]%=AI_COUNT;
}
}break;
case WM_KEYDOWN:
{
//check for escape key
if(wParam==VK_ESCAPE)
{
DestroyWindow(hWndMain);
}
//check for F2(new game)
if(wParam==VK_F2)
{
iGameState=GS_NEWGAME;
}
return(0);//handled message
}break;
case WM_DESTROY://the window is being destroyed
{
//tell the application we are quitting
PostQuitMessage(0);
//handled message, so return 0
return(0);
}break;
case WM_PAINT://the window needs repainting
{
//a variable needed for painting information
PAINTSTRUCT ps;
//start painting
HDC hdc=BeginPaint(hwnd,&ps);
/////////////////////////////
//painting code would go here
/////////////////////////////
//end painting
EndPaint(hwnd,&ps);
//handled message, so return 0
return(0);
}break;
}
//pass along any other message to default message handler
return(DefWindowProc(hwnd,uMsg,wParam,lParam));
}
//////////////////////////////////////////////////////////////////////////////
//WINMAIN
//////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
//assign instance to global variable
hInstMain=hInstance;
//create window class
WNDCLASSEX wcx;
//set the size of the structure
wcx.cbSize=sizeof(WNDCLASSEX);
//class style
wcx.style=CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
//window procedure
wcx.lpfnWndProc=TheWindowProc;
//class extra
wcx.cbClsExtra=0;
//window extra
wcx.cbWndExtra=0;
//application handle
wcx.hInstance=hInstMain;
//icon
wcx.hIcon=LoadIcon(NULL,IDI_APPLICATION);
//cursor
wcx.hCursor=LoadCursor(NULL,IDC_ARROW);
//background color
wcx.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
//menu
wcx.lpszMenuName=NULL;
//class name
wcx.lpszClassName=WINDOWCLASS;
//small icon
wcx.hIconSm=NULL;
//register the window class, return 0 if not successful
if(!RegisterClassEx(&wcx)) return(0);
//create main window
hWndMain=CreateWindowEx(0,WINDOWCLASS,WINDOWTITLE, WS_POPUP | WS_VISIBLE,0,0,320,240,NULL,NULL,hInstMain,NULL);
//error check
if(!hWndMain) return(0);
//if program initialization failed, then return with 0
if(!Prog_Init()) return(0);
//message structure
MSG msg;
//message pump
for(;;)
{
//look for a message
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
//there is a message
//check that we arent quitting
if(msg.message==WM_QUIT) break;
//translate message
TranslateMessage(&msg);
//dispatch message
DispatchMessage(&msg);
}
//run main game loop
Prog_Loop();
}
//clean up program data
Prog_Done();
//return the wparam from the WM_QUIT message
return(msg.wParam);
}
//////////////////////////////////////////////////////////////////////////////
//INITIALIZATION
//////////////////////////////////////////////////////////////////////////////
bool Prog_Init()
{
//seed random number generator
srand((int)GetTickCount());
//create directdraw interface
lpdd=LPDD_Create(hWndMain,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);
//set display mode(800x600x16)
lpdd->SetDisplayMode(800,600,16,0,0);
//create primary surface
lpddsMain=LPDDS_CreatePrimary(lpdd,1);
//get back buffer
lpddsBack=LPDDS_GetSecondary(lpddsMain);
//load in the tileset
tsReversi.Load(lpdd,"IsoHex10_4.bmp");
//clear the board
SetUpBoard();
//set game state
iGameState=GS_NONE;
//set initial AI levels
iAILevel[0]=AI_HUMAN;
iAILevel[1]=AI_RANDOM;
return(true);//return success
}
//////////////////////////////////////////////////////////////////////////////
//CLEANUP
//////////////////////////////////////////////////////////////////////////////
void Prog_Done()
{
//release primary
LPDDS_Release(&lpddsMain);
//release ddraw
LPDD_Release(&lpdd);
}
//////////////////////////////////////////////////////////////////////////////
//MAIN GAME LOOP
//////////////////////////////////////////////////////////////////////////////
void Prog_Loop()
{
//clear out back buffer
DDBLTFX ddbltfx;
DDBLTFX_ColorFill(&ddbltfx,0);
lpddsBack->Blt(NULL,NULL,NULL,DDBLT_WAIT | DDBLT_COLORFILL,&ddbltfx);
switch(iGameState)
{
case GS_WAITFORINPUT:
{
//make move appropriate to the AI
switch(iAILevel[iPlayer])
{
case AI_RANDOM:
{
MakeRandomMove(iPlayer);
}break;
case AI_GREEDY:
{
MakeGreedyMove(iPlayer);
}break;
case AI_MISER:
{
MakeMiserMove(iPlayer);
}break;
}
}break;
case GS_NEWGAME:
{
//clear the board
SetUpBoard();
//set player
iPlayer=PLAYERTWO;
//change gamestate
iGameState=GS_NEXTPLAYER;
}break;
case GS_NEXTPLAYER:
{
//scan for moves
ScanForMoves(iPlayer);
//if no more valid moves, game over
if((!AnyValidMoves(PLAYERTWO)) && (!AnyValidMoves(PLAYERONE)))
{
iGameState=GS_NONE;
}
else
{
//find if opponent has any moves
if(AnyValidMoves(1-iPlayer))
{
iPlayer=1-iPlayer;
}
//scan for moves by current player
ScanForMoves(iPlayer);
//get next move
iGameState=GS_WAITFORINPUT;
}
}break;
case GS_FLIP:
{
switch(iPlayer)
{
case PLAYERTWO:
{
if(iAnimation==0)
{
FinishMove(iPlayer);
iGameState=GS_NEXTPLAYER;
}
else
{
iAnimation--;
}
}break;
case PLAYERONE:
{
if(iAnimation==14)
{
FinishMove(iPlayer);
iGameState=GS_NEXTPLAYER;
}
else
{
iAnimation++;
}
}break;
}
}break;
}
//show the board
ShowBoard();
//show the scores
ShowScores();
//show players
ShowPlayers();
//flip
lpddsMain->Flip(NULL,DDFLIP_WAIT);
}
void SaveBoard()
{
//loop through board squares
for(int x=0;x<8;x++)
{
for(int y=0;y<8;y++)
{
//save square to backup
BackUpBoard[x][y]=Board[x][y];
}
}
}
void RestoreBoard()
{
//loop through board squares
for(int x=0;x<8;x++)
{
for(int y=0;y<8;y++)
{
//restore from backup
Board[x][y]=BackUpBoard[x][y];
}
}
}
void SetUpBoard()
{
//loop through board squares
for(int x=0;x<8;x++)
{
for(int y=0;y<8;y++)
{
//setup board square
Board[x][y].bHilite=false;
Board[x][y].iTileNum=0;
Board[x][y].iPiece=PIECEEMPTY;
Board[x][y].bLastMove=false;
}
}
//place initial pieces
Board[3][3].iPiece=PIECEWHITE;
Board[4][4].iPiece=PIECEWHITE;
Board[3][4].iPiece=PIECEBLACK;
Board[4][3].iPiece=PIECEBLACK;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?