-
Notifications
You must be signed in to change notification settings - Fork 0
/
BattleShip.c
540 lines (523 loc) · 17.7 KB
/
BattleShip.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
// Includes
#include <math.h>
#include <conio.c>
#include <time.h>
#include <ctype.h>
// Key Bindings
#define ESC 27
#define ENTER 13
#define ARRIBA 72
#define ABAJO 80
#define DERECHA 77
#define IZQUIERDA 75
// Max size of...
#define ROWS 10
#define COLUMNS 10
#define LIMIT 5
// Game parameters
#define OCEAN 1
#define USED 2
#define MUSED 3
#define SHP 83
#define MSHP 69
#define HIT 88
#define MISS 79
#define XHIT 120
#define INITIAL -1
// Distance between matrix spaces
#define ESP ((int)log10(ROWS * COLUMNS))
// int modules
int randRange(int, int);
int checkPlay(int[][COLUMNS], int, int);
int checkOcean(int[][COLUMNS], int, int);
int confirmShips(void);
int putShip(int[][COLUMNS], int, int);
// Void modules
void genOcean(int[][COLUMNS], int, int);
void showOceanXY(int[][COLUMNS], int, int, int, int, int, int);
void showTimeXY(int, int, int);
void playerTurn(int[][COLUMNS], int, int);
void machineTurn(int[][COLUMNS], int, int);
void copyOcean(int[][COLUMNS], int[][COLUMNS], int, int);
void usedMoves(int[][COLUMNS], int[][COLUMNS], int[][COLUMNS], int, int, int, int);
void machineShip(int[][COLUMNS]);
void setColor(int, int);
void defaultColor(void);
void instructions(void);
int main()
{
int ships, eneShips, stage, actRow, actCol, key, eneRow = INITIAL, eneCol = INITIAL, rep, game, seg;
int ocean[ROWS][COLUMNS], oceanShip[ROWS][COLUMNS], tempOcean[ROWS][COLUMNS], eneOcean[ROWS][COLUMNS];
_setcursortype(0);
srand(time(NULL));
gotoxy(24, 5);
printf("Welcome to the game \"Battle Ship\"");
gotoxy(37, 7);
printf("Ocean");
gotoxy(17, 10);
printf("Would you like to read the instructions%c (y)es or (n)o\n\n", 63);
do
{
fflush(stdin);
key = getch();
} while (key != 'y' && key != 'n');
if (key == 'y')
instructions();
else
{
gotoxy(17, 10);
printf(" ");
}
do
{
ships = eneShips = stage = rep = game = 0, actRow = ROWS / 2, actCol = COLUMNS / 2;
genOcean(ocean, ROWS, COLUMNS), genOcean(oceanShip, ROWS, COLUMNS), genOcean(tempOcean, ROWS, COLUMNS), genOcean(eneOcean, ROWS, COLUMNS);
do
{
gotoxy(24, 21);
printf("Your ships: %d | Enemy ships: %d", ships, eneShips);
showOceanXY(ocean, ROWS, COLUMNS, 30, 10, actRow, actCol);
_setcursortype(0);
do
{
fflush(stdin);
key = getch();
} while (key != ESC && key != ARRIBA && key != ABAJO && key != DERECHA && key != IZQUIERDA && key != ENTER);
// Movimiento.
if (key == ARRIBA)
if (actRow > 0)
actRow--;
else
actRow = ROWS - 1;
if (key == ABAJO)
if (actRow < ROWS - 1)
actRow++;
else
actRow = 0;
if (key == IZQUIERDA)
if (actCol > 0)
actCol--;
else
actCol = COLUMNS - 1;
if (key == DERECHA)
if (actCol < COLUMNS - 1)
actCol++;
else
actCol = 0;
if (stage == 0)
{
if (key == ENTER)
if (putShip(ocean, actRow, actCol) == SHP)
{
if (LIMIT > ships)
{
ocean[actRow][actCol] = SHP,
ships++;
}
}
else
{
ocean[actRow][actCol] = OCEAN;
ships--;
}
if (key == ESC && ships == LIMIT)
if (confirmShips())
stage++;
}
if (stage == 1)
{
for (eneShips = 0; LIMIT > eneShips; eneShips++)
{
gotoxy(26, 24);
printf("Enemy's ship #%d deploying...", eneShips + 1);
sleep(1);
machineShip(ocean);
}
system("cls");
copyOcean(ocean, oceanShip, ROWS, COLUMNS);
genOcean(ocean, ROWS, COLUMNS);
stage++;
seg = time(NULL);
}
else if (stage == 2)
{
if (key == ENTER)
{
if (checkOcean(tempOcean, actRow, actCol))
{
ocean[actRow][actCol] = checkPlay(oceanShip, actRow, actCol);
playerTurn(ocean, actRow, actCol);
gotoxy(24, 24);
if (ocean[actRow][actCol] == XHIT)
ships--;
if (ocean[actRow][actCol] == HIT)
eneShips--;
usedMoves(tempOcean, eneOcean, ocean, actRow, actCol, eneRow, eneCol);
sleep(1);
if (eneShips)
{
do
{
eneRow = randRange(0, COLUMNS - 1);
eneCol = randRange(0, COLUMNS - 1);
} while (!checkOcean(eneOcean, eneRow, eneCol));
if (checkOcean(eneOcean, eneRow, eneCol))
{
if (checkPlay(oceanShip, eneRow, eneCol) != MISS)
ocean[eneRow][eneCol] = checkPlay(oceanShip, eneRow, eneCol);
machineTurn(ocean, eneRow, eneCol);
if (ocean[eneRow][eneCol] == XHIT)
ships--;
if (ocean[eneRow][eneCol] == HIT)
eneShips--;
usedMoves(tempOcean, eneOcean, ocean, actRow, actCol, eneRow, eneCol);
}
}
}
showTimeXY(time(NULL) - seg, 35, 22);
if (!ships || !eneShips)
{
system("cls");
showOceanXY(ocean, ROWS, COLUMNS, 30, 10, actRow, actCol);
gotoxy(24, 21);
printf("Your ships: %d | Enemy ships: %d ", ships, eneShips);
gotoxy(33, 23);
if (!eneShips)
printf("%cYou won%c\n", 173, 33);
else
printf("%cYou lost%c\n", 173, 33);
gotoxy(25, 25);
printf("Would you like to play again%c (y)es or (n)o ", 63);
do
{
fflush(stdin);
key = getch();
} while (key != 'y' && key != 'n');
if (key == 'y')
game = 1;
else
{
gotoxy(25, 25);
printf(" ");
gotoxy(25, 23);
printf(" %cThanks for playing%c ", 173, 33);
sleep(1);
return 0;
}
}
}
}
} while (!game);
system("cls");
} while (!rep);
}
/*
Function: genOcean
Arguments: int ocean, matrix to be generated.
int rows, matrix's quantity of rows.
int columns, matrix's quantity of columns.
Objective: to create the matrix 'ocean' which has n-'rows' rows and
n-'columns' columns.
Return: None.
*/
void genOcean(int ocean[][COLUMNS], int rows, int columns)
{
for (int rowPos = 0; rowPos < rows; rowPos++)
for (int colPos = 0; colPos < columns; colPos++)
ocean[rowPos][colPos] = OCEAN;
return;
}
/*
Function: copyOcean
Arguments: int oldMat, matrix to be copied.
int newMat, new matrix copy.
int rows, matrix's quantity of rows.
int columns, matrix's quantity of columns.
Objective: to copy 'oldMat's' values in 'newMat's' ones.
Return: None.
*/
void copyOcean(int oldMat[][COLUMNS], int newMat[][COLUMNS], int rows, int columns)
{
for (int rowPos = 0; rowPos < rows; rowPos++)
for (int colPos = 0; colPos < columns; colPos++)
newMat[rowPos][colPos] = oldMat[rowPos][colPos];
return;
}
/*
Function: showOceanXY
Arguments: int ocean, matrix to be printed.
int rows, matrix's quantity of rows.
int columns, matrix's quantity of columns.
int posX, horizontal plane's position.
int posY, vertical plane's position.
int actRow, current matrix's row position.
int actCol, current matrix's columns position.
Objective: to print the matrix 'ocean' which has n-'rows' rows and
n-'columns' columns, in posX and posY positions,
depending on the value, the color will change.
Return: None.
*/
void showOceanXY(int ocean[][COLUMNS], int rows, int columns, int posX, int posY, int actRow, int actCol)
{
for (int rowPos = 0; rowPos < rows; rowPos++)
for (int colPos = 0; colPos < columns; colPos++)
{
if (rowPos == actRow && colPos == actCol)
setColor(LIGHTMAGENTA, LIGHTMAGENTA);
else if (ocean[rowPos][colPos] == SHP)
setColor(WHITE, BLUE);
else if (ocean[rowPos][colPos] == MSHP)
setColor(WHITE, RED);
else if (ocean[rowPos][colPos] == OCEAN)
setColor(CYAN, CYAN);
else if (ocean[rowPos][colPos] == MISS)
setColor(WHITE, CYAN);
else if (ocean[rowPos][colPos] == HIT)
setColor(RED, CYAN);
else if (ocean[rowPos][colPos] == XHIT)
setColor(BLUE, CYAN);
else
defaultColor();
gotoxy(posX + colPos * ESP, posY + rowPos);
printf("%*c", ESP, ocean[rowPos][colPos]);
}
defaultColor();
return;
}
/*
Function: putShip
Arguments: int ocean, matrix to be evaluated (putting ships).
int rows, matrix's quantity of rows.
int columns, matrix's quantity of columns.
Objective: to put or remove ships in the matrix 'ocean'.
Return: int 'SHP' if the position was 'OCEAN'.
int 'OCEAN' if the position was 'SHP'.
*/
int putShip(int ocean[][COLUMNS], int actRow, int actCol)
{
if (checkOcean(ocean, actRow, actCol))
return SHP;
else
return OCEAN;
}
/*
Function: machineShip
Arguments: int eneOcean, enemy's matrix to be evaluated.
Objective: to put randomly ships in the matrix 'eneOcean'.
Return: None.
*/
void machineShip(int eneOcean[][COLUMNS])
{
int actCol, actRow;
do
{
actCol = randRange(0, COLUMNS - 1);
actRow = randRange(0, COLUMNS - 1);
} while (eneOcean[actRow][actCol] != OCEAN);
eneOcean[actRow][actCol] = MSHP;
return;
}
/*
Function: checkPlay
Arguments: int ocean, matrix to be evaluated.
int actRow, current matrix's row position.
int actCol, current matrix's columns position.
Objective: to check what happened with the "shot".
Return: int HIT, if hit machine's ships.
int XHIT, if hit player's ships.
int MISS, if didn't hit anything.
*/
int checkPlay(int ocean[][COLUMNS], int actRow, int actCol)
{
if (ocean[actRow][actCol] == MSHP)
return HIT;
else if (ocean[actRow][actCol] == SHP)
return XHIT;
else
return MISS;
}
/*
Function: checkOcean
Arguments: int tempOcean, matrix to be evaluated.
int actRow, current matrix's row position.
int actCol, current matrix's columns position.
Objective: to check if the position selected is available to use.
Return: int true or false
*/
int checkOcean(int tempOcean[][COLUMNS], int actRow, int actCol)
{
if (tempOcean[actRow][actCol] == OCEAN)
return 1;
else
return 0;
}
/*
Function: copyOcean
Arguments: int tempMat, player's matrix.
int eneOcean, machine's matrix.
int ocean, game's mother matrix.
int actRow, current player's matrix's row position.
int actCol, current player's matrix's columns position.
int eneRow, current machines's matrix's row position.
int eneCol, current machines's matrix's columns position.
Objective: to fill with USED or MUSED 'tempOcean' and 'eneOcean' matrix, depending on the last player's game effect.
Return: None.
*/
void usedMoves(int tempOcean[][COLUMNS], int eneOcean[][COLUMNS], int ocean[][COLUMNS], int actRow, int actCol, int eneRow, int eneCol)
{
tempOcean[actRow][actCol] = USED;
eneOcean[eneRow][eneCol] = MUSED;
// The player.
if (ocean[actRow][actCol] == HIT)
tempOcean[actRow][actCol] = USED;
if (ocean[actRow][actCol] == XHIT)
tempOcean[actRow][actCol] = USED;
if (ocean[actRow][actCol] == HIT)
eneOcean[actRow][actCol] = MUSED;
if (ocean[actRow][actCol] == XHIT)
eneOcean[actRow][actCol] = MUSED;
// The enemy
if (ocean[eneRow][eneCol] == HIT)
eneOcean[eneRow][eneCol] = MUSED;
if (ocean[eneRow][eneCol] == XHIT)
eneOcean[eneRow][eneCol] = MUSED;
if (ocean[eneRow][eneCol] == HIT)
tempOcean[eneRow][eneCol] = USED;
if (ocean[eneRow][eneCol] == XHIT)
tempOcean[eneRow][eneCol] = USED;
return;
}
/*
Function: playerTurn
Arguments: int ocean, matrix to be evaluated.
int actRow, current matrix's row position.
int actCol, current matrix's columns position.
Objective: to inform to the player what happened with it's move
Return: None.
*/
void playerTurn(int ocean[][COLUMNS], int actRow, int actCol)
{
gotoxy(24, 24);
if (ocean[actRow][actCol] == XHIT)
printf("%cOh no%c, you destroyed one of your ships :( ", 173, 33);
else if (ocean[actRow][actCol] == HIT)
printf("%cBoom%c %cyou destroyed a enemy's ships%c ", 173, 33, 173, 33);
else
printf("%cSorry, you missed your shot%c ", 173, 33);
return;
}
/*
Function: machineTurn
Arguments: int ocean, matrix to be evaluated.
int actRow, current matrix's row position.
int actCol, current matrix's columns position.
Objective: to inform to the player what happened with machine's move
Return: None.
*/
void machineTurn(int ocean[][COLUMNS], int eneRow, int eneCol)
{
gotoxy(24, 24);
if (ocean[eneRow][eneCol] == HIT)
printf("%cOh no%c, the machine destroyed one of it's ships ", 173, 33);
else if (ocean[eneRow][eneCol] == XHIT)
printf("%cBoom%c %cthe machine destroyed one of your ships%c ", 173, 33, 173, 33);
else
printf("%cThe machine missed the shot%c ", 173, 33);
return;
}
/*
Function: confirmShips
Arguments: void
Objective: Preguntarle la jugador si desea confirmar la ubicación de las naves colocadas.
Return: true (int) quiere confirmar;
false (int) no quiere confirmar.
*/
int confirmShips()
{
int key;
gotoxy(18, 24);
printf("Confirm your ship's location (y)es or (n)o ");
fflush(stdin);
key = tolower(getch());
gotoxy(18, 24);
printf(" ");
if (key == 'y')
return 1;
else
return 0;
}
/*
Function: instructions
Arguments: None.
Objective: Explain to the player how to play the game.
Return: None.
*/
void instructions()
{
gotoxy(0, 19);
printf("1. You must set %d ships in the ocean, with \'ENTER\' key you can set or remove ships with freedom.\n", LIMIT);
printf("2. Once %d ships are all set, press \'ESC\' key to confirm the positions of your ships\n", LIMIT);
printf("3. Once playing, you would not be able to see any ships's location, that includes your own ships, be careful, you could destroy them too\n");
printf("4. Press \'ENTER\' key to chose a position to be evaluated, then the machine would play.\n");
printf("5. World win who destroy rival's ships first.\n");
system("pause");
system("cls");
return;
}
/*
Function: randRange
Arguments: int minLimit, inferior limit.
int maxLimit, superior limit.
Objective: to get a random number.
Return: int, a random number.
*/
int randRange(int minLimit, int maxLimit)
{
return rand() % (maxLimit - minLimit + 1) + minLimit;
}
/*
Function: defaultColor
Arguments: None.
Objective: to set default colors.
Return: None.
*/
void defaultColor()
{
textcolor(LIGHTGRAY);
textbackground(BLACK);
return;
}
/*
Function: setColor
Arguments: int TC, text's color.
int BC, background's color.
Objective: to set text color 'TC' and background 'BC'.
Return: None.
*/
void setColor(int TC, int BC)
{
textcolor(TC);
textbackground(BC);
return;
}
/*
Function: showTimeXY
Arguments: int seg, seconds to be evaluated.
int posX, horizontal plane's position.
int posY, vertical plane's position.
Objective: to get and show the current time lapsed.
Return: None.
*/
void showTimeXY(int seg, int posX, int posY)
{
int min, hour;
min = (seg / 60);
seg -= (min * 60);
hour = (min / 60);
seg -= (hour * 3600);
gotoxy(posX, posY);
setColor(WHITE, BLACK);
printf("%02d:%02d:%02d", hour, min, seg);
defaultColor();
return;
}