Last active
January 8, 2016 20:16
-
-
Save naezith/016ead1f2dda2a80a41b to your computer and use it in GitHub Desktop.
Battleships Game against AI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// There are 5 ships for you and your enemy and their sizes are 1, 2, 3, 4, 5. Map is 10x10 | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <conio.h> | |
#include <time.h> | |
#define GRID_SIZE 10 | |
typedef struct POINT{ int i, j; } POINT; // Coordinate holder | |
typedef struct SHIP_PART { | |
POINT pos; // Position of the part | |
int hit; // This part hit or not | |
} SHIP_PART; | |
typedef struct SHIP { | |
SHIP_PART parts[5]; // Allocate for the biggest, aircraft carrier | |
int size; // Size of the ship, 1-5 | |
} SHIP; | |
SHIP ships[2][5]; | |
// Functions | |
int randPos(){ return rand() % GRID_SIZE; }; // Return a random position on field | |
void askForProceed(){ | |
printf(" <Press a key to proceed>"); | |
_getch(); | |
} | |
void init(); | |
int playerTurn(); | |
int AITurn(); | |
void printFields(); | |
SHIP* getShip(int AI_field, int i, int j); | |
SHIP_PART* getPart(SHIP* ship, int i, int j); | |
int allShipsSunk(int AI_Field); | |
// Returns the ship if there is, in the position n, m | |
SHIP* getShip(int AI_field, int i, int j){ | |
int k, l; | |
for(k = 0; k < 5; ++k){ | |
SHIP* curr_ship = &ships[AI_field][k]; | |
for(l = 0; l < curr_ship->size; ++l){ | |
POINT* pos = &curr_ship->parts[l].pos; | |
if(pos->i == i && pos->j == j) return curr_ship; // Found ship | |
} | |
} | |
return NULL; // No ships in this position | |
} | |
// Returns the part of the ship for the given position | |
SHIP_PART* getPart(SHIP* ship, int i, int j){ | |
int k; | |
for(k = 0; k < ship->size; ++k) { | |
POINT* pos = &ship->parts[k].pos; | |
if(pos->i == i && pos->j == j) return &ship->parts[k]; // Found part | |
} return NULL; | |
} | |
int difficulty; // Enemy's accuracy | |
int shot_before[GRID_SIZE][GRID_SIZE] = {0}; | |
void init(){ | |
// Get difficulty input from player | |
printf("\n BATTLESHIPS \n Enter difficulty(0-100): "); | |
scanf("%d", &difficulty); | |
if(difficulty > 100) difficulty = 100; | |
if(difficulty < 0) difficulty = 0; | |
// Clean parts | |
int k, i, j; | |
for(j = 0; j < 2; ++j){ // Loop player and AI fields | |
for(k = 0; k < 5; ++k){ // Loop all ships | |
SHIP* curr_ship = &ships[j][k]; | |
curr_ship->size = k + 1; // Set current ship's size | |
// Reset all parts | |
for(i = 0; i < curr_ship->size; ++i){ | |
curr_ship->parts[i].hit = 0; | |
curr_ship->parts[i].pos.i = curr_ship->parts[i].pos.j = -1; | |
} | |
} | |
} | |
// Randomly place ships | |
for(j = 0; j < 2; ++j){ // Loop player and AI fields | |
for(k = 0; k < 5; ++k){ // Loop all ships | |
SHIP* curr_ship = &ships[j][k]; | |
int placed = 0; // Did we place the ship? | |
POINT part_coords[5]; // We will fill this with future ship part coordinates | |
int vertical = rand() % 2; // Is it vertically placed or not | |
while(!placed){ | |
// Find an empty start coordinate | |
do { part_coords[0].i = randPos(); part_coords[0].j = randPos(); | |
} while(getShip(j, part_coords[0].i, part_coords[0].j) != NULL); | |
// Put other ship parts | |
int i; | |
POINT start = part_coords[0]; | |
for(i = 1; i < curr_ship->size; ++i){ | |
// Place vertically if place is empty | |
if(vertical && getShip(j, start.i + i, start.j) == NULL){ | |
part_coords[i].i = start.i + i; | |
part_coords[i].j = start.j; | |
} | |
// Place horizontally if place is empty | |
else if(!vertical && getShip(j, start.i, start.j + i) == NULL){ | |
part_coords[i].i = start.i; | |
part_coords[i].j = start.j + i; | |
} | |
else break; // There is ship in this place, find another start position | |
// Out of the grid, find another start position | |
if(part_coords[i].i >= GRID_SIZE || part_coords[i].j >= GRID_SIZE) break; | |
} | |
// Place the ship if we found enough empty area | |
if(i == curr_ship->size){ | |
for(i = 0; i < curr_ship->size; ++i) curr_ship->parts[i].pos = part_coords[i]; | |
placed = 1; | |
} | |
} | |
} | |
} | |
} | |
int playerTurn(){ | |
// Take coordinate to shoot torpedo at | |
int i, j; | |
printf("\n Your turn to attack, commander! Give me a coordinate to shoot at\n x << "); | |
scanf("%d", &j); | |
printf(" y << "); | |
scanf("%d", &i); | |
int hit = 0; // Did we hit? | |
SHIP* ship = getShip(1, i, j); | |
if(ship == NULL) hit = 0; // Miss | |
else{ // Hit | |
SHIP_PART* part = getPart(ship, i, j); | |
if(part->hit){ // Already hit this place | |
printf("\n ... We shot that coordinate before, commander!"); | |
return playerTurn(); | |
} | |
part->hit = hit = 1; | |
} | |
shot_before[i][j] = 1; // Mark this place | |
printFields(); // Refresh the map | |
if(hit) printf("\n We hit them, sir!"); | |
else printf(" You missed, sir."); | |
if(allShipsSunk(1)){ // Did we win? | |
printf("\n Sir! We just destroyed all the enemy ships! We won this battle!"); | |
return 1; | |
} | |
askForProceed(); | |
return 0; | |
} | |
int allShipsSunk(int AI_Field){ | |
int i, j; | |
for(i = 0; i < 5; ++i){ | |
SHIP* ship = &ships[AI_Field][i]; | |
for(j = 0; j < ship->size; ++j){ | |
if(!ship->parts[j].hit) return 0; | |
} | |
} | |
return 1; | |
} | |
int AITurn(){ | |
printf("\n It is their turn to attack, sir!"); | |
askForProceed(); | |
// Will the AI hit or not? This also depends on difficulty | |
if(rand() % 100 < difficulty){ // Hit | |
int will_hit = 1; | |
while(will_hit){ // Find a part we did not hit yet | |
SHIP* ship = &ships[0][rand() % 5]; | |
SHIP_PART* part = &ship->parts[rand() % ship->size]; | |
if(part->hit) will_hit = 1; // Shoot again | |
else{ // This is a non-hit part, hit it! | |
part->hit = 1; | |
will_hit = 0; | |
printFields(); | |
printf("\n They hit our ship, sir!"); | |
} | |
} | |
} | |
else printf("\n Enemy torpedo missed our ships!"); | |
if(allShipsSunk(0)){ // Did AI win? | |
printf("\n ***ALL OF YOUR SHIPS ARE DESTROYED, YOU LOST!***"); | |
return 1; | |
} | |
askForProceed(); | |
return 0; | |
} | |
int main(){ | |
srand(time(0)); // For better randomness | |
system("color 1F"); // Set background blue and text color white | |
init(); // Make the game ready to play | |
do{ printFields(); } while(!playerTurn() && !AITurn()); // Play until somebody wins | |
return 0; | |
} | |
void printFields(){ | |
system("CLS"); | |
int i, j; | |
printf("\n BATTLESHIPS GAME "); | |
printf("\n You Enemy\n "); | |
for(j = 0; j < GRID_SIZE; ++j) printf(" %d ", j); | |
printf(" "); | |
for(j = 0; j < GRID_SIZE; ++j) printf(" %d ", j); | |
printf("\n "); | |
for(j = 0; j < GRID_SIZE; ++j) printf(" _ "); | |
printf(" "); | |
for(j = 0; j < GRID_SIZE; ++j) printf(" _ "); | |
printf("\n"); | |
for(i = 0; i < GRID_SIZE; ++i){ | |
printf(" %d |", i); | |
// Your area | |
for(j = 0; j < GRID_SIZE; ++j){ | |
SHIP* ship = getShip(0, i, j); | |
if(ship != NULL){ | |
SHIP_PART* part = getPart(ship, i, j); | |
printf(" %c ", part->hit ? 'X' : '0' + ship->size); | |
} | |
else printf(" . "); | |
} | |
printf(" %d |", i); | |
// Enemy area | |
for(j = 0; j < GRID_SIZE; ++j){ | |
SHIP* ship = getShip(1, i, j); | |
if(ship != NULL){ | |
SHIP_PART* part = getPart(ship, i, j); | |
printf(" %c ", part->hit ? 'X' : '.'); | |
} | |
else printf(" %c ", shot_before[i][j] ? 'O' : '.'); | |
} | |
printf("\n"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment