Added all previous files
This commit is contained in:
parent
4466ee8a4c
commit
f04fb2189a
59 changed files with 64921 additions and 0 deletions
15
lab11/Makefile
Normal file
15
lab11/Makefile
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
battleship: project.o battlefunc.o gfx2.o
|
||||
gcc project.o battlefunc.o gfx2.o -o project -lX11
|
||||
|
||||
project.o: project.c battlefunc.h gfx2.h
|
||||
gcc -c project.c -o project.o
|
||||
|
||||
battlefunc.o: battlefunc.c battlefunc.h gfx2.h
|
||||
gcc -c battlefunc.c -o battlefunc.o
|
||||
|
||||
run: project
|
||||
./project
|
||||
|
||||
clean:
|
||||
rm *.o
|
||||
rm project
|
||||
310
lab11/battlefunc.c
Normal file
310
lab11/battlefunc.c
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
// Author: Owen Dorweiler
|
||||
// Class: Fundamentals of Computing
|
||||
// Assignment: Final Project
|
||||
// Due: 15 December 2024
|
||||
|
||||
#include "battlefunc.h"
|
||||
|
||||
void startMenu() {
|
||||
system("clear"); // Clear the screen
|
||||
printf("\n====== BATTLESHIP ------\n\n");
|
||||
printf("This is a two-player battleship game.\n");
|
||||
printf("When placing ships, don't let the other player see.\n");
|
||||
printf("Place this window side-by-side with the popup before continuing.\n\n");
|
||||
printf("Press [ENTER] to begin.\n");
|
||||
getchar();
|
||||
}
|
||||
|
||||
void initBoard(char board[][14]) {
|
||||
for (int x = 0; x < 14; x++) {
|
||||
for (int y = 0; y < 14; y++) {
|
||||
board[x][y] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initShips(Ships ships[]) {
|
||||
strcpy(ships[0].type, "Aircraft Carrier");
|
||||
ships[0].length = 5;
|
||||
strcpy(ships[1].type, "Battleship");
|
||||
ships[1].length = 4;
|
||||
strcpy(ships[2].type, "Cruiser");
|
||||
ships[2].length = 3;
|
||||
strcpy(ships[3].type, "Submarine");
|
||||
ships[3].length = 3;
|
||||
strcpy(ships[4].type, "Destroyer");
|
||||
ships[4].length = 2;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
ships[i].hitsLeft = ships[i].length;
|
||||
ships[i].sunk = false;
|
||||
}
|
||||
}
|
||||
|
||||
void placeShips(Ships ships[], int player, char board[][14]) {
|
||||
printBoard();
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
system("clear");
|
||||
printf("Player %d: Place your ships.\n\n", player);
|
||||
printf("Ship: %s\nLength: %d\n\n", ships[i].type, ships[i].length);
|
||||
printf("Select a valid starting coordinate by clicking on the board.\n");
|
||||
|
||||
// Get coordinates and save to ship struct
|
||||
int startX, startY;
|
||||
bool validVertical, validHorizontal;
|
||||
do {
|
||||
getCoordinates(&startX, &startY);
|
||||
validVertical = validPlacement(startX, startY, ships[i].length, 'v', board);
|
||||
validHorizontal = validPlacement(startX, startY, ships[i].length, 'h', board);
|
||||
} while (!validVertical && !validHorizontal); // Reject coordinate if no valid placement availabe
|
||||
|
||||
// Tell user, draw point and save to struct if valid placement available
|
||||
printf("You selected coordinate %c%d.\n\n", 'A' + startY, startX + 1);
|
||||
drawAtPoint(startX, startY, 150, 150, 150);
|
||||
ships[i].startX = startX;
|
||||
ships[i].startY = startY;
|
||||
|
||||
// If one position is not valid, place it as the other
|
||||
if (!validVertical) {
|
||||
ships[i].orientation = 'h';
|
||||
addShipToBoard(ships[i], i, board); // Add horizontally
|
||||
printf("The only valid placement is horizontal.\n");
|
||||
} else if (!validHorizontal) {
|
||||
ships[i].orientation = 'v';
|
||||
addShipToBoard(ships[i], i, board); // Add vertically
|
||||
printf("The only valid placement is vertical.\n");
|
||||
// If both are valid, let the user pick an orientation
|
||||
} else {
|
||||
char orientation;
|
||||
do {
|
||||
printf("Enter orientation [v/h]: ");
|
||||
scanf(" %c", &orientation); // Note the space before %c
|
||||
orientation = tolower(orientation);
|
||||
} while (orientation != 'v' && orientation != 'h'); // Input validation
|
||||
ships[i].orientation = orientation;
|
||||
addShipToBoard(ships[i], i, board);
|
||||
}
|
||||
|
||||
usleep(2000000); // Pause 2 secs
|
||||
}
|
||||
}
|
||||
|
||||
void printBoard() {
|
||||
gfx_clear();
|
||||
int xRef, yRef;
|
||||
|
||||
// Draw grid lines
|
||||
gfx_color(0, 255, 0);
|
||||
for (int a = 0; a < 15; a++) {
|
||||
xRef = WIN_WIDTH/2 - BOARD_SIDE/2;
|
||||
yRef = WIN_HEIGHT/2 - BOARD_SIDE/2;
|
||||
gfx_line(xRef + (BOARD_SIDE/14)*a, yRef, xRef + (BOARD_SIDE/14)*a, yRef + BOARD_SIDE);
|
||||
gfx_line(xRef, yRef + (BOARD_SIDE/14)*a, xRef + BOARD_SIDE, yRef + (BOARD_SIDE/14)*a);
|
||||
}
|
||||
|
||||
gfx_color(255, 255, 255);
|
||||
|
||||
// Draw row labels (0-14)
|
||||
for (int i = 0; i < 14; i++) {
|
||||
char label[2];
|
||||
sprintf(label, "%d", i + 1);
|
||||
gfx_text(xRef + (BOARD_SIDE/14)*i + 25, yRef + BOARD_SIDE + 30, label);
|
||||
}
|
||||
|
||||
// Draw column labels (A-N)
|
||||
for (int i = 0; i < 14; i++) {
|
||||
char label[2];
|
||||
label[0] = 'A' + i;
|
||||
label[1] = '\0';
|
||||
gfx_text(xRef - 30, yRef + (BOARD_SIDE/14)*i + 30, label);
|
||||
}
|
||||
|
||||
gfx_flush();
|
||||
}
|
||||
|
||||
// Function to get the coordinates of the board
|
||||
void getCoordinates(int *startX, int *startY) {
|
||||
int xRef = WIN_WIDTH/2 - BOARD_SIDE/2;
|
||||
int yRef = WIN_HEIGHT/2 - BOARD_SIDE/2;
|
||||
|
||||
// Get a valid click within the borders of the grid
|
||||
int inpt, xPos, yPos;
|
||||
do {
|
||||
inpt = gfx_wait();
|
||||
|
||||
if (inpt == 1) {
|
||||
xPos = gfx_xpos();
|
||||
yPos = gfx_ypos();
|
||||
}
|
||||
} while (xPos < xRef || xPos > xRef + BOARD_SIDE || yPos < yRef || yPos > yRef + BOARD_SIDE);
|
||||
|
||||
// Convert from screen coordinates to board coordinates
|
||||
*startX = (xPos - xRef) / (BOARD_SIDE/14);
|
||||
*startY = (yPos - yRef) / (BOARD_SIDE/14);
|
||||
}
|
||||
|
||||
void drawAtPoint(int xCoor, int yCoor, int red, int green, int blue) {
|
||||
gfx_color(red, green, blue);
|
||||
|
||||
// Convert grid coordintes to screen coordinates
|
||||
int xRef = WIN_WIDTH/2 - BOARD_SIDE/2;
|
||||
int yRef = WIN_HEIGHT/2 - BOARD_SIDE/2;
|
||||
int x = xRef + (BOARD_SIDE/14)*xCoor + BOARD_SIDE/28;
|
||||
int y = yRef + (BOARD_SIDE/14)*yCoor + BOARD_SIDE/28;
|
||||
int radius = (BOARD_SIDE / 28) - 10;
|
||||
|
||||
gfx_fill_circle(x, y, radius); // Draw a filed circle
|
||||
gfx_flush();
|
||||
}
|
||||
|
||||
bool validPlacement(int startX, int startY, int length, char orientation, char board[][14]) {
|
||||
if (orientation == 'v') {
|
||||
if (startY + length - 1 > 13) return false; // Check out of bounds
|
||||
for (int y = startY; y < startY + length; y++) {
|
||||
if (board[startX][y] != ' ') return false; // Check for ships
|
||||
}
|
||||
} else {
|
||||
if (startX + length - 1 > 13) return false; // Check out of bounds
|
||||
for (int x = startX; x < startX + length; x++) {
|
||||
if (board[x][startY] != ' ') return false; // Check for ships
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void addShipToBoard(Ships ship, int index, char board[][14]) {
|
||||
if (ship.orientation == 'v') {
|
||||
for (int y = ship.startY; y < ship.startY + ship.length; y++) {
|
||||
board[ship.startX][y] = '0' + index;
|
||||
}
|
||||
} else {
|
||||
for (int x = ship.startX; x < ship.startX + ship.length; x++) {
|
||||
board[x][ship.startY] = '0' + index;
|
||||
}
|
||||
}
|
||||
|
||||
drawShip(ship, 150, 150, 150);
|
||||
}
|
||||
|
||||
void drawShip(Ships ship, int red, int green, int blue) {
|
||||
int xRef = WIN_WIDTH/2 - BOARD_SIDE/2;
|
||||
int yRef = WIN_HEIGHT/2 - BOARD_SIDE/2;
|
||||
|
||||
// Draw the end coordinates
|
||||
drawAtPoint(ship.startX, ship.startY, red, green, blue);
|
||||
if (ship.orientation == 'v') {
|
||||
drawAtPoint(ship.startX, ship.startY + ship.length - 1, red, green, blue);
|
||||
} else {
|
||||
drawAtPoint(ship.startX + ship.length - 1, ship.startY, red, green, blue);
|
||||
}
|
||||
|
||||
int x = (xRef + (BOARD_SIDE/14)*ship.startX + BOARD_SIDE/28);
|
||||
int y = (yRef + (BOARD_SIDE/14)*ship.startY + BOARD_SIDE/28);
|
||||
|
||||
// Draw a rectangle between them
|
||||
gfx_color(red, green, blue);
|
||||
if (ship.orientation == 'v') {
|
||||
int height = (BOARD_SIDE/14)*(ship.length - 1);
|
||||
gfx_fill_rectangle(x - (BOARD_SIDE/28) + 6, y, (BOARD_SIDE/14) - 12, height);
|
||||
} else {
|
||||
int width = (BOARD_SIDE/14)*(ship.length - 1);
|
||||
gfx_fill_rectangle(x, y - (BOARD_SIDE/28) + 6, width, (BOARD_SIDE/14) - 12);
|
||||
}
|
||||
gfx_flush();
|
||||
}
|
||||
|
||||
void drawShots(Ships ships[], char board[][14]) {
|
||||
for (int y = 0; y < 14; y++) {
|
||||
for (int x = 0; x < 14; x++) {
|
||||
if (board[x][y] == 'M')
|
||||
drawAtPoint(x, y, 255, 255, 0); // Draw yellow if miss
|
||||
else if (board[x][y] == 'H')
|
||||
drawAtPoint(x, y, 255, 0, 0); // Draw red if hit
|
||||
}
|
||||
}
|
||||
|
||||
// Draw sunk ships
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (ships[i].sunk)
|
||||
drawShip(ships[i], 255, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int fire(int player, Ships ships[], char board[][14], int *hits) {
|
||||
int xCoor, yCoor;
|
||||
char value;
|
||||
|
||||
printf("Player %d: Fire when ready.\n\n", player);
|
||||
printf("Select a square on the board to fire.\n\n");
|
||||
|
||||
// Get a shot from the user
|
||||
do {
|
||||
getCoordinates(&xCoor, &yCoor);
|
||||
value = board[xCoor][yCoor];
|
||||
} while (value == 'H' || value == 'M'); // Reject if already tried previously
|
||||
|
||||
// If it's a hit, tell the user, put on board, increment hits, and return the value to runGame()
|
||||
if (value >= '0' && value <= '4') {
|
||||
drawAtPoint(xCoor, yCoor, 255, 0, 0);
|
||||
gfx_flush();
|
||||
(*hits)++;
|
||||
printf("HIT CONFIRMED at %c%d.\n", 'A' + yCoor, xCoor + 1);
|
||||
board[xCoor][yCoor] = 'H';
|
||||
if (shipSunk(&ships[value - '0'])) {
|
||||
drawShip(ships[value - '0'], 255, 0, 0);
|
||||
printf("%s SUNK.\n", ships[value - '0'].type); // Print message saying ship has been hit
|
||||
return true; // Id ship is sunk, return true;
|
||||
}
|
||||
// Otherwise, record it as a miss
|
||||
} else {
|
||||
drawAtPoint(xCoor, yCoor, 255, 255, 0);
|
||||
gfx_flush();
|
||||
printf("MISS at %c%d.\n", 'A' + yCoor, xCoor + 1);
|
||||
board[xCoor][yCoor] = 'M';
|
||||
}
|
||||
|
||||
return false; // If ship is not sunk, return false;
|
||||
}
|
||||
|
||||
void printHits(int p1hits, int p2hits) {
|
||||
printf("Confirmed Hits:\n");
|
||||
|
||||
// Print Player 1 hits
|
||||
printf("Player 1: [");
|
||||
for (int i = 0; i < p1hits; i++) {
|
||||
printf("#");
|
||||
}
|
||||
for (int i = 0; i < 17 - p1hits; i++) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("]\n");
|
||||
|
||||
// Print Player 2 hits
|
||||
printf("Player 2: [");
|
||||
for (int i = 0; i < p2hits; i++) {
|
||||
printf("#");
|
||||
}
|
||||
for (int i = 0; i < 17 - p2hits; i++) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("]\n\n");
|
||||
}
|
||||
|
||||
bool shipSunk(Ships *ship) {
|
||||
ship->hitsLeft--; // Decrement the life counter
|
||||
if (ship->hitsLeft == 0) {
|
||||
ship->sunk = true;
|
||||
return true; // If ship is sunk, return true
|
||||
}
|
||||
|
||||
return false; // Otherwise return false
|
||||
}
|
||||
|
||||
bool allSunk(Ships ships[]) {
|
||||
// If every ship is sunk, return true
|
||||
if (ships[0].sunk && ships[1].sunk && ships[2].sunk && ships[3].sunk && ships[4].sunk) return true;
|
||||
|
||||
return false; // Otherwise return false
|
||||
}
|
||||
43
lab11/battlefunc.h
Normal file
43
lab11/battlefunc.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Author: Owen Dorweiler
|
||||
// Class: Fundamentals of Computing
|
||||
// Assignment: Final Project
|
||||
// Due: 15 December 2024
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "gfx2.h"
|
||||
|
||||
#define WIN_WIDTH 1200
|
||||
#define WIN_HEIGHT 1000
|
||||
#define BOARD_SIDE 770
|
||||
|
||||
typedef struct {
|
||||
char type[16];
|
||||
int length;
|
||||
int startX;
|
||||
int startY;
|
||||
char orientation;
|
||||
int hitsLeft;
|
||||
bool sunk;
|
||||
} Ships;
|
||||
|
||||
void startMenu();
|
||||
void initBoard(char [][14]);
|
||||
void initShips(Ships []);
|
||||
void placeShips(Ships [], int, char [][14]);
|
||||
void printBoard();
|
||||
void getCoordinates(int*, int*);
|
||||
void drawAtPoint(int, int, int, int, int);
|
||||
bool validPlacement(int, int, int, char, char [][14]);
|
||||
void addShipToBoard(Ships, int, char [][14]);
|
||||
void drawShip(Ships, int, int, int);
|
||||
void drawShots(Ships [], char board[][14]);
|
||||
int fire(int, Ships [], char [][14], int*);
|
||||
void printHits(int, int);
|
||||
bool shipSunk(Ships*);
|
||||
bool allSunk(Ships []);
|
||||
BIN
lab11/battlefunc.o
Normal file
BIN
lab11/battlefunc.o
Normal file
Binary file not shown.
90
lab11/gfx2.h
Normal file
90
lab11/gfx2.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// gfx2.h
|
||||
|
||||
#ifndef GFX2_H
|
||||
#define GFX2_H
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/cursorfont.h>
|
||||
|
||||
// Open a new graphics window.
|
||||
void gfx_open( int width, int height, const char *title );
|
||||
|
||||
// Flush all previous output to the window.
|
||||
void gfx_flush();
|
||||
|
||||
// Change the current drawing color.
|
||||
void gfx_color( int red, int green, int blue );
|
||||
|
||||
// Clear the graphics window to the background color.
|
||||
void gfx_clear();
|
||||
|
||||
// Change the current background color.
|
||||
void gfx_clear_color( int red, int green, int blue );
|
||||
|
||||
// Check to see if an event is waiting.
|
||||
int gfx_event_waiting();
|
||||
|
||||
// Wait for the user to press a key or mouse button.
|
||||
char gfx_wait();
|
||||
|
||||
// Return the X and Y coordinates of the last event.
|
||||
int gfx_xpos();
|
||||
int gfx_ypos();
|
||||
|
||||
// Return the X and Y dimensions of the screen (monitor).
|
||||
int gfx_xsize();
|
||||
int gfx_ysize();
|
||||
|
||||
// Draw a point at (x,y)
|
||||
void gfx_point( int x, int y );
|
||||
|
||||
// Draw a line from (x1,y1) to (x2,y2)
|
||||
void gfx_line( int x1, int y1, int x2, int y2 );
|
||||
|
||||
// Draw a circle centered at (xc,yc) with radius r
|
||||
void gfx_circle( int xc, int yc, int r );
|
||||
|
||||
// Display a string at (x,y)
|
||||
void gfx_text( int x, int y , const char *text );
|
||||
|
||||
// -------------------
|
||||
// new functions added
|
||||
// -------------------
|
||||
|
||||
// Draw a filled circle centered at (xc,yc) with radius r
|
||||
void gfx_fill_circle( int xc, int yc, int r );
|
||||
|
||||
// Draw an ellipse centered at (xc,yc) with radii r1 and r2
|
||||
void gfx_ellipse( int xc, int yc, int r1, int r2 );
|
||||
|
||||
// Draw an arc whose top left corner of its bounding rectangle is at (x,y),
|
||||
// with width w and height h, starting at angle a1 and sweeping an angle of a2 (degrees);
|
||||
// a1 of 0 is at the 3 O'Clock position, and the a2 sweep is positive counter-clockwise
|
||||
void gfx_arc( int x, int y, int w, int h, int a1, int a2 );
|
||||
|
||||
// Draw a filled arc (similar description to gfx_arc)
|
||||
void gfx_fill_arc( int x, int y, int w, int h, int a1, int a2 );
|
||||
|
||||
// Draw a rectangle with top-left corner at (x,y) with width w and height h
|
||||
void gfx_rectangle( int x, int y, int w, int h );
|
||||
|
||||
// Draw a filled rectangle (similar description to gfx_rectangle)
|
||||
void gfx_fill_rectangle( int x, int y, int w, int h );
|
||||
|
||||
// Draw a polygon whose "num_pts" number of corners are in the "pointsarr" array
|
||||
// (note: uses Xlib's XPoint struct)
|
||||
void gfx_polygon( XPoint *pointsarr, int num_pts );
|
||||
|
||||
// Draw a filled polygon (similar description to gfx_polygon)
|
||||
void gfx_fill_polygon( XPoint *pointsarr, int num_pts );
|
||||
|
||||
// Change the font that gfx_text will use
|
||||
// (see the file /usr/share/X11/fonts/misc/fonts.alias for possible fonts)
|
||||
void gfx_changefont( char * );
|
||||
|
||||
// change the cursor (mouse pointer)
|
||||
// (see the file /usr/include/X11/cursorfont.h for possible cursors)
|
||||
void gfx_changecursor( int );
|
||||
|
||||
#endif
|
||||
|
||||
65
lab11/project.c
Normal file
65
lab11/project.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
// Author: Owen Dorweiler
|
||||
// Class: Fundamentals of Computing
|
||||
// Assignment: Final Project
|
||||
// Due: 15 December 2024
|
||||
|
||||
#include "battlefunc.h"
|
||||
|
||||
int main() {
|
||||
int selection;
|
||||
|
||||
// Create gameboard and ship structs
|
||||
char board1[14][14], board2[14][14];
|
||||
Ships ships1[5];
|
||||
Ships ships2[5];
|
||||
|
||||
gfx_open(WIN_WIDTH, WIN_HEIGHT, "Battleship"); // Open the window
|
||||
startMenu();
|
||||
|
||||
// Initialize gameboards and ships
|
||||
initBoard(board1);
|
||||
initBoard(board2);
|
||||
initShips(ships1);
|
||||
initShips(ships2);
|
||||
|
||||
// Have both players place their ships
|
||||
placeShips(ships1, 1, board1);
|
||||
placeShips(ships2, 2, board2);
|
||||
|
||||
int player = 1, p1hits = 0, p2hits = 0;
|
||||
bool win = false; // Set up a win variable
|
||||
|
||||
// Start the game
|
||||
do {
|
||||
system("clear");
|
||||
gfx_clear();
|
||||
printBoard();
|
||||
|
||||
printHits(p1hits, p2hits);
|
||||
|
||||
if (player == 1) {
|
||||
drawShots(ships2, board2); // Draw the previous shots and sunk ships on the screen
|
||||
if (fire(player, ships2, board2, &p1hits)) { // If fire returns true, ship was sunk
|
||||
if (allSunk(ships2)) win = true; // If all ships are sunk, set win to true
|
||||
}
|
||||
} else {
|
||||
drawShots(ships1, board1);
|
||||
if (fire(player, ships1, board1, &p2hits)) {
|
||||
if (allSunk(ships1)) win = true;
|
||||
}
|
||||
}
|
||||
|
||||
usleep(2000000); // Pause 2 secs
|
||||
|
||||
// If win, display message and end the game
|
||||
if (win) {
|
||||
system("clear");
|
||||
printf("Player %d wins. Congratulations, Commander.\n\n", player);
|
||||
}
|
||||
// If no win, switch whose turn it is
|
||||
else if (player == 1) player = 2;
|
||||
else player = 1;
|
||||
} while (!win);
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
lab11/project.o
Normal file
BIN
lab11/project.o
Normal file
Binary file not shown.
Loading…
Reference in a new issue