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

Last change on this file since 4369 was 4369, checked in by Sam Hocevar, 10 years ago

Add the copyright unit test and update copyright information everywhere.

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