4-gewinnt  1.0.0
Klassiker "4-gewinnt" als Konsolenanwendung
 Alle Datenstrukturen Dateien Funktionen Variablen Makrodefinitionen Seiten
gamefunction.c
gehe zur Dokumentation dieser Datei
1 #pragma once
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <conio.h>
6 
7 // global variables
8 char player1[20];
9 char player2[20];
10 
15 int coinPosition = 1; //where the coin is actually placed
17 char playersCoin; //contains X or O
18 char victor;
19 int moves;
20 int end = 0;
21 
28 void gameFunction(){
29  moves = 0;
30  playersTurn = irand(0,1);
31  char keyStrokeName[2];
32  keyStrokeName[1] = '\0';
33  player1[0] = '\0';
34  player2[0] = '\0';
35  /*
36  player1 name
37  loop as long player did not press enter
38  */
39  do {
40  //check length
41  if (strlen(player1)>=19)
42  break;
43  //buffer
44  startBuffer(50);
45  output("Please enter a name for Player 1: \n");
46  output("> %s_\n", player1);
47  //flush buffer
48  flushBuffer();
49  //wait for a new char and give it to var
50  keyStrokeName[0] = getch();
51  //check for special inputs
52  if ((keyStrokeName[0] == '\b') && (strlen(player1)) > 0) {
53  //if backspace was entered
54  player1[strlen(player1)-1] = '\0'; //set nilbyte to pointer-1
55  }
56  else if (keyStrokeName[0] == '\r') {} //if enter do nothing
57  else if ((keyStrokeName[0] == '\b') && (strlen(player1)) == 0) {} //if string empty and backspace entered do nothing
58  else {
59  keyStrokeName[0] = lower_to_upper(keyStrokeName[0]);
60  strcat(player1, keyStrokeName);
61  }
62  } while(((keyStrokeName[0] != '\r') && (player1[0] != '\0') && !(strlen(player1)>15)) || (strlen(player1)<3));
63  /*
64  player2 name
65  loop as long player did not press enter
66  */
67  do {
68  //check length
69  if (strlen(player1)>=19)
70  break;
71  //buffer
72  startBuffer(55);
73  output("Please enter a name for Player 1: \n");
74  output("%s\n\n", player1);
75  output("Please enter a name for Player 2: \n");
76  output("> %s_\n", player2);
77  //flush buffer
78  flushBuffer();
79  //wait for a new char and give it to var
80  keyStrokeName[0] = getch();
81  //check for special inputs
82  if ((keyStrokeName[0] == '\b') && (strlen(player2)) > 0) {
83  //if backspace was entered
84  player2[strlen(player2)-1] = '\0'; //set nilbyte to pointer-1
85  }
86  else if (keyStrokeName[0] == '\r') {} //if enter do nothing
87  else if ((keyStrokeName[0] == '\b') && (strlen(player2)) == 0) {} //if string empty and backspace entered do nothing
88  else {
89  keyStrokeName[0] = lower_to_upper(keyStrokeName[0]);
90  strcat(player2, keyStrokeName);
91  }
92  } while(((keyStrokeName[0] != '\r') && (player2[0] != '\0') && !(strlen(player2)>15)) || (strlen(player2)<3));
93  //check that player1 and player2 names are not the same
94  if (strcmp(player1, player2)==0) {
95  player2[(strlen(player2))] = '1'; // add a symbolic 1 to the end of the name ;-)
96  player2[(strlen(player2))+1] = '\0';
97  }
98  //start buffer for completion
99  startBuffer(55);
100  output("Thank you %s and %s! The game will start now.\n\nPlease press enter to continue...", player1, player2);
101  flushBuffer();
102  //wait for a key
103  getch();
104  //Loop till the game is done
105  int winnerLine =NO_HIGHLIGHT;
106  while(end == 0){
107  // start the game flow
108  startGame();
109  //check for winners or draw
110  if( victor == FIELD_PLAYER1){
111  end = 1;
112  moves = (moves/2)+(moves%2);
113  consoleClear();
114  startBuffer(50);
116  winnerLine = updateSaveHoS(player1,player2,moves);
117  //output victor
118  output("%s has won!\n\n", player1);
119  output("Press any key to continue to Hall of Shame...\n");
120  //show all
121  flushBuffer();
122  //wait for any keystroke
123  getch();
124  //continue to hall of shame
125  showHallOfShame(winnerLine,winnerLine-4);
126  }
127  else if( victor == FIELD_PLAYER2){
128  end = 1;
129  moves = (moves/2)+(moves%2);
130  consoleClear();
131  startBuffer(50);
133  winnerLine = updateSaveHoS(player2,player1,moves);
134  //output victor
135  output("%s has won!\n\n", player2);
136  output("Press any key to continue to Hall of Shame...\n");
137  //show all
138  flushBuffer();
139  //wait for any keystroke
140  getch();
141  //continue to hall of shame
142  showHallOfShame(winnerLine, winnerLine-4);
143  }
144  if(checkDraw() == 0){
145  end = 1;
146  consoleClear();
147  startBuffer(50);
149  //output draw
150  output("Game ended with a draw...\n\n");
151  output("Press any key to continue to Hall of Shame...\n");
152  //show all
153  flushBuffer();
154  //wait for any keystroke
155  getch();
156  //continue to hall of shame
158  }
159  }
160 
161  //free our game-board
162  clearAll();
163  return;
164 }
165 
171 void clearAll() {
172  //clear board
175  end = 0;
176  //reset some variables
177  victor = '\0';
178  gameFieldCreated = 0; //set to 0, because board was deleted
179  playersTurn = 0; //player1 starts the game
180  coinPosition = 1; //where the coin is actually placed
181  return;
182 }
183 
194 void playerAction() {
195  char *spaceBetweenNames;
196  spaceBetweenNames = malloc((gameFieldWidth * 3) * sizeof(char));
197  //if alloc failed return
198  if (spaceBetweenNames==NULL) {
199  exit(EXITCODE_OUTOFMEMORY);
200  }
201  //check which players turn it is and sets the coin
202  playersCoin = '\0';
203  //output buffer
204  startBuffer(50);
205  if (playersTurn == 0) {
206  setLineAlign(-1);
207  output("%s's turn\n\n", player1);
209  }else{
210  setLineAlign(+1);
211  output("%s's turn\n\n", player2);
213  }
214  setLineAlign(0);
215  //draw the coin
217  //draw the board
219  //end buffer
220  flushBuffer();
221  userInput = getch();
222  switch(userInput){
223  //dummy for key left
224  case 75: //left
225  if (coinPosition > 1)
226  coinPosition--;
227  break;
228  //dummy for key right
229  case 77: //right
231  coinPosition++;
232  break;
233  case 27: //escape
234  //go back to menu
235  end = 1;
236  break;
237  //let coin fall
238  case 13: //enter key
240  moves++;
241  break;
242  }
243  free(spaceBetweenNames);
244 }
245 
252 void throwCoin(int pos, char player) {
253  int lowestCoin = 0, i;
254  //get the lowest field
255  // LOOP DOWN if found, set lowestCoin
256  for(i = 0; i <= gameFieldHeigth-1; i++) {
257  // if we found an empty field, leave this loop and set lowest coin
258  // to the found field, so that game flow can set the next coin here
259  if (getField(&gameField,pos-1,i) == FIELD_EMPTY){
260  lowestCoin = i;
261  break;
262  }
263  }
264  //check if most upper field is filled with coin
266  return;
267  }else{
268  //set the coin for player 1 or 2 to the lowest possible column
269  if(player == FIELD_PLAYER1){
270  setField(&gameField,pos-1,lowestCoin,FIELD_PLAYER1);
271  //added looking for winner here
272  victor = checkForWinner(pos-1, lowestCoin,FIELD_PLAYER1);
273  }else if(player == FIELD_PLAYER2){ //if player 2
274  setField(&gameField,pos-1,lowestCoin,FIELD_PLAYER2);
275  victor = checkForWinner(pos-1, lowestCoin,FIELD_PLAYER2);
276  }
277  }
278  //switch to player 2 or back to 1
279  if (playersTurn == 1)
280  playersTurn = 0;
281  else playersTurn = 1;
282  return;
283 }
284 
291 void drawCoin(int pos, char CoinType){
292  int i;
293  char *canvas;
294  canvas = malloc((gameFieldWidth * 4) * sizeof(char));
295  //if alloc failed return
296  if (canvas==NULL) {
297  exit(EXITCODE_OUTOFMEMORY);
298  }
299  //writing-to-canvas setup (clear string)
300  canvas[0] = '\0';
301  //keep boundaries
302  if (pos < gameFieldWidth || pos > 1) {
303  strcat(canvas,"(");
304  for(i = 1; i <= gameFieldWidth; i++) {
305  //if the coin should be placed draw it
306  if (i == pos) {
307  strcat(canvas," ");
308  if(CoinType == FIELD_PLAYER1){
309  strcat(canvas,FONT_COIN_PLAYER1);
310  }else{
311  strcat(canvas,FONT_COIN_PLAYER2);
312  }
313 
314  strcat(canvas," ");
315  }else{
316  //draw empty
317  strcat(canvas," ");
318  }
319  }
320  strcat(canvas,")\n");
321  //we're done, output the whole thing
322  output("%s",canvas);
323  }
324  //free memory
325  free(canvas);
326  return;
327 }
328 
333 void startGame(){
334  //checks if field already exists
335  if (gameFieldCreated == 0) {
336  //create new game board (includes clear)
338  //set gameFieldCreated to 1
339  gameFieldCreated = 1;
340  }
341  }
342  //call playerAction to let game begin
343  playerAction();
344 }
345 
346 
356 char checkForWinner(int x, int y, char player){
357  // horizontal check first right then left summarized together
358  int lineCount = 0;
359  lineCount = 1 + neighbourRow(x+1,y,+1,0,player) + neighbourRow(x-1,y,-1,0,player);
360  if(lineCount >= 4){
361  return player;
362  }
363  else{
364  lineCount=0;
365  }
366 
367  // vertical check first up and then down summarized together
368  lineCount = 1 + neighbourRow(x,y+1,0,1,player) + neighbourRow(x,y-1,0,-1,player);
369  if(lineCount >= 4){
370  return player;
371  }
372  else{
373  lineCount=0;
374  }
375 
376  // diagonal checks
377 
378  // first variant /
379  lineCount = 1 + neighbourRow(x-1,y+1,-1,1,player) + neighbourRow(x+1,y-1,1,-1,player);
380  if(lineCount >= 4){
381  return player;
382  }
383  else{
384  lineCount=0;
385  }
386  //second variant
387  lineCount = 1 + neighbourRow(x+1,y+1,1,1,player) + neighbourRow(x-1,y-1,-1,-1,player);
388  if(lineCount >= 4){
389  return player;
390  }
391  else{
392  lineCount=0;
393  }
394  return FIELD_EMPTY;
395 
396 }
406 int neighbourRow(int x, int y ,int xMovement, int yMovement, char player){
407  if (getField(&gameField,x,y) == player){
408  return 1 + neighbourRow(x+xMovement,y+yMovement,xMovement,yMovement,player);
409  }
410  else{
411  return 0;
412  }
413 }
414 
419 int checkDraw(){
420  int i =0;
421  for(i=0;i<gameFieldWidth;i++){
423  return 1;
424  }
425  }
426  return 0;
427 }
433 int irand( int a, int e){
434  double r = e - a + 1;
435  return a + (int)(r * rand()/(RAND_MAX+1.0));
436 }
437 
438 
446 void animateFalling(struct board* currBoard,unsigned int xPos,char CoinType){
447  //determing which type of coin is going to fall
448  char coin;
449  if(CoinType == FIELD_PLAYER1){
450  coin='X';
451  }else{
452  coin='O';
453  }
454 
455 
456 
457 
458 
459  unsigned int currY=currBoard->height-1;
460  char* old;
461  //(getField(currBoard,xPos,currY)!=FIELD_EMPTY)&&
462  while((currY!=0)){
463  //no deletions possible at first run of loop
464  if(currY!=currBoard->height-1){
465  //delete coin one field above
466  old=calcFieldAddress(currBoard,xPos,currY+1);
467  old=&FIELD_EMPTY;
468  }
469  //setting coin one field lower
470  char* curr=calcFieldAddress(currBoard,xPos,currY);
471  curr=&coin;
472  currY--;
473 
474  drawBoard(currBoard);
475  //improvised wait Method
476  int x=0;
477  for(x=0;x<1000000;x++){
478  //funny nothing will ever happen here :D
479  x=x;
480  };
481 
482 
483  }
488  old=calcFieldAddress(currBoard,xPos,currY);
489 // &old=FIELD_EMPTY;
490  old=FIELD_EMPTY;
491  //return;
492 
493 }
494 
char player2[20]
Definition: gamefunction.c:9
void showHallOfShame(int highlight, int startFrom)
Definition: hallofshame.c:13
void consoleClear()
Definition: system.c:428
void startGame()
Definition: gamefunction.c:333
char getField(struct board *target, int x, int y)
Definition: board.c:72
const char FIELD_PLAYER2
Definition: variables.h:40
const char FIELD_PLAYER1
Definition: variables.h:39
struct board gameField
Definition: gamefunction.c:11
int neighbourRow(int x, int y, int xMovement, int yMovement, char player)
Definition: gamefunction.c:406
void playerAction()
Definition: gamefunction.c:194
const int EXITCODE_OUTOFMEMORY
Definition: variables.h:3
void clearBoard(struct board *target)
Definition: board.c:43
void setLineAlign(int align)
Definition: system.c:344
void setField(struct board *target, int x, int y, char value)
Definition: board.c:87
void flushBuffer()
Definition: system.c:188
void startBuffer(int maxTextLength)
Definition: system.c:319
char checkForWinner(int x, int y, char player)
Definition: gamefunction.c:356
const char FIELD_EMPTY
Definition: variables.h:38
unsigned int height
Definition: variables.h:45
int coinPosition
Definition: gamefunction.c:15
void gameFunction()
Definition: gamefunction.c:28
int end
Definition: gamefunction.c:20
void throwCoin(int pos, char player)
Definition: gamefunction.c:252
int gameFieldHeigth
Definition: gamefunction.c:13
int updateSaveHoS(char *victor, char *victim, int moves)
Definition: hallofshame.c:101
char * FONT_COIN_PLAYER2
Definition: fancyfont.c:16
char playersCoin
Definition: gamefunction.c:17
char lower_to_upper(char ch1)
Definition: system.c:444
int playersTurn
Definition: gamefunction.c:16
int irand(int a, int e)
Definition: gamefunction.c:433
void animateFalling(struct board *currBoard, unsigned int xPos, char CoinType)
Definition: gamefunction.c:446
char * calcFieldAddress(struct board *target, int x, int y)
Definition: board.c:60
int checkDraw()
Definition: gamefunction.c:419
void clearAll()
Definition: gamefunction.c:171
void freeBoard(struct board *target)
Definition: board.c:95
void drawCoin(int pos, char CoinType)
Definition: gamefunction.c:291
char * FONT_COIN_PLAYER1
Definition: fancyfont.c:15
char victor
Definition: gamefunction.c:18
int newBoard(struct board *target, unsigned int width, unsigned int height)
Definition: board.c:15
int gameFieldCreated
Definition: gamefunction.c:14
void drawBoard(struct board *target)
Definition: board.c:103
int moves
Definition: gamefunction.c:19
char player1[20]
Definition: gamefunction.c:8
const int NO_HIGHLIGHT
Definition: variables.h:67
int gameFieldWidth
Definition: gamefunction.c:12
unsigned char userInput
Definition: variables.h:36
int output(const char *input,...)
Definition: system.c:144