Multi-game multiplayer arcade gaming system meant for the blue O when playing Super Tic-Tac-Toe.
Dependencies: 4DGL-uLCD-SE PinDetect SDFileSystem mbed wave_player
BlueO.h
- Committer:
- soapy12312
- Date:
- 2015-12-04
- Revision:
- 2:da0f01fbd25c
File content as of revision 2:da0f01fbd25c:
/******************************************************* * This header program declares all of the functions and * variables used by the blue O player in Super * Tic-Tac-Toe. *******************************************************/ #define FORWARDSLASH 0 #define BACKWARDSLASH 1 #define VERTICAL 2 #define HORIZONTAL 3 #define BOMB "/sd/wavfiles/bomb.wav" #define WIN "/sd/win.wav" #define MEH "/sd/Meh.wav" /******************************************************* * This structure is used to represent the individual * blocks within a small grid. *******************************************************/ struct smallGrid { char individualGrid[3][3]; char done; }; /******************************************************* * This structure is used to represent the small * blocks within the whole grid. *******************************************************/ struct largeGrid { smallGrid smallGrid[3][3]; char done; }; class BlueO { public: // Player O constructor BlueO(DigitalOut &reset, InterruptIn &input, Mpr121 &MPR121, RGBLED &RGB, SDFileSystem &sd, Serial &XBee, uLCD_4DGL &uLCD, wave_player &waver) : reset(reset), input(input), MPR121(MPR121), RGB(RGB), sd(sd), XBee(XBee), uLCD(uLCD), waver(waver) { uLCD.baudrate(MAXBAUDRATE); key = -1; // Set up XBee reset = 0; wait(0.001); reset = 1; wait(0.001); } // Play the game void playSuperTicTacToe() { initializeInterrupt(); displayInstructions(); initializeGrid(); XBee.putc(true); bool readyToPlay = false; bool print = true; while (readyToPlay == false) { if (XBee.readable() == true) { readyToPlay = XBee.getc(); print = false; } if (print == true) { uLCD.cls(); uLCD.printf("Waiting for other player..."); print = false; } } uLCD.cls(); drawStage(); // False: player one's turn; true: player two's turn bool turn = true; // Loop through the game while (grid.done == (char)(-1)) { turn = !turn; takeTurn(turn); gameWin(turn); } uLCD.cls(); if (grid.done == 0) { uLCD.printf("The other player\nwins."); playSound(BOMB); } else if (grid.done == 1) { uLCD.printf("You win!"); playSound(WIN); } else if (grid.done == 128) { uLCD.printf("It's a draw!"); playSound(MEH); } wait(3); uLCD.cls(); } private: DigitalOut &reset; InterruptIn &input; Mpr121 &MPR121; RGBLED &RGB; SDFileSystem &sd; Serial &XBee; uLCD_4DGL &uLCD; wave_player &waver; bool keyAllowed; volatile int key; largeGrid grid; // Initialize the interrupt void initializeInterrupt() { input.fall(this, &BlueO::keyInterrupt); wait(0.01); input.mode(PullUp); wait(0.01); } // Determine value of the key pressed void keyInterrupt() { if (keyAllowed == true) { int value = MPR121.read(0x00); value += MPR121.read(0x01) << 8; for (int i = 0; i < 12; i++) { if (((value >> i) & 0x01) == 1) { key = i; } } // Ununsed keys if ((key == 3) || (key == 7) || (key == 11)) { key = -1; } } else { key = -1; } } // Initialize the grid void initializeGrid() { grid.done = (char)(-1); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { grid.smallGrid[i][j].done = (char)(-1); for (int k = 0; k < 3; k++) { for (int l = 0; l < 3; l++) { grid.smallGrid[i][j].individualGrid[k][l] = (char)(-1); } } } } } // Display instructions void displayInstructions() { uLCD.printf("Hello, and welcome"); uLCD.printf("to a game of Super"); uLCD.printf("Tic-Tac-Toe. Use "); uLCD.printf("the bottom three "); uLCD.printf("rows of the touch "); uLCD.printf("keypad to select "); uLCD.printf("the large grid "); uLCD.printf("followed by the "); uLCD.printf("small grid. You "); uLCD.printf("are the blue O.\n\n"); uLCD.printf("Press any key to "); uLCD.printf("begin playing."); wait(0.1); key = -1; keyAllowed = true; while (key == -1) { wait(0.01); } key = -1; uLCD.cls(); } // Play a sound file void playSound(char *wav) { // Open sound file FILE *wave_file; wave_file = fopen(wav, "r"); // Play wav file waver.play(wave_file); // Close wav file fclose(wave_file); } // Draw the stage void drawStage() { for (int i = 15; i < 120; i += 14) { uLCD.line(i, 2, i, 127, YELLOW); uLCD.line(2, i, 127, i, YELLOW); } for (int i = 43; i < 120; i += 42) { uLCD.line(i, 2, i, 127, WHITE); uLCD.line(2, i, 127, i, WHITE); } } // Draw small X void drawSmallX(int largeX, int largeY, int smallX, int smallY) { int xCoordinate = 1 + (largeX * 42) + (smallX * 14) + 7; int yCoordinate = 1 + (largeY * 42) + (smallY * 14) + 7; int x1 = xCoordinate - 6; int x2 = xCoordinate + 6; int y1 = yCoordinate - 6; int y2 = yCoordinate + 6; uLCD.line(x1 + 1, y1 + 1, x2, y2, RED); uLCD.line(x1 + 1, y2 - 1, x2, y1, RED); } // Draw small O void drawSmallO(int largeX, int largeY, int smallX, int smallY) { int xCoordinate = 1 + (largeX * 42) + (smallX * 14) + 7; int yCoordinate = 1 + (largeY * 42) + (smallY * 14) + 7; uLCD.circle(xCoordinate, yCoordinate, 5, BLUE); } // Draw large X void drawLargeX(int largeX, int largeY) { int xCoordinate = 1 + (largeX * 42) + 21; int yCoordinate = 1 + (largeY * 42) + 21; int x1 = xCoordinate - 20; int x2 = xCoordinate + 20; int y1 = yCoordinate - 20; int y2 = yCoordinate + 20; uLCD.filled_rectangle(x1, y1, x2, y2, BLACK); uLCD.line(x1 + 1, y1 + 1, x2, y2, RED); uLCD.line(x1 + 1, y2 - 1, x2, y1, RED); } // Draw large O void drawLargeO(int largeX, int largeY) { int xCoordinate = 1 + (largeX * 42) + 21; int yCoordinate = 1 + (largeY * 42) + 21; int x1 = xCoordinate - 20; int x2 = xCoordinate + 20; int y1 = yCoordinate - 20; int y2 = yCoordinate + 20; uLCD.filled_rectangle(x1, y1, x2, y2, BLACK); uLCD.circle(xCoordinate, yCoordinate, 19, BLUE); } // Find x-coordinate based on key input int xGrid() { int x; if ((key == 0) || (key == 1) || (key == 2)) { x = 0; } else if ((key == 4) || (key == 5) || (key == 6)) { x = 1; } else if ((key == 8) || (key == 9) || (key == 10)) { x = 2; } else { x = -1; } return x; } // Find y-coordinate based on key input int yGrid() { int y; if ((key == 2) || (key == 6) || (key == 10)) { y = 0; } else if ((key == 1) || (key == 5) || (key == 9)) { y = 1; } else if ((key == 0) || (key == 4) || (key == 8)) { y = 2; } else { y = -1; } return y; } // Display a certain small grid in a set color void drawSmallGrid(int x, int y, int color) { int x1 = 1 + (x * 42) + 1; int x2 = x1 + 40; int y1 = 1 + (y * 42) + 1; int y2 = y1 + 40; for (int i = x1; i < x2; i += 14) { for (int j = y1; j < y2; j += 14) { uLCD.filled_rectangle(i, j, i + 12, j + 12, color); } } for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (grid.smallGrid[x][y].individualGrid[i][j] == 0) { drawSmallX(x, y, i, j); } else if (grid.smallGrid[x][y].individualGrid[i][j] == 1) { drawSmallO(x, y, i, j); } } } } // Draw a line if a player takes a small grid void drawSmallWinLine(int x1, int y1, int orientation) { int x2 = x1; int y2 = y1; if (orientation == FORWARDSLASH) { x2 = x1 - 41; y2 = y1 + 41; } else if (orientation == BACKWARDSLASH) { x2 = x1 + 41; y2 = y1 + 41; } else if (orientation == VERTICAL) { y2 = y1 + 41; } else if (orientation == HORIZONTAL) { x2 = x1 + 41; } uLCD.line(x1, y1, x2, y2, GREEN); wait(1); } // Check whether a player has taken a small grid bool smallGridWin(int largeX, int largeY, int smallX, int smallY) { bool taken = false; char individual[3][3]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { individual[i][j] = grid.smallGrid[largeX][largeY].individualGrid[i][j]; } } int x1 = 1 + (largeX * 42) + 1; int y1 = 1 + (largeY * 42) + 1; int orientation = -1; if ((individual[0][0] == individual[1][1]) && (individual[1][1] == individual[2][2]) && (individual[0][0] != (char)(-1))) { orientation = BACKWARDSLASH; taken = true; } else if ((individual[2][0] == individual[1][1]) && (individual[1][1] == individual[0][2]) && (individual[2][0] != (char)(-1))) { orientation = FORWARDSLASH; x1 += 40; taken = true; } else if ((individual[0][0] == individual[1][0]) && (individual[1][0] == individual[2][0]) && (individual[0][0] != (char)(-1))) { orientation = HORIZONTAL; y1 += 6; taken = true; } else if ((individual[0][1] == individual[1][1]) && (individual[1][1] == individual[2][1]) && (individual[0][1] != (char)(-1))) { orientation = HORIZONTAL; y1 += 20; taken = true; } else if ((individual[0][2] == individual[1][2]) && (individual[1][2] == individual[2][2]) && (individual[0][2] != (char)(-1))) { orientation = HORIZONTAL; y1 += 34; taken = true; } else if ((individual[0][0] == individual[0][1]) && (individual[0][1] == individual[0][2]) && (individual[0][0] != (char)(-1))) { orientation = VERTICAL; x1 += 6; taken = true; } else if ((individual[1][0] == individual[1][1]) && (individual[1][1] == individual[1][2]) && (individual[1][0] != (char)(-1))) { orientation = VERTICAL; x1 += 20; taken = true; } else if ((individual[2][0] == individual[2][1]) && (individual[2][1] == individual[2][2]) && (individual[2][0] != (char)(-1))) { orientation = VERTICAL; x1 += 34; taken = true; } else { orientation = -1; taken = false; } // Check to see if there is a draw if (taken == false) { bool draw = true; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (individual[i][j] != (char)(-1)) { draw = false; } } } if (draw == true) { grid.smallGrid[largeX][largeY].done = 128; } } drawSmallWinLine(x1, y1, orientation); return taken; } // Take a turn void takeTurn(bool turn) { // Player selects small grid, then individual grid int keyInputs[2] = {-1, -1}; // If it is player one's turn if (turn == false) { RGB = RED; // Allow user input keyAllowed = true; int largeX = 0; int largeY = 0; key = -1; // Ready to proceed XBee.putc(true); // Wait for player to select small grid while ((keyInputs[0] == -1) || (grid.smallGrid[largeX][largeY].done != (char)(-1))) { // Read in the value through the XBee if (XBee.readable() == true) { key = XBee.getc(); keyInputs[0] = key; largeX = xGrid(); largeY = yGrid(); } } // Highlight selected grid drawSmallGrid(largeX, largeY, PINK); playSound("/sd/select.wav"); // Allow user input keyAllowed = true; key = -1; // Ready to proceed XBee.putc(true); // Wait for player to select individual grid while (keyInputs[1] == -1) { wait(0.01); // Read in the value through the XBee if (XBee.readable() == true) { key = XBee.getc(); keyInputs[1] = key; } } int smallX = xGrid(); int smallY = yGrid(); grid.smallGrid[largeX][largeY].individualGrid[smallX][smallY] = 0; drawSmallGrid(largeX, largeY, BLACK); drawSmallX(largeX, largeY, smallX, smallY); key = -1; playSound("/sd/select.wav"); // Check if player one has taken a small grid if (smallGridWin(largeX, largeY, smallX, smallY) == true) { grid.smallGrid[largeX][largeY].done = 0; drawLargeX(largeX, largeY); } else { bool draw = true; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (grid.smallGrid[largeX][largeY].individualGrid[i][j] == (char)(-1)) { draw = false; } } } if (draw == true) { grid.smallGrid[largeX][largeY].done = 128; } } // Ready to proceed XBee.putc(true); // If it is player two's turn } else { RGB = BLUE; // Allow user input keyAllowed = true; int largeX = 0; int largeY = 0; key = -1; // Check if the other player is ready to proceed bool ready = false; while (ready == false) { if (XBee.readable() == true) { ready = XBee.getc(); } } // Wait for player to select small grid while ((keyInputs[0] == -1) || (grid.smallGrid[largeX][largeY].done != (char)(-1))) { wait(0.01); keyInputs[0] = key; largeX = xGrid(); largeY = yGrid(); } // Send out the small grid value through the XBee XBee.putc(keyInputs[0]); // Highlight selected grid drawSmallGrid(largeX, largeY, CYAN); playSound("/sd/select.wav"); // Allow user input keyAllowed = true; key = -1; // Check if the other player is ready to proceed ready = false; while (ready == false) { if (XBee.readable() == true) { ready = XBee.getc(); } } wait(0.5); // Wait for player to select individual grid while (keyInputs[1] == -1) { wait(0.01); if (grid.smallGrid[largeX][largeY].individualGrid[xGrid()][yGrid()] == (char)(-1)) { keyInputs[1] = key; } } // Send out the individual grid value through the XBee XBee.putc(keyInputs[1]); int smallX = xGrid(); int smallY = yGrid(); grid.smallGrid[largeX][largeY].individualGrid[smallX][smallY] = 1; drawSmallGrid(largeX, largeY, BLACK); drawSmallO(largeX, largeY, smallX, smallY); key = -1; playSound("/sd/select.wav"); // Check if player two has taken a small grid if (smallGridWin(largeX, largeY, smallX, smallY) == true) { grid.smallGrid[largeX][largeY].done = 1; drawLargeO(largeX, largeY); } else { bool draw = true; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (grid.smallGrid[largeX][largeY].individualGrid[i][j] == (char)(-1)) { draw = false; } } } if (draw == true) { grid.smallGrid[largeX][largeY].done = 128; } } // Check if the other player is ready to proceed ready = false; while (ready == false) { if (XBee.readable() == true) { ready = XBee.getc(); } } } } // Draw final line when a player wins void drawLargeWinLine(int x1, int y1, int orientation) { int x2 = 127; int y2 = 127; if (orientation == FORWARDSLASH) { x2 = 0; } else if (orientation == HORIZONTAL) { y2 = y1; } else if (orientation == VERTICAL) { x2 = x1; } wait(1); uLCD.line(x1, y1, x2, y2, GREEN); wait(3); } // Check whether a player has won void gameWin(bool turn) { bool won = false; char small[3][3]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { small[i][j] = grid.smallGrid[i][j].done; } } int x1 = 2; int y1 = 2; int orientation = -1; if ((small[0][0] == small[1][1]) && (small[1][1] == small[2][2]) && (small[0][0] != (char)(-1)) && (small[0][0] != 128)) { orientation = BACKWARDSLASH; won = true; } else if ((small[2][0] == small[1][1]) && (small[1][1] == small[0][2]) && (small[2][0] != (char)(-1)) && (small[2][0] != 128)) { orientation = FORWARDSLASH; x1 = 126; won = true; } else if ((small[0][0] == small[1][0]) && (small[1][0] == small[2][0]) && (small[0][0] != (char)(-1)) && (small[0][0] != 128)) { orientation = HORIZONTAL; y1 += 21; won = true; } else if ((small[0][1] == small[1][1]) && (small[1][1] == small[2][1]) && (small[0][1] != (char)(-1)) && (small[0][1] != 128)) { orientation = HORIZONTAL; y1 += 63; won = true; } else if ((small[0][2] == small[1][2]) && (small[1][2] == small[2][2]) && (small[0][2] != (char)(-1)) && (small[0][2] != 128)) { orientation = HORIZONTAL; y1 += 105; won = true; } else if ((small[0][0] == small[0][1]) && (small[0][1] == small[0][2]) && (small[0][0] != (char)(-1)) && (small[0][0] != 128)) { orientation = VERTICAL; x1 += 21; won = true; } else if ((small[1][0] == small[1][1]) && (small[1][1] == small[1][2]) && (small[1][0] != (char)(-1)) && (small[1][0] != 128)) { orientation = VERTICAL; x1 += 63; won = true; } else if ((small[2][0] == small[2][1]) && (small[2][1] == small[2][2]) && (small[2][0] != (char)(-1)) && (small[2][0] != 128)) { orientation = VERTICAL; x1 += 105; won = true; } else { orientation = -1; won = false; } // Check to see if there is a draw if (won == false) { bool draw = true; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (small[i][j] == (char)(-1)) { draw = false; } } } if (draw == true) { grid.done = 128; wait(3); } } else { if (turn == false) { grid.done = 0; } else { grid.done = 1; } drawLargeWinLine(x1, y1, orientation); } } };