Jump to content
  • Advertisement

RedKMan

Member
  • Content Count

    90
  • Joined

  • Last visited

Community Reputation

122 Neutral

About RedKMan

  • Rank
    Member
  1. Thanks for replying, the objects are all in one array though. I've had a change of mind and I'm now trying to have the bricks moving in a space invaders type pattern but not moving down one each time. When the first brick to hit the right border reverses its movement I want all bricks on that row to do the same. Then when the first brick to hit the left border reverses its movement I want all bricks on that row to do the same. So they never collide and just keep moving right to left. This is how I init the array. public void initBrickArray() { int k = 0; for(int i = 0; i < 5; i++) { for(int j = 0; j < 6; j++) { myBrick[k] = new Brick(j * 80 + 14, i * 40 + 40); k++; } } } This is how I test to see if any brick hits the borders and make them reverse direction. public void brickTest(int width, int height) { if(x > width - brickWidth - OFFSET) { direction = -2; } if(x <= 0) { direction = 2; } x = x + direction; } This is how I check to see if the first brick hits the border (not working)! public void brickCollisionTest(int width, int height) { for(int i = 0; i < 30; i++) { myBrick.brickTest(width, height); if(i < 29) { // if(myBrick.area().intersects(myBrick[i + 1].area())) if(myBrick.getX() == myBrick[i + 1].getX()) { myBrick.setDirection(-myBrick.getDirection()); } } } Anyone help?
  2. I'm doing a simple breakout clone and have completed it. I now want to add an extra element to it. I want the bricks to move from one side of the screen to the other. For example every brick on every row starts off moving right. When the last brick on the row (the first brick to hit the right border of the JFrame) hits the border it should bounce off it and start moving left. This should cause it to collide with the brick to the left of it causing that brick to bounce off it and move left hitting the next brick and so on. Basically the bricks switch direction when they hit either each other or the borders. so far I can have an array of two bricks move from left to right bouncing off the sides but not each other. I've tried using intersect() but this isn't really working. I can't think of a nice way of checking if element i in the array intersects with element [i - 1] or element [i + 1] as this causes Array out of bounds exceptions with the first and last element. Wondering if anyone has any thoughts? Many Thanks,
  3. I have drawn a grid of ellipses using the code below. for(x =1 ; x <= ROWS; x++) { for(y = 2; y <= COLUMNS; y++) { Ellipse(hdc, x * 100 + 20, y * 100 + 20, (x + 1) * 100, (y + 1) * 100); } } Please ignore the fact y starts at 2, its a quick fix to a display problem :). The + 20 puts a space of that value between all ellipses. Basically these ellipses represent slots on a connect four board. What I'm totally stumped on is how to know which ellipse has been clicked. I know that LPARAM LOWORD and HIWORD hold the x,y coordinates of the mouse click. Problem I'm having is finding a way to map that mouse click to the right ellipse. Suggestions appreciated.
  4. Massive thanks for the suggestions they have really helped me. I think function naming is going to be a problem of mine for a long time to come :).
  5. I'm trying to implement enum's and just wanted to double check I have the right idea here. I kinda prefer everything to be encapsulated hence the reason for sticking the enum decleration in the GameBoard class. I know its a pain having to use GameBoard:: everywhere but feels better. Also be great if anyone can take a quick look at the overall project and point out anything that could be done better or sticks out as being ugly. My plan is to put the actual drawing functions, drawBoard and drawMarker in the WinMain() rather than encapsulate them in GameBoard / Player classes because they don't really fit in there as these classes contain more logic methods. I'm really try to attain good OO practise, elegant code, proper abstraction and good encapsulation so if I'm going wrong would be great if someone could advie where. GameBoard.h [Source] #ifndef GAMEBOARD_H #define GAMEBOARD_H #include <iostream> #include <vector> #include <math.h> #include <tchar.h> #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <string> class GameBoard { public: GameBoard(); // Values that can only exist on the board. enum BOARDVALUES {BLANK, RED, YELLOW}; // Get the board const std::vector<unsigned>& getBoard(); // Return the value stored at position on the board. const unsigned getValue(unsigned position); // Initialise the board void initialise(); // Update the instance variable board with the current player's marker in the relevant // position in the array. bool setBoard(unsigned position, BOARDVALUES playerMarker); // Update the instance variable board by setting the location position to blank. // This is for use with the WinMain.cpp function evaluateAI(). void unsetBoard(unsigned position); // Check to see if there are any places left on the board. const bool placesAvailable(); // Check to see if the player has produced a winning game state. const bool checkWinningLine(BOARDVALUES playerMarker); private: std::vector<unsigned> board; }; #endif [/Source] Player.h [Source] #ifndef PLAYER_H #define PLAYER_H #include <string> #include <tchar.h> #include "GameBoard.h" class Player { public: // Player Class Constructor. Player(); // Get the players name. const std::wstring& getName(); // Get the players marker. const GameBoard::BOARDVALUES getMarker(); // Get the players current position selection. const unsigned getPosition(); // Get the number of games won. const unsigned getGamesWon(); // Get the players state. const bool getState(); // Set the players name. void setName(const std::wstring &aName); // Set the players marker. void setMarker(GameBoard::BOARDVALUES aMarker); // Set the players position selection. void setPosition(unsigned aPosition); // Set the state of the player. void setState(bool aState); // Increments the number of games the player has won by one. void incrementGamesWon(); // Clears the number of games the player has won to zero. void clearGamesWon(); private: std::wstring name; // The name of the player. GameBoard::BOARDVALUES marker; // The mark this player will place on the board. unsigned position; // Holds the current position choice. unsigned gamesWon; // Holds the number of times this player has won. bool state; // True if it's this players turn, false otherwise. }; #endif [/Source] GameBoard.cpp [Source] #include "GameBoard.h" //--------------------------------------------------------------- // Name: Constructor() // Desc: Sets the size of the board to 7 * 6 and sets all the // elements to zero. //--------------------------------------------------------------- GameBoard::GameBoard() : board(7 * 6, 0) { } //--------------------------------------------------------------- // Name: getBoard() // Desc: Returns the board. //--------------------------------------------------------------- const std::vector<unsigned>& GameBoard::getBoard() { return board; } //--------------------------------------------------------------- // Name: getValue() // Desc: Returns the value stored at position of the board. //--------------------------------------------------------------- const unsigned GameBoard::getValue(unsigned position) { return board[position]; } //--------------------------------------------------------------- // Name: initBoard() // Desc: Sets the size of the board to 7 * 6 and sets all the // elements to zero. //--------------------------------------------------------------- void GameBoard::initialise() { board.assign(7 * 6, BLANK); } //--------------------------------------------------------------- // Name: setBoard() // Desc: Checks to make sure the choice is empty and valid, // e.g. within the range of 0 and 42 and does not // allready contain a playerMarker. Sets the position // to either a yellow or red marker. //--------------------------------------------------------------- bool GameBoard::setBoard(unsigned position, BOARDVALUES playerMarker) { bool success = true; // Bounds check. if((position < 0) || (position > board.size())) { success = false; } // Check to see if position is empty. if(getValue(position) != 0) { success = false; } // position is valid so update the board at position // with playerMarker. board[position] = playerMarker; return success; } //--------------------------------------------------------------- // Name: unsetBoard() // Desc: Sets the position on the board to empty. For use // with evaluateAI. //--------------------------------------------------------------- void GameBoard::unsetBoard(unsigned position) { board[position] = BLANK; } //--------------------------------------------------------------- // Name: placesAvailable() // Desc: Returns true if there are still spaces available or false // otherwise. //--------------------------------------------------------------- const bool GameBoard::placesAvailable() { bool success = false; for(unsigned index = 0; index < board.size(); index++) { // Check to see if there are spaces still available. if(board[index] == BLANK) { success = true; } } return success; } //--------------------------------------------------------------- // Name: checkWinningLine() // Desc: Returns true if player has winning line or false otherwise. //--------------------------------------------------------------- const bool GameBoard::checkWinningLine(BOARDVALUES playerMarker) { bool success = false; return success; } [/Source] Player.cpp [Source] #include "Player.h" //--------------------------------------------------------------- // Name: Constructor() // Desc: Player Class Constructor //--------------------------------------------------------------- Player::Player() : gamesWon(0) { } //--------------------------------------------------------------- // Name: getName() // Desc: Returns the value held in the attribute name. //--------------------------------------------------------------- const std::wstring& Player::getName() { return name; } //--------------------------------------------------------------- // Name: getMarker() // Desc: Returns the value held in the attribute marker. //--------------------------------------------------------------- const GameBoard::BOARDVALUES Player::getMarker() { return marker; } //--------------------------------------------------------------- // Name: getPosition() // Desc: Returns the value held in the attribute position. //--------------------------------------------------------------- const unsigned Player::getPosition() { return position; } //--------------------------------------------------------------- // Name: getGamesWon() // Desc: Returns the value held in the attribute gamesWon. //--------------------------------------------------------------- const unsigned Player::getGamesWon() { return gamesWon; } //--------------------------------------------------------------- // Name: getState() // Desc: Returns the value held in the attribute state. //--------------------------------------------------------------- const bool Player::getState() { return state; } //--------------------------------------------------------------- // Name: setName() // Desc: Sets the attribute name. //--------------------------------------------------------------- void Player::setName(const std::wstring &aName) { name = aName; } //--------------------------------------------------------------- // Name: setMarker() // Desc: Sets the attribute marker to either 1 = Red or 2 = Yellow. //--------------------------------------------------------------- void Player::setMarker(GameBoard::BOARDVALUES aMarker) { marker = aMarker; } //--------------------------------------------------------------- // Name: setPosition() // Desc: Sets the attribute position to either 1 = Red or 2 = Yellow. //--------------------------------------------------------------- void Player::setPosition(unsigned aPosition) { position = aPosition; } //--------------------------------------------------------------- // Name: setState() // Desc: Sets the attribute state to either true or false. //--------------------------------------------------------------- void Player::setState(bool aState) { state = aState; } //--------------------------------------------------------------- // Name: incrementGamesWon() // Desc: Increments the number of games the player has won by one. //--------------------------------------------------------------- void Player::incrementGamesWon() { gamesWon++; } //--------------------------------------------------------------- // Name: clearGamesWon() // Desc: Clears the number of games the player has won to zero. //--------------------------------------------------------------- void Player::clearGamesWon() { gamesWon = 0; } [/Source]
  6. RedKMan

    Simple WIN32 Game Loop

    Very nice boogyman19946, given me some ideas :) Thanks Deliverance. I'm pretty happy with it and it works. I've already made some mods since my last project. It will be a process as I complete and move onto other projects.
  7. I'm going to do a simple WIN32 GDI only Connect Four game. Just wondering if the WinMain .cpp code below is OK enough for something like this. Can I make it more effecient or is it fit for the purpose? I used something similar for a Tic Tac Toe game and it worked fine just wondering if there's a better more elegant solution out there. Is it OK to organise things into the three functions initGame(), mainGame(), shutdownGame() like this? [Source] #include <windows.h> #include <tchar.h> #include <time.h> #include <stdio.h> #include <stdlib.h> // Windows application variables. HWND g_hWnd = 0; HINSTANCE g_hInstance = 0; BOOL g_bActive = FALSE; BOOL g_bDone = FALSE; TCHAR g_szAppClass[] = TEXT( "Application" ); TCHAR g_szAppTitle[] = TEXT( "Connect Four" ); // Windows application function prototypes. LRESULT WINAPI MsgProc( HWND, UINT, WPARAM, LPARAM ); // Game application function prototypes. void initGame(); void mainGame(); void shutdownGame(); //--------------------------------------------------------------- // Name: WinMain() // Desc: Called as soon as the Application is loaded. //--------------------------------------------------------------- int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { WNDCLASSEX wndclass; HWND hWnd; MSG msg; // Setup the window attributes wndclass.cbSize = sizeof( wndclass ); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; wndclass.lpfnWndProc = MsgProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); wndclass.hbrBackground = ( HBRUSH ) ( COLOR_WINDOW ); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = g_szAppClass; // Registered class name wndclass.hIconSm = LoadIcon( NULL, IDI_APPLICATION ); // Register the new window if( RegisterClassEx( &wndclass ) == 0 ) exit(1); // Create the main window. Window parameters make the main window // 640X480 only hWnd = CreateWindow( g_szAppClass, // Class Name g_szAppTitle, // Name displayed on title bar WS_OVERLAPPEDWINDOW, // Window style, using Popup 0, // X Position (Top Left) 0, // Y Position (Top Right) 640, // X Position (Bottom Right) 640, // Y Position (Bottom Left) NULL, NULL, hInstance, NULL ); // Tell windows to show the application ShowWindow( hWnd, nCmdShow ); // Update the client by sending an initial WM_PAINT msg UpdateWindow( hWnd ); // Save the main window handle g_hWnd = hWnd; // Save the main application instance g_hInstance = hInstance; initGame(); // Main Message Loop. Keep looping through this application until // the user chooses to exit. When the user chooses exit by clicking // the red X box top right of the window for example. A WM_QUIT // message will be sent to the application which prompts the application // to exit. ZeroMemory( &msg, sizeof( msg ) ); while( !g_bDone ) { while( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } if(msg.message == WM_QUIT) { break; } if( g_bActive ) { mainGame(); } } shutdownGame(); UnregisterClass( g_szAppClass, hInstance ); // Return back to Windows return( ( int ) msg.wParam ); } //--------------------------------------------------------------- // Name: MsgProc() // Desc: This is the main window message handling function //--------------------------------------------------------------- LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { PAINTSTRUCT ps; HDC hdc; switch( msg ) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); break; case WM_ACTIVATE: // The message WM_ACTIVE is sent whenever the application has focus. // For example if the application is minimised then it is not in focus. // As the application is not in focus it is pointless wasting clock // cycles and graphics hardware to render to what cannot be seen. g_bActive = ( BOOL ) wParam; break; case WM_KEYDOWN: // Whenever a key is pressed (non-accelerated ie shift and f5, then // this message is sent. switch( wParam ) { case VK_ESCAPE: // If the user presses the Escape key then we will quit the // application g_bDone = TRUE; PostMessage( g_hWnd, WM_CLOSE, 0, 0 ); return 0; }; break; case WM_DESTROY: // The message WM_DESTROY is sent by the Windows Messaging System // when our message queue recieves the WM_QUIT message from the // application. It just cleans everything up and quits the // application g_bDone = TRUE; PostQuitMessage( 0 ); return 1; break; default: break; } // If any messages reach here then it was not handled by our application. // So we will return it back to the queue so the next Windows application // like a background task. return DefWindowProc( hWnd, msg, wParam, lParam ); } //--------------------------------------------------------------- // Name: initGame() // Desc: //--------------------------------------------------------------- void initGame() { // Initialisation. } //--------------------------------------------------------------- // Name: mainGame() // Desc: //--------------------------------------------------------------- void mainGame() { // Game calls. } //--------------------------------------------------------------- // Name: shutdownGame() // Desc: //--------------------------------------------------------------- void shutdownGame() { // Cleanup. } [/Source]
  8. This is excellant, exactly what I needed. Thanks guys :)
  9. Thanks boogyman19946, some useful stuff :).
  10. GameBoard.h //--------------------------------------------------------------- // File: GameBoard.h // // Desc: The class that deals with all gameboard activity. // // Date: January 2nd, 2010. //--------------------------------------------------------------- #ifndef GAMEBOARD_H #define GAMEBOARD_H #include <iostream> #include <vector> #include <math.h> #include <tchar.h> #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <string> class GameBoard { public: GameBoard(); // Get the board size. const unsigned getBoardSize(); // Get the board dimensions. const unsigned getBoardDims(); // Get the board const std::vector<char>& getBoard(); // Return the value stored at x, y of the board. const char getBoard(unsigned row, unsigned column); // Initialise the board void initBoard(); // Convert 2D Row / Column Index to 1D Value. unsigned convertIndex(unsigned row, unsigned column); // Update the instance variable board with the current player's marker in the relevant // position in the array. bool setBoard(unsigned row, unsigned column, WCHAR playerMarker); // Update the instance variable board with the AI players marker in // the relevant position in the array. bool setBoard(unsigned move, WCHAR playerMarker); // Update the instance variable board by setting the location row, col to blank. // This is for use with the WinMain.cpp function evaluateAI(). void unsetBoard(unsigned row, unsigned column); // Check to see if there are any places left on the board. const bool gameOver(); // Check to see if the player has produced a winning game state. const bool checkWinningLine(WCHAR playerMarker); private: unsigned boardSize; std::vector<char> board; unsigned boardDims; }; #endif Player.h //--------------------------------------------------------------- // File: Player.h // // Desc: The class that represents the players. // // Date: January 2nd, 2010. //--------------------------------------------------------------- #ifndef PLAYER_H #define PLAYER_H #include <string> #include <tchar.h> #include "GameBoard.h" class Player { public: // Player Class Constructor. Player(); // Get the players name. const std::wstring& getName(); // Get the players marker. const WCHAR getMarker(); // Get the players current row selection. const int getRow(); // Get the players current column selection. const int getColumn(); // Get the number of games won. const int getGamesWon(); // Get the players state. const bool getState(); // Set the players name. void setName(const std::wstring &playerName); // Set the players marker. void setMarker(WCHAR playerMarker); // Set the players row selection. void setRow(int playerRow); // Set the players column selection. void setColumn(int playerColumn); // Set the state of the player. void setState(bool playerState); // Increments the number of games the player has won by one. void incrementGamesWon(); // Clears the number of games the player has won to zero. void clearGamesWon(); private: std::wstring name; // The name of the player. WCHAR marker; // The mark this player will place on the board. Can either be X or O. int row; // Holds the current row choice. int column; // Holds the current column choice. int gamesWon; // Holds the number of times this player has won. bool state; // True if it's this players turn, false otherwise. }; #endif GameBoard.CPP //--------------------------------------------------------------- // File: GameBoard.cpp // // Desc: Implements the game board. // // Date: January 2nd, 2010. //--------------------------------------------------------------- #include "GameBoard.h" //--------------------------------------------------------------- // Name: Constructor() // Desc: Takes an integer value which is used to set the size of // the board. Calls initBoard() to initialise or reset the // game board. //--------------------------------------------------------------- GameBoard::GameBoard() : boardSize(3 * 3), boardDims(3), board(3 * 3, '\0') { } //--------------------------------------------------------------- // Name: getBoardSize() // Desc: Returns the size of the board. //--------------------------------------------------------------- const unsigned GameBoard::getBoardSize() { return boardSize; } //--------------------------------------------------------------- // Name: getBoardDims() // Desc: Returns the dimensions of the board. //--------------------------------------------------------------- const unsigned GameBoard::getBoardDims() { return boardDims; } //--------------------------------------------------------------- // Name: getBoard() // Desc: Returns the board. //--------------------------------------------------------------- const std::vector<char>& GameBoard::getBoard() { return board; } //--------------------------------------------------------------- // Name: getBoard() // Desc: Return the value stored at x, y of the board. //--------------------------------------------------------------- const char GameBoard::getBoard(unsigned row, unsigned column) { return board[convertIndex(row, column)]; } //--------------------------------------------------------------- // Name: initBoard() // Desc: Initialise / clear the game board //--------------------------------------------------------------- void GameBoard::initBoard() { board.assign(boardSize, '\0'); } //--------------------------------------------------------------- // Name: convertIndex() // Desc: Convert 2D Row / Column Index to 1D Value. //--------------------------------------------------------------- unsigned GameBoard::convertIndex(unsigned row, unsigned column) { return row * (boardDims) + column; } //--------------------------------------------------------------- // Name: setBoard() // Desc: Checks to make sure the choice is empty and valid, // e.g. within the range of 0 and 2 for both row and column // and does not allready contain a O or X. // Sets the location row, column to either X or O // depending on the argument marker. //--------------------------------------------------------------- bool GameBoard::setBoard(unsigned row, unsigned column, WCHAR playerMarker) { // Check to see if either row or column is greater than // the actual board size. if((convertIndex(row, column) < 0) || (convertIndex(row, column) > boardSize)) { return false; } // Check to see if the players choice is an empty position. if(getBoard(row, column) != '\0') { return false; } // The user choice is valid and the location is empty so update // the game board with the players relevant marker either X or O. board[convertIndex(row, column)] = playerMarker; return true; } //--------------------------------------------------------------- // Name: setBoard() // Desc: ** Temp solution for setting board for AI ** //--------------------------------------------------------------- bool GameBoard::setBoard(unsigned move, WCHAR playerMarker) { // Check to see if the players choice is an empty position. if(board[move] != '\0') { return false; } board[move] = playerMarker; return true; } //--------------------------------------------------------------- // Name: unsetBoard() // Desc: Sets the board location row, col to empty. //--------------------------------------------------------------- void GameBoard::unsetBoard(unsigned row, unsigned column) { board[convertIndex(row, column)] = '\0'; } //--------------------------------------------------------------- // Name: gameOver() // Desc: Returns true if there are still spaces available or false // otherwise. //--------------------------------------------------------------- const bool GameBoard::gameOver() { for(unsigned index = 0; index < boardSize; index++) { // Check to see if there are spaces still available. if(board[index] == '\0') { return true; } } return false; } //--------------------------------------------------------------- // Name: checkWinningLine() // Desc: Returns true if player has winning line or false otherwise. //--------------------------------------------------------------- const bool GameBoard::checkWinningLine(WCHAR playerMarker) { int rowCheck; int colCheck; int diagCheck = 0; int diagCheck1 = 0; int y = 0; int c = 2; for(int i = 0; i < 3; i++, y++, c--) { rowCheck = 0; colCheck = 0; if(getBoard(i, y) == playerMarker) diagCheck++; if(getBoard(i, c) == playerMarker) diagCheck1++; for(int j = 0; j < 3; j++) { if(getBoard(i, j) == playerMarker) rowCheck++; if(getBoard(j, i) == playerMarker) colCheck++; } if((rowCheck == 3) || (colCheck == 3)) return true; } if((diagCheck == 3) || (diagCheck1 == 3)) return true; return false; } Player.cpp //--------------------------------------------------------------- // File: Player.cpp // // Desc: Implements the players. // // Date: January 2nd, 2010. //--------------------------------------------------------------- #include "Player.h" //--------------------------------------------------------------- // Name: Constructor() // Desc: Player Class Constructor //--------------------------------------------------------------- Player::Player() : gamesWon(0) { } //--------------------------------------------------------------- // Name: getName() // Desc: Returns the value held in the attribute playerName. //--------------------------------------------------------------- const std::wstring& Player::getName() { return name; } //--------------------------------------------------------------- // Name: getMarker() // Desc: Returns the value held in the attribute playerMarker. //--------------------------------------------------------------- const WCHAR Player::getMarker() { return marker; } //--------------------------------------------------------------- // Name: getRow() // Desc: Returns the value held in the attribute playerRow. //--------------------------------------------------------------- const int Player::getRow() { return row; } //--------------------------------------------------------------- // Name: getColumn() // Desc: Returns the value held in the attribute playerColumn. //--------------------------------------------------------------- const int Player::getColumn() { return column; } //--------------------------------------------------------------- // Name: getGamesWon() // Desc: Returns the value held in the attribute gamesWon. //--------------------------------------------------------------- const int Player::getGamesWon() { return gamesWon; } //--------------------------------------------------------------- // Name: getState() // Desc: Returns the value held in the attribute State. //--------------------------------------------------------------- const bool Player::getState() { return state; } //--------------------------------------------------------------- // Name: setName() // Desc: Sets the attribute playerName. //--------------------------------------------------------------- void Player::setName(const std::wstring &playerName) { name = playerName; } //--------------------------------------------------------------- // Name: setMarker() // Desc: Sets the attribute playerMarker to either X or O. //--------------------------------------------------------------- void Player::setMarker(WCHAR playerMarker) { marker = playerMarker; } //--------------------------------------------------------------- // Name: setRow() // Desc: Sets the attribute playerRow to either 0, 1 or 2. //--------------------------------------------------------------- void Player::setRow(int playerRow) { row = playerRow; } //--------------------------------------------------------------- // Name: setColumn() // Desc: Sets the attribute playerColumn to either 0, 1 or 2. //--------------------------------------------------------------- void Player::setColumn(int playerColumn) { column = playerColumn; } //--------------------------------------------------------------- // Name: setState() // Desc: Sets the attribute state to either true or false. //--------------------------------------------------------------- void Player::setState(bool playerState) { state = playerState; } //--------------------------------------------------------------- // Name: incrementGamesWon() // Desc: Increments the number of games the player has won by one. //--------------------------------------------------------------- void Player::incrementGamesWon() { gamesWon++; } //--------------------------------------------------------------- // Name: clearGamesWon() // Desc: Clears the number of games the player has won to zero. //--------------------------------------------------------------- void Player::clearGamesWon() { gamesWon = 0; } WinMain.cpp //--------------------------------------------------------------- // File: WinMain.cpp // // Desc: Game Application // // Date: January 2nd, 2010. //--------------------------------------------------------------- #include <windows.h> #include <tchar.h> #include <time.h> #include <stdio.h> #include <stdlib.h> #include "GameBoard.h" #include "Player.h" #include "Resource.h" // Windows application variables. HWND g_hWnd = 0; HINSTANCE g_hInstance = 0; BOOL g_bActive = FALSE; BOOL g_bDone = FALSE; TCHAR g_szAppClass[] = TEXT( "Application" ); TCHAR g_szAppTitle[] = TEXT( "Tic Tac Toe V0.1" ); // Tic Tac Toe game application variables. GameBoard TicTacToe; // Instantiate an object of GameBoard for the game. Player players[2]; // Array of two Player objects. bool onePlayerGame; // If True then single player game, if false then two player game. std::wstring names[2]; // Array holding the players names. int currentPlayer; // Determines if its player 0 or player 1's turn. bool bValidMove; // Is the move valid. bool gameOver; // Is the game over, true if the board is full or someone has won. int aiMove; // Holds the computers choice. WCHAR marker[2] = {'X', 'O'}; // Array holding the players markers. bool state[2] = {true, false}; // Array holding the players state. True = current active player. // Tic Tac Toe game application function prototypes. void initGame(); const void displayBoard(GameBoard &gameBoard, Player &playerOne, Player &playerTwo, HWND hWnd); bool gameState(GameBoard &TicTacToe, Player &player, HWND hWnd); int random(); bool placeMarker(GameBoard &TicTacToe, Player &player, LPARAM lParam, HWND hWnd); int evaluateAI(GameBoard &TicTacToe, int Player, int &bestMove); bool placeMarkerAI(GameBoard &TicTacToe, Player &player, int aiMove, HWND hWnd); void drawX(int row, int column, HDC hdc); void drawO(int row, int column, HDC hdc); bool replayGame(); void finalScores(); int setCurrentPlayer(); // Windows application function prototypes. INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, INT ); LRESULT WINAPI MsgProc( HWND, UINT, WPARAM, LPARAM ); BOOL CALLBACK IntroDlgProc( HWND hIntroDlg, UINT Message, WPARAM wParam, LPARAM lParam ); //--------------------------------------------------------------- // Name: WinMain() // Desc: Called as soon as the Application is loaded. //--------------------------------------------------------------- int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { WNDCLASSEX wndclass; HWND hWnd; MSG msg; // Setup the window attributes wndclass.cbSize = sizeof( wndclass ); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; wndclass.lpfnWndProc = MsgProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); wndclass.hbrBackground = ( HBRUSH ) ( COLOR_WINDOW ); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = g_szAppClass; // Registered class name wndclass.hIconSm = LoadIcon( NULL, IDI_APPLICATION ); // Register the new window if( RegisterClassEx( &wndclass ) == 0 ) exit(1); // Create the main window. Window parameters make the main window // 640X480 only hWnd = CreateWindow( g_szAppClass, // Class Name g_szAppTitle, // Name displayed on title bar WS_OVERLAPPEDWINDOW, // Window style, using Popup 0, // X Position (Top Left) 0, // Y Position (Top Right) 640, // X Position (Bottom Right) 640, // Y Position (Bottom Left) NULL, NULL, hInstance, NULL ); // Tell windows to show the application ShowWindow( hWnd, nCmdShow ); // Update the client by sending an initial WM_PAINT msg UpdateWindow( hWnd ); // Save the main window handle g_hWnd = hWnd; // Save the main application instance g_hInstance = hInstance; // call device selection dialog INT nResult = DialogBox( g_hInstance, MAKEINTRESOURCE( IDD_DIALOG1 ), hWnd, IntroDlgProc ); if( nResult == -1 ) { MessageBox( hWnd, L"IntroDialog() Error", L"WinMain()", MB_OK | MB_ICONINFORMATION ); return E_FAIL; } if( nResult == 2 ) { MessageBox( hWnd, L"IntroDialog() Cancelled by user", L"WinMain()", MB_OK | MB_ICONINFORMATION ); return S_FALSE; } initGame(); // Main Message Loop. Keep looping through this application until // the user chooses to exit. When the user chooses exit by clicking // the red X box top right of the window for example. A WM_QUIT // message will be sent to the application which prompts the application // to exit. ZeroMemory( &msg, sizeof( msg ) ); while( !g_bDone ) { while( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } if(msg.message == WM_QUIT) { break; } // Set the current player. currentPlayer = setCurrentPlayer(); if( g_bActive ) { if(onePlayerGame) { if(players[currentPlayer].getName() == L"Computer") { evaluateAI(TicTacToe, currentPlayer, aiMove); bValidMove = placeMarkerAI(TicTacToe, players[currentPlayer], aiMove, hWnd); if(bValidMove) { if(players[0].getState()) { players[0].setState(false); players[1].setState(true); } else if(!players[0].getState()) { players[0].setState(true); players[1].setState(false); } } else { std::wstring pErrorText = players[currentPlayer].getName() + L" please try again!. "; MessageBox( hWnd, pErrorText.c_str(), L"MsgProc WM_LBUTTONDOWN Error", MB_OK | MB_ICONINFORMATION ); } InvalidateRect(hWnd, 0, TRUE); gameOver = gameState(TicTacToe, players[currentPlayer], hWnd); if(gameOver) { if(!replayGame()) { g_bDone = TRUE; finalScores(); PostMessage( g_hWnd, WM_CLOSE, 0, 0 ); } else { bValidMove = FALSE; TicTacToe.initBoard(); InvalidateRect(hWnd, 0, TRUE); } } } } } } UnregisterClass( g_szAppClass, hInstance ); // Return back to Windows return( ( int ) msg.wParam ); } //--------------------------------------------------------------- // Name: MsgProc() // Desc: This is the main window message handling function //--------------------------------------------------------------- LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { PAINTSTRUCT ps; HDC hdc; bool bValidMove; bool gameOver; int aiMove; switch( msg ) { case WM_LBUTTONDOWN: currentPlayer = setCurrentPlayer(); if(players[currentPlayer].getName() != L"Computer") { bValidMove = placeMarker(TicTacToe, players[currentPlayer], lParam, hWnd); } if(bValidMove) { if(players[0].getState()) { players[0].setState(false); players[1].setState(true); } else if(!players[0].getState()) { players[0].setState(true); players[1].setState(false); } } else { std::wstring pErrorText = players[currentPlayer].getName() + L" please try again!. "; MessageBox( hWnd, pErrorText.c_str(), L"MsgProc WM_LBUTTONDOWN Error", MB_OK | MB_ICONINFORMATION ); } InvalidateRect(hWnd, 0, TRUE); gameOver = gameState(TicTacToe, players[currentPlayer], hWnd); if(gameOver) { if(!replayGame()) { g_bDone = TRUE; finalScores(); PostMessage( g_hWnd, WM_CLOSE, 0, 0 ); } else { bValidMove = FALSE; TicTacToe.initBoard(); InvalidateRect(hWnd, 0, TRUE); } } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); displayBoard(TicTacToe, players[0], players[1], hWnd); // Draw Xs and Os for (int iX = 0; iX < 3; iX++) { for (int iY = 0; iY < 3; iY++) { if(TicTacToe.getBoard(iY, iX) == 'X') { drawX(iY, iX, hdc); } else if (TicTacToe.getBoard(iY, iX) == 'O') { drawO(iY, iX, hdc); } } } EndPaint(hWnd, &ps); break; case WM_ACTIVATE: // The message WM_ACTIVE is sent whenever the application has focus. // For example if the application is minimised then it is not in focus. // As the application is not in focus it is pointless wasting clock // cycles and graphics hardware to render to what cannot be seen. g_bActive = ( BOOL ) wParam; break; case WM_KEYDOWN: // Whenever a key is pressed (non-accelerated ie shift and f5, then // this message is sent. switch( wParam ) { case VK_ESCAPE: // If the user presses the Escape key then we will quit the // application g_bDone = TRUE; PostMessage( g_hWnd, WM_CLOSE, 0, 0 ); return 0; }; break; case WM_DESTROY: // The message WM_DESTROY is sent by the Windows Messaging System // when our message queue recieves the WM_QUIT message from the // application. It just cleans everything up and quits the // application g_bDone = TRUE; PostQuitMessage( 0 ); return 1; break; default: break; } // If any messages reach here then it was not handled by our application. // So we will return it back to the queue so the next Windows application // like a background task. return DefWindowProc( hWnd, msg, wParam, lParam ); } //--------------------------------------------------------------- // Name: IntroDlgProc() // Desc: IntroDialog Message Handler //--------------------------------------------------------------- BOOL CALLBACK IntroDlgProc( HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam ) { HWND hP1Name = GetDlgItem( hDlg, IDC_P1Name ); HWND hP2Name = GetDlgItem( hDlg, IDC_P2Name ); HWND h1PGame = GetDlgItem( hDlg, IDC_1PGame ); HWND h2PGame = GetDlgItem( hDlg, IDC_2PGame ); TCHAR P1Name[128]; TCHAR P2Name[128]; switch( Message ) { case WM_INITDIALOG: // Set the radio button to Two Player SendMessage( h2PGame, BM_SETCHECK, BST_CHECKED, 0 ); return TRUE; break; case WM_COMMAND: switch( LOWORD( wParam ) ) { case IDOK: GetDlgItemText ( hDlg , IDC_P1Name , P1Name , 128 ); GetDlgItemText ( hDlg , IDC_P2Name , P2Name , 128 ); names[0] = P1Name; names[1] = P2Name; onePlayerGame = SendMessage( h2PGame, BM_GETCHECK, 0, 0 ) != BST_CHECKED; EndDialog( hDlg, IDOK ); return TRUE; break; case IDCANCEL: EndDialog( hDlg, IDCANCEL ); return TRUE; break; case IDC_P1Name: break; case IDC_P2Name: break; case IDC_1PGame: if( SendMessage( h1PGame, BM_GETCHECK, 0, 0 ) == BST_CHECKED ) SetWindowText(hP2Name, L"Computer"); onePlayerGame = TRUE; break; case IDC_2PGame: if( SendMessage( h2PGame, BM_GETCHECK, 0, 0 ) == BST_CHECKED ) SetWindowText(hP2Name, L""); onePlayerGame = FALSE; break; } break; } return FALSE; } //--------------------------------------------------------------- // Name: initGame() // Desc: //--------------------------------------------------------------- void initGame() { srand ( time(NULL) ); // Initialises the random seed for the random() function. if(random() % 2) { std::swap(marker[0], marker[1]); } if(random() % 2) { std::swap(state[0], state[1]); } players[0].setName(names[0]); players[0].setMarker(marker[0]); players[0].setState(state[0]); players[1].setName(names[1]); players[1].setMarker(marker[1]); players[1].setState(state[1]); if(players[0].getState()) { std::wstring pText = players[0].getName() + L" you will go first and your marker will be an " + players[0].getMarker() + L"\n\n" + players[1].getName() + L" you will go second and your marker will be an " + players[1].getMarker(); MessageBox( g_hWnd, pText.c_str(), L"Player Settings", MB_OK | MB_ICONINFORMATION ); currentPlayer = 0; } else { std::wstring pText = players[1].getName() + L" you will go first and your marker will be an " + players[1].getMarker() + L"\n\n" + players[0].getName() + L" you will go second and your marker will be an " + players[0].getMarker(); MessageBox( g_hWnd, pText.c_str(), L"Player Settings", MB_OK | MB_ICONINFORMATION ); currentPlayer = 1; } // Initialise the gameboard TicTacToe.initBoard(); InvalidateRect(g_hWnd, 0, TRUE); } //--------------------------------------------------------------- // Name: placeMarker() // Desc: //--------------------------------------------------------------- bool placeMarker(GameBoard &TicTacToe, Player &player, LPARAM lParam, HWND hWnd) { int x = LOWORD(lParam); int y = HIWORD(lParam); bool posOK = true; // If the player has not clicked on the actual board but somewhere else // on the screen then display an error message. if( ( ( y < 100 ) || ( y > 550 ) || ( x < 95 ) || ( x > 545 ) ) ) { std::wstring pErrorText = players[currentPlayer].getName() + L" please click on the board. "; MessageBox( hWnd, pErrorText.c_str(), L"Selection Error", MB_OK | MB_ICONINFORMATION ); posOK = false; } // If the user has clicked on the gameboard then work out where they have // clicked by converting the x and y LPARAM coordinates into suitable // row and column coordinates and then set the current players row // and column attributes to those coordinates. else { if( ( y >= 100 ) && ( y <= 250 ) ) { if( ( x >= 95 ) && ( x <= 245 ) ) { players[currentPlayer].setRow(0); players[currentPlayer].setColumn(0); } if( ( x >= 246 ) && ( x <= 395 ) ) { players[currentPlayer].setRow(0); players[currentPlayer].setColumn(1); } if( ( x >= 396 ) && ( x <= 545 ) ) { players[currentPlayer].setRow(0); players[currentPlayer].setColumn(2); } } if( ( y >= 251 ) && ( y <= 400 ) ) { if( ( x >= 95 ) && ( x <= 245 ) ) { players[currentPlayer].setRow(1); players[currentPlayer].setColumn(0); } if( ( x >= 246 ) && ( x <= 395 ) ) { players[currentPlayer].setRow(1); players[currentPlayer].setColumn(1); } if( ( x >= 396 ) && ( x <= 545 ) ) { players[currentPlayer].setRow(1); players[currentPlayer].setColumn(2); } } if( ( y >= 401 ) && ( y <= 550 ) ) { if( ( x >= 95 ) && ( x <= 245 ) ) { players[currentPlayer].setRow(2); players[currentPlayer].setColumn(0); } if( ( x >= 246 ) && ( x <= 395 ) ) { players[currentPlayer].setRow(2); players[currentPlayer].setColumn(1); } if( ( x >= 396 ) && ( x <= 545 ) ) { players[currentPlayer].setRow(2); players[currentPlayer].setColumn(2); } } if(!TicTacToe.setBoard(players[currentPlayer].getRow(), players[currentPlayer].getColumn(), players[currentPlayer].getMarker())) { std::wstring pError = L"The values can only be between 0 and 2 and the position must be empty!"; MessageBox( hWnd, pError.c_str(), L"Player Settings", MB_OK | MB_ICONINFORMATION ); posOK = false; } } return posOK; } //--------------------------------------------------------------- // Name: evaluateAI() // Desc: Uses basic Negamax algorithim to determine where the // AI places it's next move. //--------------------------------------------------------------- int evaluateAI(GameBoard &TicTacToe, int Player, int &bestMove ) { int bestScore; int score; #define WIN 1; #define LOSS -1; #define DRAW 0; if(!TicTacToe.gameOver()) { if(TicTacToe.checkWinningLine(players[Player].getMarker())) { return WIN; } if(TicTacToe.checkWinningLine(players[1 - Player].getMarker())) { return LOSS; } return DRAW; } else if(TicTacToe.checkWinningLine(players[Player].getMarker())) { return WIN; } else if(TicTacToe.checkWinningLine(players[1 - Player].getMarker())) { return LOSS; } else { bestScore = LOSS; int notUsed; for(int row = 0; row < 3; row++) { for(int col = 0; col < 3; col++) { if(TicTacToe.getBoard(row, col) == '\0') { TicTacToe.setBoard(row, col, players[Player].getMarker()); score = -evaluateAI(TicTacToe, 1 - Player, notUsed); if(score > bestScore) { bestMove = TicTacToe.convertIndex(row, col); bestScore = score; } TicTacToe.unsetBoard(row, col); } } } } return bestScore; } //--------------------------------------------------------------- // Name: placeMarkerAI() // Desc: Places the AI's marker once evaluateAI() has // returned an appropriate value. //--------------------------------------------------------------- bool placeMarkerAI(GameBoard &TicTacToe, Player &player, int aiMove, HWND hWnd) { bool posOK = true; if(!TicTacToe.setBoard(aiMove, players[currentPlayer].getMarker())) { std::wstring pError = L"The values can only be between 0 and 2 and the position must be empty!"; MessageBox( hWnd, pError.c_str(), L"Player Settings", MB_OK | MB_ICONINFORMATION ); posOK = false; } return posOK; } //--------------------------------------------------------------- // Name: random() // Desc: Return a random number. //--------------------------------------------------------------- int random() { return rand() % 10 + 1; } //--------------------------------------------------------------- // Name: displayBoard() // Desc: Display the game board. //--------------------------------------------------------------- const void displayBoard(GameBoard &gameBoard, Player &playerOne, Player &playerTwo, HWND hWnd) { const std::vector<char> &board = gameBoard.getBoard(); HDC hdc = GetDC(hWnd); SetTextColor(hdc, RGB(131, 139, 131)); SetBkColor(hdc, RGB(0, 0, 0)); SetBkMode(hdc, TRANSPARENT); std::wstring title = L"Tic Tac Toe by Paul Kirkbride"; TextOut(hdc, 215, 20, title.c_str() ,title.length()); SetTextColor(hdc, RGB(49, 79, 79)); SetBkColor(hdc, RGB(0, 0, 0)); SetBkMode(hdc, TRANSPARENT); std::wstring playerInfo = L"Player1: " + playerOne.getName() + L" ( " + playerOne.getMarker() + L" ) Player2: " + playerTwo.getName() + L" ( " + playerTwo.getMarker() + L" ) "; TextOut(hdc, 150, 50, playerInfo.c_str() ,playerInfo.length()); HPEN black_pen = CreatePen(PS_SOLID, 3, RGB(0, 0, 0)); HPEN old_pen = (HPEN)SelectObject(hdc, black_pen); // Top Horizontal Line MoveToEx(hdc, 95, 250, NULL); LineTo(hdc, 545, 250); // Bottom Horizontal Line MoveToEx(hdc, 95, 400, NULL); LineTo(hdc, 545, 400); // First Vertical Line MoveToEx(hdc, 245, 100, NULL); LineTo(hdc, 245, 550); // Second Vertical Line MoveToEx(hdc, 395, 100, NULL); LineTo(hdc, 395, 550); } //--------------------------------------------------------------- // Name: gameState() // Desc: Checks to see if the current player has won the game. //--------------------------------------------------------------- bool gameState(GameBoard &TicTacToe, Player &player, HWND hWnd) { bool gameOver = false; bool won = false; if(TicTacToe.checkWinningLine(player.getMarker())) { std::wstring pWon = L"Congratulations " + player.getName() + L" you have won the game."; MessageBox( hWnd, pWon.c_str(), L"Game State", MB_OK | MB_ICONINFORMATION ); player.incrementGamesWon(); gameOver = true; won = true; } if((!TicTacToe.gameOver()) && (!won)) { std::wstring pWon = L"Unlucky " + players[0].getName() + L" and " + players[1].getName() + L" you have tied."; MessageBox( hWnd, pWon.c_str(), L"Game State", MB_OK | MB_ICONINFORMATION ); gameOver = true; } return gameOver; } //--------------------------------------------------------------- // Name: drawX() // Desc: //--------------------------------------------------------------- void drawX(int row, int column, HDC hdc) { const int squareSize = 150; HPEN hPenOld; HPEN hLinePen; COLORREF lineColor; lineColor = RGB(255, 0, 0); const int penWidth = 10; hLinePen = CreatePen(PS_SOLID, penWidth, lineColor); hPenOld = (HPEN)SelectObject(hdc, hLinePen); // Get Bounds. const int lowX = column * squareSize + 20 * penWidth; const int highX = (column + 1) * squareSize - 2 * penWidth; const int lowY = row * squareSize + 20 * penWidth; const int highY = (row + 1) * squareSize - 2 * penWidth; MoveToEx(hdc, lowX, lowY, NULL); LineTo(hdc, highX, highY); MoveToEx(hdc, lowX, highY, NULL); LineTo(hdc, highX, lowY); SelectObject(hdc, hPenOld); DeleteObject(hLinePen); } //--------------------------------------------------------------- // Name: drawO() // Desc: //--------------------------------------------------------------- void drawO(int row, int column, HDC hdc) { const int squareSize = 150; HPEN hPenOld; HPEN hLinePen; COLORREF lineColor; lineColor = RGB(0, 0, 255); const int penWidth = 10; hLinePen = CreatePen(PS_SOLID, penWidth, lineColor); hPenOld = (HPEN)SelectObject(hdc, hLinePen); // Get Bounds. const int lowX = column * squareSize + 20 * penWidth; const int highX = (column + 1) * squareSize - 2 * penWidth; const int lowY = row * squareSize + 20 * penWidth; const int highY = (row + 1) * squareSize - 2 * penWidth; Arc(hdc, lowX, lowY, highX, highY, 0, 0, 0, 0); SelectObject(hdc, hPenOld); DeleteObject(hLinePen); } //--------------------------------------------------------------- // Name: replayGame() // Desc: Once the game is over, either one has won or its a tie // then do we want to play again. //--------------------------------------------------------------- bool replayGame() { int response; bool replay = false; response = MessageBox( g_hWnd, L"Would you like to play again?", L"Replay Game", MB_YESNO | MB_ICONINFORMATION ); if( response == IDYES) { replay = true; } return replay; } //--------------------------------------------------------------- // Name: finalScores() // Desc: Just before the application closes we let the players // know their final scores. //--------------------------------------------------------------- void finalScores() { std::wstring pScores; if(players[0].getGamesWon() > players[1].getGamesWon()) { pScores = L"Congratulations " + players[0].getName() + L" you have won the most games."; } if(players[0].getGamesWon() == players[1].getGamesWon()) { pScores = players[0].getName() + L" you have tied with " + players[1].getName(); } if(players[1].getGamesWon() > players[0].getGamesWon()) { pScores = L"Congratulations " + players[1].getName() + L" you have won the most games."; } MessageBox( g_hWnd, pScores.c_str(), L"Final Scores", MB_OK | MB_ICONINFORMATION ); } //--------------------------------------------------------------- // Name: setCurrentPlayer() // Desc: Switches the current player. //--------------------------------------------------------------- int setCurrentPlayer() { int curPlayer; if(players[0].getState()) { curPlayer = 0; } else { curPlayer = 1; } return curPlayer; }
  11. Since completing a console version of Tic Tac Toe I decided to work on a WIN32 version. I've now completed it to a level I am happy with. I know I could add better graphics, sound, menus etc. I'm leaving that for my next Connect Four project. As this is my first project in WIN32 I've not been hundred percent certain on how I've been doing things. I was hoping some more experience WIN32 programmers can take a look and see if what I'm doing is correct especially with my game loop. I know it's a bit crappy but it's been a massive learning curve for me :) My next Connect Four project will be based kinda on this project so I don't want to carry across any bad habits or in-effecient, ugly coding practises. I've tried to make the coding as elegant as my knowledge / experience permits. Be a massive help if someone can take a quick look. [Edited by - RedKMan on July 19, 2010 12:27:02 PM]
  12. RedKMan

    C++ NegaMax bug help

    Massive thanks CLB, now works perfectly :). For anyone interested the working version is below. int evaluateAI(GameBoard &TicTacToe, int Player, int &bestMove ) { int bestScore; int score; #define WIN 1; #define LOSS -1; #define DRAW 0; if(!TicTacToe.gameOver()) { if(TicTacToe.checkWinningLine(players[Player].getMarker())) { return WIN; } if(TicTacToe.checkWinningLine(players[1 - Player].getMarker())) { return LOSS; } return DRAW; } else if(TicTacToe.checkWinningLine(players[Player].getMarker())) { return WIN; } else if(TicTacToe.checkWinningLine(players[1 - Player].getMarker())) { return LOSS; } else { bestScore = LOSS; int notUsed; for(int row = 0; row < 3; row++) { for(int col = 0; col < 3; col++) { if(TicTacToe.getBoard(row, col) == '\0') { TicTacToe.setBoard(row, col, players[Player].getMarker()); score = -evaluateAI(TicTacToe, 1 - Player, notUsed); if(score > bestScore) { bestMove = TicTacToe.convertIndex(row, col); bestScore = score; } TicTacToe.unsetBoard(row, col); } } } } return bestScore; }
  13. RedKMan

    C++ NegaMax bug help

    if(!TicTacToe.gameOver()) { return DRAW; } The above is actually checking to see if there are any places still available to play on the board. If there are no empty places then return DRAW. So if there is still a blank space available it is skipped. It's working up until the situation I mentioned above. This is whats giving me a headache, it works up until this point and trying to debug it and figure out what is happening is very confusing :(.
  14. RedKMan

    C++ NegaMax bug help

    For the most part the function below works well. When the computer plays first it always chooses position 0 and it always ends in a draw (unless I don't choose the center position (4) and then the computer wins). However, when I play first I always win when I start at position 0. An example play is below based on me playing first and my marker being O. O X 2 X X O O O 8 So, it has blocked me up until this point and tried to win itself. Now it is the computers choice but rather than play position 8 to stop me winning it goes with position 2 allowing me to play position 8 and steal a sweet victory. Up until the final two places left on the board it behaves as it should, blocking me and trying to win. So it is working to a degree just not when this situation occurs. I've tried debugging and stepping through but if I'm honest it's kinda hard to follow exactly what is going on with it all. Just wondering if anyone can spot a silly error or suggest how I can solve this bug. Like I said when the computer plays first it works correctly with no bugs. int evaluateAI(GameBoard &TicTacToe, int Player, int &bestMove ) { int bestScore; int score; #define WIN 1; #define LOSS -1; #define DRAW 0; if(!TicTacToe.gameOver()) { return DRAW; } else if(TicTacToe.checkWinningLine(players[Player].getMarker())) { return WIN; } else if(TicTacToe.checkWinningLine(players[1 - Player].getMarker())) { return LOSS; } else { bestScore = LOSS; int notUsed; for(int row = 0; row < 3; row++) { for(int col = 0; col < 3; col++) { if(TicTacToe.getBoard(row, col) == '\0') { TicTacToe.setBoard(row, col, players[Player].getMarker()); score = -evaluateAI(TicTacToe, 1 - Player, notUsed); if(score > bestScore) { bestMove = TicTacToe.convertIndex(row, col); bestScore = score; } TicTacToe.unsetBoard(row, col); } } } } return bestScore; }
  15. I cannot get my head around this at all. Suppose that v is of type Vector of Integers and we know the following:- 1. v is sorted. 2. No two items in v are the same. 3. v.at(1) is 12. For an integer n, where 1 <= n <= v.size(), let p(n) be the following proposition: p(n): v.at(n) => 11 + n. A. Explain why p(1) is true? B. suppose that p(k - 1) is true (where 1 < k <= v.size()). Explain why p(k) must then be true. C. Complete a proof that p(n) is true for all integers n with 1 <= n < v.size(). For A. I have, In plain English the proposition means, The n at position n in v is greater than or equal to 11 + n. Let n = 1. P(1): v.at(1) ≥ 11 + 1 = 12. (B) From statement 3 which indicates v.at(1) is 12 and statement 2 which indicates no two items in v are the same, the above statement proves p(1) is true. I'm struggling with the Inductive hypothesis (question b).
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!