source: libcaca/trunk/examples/conio.c @ 4045

Last change on this file since 4045 was 3588, checked in by Sam Hocevar, 11 years ago

Start implementing a full <conio.h> replacement with a libcaca backend.

  • Property svn:keywords set to Id
File size: 14.5 KB
Line 
1/*4il.c (4 in line) - compiled under Borland C++ 5.0.
2 *Version : Beta
3 *Author : Cheok Yan Cheng
4 *Date started coding : 11/10/2000
5 *Date finished coding : 13/10/2000
6 */
7
8/*If you had encounted any problem, bugs or comment on this source code
9 *you are welcomed to contact me by my e-mail : yccheok@yahoo.com
10 */
11
12/*Some terms in this source code that you encounted may looked strange to you.
13 *However, I have no time to include the explaination in detail.
14 *If you really want to know, please contact me through e-mail.
15 *Sorry for the inconvenience
16 */
17
18#include "config.h"
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <time.h>
23
24#include "caca_conio.h"
25
26#undef  max
27
28#define X_BOARD 8
29#define Y_BOARD 8
30#define BOARD_SIZE  X_BOARD*Y_BOARD
31
32#define BOOLEAN int
33#define TRUE 1
34#define FALSE 0
35
36#define WIN 1
37#define LOSE -1
38#define DRAW 0
39#define OK 2
40
41#define COMPUTER 0
42#define HUMAN 1
43#define EMPTY -1
44#define BASE -2
45
46#define WIN_MESSAGE  "I Win! Press Any Key To Continue...\n"
47#define LOSE_MESSAGE "You Win! Press Any Key To Continue...\n"
48#define DRAW_MESSAGE "Draw! Press Any Key To Continue...\n"
49
50BOOLEAN computerMove(void);
51BOOLEAN doubleHaed(int, int [Y_BOARD][X_BOARD]);
52BOOLEAN humanMove(int);
53BOOLEAN isFull(void);
54BOOLEAN isWon(int, int [Y_BOARD][X_BOARD]);
55BOOLEAN twoSnake(int, int, int [Y_BOARD][X_BOARD]);
56int bestmove(void);
57int max(int [X_BOARD]);
58int status(void);
59int xDoubleHead(int, int [Y_BOARD][X_BOARD]);
60int xTwoSnake(int, int [Y_BOARD][X_BOARD]);
61int xWon(int, int [Y_BOARD][X_BOARD]);
62int y_Base(int, int [Y_BOARD][X_BOARD]);
63void duplicate(int [Y_BOARD][X_BOARD], int [Y_BOARD][X_BOARD]);
64void drawBoard(void);
65void drawPiece(void);
66void genNumWin(int [X_BOARD]);
67void getHumanMove(void);
68void init(void);
69void makeMove(int, int, int [Y_BOARD][X_BOARD]);
70void sorting(int n[X_BOARD]);
71
72int move[X_BOARD] = {3, 4, 2, 5, 1, 6, 0, 7};
73int col[X_BOARD]  = {-1,-1,-1,-1,-1,-1,-1,-1};
74int square[Y_BOARD][X_BOARD] =
75                        { {-1, -1, -1, -1, -1, -1, -1, -1},
76                          {-1, -1, -1, -1, -1, -1, -1, -1},
77                          {-1, -1, -1, -1, -1, -1, -1, -1},
78                          {-1, -1, -1, -1, -1, -1, -1, -1},
79                          {-1, -1, -1, -1, -1, -1, -1, -1},
80                          {-1, -1, -1, -1, -1, -1, -1, -1},
81                          {-1, -1, -1, -1, -1, -1, -1, -1},
82                          {-2, -2, -2, -2, -2, -2, -2, -2},
83                        };
84
85BOOLEAN computerMove(void)
86{
87  int x_best;
88  if (isFull())
89    return FALSE;
90  x_best = bestmove();
91  gotoxy(52,2);
92  printf("x:%d, y:%d\n" ,x_best+1 ,Y_BOARD-y_Base(x_best,square));
93  makeMove(COMPUTER, x_best, square);
94  return TRUE;
95}
96
97BOOLEAN doubleHead(int who, int xsquare[Y_BOARD][X_BOARD])
98{
99  int x,y;
100  for(y=0; y<Y_BOARD; y++)
101  {
102    for(x=0; x<(X_BOARD-4); x++)
103    {
104      if( xsquare[y][x] == BASE &&
105          xsquare[y][x+1] == who &&
106          xsquare[y][x+2] == who &&
107          xsquare[y][x+3] == who &&
108          xsquare[y][x+4] == BASE )
109      return TRUE;
110    }
111  }
112  return FALSE;
113}
114
115BOOLEAN humanMove(int x)
116{
117  gotoxy(1,20);
118  if ((x < 0) || x >= X_BOARD)
119    return FALSE;
120  if (y_Base(x, square) == -1) /*indicate no base at that x-coulomb*/
121    return FALSE;
122  if (isFull()) /*the board is full*/
123    return FALSE;
124  gotoxy(52,5);
125  printf("x:%d, y:%d\n" ,x+1 ,Y_BOARD-y_Base(x,square));
126  makeMove(HUMAN,x,square);
127  return TRUE;
128}
129
130BOOLEAN isFull()
131{
132  int x;
133  for(x=0; x<X_BOARD; x++)
134  {
135    if(square[0][x] == EMPTY || square[0][x] == BASE)
136      return FALSE;
137  }
138  return TRUE;
139}
140
141BOOLEAN isWon(int who, int xsquare[Y_BOARD][X_BOARD])
142{
143  int x,y;
144  for(x=0; x<X_BOARD; x++)
145  {
146    for(y=0; y<Y_BOARD; y++)
147    {
148      /*horizontal position*/
149      if( xsquare[y][x]   == who &&
150          xsquare[y][x+1] == who &&
151          xsquare[y][x+2] == who &&
152          xsquare[y][x+3] == who &&
153          (x+3)<X_BOARD
154        )
155        return TRUE;
156
157      /*vertical position*/
158      if( xsquare[y][x]   == who &&
159          xsquare[y+1][x] == who &&
160          xsquare[y+2][x] == who &&
161          xsquare[y+3][x] == who &&
162          (y+3)<Y_BOARD
163        )
164        return TRUE;
165
166      /*downstair diagonal position*/
167      if( xsquare[y][x]      == who &&
168          xsquare[y+1][x+1]  == who &&
169          xsquare[y+2][x+2]  == who &&
170          xsquare[y+3][x+3]  == who &&
171          (x+3)<X_BOARD            &&
172          (y+3)<Y_BOARD
173        )
174        return TRUE;
175
176      /*upstair diagonal position*/
177      if( xsquare[y][x]      == who &&
178          xsquare[y-1][x+1]  == who &&
179          xsquare[y-2][x+2]  == who &&
180          xsquare[y-3][x+3]  == who &&
181          (x+3)<X_BOARD            &&
182          (y-3)>=0
183        )
184        return TRUE;
185    }
186  }
187  return FALSE;
188}
189
190BOOLEAN twoSnake(int who, int x, int xsquare[Y_BOARD][X_BOARD])
191{
192  int xxsquare[Y_BOARD][X_BOARD];
193  int n[Y_BOARD] = {0,0,0,0,0,0,0,0};
194  int i;
195
196  for(i=0; i<Y_BOARD; i++)
197  {
198    if(xsquare[i][x] == BASE || xsquare[i][x] == EMPTY)
199    {
200      duplicate(xxsquare, xsquare);
201      xxsquare[i][x] = who;
202
203      if(isWon(who, xxsquare))
204        n[i] = TRUE;
205    }
206  }
207
208  for(i=0; i<(Y_BOARD-1); i++)
209  {
210    if( n[i] == TRUE && n[i+1] == TRUE )
211      return TRUE;
212  }
213  return FALSE;
214}
215
216int bestmove()
217{
218  int xsquare[Y_BOARD][X_BOARD], n[X_BOARD], i, snake;
219
220  gotoxy(1,19);
221  textcolor(4);
222  if(xWon(COMPUTER, square) != -1)
223  {
224    cprintf("Computer Previous Depth : +1\n");
225    return xWon(COMPUTER, square);
226  }
227  if(xWon(HUMAN, square) != -1)
228  {
229    cprintf("Computer Previous Depth : -1\n");
230    return xWon(HUMAN, square);
231  }
232
233  for(i=0; i<X_BOARD; i++)
234  {
235    if(y_Base(move[i], square) != -1 && col[move[i]] == COMPUTER)
236    {
237      duplicate(xsquare, square);
238      makeMove(COMPUTER, move[i], xsquare);
239      if(xWon(HUMAN, xsquare) == -1)
240      {
241        cprintf("Computer Previous Depth : +2\n");
242        return move[i];
243      }
244    }
245  }
246
247  if(xDoubleHead(COMPUTER, square) != -1)
248  {
249    duplicate(xsquare, square);
250    makeMove(COMPUTER, xDoubleHead(COMPUTER, xsquare), xsquare);
251    if(xWon(HUMAN, xsquare) == -1)
252    {
253      cprintf("Computer Previous Depth : +3\n");
254      return xDoubleHead(COMPUTER, square);
255    }
256  }
257
258  if(xDoubleHead(HUMAN, square) != -1)
259  {
260    duplicate(xsquare, square);
261    makeMove(COMPUTER, xDoubleHead(HUMAN, xsquare), xsquare);
262    if(xWon(HUMAN, xsquare) == -1)
263    {
264      cprintf("Computer Previous Depth : -3\n");
265      return xDoubleHead(HUMAN, square);
266    }
267  }
268
269  snake =xTwoSnake(COMPUTER, square);
270  if( snake != -1)
271  {
272    duplicate(xsquare, square);
273    makeMove(COMPUTER, snake, xsquare);
274    if(xWon(HUMAN, xsquare) == -1)
275    {
276      cprintf("Computer Previous Depth : +4\n");
277      return snake;
278    }
279  }
280  if(xTwoSnake(HUMAN, square) != -1)
281  {
282    duplicate(xsquare, square);
283    makeMove(COMPUTER, xTwoSnake(HUMAN, xsquare), xsquare);
284    if(xWon(HUMAN, xsquare) == -1)
285    {
286      cprintf("Computer Previous Depth : -4\n");
287      return xTwoSnake(HUMAN, square);
288    }
289  }
290
291  genNumWin(n);
292  sorting(n);
293
294  for(i=0; i<X_BOARD; i++)
295  {
296    if( y_Base (n[i], square) != -1)
297    {
298      duplicate(xsquare, square);
299      makeMove(COMPUTER, n[i], xsquare);
300      if(xWon(HUMAN, xsquare) == -1)
301      {
302        cprintf("Computer Previous Depth : +5\n");
303        return n[i];
304      }
305    }
306  }
307
308  for(i=0; i<X_BOARD; i++)
309  {
310    if( y_Base (move[i], square) != -1)
311    {
312      cprintf("Computer Previous Depth : +0\n");
313      return move[i];
314    }
315  }
316  return -1;
317}
318
319int max(int n[X_BOARD])
320{
321  int i, big;
322  big = 0;
323  for(i=0; i<X_BOARD; i++)
324  {
325    if(n[i]>big)
326      big = n[i];
327  }
328  return big;
329}
330
331int status()
332{
333  if (isWon(COMPUTER, square))
334    return WIN;
335  else
336    if (isWon(HUMAN, square))
337      return LOSE;
338    else
339      if (isFull())
340        return DRAW;
341      else
342        return OK;
343}
344
345int xDoubleHead(int who, int xsquare[Y_BOARD][X_BOARD])
346{
347  int x;
348  int xxsquare[Y_BOARD][X_BOARD];
349  for(x=0; x<X_BOARD; x++)
350  {
351    if(y_Base(x,xsquare) != -1)
352    {
353      duplicate(xxsquare, xsquare);
354      makeMove(who, x, xxsquare);
355      if(doubleHead(who, xxsquare))
356        return x;
357    }
358  }
359  return -1;
360}
361
362int xTwoSnake(int who, int xsquare[Y_BOARD][X_BOARD])
363{
364  int x, dx;
365  int xxsquare[Y_BOARD][X_BOARD];
366  for(x=0; x<X_BOARD; x++)
367  {
368    if(y_Base(move[x],xsquare) != -1)
369    {
370      duplicate(xxsquare, xsquare);
371      makeMove(who, move[x], xxsquare);
372      for(dx=0; dx<X_BOARD; dx++)
373      {
374        if( twoSnake(who, move[dx], xxsquare) && col[move[dx]] != who)
375        {
376          if(who == COMPUTER)
377            col[move[dx]] = who;
378          return move[x];
379        }
380      }
381    }
382  }
383  return -1;
384}
385
386int xWon(int who, int xsquare[Y_BOARD][X_BOARD])
387{
388  int x;
389  int xxsquare[Y_BOARD][X_BOARD];
390  for(x=0; x<X_BOARD; x++)
391  {
392    if(y_Base(x,xsquare) != -1)
393    {
394      duplicate(xxsquare, xsquare);
395      makeMove(who, x, xxsquare);
396      if(isWon(who, xxsquare))
397        return x;
398    }
399  }
400  return -1;
401}
402
403int y_Base(int x, int xsquare[Y_BOARD][X_BOARD])
404{
405  int y;
406  for(y=0; y<Y_BOARD; y++)
407  {
408    if(xsquare[y][x] == BASE)
409      return y;
410  }
411  return -1; /*indicate no base at that x*/
412}
413
414void duplicate(int xSquare[Y_BOARD][X_BOARD], int oSquare[Y_BOARD][X_BOARD])
415{
416  int x,y;
417  for(x=0; x<X_BOARD; x++)
418  {
419    for(y=0; y<Y_BOARD; y++)
420    {
421      xSquare[y][x] = oSquare[y][x];
422    }
423  }
424}
425
426void drawBoard()
427{
428  textcolor(0);
429  textbackground(7);
430  clrscr();
431  gotoxy(1,1);
432  printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
433  printf("|     |     |     |     |     |     |     |     |\n");
434  printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
435  printf("|     |     |     |     |     |     |     |     |\n");
436  printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
437  printf("|     |     |     |     |     |     |     |     |\n");
438  printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
439  printf("|     |     |     |     |     |     |     |     |\n");
440  printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
441  printf("|     |     |     |     |     |     |     |     |\n");
442  printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
443  printf("|     |     |     |     |     |     |     |     |\n");
444  printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
445  printf("|     |     |     |     |     |     |     |     |\n");
446  printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
447  printf("|     |     |     |     |     |     |     |     |\n");
448  printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
449  printf("ARROW:move\tSPACE:select\tESC:exit\n");
450  textcolor(1);
451  gotoxy(44,20);
452  cprintf("%-1s","4 In Line\n");
453  gotoxy(44,21);
454  cprintf("%-1s","ver Beta by Cheok Yan Cheng\n");
455  gotoxy(44,22);
456  cprintf("E-mail : yccheok@yahoo.com\n");
457  gotoxy(44,23);
458  cprintf("Web Site: www.geocities.com/yccheok\n");
459  gotoxy(44,24);
460  cprintf("Source code included!\n");
461  gotoxy(1,22);
462  printf("Human's Piece is O\n");
463  gotoxy(1,23);
464  printf("Computer's Piece is X\n");
465  gotoxy(52,1);
466  printf("Computer Move :\n");
467  gotoxy(52,4);
468  printf("Human Move :\n");
469}
470
471void drawPiece()
472{
473  int x,y;
474  for(x=0; x<X_BOARD; x++)
475  {
476    for(y=0; y<Y_BOARD; y++)
477    {
478      if(square[y][x] == HUMAN)
479      {
480        gotoxy(x*6+4, y*2+2);
481        textcolor(1);
482        cprintf("O\n");
483      }
484      else
485      if(square[y][x] == COMPUTER)
486      {
487        gotoxy(x*6+4, y*2+2);
488        textcolor(4);
489        cprintf("X\n");
490      }
491    }
492  }
493}
494
495void genNumWin(int n[X_BOARD])
496{
497  int i, j, k, mov;
498  int xsquare[Y_BOARD][X_BOARD];
499  int xxsquare[Y_BOARD][X_BOARD];
500
501  for(i=0; i<X_BOARD; i++)
502  {
503    n[i]=0;
504    if(y_Base(i, square) != -1)               /*has base exsit?*/
505    {
506      duplicate(xsquare, square);
507      makeMove(COMPUTER, i, xsquare);
508
509      for(j=0; j<X_BOARD; j++)
510      {
511        for(k=0; k<Y_BOARD; k++)
512        {
513          if(xsquare[k][j] == EMPTY || xsquare[k][j] == BASE)
514          {
515            duplicate(xxsquare, xsquare);
516            xxsquare[k][j] = COMPUTER;
517            if(isWon(COMPUTER, xxsquare))
518              n[i]++;
519          }
520        }
521      }
522    }
523  }
524}
525
526void getHumanMove()
527{
528  int x=3 ;
529  int ch;
530        while(TRUE)
531  {
532    gotoxy(x*6 +4, 2);
533    ch = (int)getch();
534    switch(ch)
535    {
536      case 75:/*LEFT*/
537        if(x>0)
538          x--;
539        break;
540      case 77:/*RIGHT*/
541        if(x<(X_BOARD-1))
542          x++;
543        break;
544      case 27:/*ESC*/
545        textcolor(7);
546        textbackground(0);
547        clrscr();
548        printf("Thank You For Playing 4 in line by Cheok Yan Cheng!\n");
549        exit(0);
550        break;
551      case 32:/*SPACE*/
552        if(humanMove(x))
553        {
554          drawPiece();
555          return;
556        }
557        else
558        {
559          gotoxy(1,20);
560          textcolor(4);
561          cprintf("OOPs! Wrong Move! \n");
562        }
563    }
564        }
565}
566
567void init()
568{
569  int x,y;
570  for(x=0; x<X_BOARD; x++)
571  {
572    for(y=0; y<(Y_BOARD-1); y++)
573    {
574      square[y][x] = EMPTY;
575    }
576    square[7][x] = BASE;
577    col[x] = -1;
578  }
579}
580
581void makeMove(int who, int x, int xsquare[Y_BOARD][X_BOARD])
582{
583  int y;
584  y = y_Base(x, xsquare);
585  xsquare[y][x] = who;
586  if(y>0)
587    xsquare[y-1][x] = BASE;
588}
589
590void sorting(int n[])
591{
592  int i, index, alpha;
593  int tmp[X_BOARD];
594  int store[X_BOARD];
595
596  for(index=0; index<X_BOARD; index++)
597  {
598    alpha = max(n);
599    for(i=0; i<X_BOARD; i++)
600    {
601      if(n[move[i]] == alpha)
602      {
603        store[index] = move[i];
604        n[move[i]] = -1;
605        break;
606      }
607    }
608  }
609  for(i=0; i<X_BOARD; i++)
610    n[i] = store[i];
611}
612
613void main()
614{
615  BOOLEAN myturn;
616  myturn = TRUE;
617  drawBoard();
618  srand(time(NULL));
619  rand();
620  do
621  {
622    switch (status())
623    {
624      case WIN:
625      case LOSE:
626      case DRAW:
627      init();
628      drawBoard();
629      if (myturn)
630      {
631        makeMove(COMPUTER,(2+rand()%4),square);
632      }
633      myturn = !myturn;
634      drawPiece();
635    }
636    textcolor(4);
637    gotoxy(1,20);
638    cprintf("Your Turn, Please.\n");
639    getHumanMove();
640    gotoxy(1,20);
641    textcolor(4);
642    switch (status())
643    {
644      case WIN:
645        cprintf(WIN_MESSAGE);
646        getch();
647      break;
648      case LOSE:
649        cprintf(LOSE_MESSAGE);
650        getch();
651      break;
652      case DRAW:
653        cprintf(DRAW_MESSAGE);
654        getch();
655        break;
656      default:/*OK*/
657        if(computerMove())
658        {
659          gotoxy(1,20);
660          drawPiece();
661          gotoxy(1,20);
662          switch (status())
663          {
664            case WIN:
665              cprintf(WIN_MESSAGE);
666              getch();
667            break;
668            case LOSE:
669              cprintf(LOSE_MESSAGE);
670              getch();
671            break;
672            case DRAW:
673              cprintf(DRAW_MESSAGE);
674              getch();
675            break;
676          }
677        }
678    }
679  }
680  while(TRUE);
681}
682
Note: See TracBrowser for help on using the repository browser.