fork download
  1. /* -------------------------------------------------------------------------
  2.  * Title: Target Points v1.0
  3.  * From: migf1
  4.  * Description:
  5.  * a little gambling, board game in text mode, written in ANSI C (C99)
  6.  * see function: show_help() for details
  7.  * Notes:
  8.  * the GameStatus structure is used for making it easy to add
  9.  * features like "save game" and "load game" in next versions
  10.  * -------------------------------------------------------------------------
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <string.h> // for strlen()
  15. #include <stdlib.h> // for srand(), exit()
  16. #include <ctype.h> // for isdigit()
  17. #include <time.h> // for time() (used in srand())
  18.  
  19. #define MAXINBUF 255+1 // max chars we read in the input buffer
  20. #define MAXPNAME 5+1 // max length for the player's name
  21.  
  22. #define MAXROWS 7 // board's max height
  23. #define MAXCOLS 7 // board's max width
  24.  
  25. #define CREDITS() printf("%76s\n", "\"Target Points\" by migf1");
  26.  
  27. #define PROMPT(plr, mov, maxmovs, pts, maxpts) \
  28. printf("[%s] M:%d/%d, P:%d/%d> ", (plr), (mov+1), (maxmovs), (pts), (maxpts) )
  29.  
  30. #define PAUSE() \
  31. do{ \
  32. char myinbufr[255]=""; \
  33. printf("\npress ENTER..."); \
  34. fgets(myinbufr, 255, stdin); \
  35. }while(0)
  36.  
  37. typedef enum { FALSE=0, TRUE } Bool; // our custom boolean data type
  38.  
  39. typedef struct cell { // structure of any individual cell
  40. Bool avail; // is it available for selection?
  41. int pos; // cell's position in the board
  42. int val; // cell's value
  43. }Cell;
  44.  
  45. typedef struct game { // structure of the game itself
  46. char player[ MAXPNAME ]; // player name
  47. Cell board[ MAXROWS ][ MAXCOLS ]; // the board
  48. int move, maxmoves; // current & max number of moves
  49. int points, maxpoints; // current & max number of points
  50. int score; // *** UNUSED ***
  51. }GameStatus;
  52.  
  53. // ---------------------------------------------------------------------------------
  54. void show_help( void )
  55. {
  56. puts("\n\tThis is a little gambling game written in ANSI C, by migf1.");
  57.  
  58. puts("\n\tYour task is to collect the target amount of points in as many");
  59. puts("\tmoves as the half of the total cells of the board.");
  60.  
  61. puts("\n\tCells are initially populated with random values ranging from");
  62. puts("\t0 to the total number of cells - 1 (e.g.: from 0 to 48 for a");
  63. puts("\t7x7 board). Duplicated values may appear in two or more cells.");
  64. puts("\tThe target amount of points you are after, equals to the half");
  65. puts("\tof the sum of all those values (sum of values / 2)");
  66.  
  67. puts("\n\tTo choose a cell you enter its positioning number, as shown");
  68. puts("\tin the left diagram. The value it holds will appear in the");
  69. puts("\tright diagram and it will be added to your current points.");
  70.  
  71. puts("\n\tIf you run out of moves before collecting the target amount");
  72. puts("\tof points, the game ends and you get 0 score. If you manage");
  73. puts("\tto collect the points before running out of moves, then the");
  74. puts("\tpoints collected beyond the targeted amount are multiplied");
  75. puts("\tby the moves you had left, and the result is your score");
  76.  
  77. puts("\n\tThe prompt always shows your current move and points, along");
  78.  
  79. PAUSE();
  80.  
  81. puts("\n\twith the moves you have left, and the targeted amount of");
  82. puts("\tpoints to be gathered. So make sure you check it regularly");
  83. puts("\t(M stands for move, P for points).");
  84.  
  85. puts("\n\tYou can also use the following commands at the prompt:");
  86. puts("");
  87. puts("\th\tthis help you are reading right now");
  88. puts("\tt\tshow current stats");
  89. puts("\tx\texit the game (note: you'll get 0 score!)");
  90.  
  91. puts("\n\tThe game ends either when you run out of moves, you enter");
  92. puts("\tx at the prompt, or you gather more points than the targeted");
  93. puts("\tamount (equal or more). In any case, all the cell-values will");
  94. puts("\tbe revealed in the right diagram, just before the termination");
  95. puts("\tof the program.");
  96.  
  97. puts("\n\tHave fun!");
  98.  
  99. PAUSE();
  100.  
  101. return;
  102. }
  103.  
  104. // ---------------------------------------------------------------------------------
  105. // Show current statistics
  106. //
  107. void show_stats( int move, int maxmoves, int points, int maxpoints )
  108. {
  109. printf("\n\tyou've made %d move(s), having collected %d points\n", move, points );
  110. printf( "\tyou have %d move(s) left, to collect %d more point(s)\n\n",
  111. maxmoves-move, maxpoints-points
  112. );
  113.  
  114. return;
  115. }
  116.  
  117. // ---------------------------------------------------------------------------------
  118. // Calculate and show the score on the screen, after the game has ended
  119. //
  120. void show_score( int points, int maxpoints, int move, int maxmoves, int *score)
  121. {
  122. if ( points >= maxpoints ) {
  123. printf("\t\a\a*** YES, YOU MADE IT! You collected %d points in %d moves(s)\n", points, move);
  124. *score = (points - maxpoints + 1) * (maxmoves - move + 1);
  125. printf("\t*** YOUR SCORE IS: %d\n", *score);
  126. }
  127. else {
  128. *score = 0;
  129. puts("\n\tSORRY, YOU FAILED! NO SCORE THIS TIME!");
  130. }
  131.  
  132. return;
  133. }
  134.  
  135. // ---------------------------------------------------------------------------------
  136. // Read s from standard input
  137. //
  138. char *s_get(char *s, size_t len)
  139. {
  140. char *cp;
  141.  
  142. for (cp=s; (*cp=getc(stdin)) != '\n' && (cp-s) < len-1; cp++ )
  143. ; // for-loop with empty body
  144. *cp = '\0'; // null-terminate last character
  145.  
  146. return s;
  147. }
  148.  
  149. // ---------------------------------------------------------------------------------
  150. // Trim leading & trailing spaces from s
  151. //
  152. char *s_trim( char *s )
  153. {
  154. char *cp1; // for parsing the whole s
  155. char *cp2; // for shifting & padding
  156.  
  157. // trim leading & shift left remaining
  158. for (cp1=s; isspace(*cp1); cp1++ ) // skip leading spaces, via cp1
  159. ;
  160. for (cp2=s; *cp1; cp1++, cp2++) // shift left remaining chars, via cp2
  161. *cp2 = *cp1;
  162. *cp2-- = '\0'; // mark end of left trimmed s
  163.  
  164. // replace trailing spaces with '\0's
  165. while ( cp2 > s && isspace(*cp2) )
  166. *cp2-- = '\0'; // pad with '\0'
  167.  
  168. return s;
  169. }
  170.  
  171. // ---------------------------------------------------------------------------------
  172. // Initialize the board (it also populates it with random cell-values)
  173. //
  174. int init_board( int nrows, int ncols, Cell board[nrows][ncols] )
  175. {
  176. register int i,j;
  177. int valsum = 0;
  178.  
  179. for (i=0; i<nrows; i++)
  180. {
  181. for (j=0; j < ncols; j++) {
  182. board[i][j].avail = TRUE;
  183. board[i][j].pos = i * ncols + j;
  184. board[i][j].val = rand() % (nrows*ncols);
  185. valsum += board[i][j].val;
  186. }
  187. }
  188.  
  189. return valsum;
  190. }
  191.  
  192. // ---------------------------------------------------------------------------------
  193. /*** DISABLED: UNUSED
  194.  
  195. void draw_board( int nrows, int ncols, Cell board[nrows][ncols] )
  196. {
  197. register int i,j;
  198.  
  199. for (i=0; i<nrows; i++)
  200. {
  201. for (j=0; j < ncols; j++)
  202. printf("+---");
  203. puts("+");
  204. for (j=0; j < ncols; j++)
  205. printf("| %2d ", board[i][j].val);
  206. puts("|");
  207. }
  208. for (j=0; j < ncols; j++)
  209. printf("+---");
  210. puts("+");
  211.  
  212. return;
  213. }
  214. ***/
  215.  
  216. // ---------------------------------------------------------------------------------
  217. // Draw the board diagrams on the screen, the left one with available posistions,
  218. // the right one with already selected cell-values (if cheat is TRUE, the right
  219. // diagram shows ALL cell-values, instead).
  220. //
  221. void draw_status( int nrows, int ncols, Cell board[nrows][ncols], Bool cheat )
  222. {
  223. register int i,j;
  224.  
  225. for (i=0; i<nrows; i++)
  226. {
  227. for (j=0; j < ncols; j++)
  228. printf("|----");
  229. printf("|\t");
  230. for (j=0; j < ncols; j++)
  231. printf("-----");
  232. puts("-");
  233.  
  234. for (j=0; j < ncols; j++)
  235. {
  236. if ( board[i][j].avail )
  237. printf("| %2d ", board[i][j].pos);
  238. else
  239. printf("| ## ");
  240. }
  241. printf("|\t");
  242. for (j=0; j < ncols; j++)
  243. {
  244. if ( board[i][j].avail && !cheat)
  245. printf("| ");
  246. else
  247. printf("| %2d ", board[i][j].val);
  248. }
  249. puts("|");
  250. }
  251. for (j=0; j < ncols; j++)
  252. printf("|----");
  253. printf("|\t");
  254. for (j=0; j < ncols; j++)
  255. printf("-----");
  256. puts("-");
  257.  
  258. return;
  259. }
  260.  
  261. // ---------------------------------------------------------------------------------
  262. // Read the player name form the standard input
  263. //
  264. char *get_player( char *player )
  265. {
  266. if ( !player )
  267. return NULL;
  268.  
  269. int temp;
  270. char dummy[MAXINBUF] = "";
  271.  
  272. do {
  273. printf("Player name (%d chars, more will be ignored)? ", MAXPNAME-1);
  274. s_get(dummy, MAXINBUF);
  275. s_trim(dummy);
  276. temp = strlen(dummy);
  277. if ( temp+1 > MAXPNAME)
  278. dummy[MAXPNAME-1] = '\0';
  279. strcpy(player, dummy);
  280. } while ( !*player );
  281.  
  282. return player;
  283. }
  284.  
  285. // ---------------------------------------------------------------------------------
  286. // Handle non-numerical commands (e.g.: h, t, x, etc)
  287. //
  288. void exec_charcmd( char c, int move, int maxmoves, int points, int maxpoints)
  289. {
  290. switch ( c )
  291. {
  292. case 'x':
  293. case '\0':
  294. break;
  295.  
  296. case 'h':
  297. show_help();
  298. break;
  299.  
  300. case 't':
  301. show_stats(move, maxmoves, points, maxpoints);
  302. break;
  303.  
  304. default:
  305. puts("\a\n\tinvalid command, type h for help\n");
  306. break;
  307. }
  308.  
  309. return;
  310. }
  311.  
  312. // ---------------------------------------------------------------------------------
  313. // Handle numerical commands (expecting them to be board positions)
  314. //
  315. Bool exec_poscmd( char *inbuf, int nrows, int ncols, Cell board[nrows][ncols], int *move, int *points)
  316. {
  317. int i, j, pos;
  318.  
  319. pos = atoi( inbuf );
  320. if ( pos < 0 || pos > nrows*ncols-1 ) {
  321. puts("\a\n\tinvalid position\n");
  322. return FALSE;
  323. }
  324.  
  325. i = pos / ncols;
  326. j = pos % ncols;
  327. if ( !board[ i ][ j ].avail ) {
  328. puts("\a\n\tyou have already played that position\n");
  329. return FALSE;
  330. }
  331.  
  332. board[ i ][ j ].avail = FALSE;
  333. (*move)++;
  334. (*points) += board[ i ][ j ].val;
  335. printf("\n\t%d points added to your bucket!\n\n", board[ i ][ j ].val);
  336.  
  337. return TRUE;
  338. }
  339.  
  340. // ---------------------------------------------------------------------------------
  341. int main( void )
  342. {
  343. char inbuf[MAXINBUF] = ""; // our input buffer
  344. GameStatus game = { // our current game
  345. .player = "",
  346. // .board,
  347. .move = 0, .maxmoves = (MAXROWS*MAXCOLS)/2,
  348. .points = 0, .maxpoints = 0,
  349. .score = 0
  350. };
  351.  
  352. srand( time(NULL) ); // init random generator
  353. // init target amount of points
  354. game.maxpoints = init_board( MAXROWS, MAXCOLS, game.board ) / 2;
  355. get_player( game.player ); // get player name
  356.  
  357. do { // the main loop of the game
  358. draw_status( MAXROWS, MAXCOLS, game.board, FALSE );
  359. CREDITS();
  360.  
  361. PROMPT( game.player, game.move, game.maxmoves, game.points, game.maxpoints );
  362. s_get(inbuf, MAXINBUF); // get user command
  363. s_trim( inbuf ); // (trim leading spaces)
  364.  
  365. if ( isdigit( tolower(*inbuf) ) ) // handle numerical commands
  366. exec_poscmd( inbuf, MAXROWS, MAXCOLS, game.board, &game.move, &game.points );
  367. else // handle non-numerical commands
  368. exec_charcmd( *inbuf, game.move, game.maxmoves, game.points, game.maxpoints );
  369.  
  370. } while( tolower(*inbuf) != 'x' // game ends either when x
  371. && game.move < game.maxmoves // or run out of moves
  372. && game.points < game.maxpoints ); // or maxpoints have been reached
  373.  
  374. // display the final score
  375. show_score( game.points, game.maxpoints, game.move, game.maxmoves, &game.score);
  376.  
  377. puts("\n\thave a look at the full board, before exiting\n");
  378. draw_status( MAXROWS, MAXCOLS, game.board, TRUE );
  379.  
  380. PAUSE();
  381. exit( EXIT_SUCCESS );
  382. }
  383.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty