|
- /*4il.c (4 in line) - compiled under Borland C++ 5.0.
- *Version : Beta
- *Author : Cheok Yan Cheng
- *Date started coding : 11/10/2000
- *Date finished coding : 13/10/2000
- */
-
- /*If you had encounted any problem, bugs or comment on this source code
- *you are welcomed to contact me by my e-mail : yccheok@yahoo.com
- */
-
- /*Some terms in this source code that you encounted may looked strange to you.
- *However, I have no time to include the explaination in detail.
- *If you really want to know, please contact me through e-mail.
- *Sorry for the inconvenience
- */
-
- /*Ported to libcaca
- *Copyright (c) 2009-2010 Sam Hocevar <sam@hocevar.net>
- */
-
- #include "config.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
-
- #include "caca_conio.h"
-
- #undef max
-
- #define X_BOARD 8
- #define Y_BOARD 8
- #define BOARD_SIZE X_BOARD*Y_BOARD
-
- #define BOOLEAN int
- #define TRUE 1
- #define FALSE 0
-
- #define WIN 1
- #define LOSE -1
- #define DRAW 0
- #define OK 2
-
- #define COMPUTER 0
- #define HUMAN 1
- #define EMPTY -1
- #define BASE -2
-
- #define WIN_MESSAGE "I Win! Press Any Key To Continue...\n"
- #define LOSE_MESSAGE "You Win! Press Any Key To Continue...\n"
- #define DRAW_MESSAGE "Draw! Press Any Key To Continue...\n"
-
- BOOLEAN computerMove(void);
- BOOLEAN doubleHead(int, int [Y_BOARD][X_BOARD]);
- BOOLEAN humanMove(int);
- BOOLEAN isFull(void);
- BOOLEAN isWon(int, int [Y_BOARD][X_BOARD]);
- BOOLEAN twoSnake(int, int, int [Y_BOARD][X_BOARD]);
- int bestmove(void);
- int max(int [X_BOARD]);
- int status(void);
- int xDoubleHead(int, int [Y_BOARD][X_BOARD]);
- int xTwoSnake(int, int [Y_BOARD][X_BOARD]);
- int xWon(int, int [Y_BOARD][X_BOARD]);
- int y_Base(int, int [Y_BOARD][X_BOARD]);
- void duplicate(int [Y_BOARD][X_BOARD], int [Y_BOARD][X_BOARD]);
- void drawBoard(void);
- void drawPiece(void);
- void genNumWin(int [X_BOARD]);
- void getHumanMove(void);
- void init(void);
- void makeMove(int, int, int [Y_BOARD][X_BOARD]);
- void sorting(int n[X_BOARD]);
-
- int move[X_BOARD] = {3, 4, 2, 5, 1, 6, 0, 7};
- int col[X_BOARD] = {-1,-1,-1,-1,-1,-1,-1,-1};
- int square[Y_BOARD][X_BOARD] =
- { {-1, -1, -1, -1, -1, -1, -1, -1},
- {-1, -1, -1, -1, -1, -1, -1, -1},
- {-1, -1, -1, -1, -1, -1, -1, -1},
- {-1, -1, -1, -1, -1, -1, -1, -1},
- {-1, -1, -1, -1, -1, -1, -1, -1},
- {-1, -1, -1, -1, -1, -1, -1, -1},
- {-1, -1, -1, -1, -1, -1, -1, -1},
- {-2, -2, -2, -2, -2, -2, -2, -2},
- };
-
- BOOLEAN computerMove(void)
- {
- int x_best;
- if (isFull())
- return FALSE;
- x_best = bestmove();
- gotoxy(52,2);
- printf("x:%d, y:%d\n" ,x_best+1 ,Y_BOARD-y_Base(x_best,square));
- makeMove(COMPUTER, x_best, square);
- return TRUE;
- }
-
- BOOLEAN doubleHead(int who, int xsquare[Y_BOARD][X_BOARD])
- {
- int x,y;
- for(y=0; y<Y_BOARD; y++)
- {
- for(x=0; x<(X_BOARD-4); x++)
- {
- if( xsquare[y][x] == BASE &&
- xsquare[y][x+1] == who &&
- xsquare[y][x+2] == who &&
- xsquare[y][x+3] == who &&
- xsquare[y][x+4] == BASE )
- return TRUE;
- }
- }
- return FALSE;
- }
-
- BOOLEAN humanMove(int x)
- {
- gotoxy(1,20);
- if ((x < 0) || x >= X_BOARD)
- return FALSE;
- if (y_Base(x, square) == -1) /*indicate no base at that x-coulomb*/
- return FALSE;
- if (isFull()) /*the board is full*/
- return FALSE;
- gotoxy(52,5);
- printf("x:%d, y:%d\n" ,x+1 ,Y_BOARD-y_Base(x,square));
- makeMove(HUMAN,x,square);
- return TRUE;
- }
-
- BOOLEAN isFull()
- {
- int x;
- for(x=0; x<X_BOARD; x++)
- {
- if(square[0][x] == EMPTY || square[0][x] == BASE)
- return FALSE;
- }
- return TRUE;
- }
-
- BOOLEAN isWon(int who, int xsquare[Y_BOARD][X_BOARD])
- {
- int x,y;
- for(x=0; x<X_BOARD; x++)
- {
- for(y=0; y<Y_BOARD; y++)
- {
- /*horizontal position*/
- if( xsquare[y][x] == who &&
- xsquare[y][x+1] == who &&
- xsquare[y][x+2] == who &&
- xsquare[y][x+3] == who &&
- (x+3)<X_BOARD
- )
- return TRUE;
-
- /*vertical position*/
- if( xsquare[y][x] == who &&
- xsquare[y+1][x] == who &&
- xsquare[y+2][x] == who &&
- xsquare[y+3][x] == who &&
- (y+3)<Y_BOARD
- )
- return TRUE;
-
- /*downstair diagonal position*/
- if( xsquare[y][x] == who &&
- xsquare[y+1][x+1] == who &&
- xsquare[y+2][x+2] == who &&
- xsquare[y+3][x+3] == who &&
- (x+3)<X_BOARD &&
- (y+3)<Y_BOARD
- )
- return TRUE;
-
- /*upstair diagonal position*/
- if( xsquare[y][x] == who &&
- xsquare[y-1][x+1] == who &&
- xsquare[y-2][x+2] == who &&
- xsquare[y-3][x+3] == who &&
- (x+3)<X_BOARD &&
- (y-3)>=0
- )
- return TRUE;
- }
- }
- return FALSE;
- }
-
- BOOLEAN twoSnake(int who, int x, int xsquare[Y_BOARD][X_BOARD])
- {
- int xxsquare[Y_BOARD][X_BOARD];
- int n[Y_BOARD] = {0,0,0,0,0,0,0,0};
- int i;
-
- for(i=0; i<Y_BOARD; i++)
- {
- if(xsquare[i][x] == BASE || xsquare[i][x] == EMPTY)
- {
- duplicate(xxsquare, xsquare);
- xxsquare[i][x] = who;
-
- if(isWon(who, xxsquare))
- n[i] = TRUE;
- }
- }
-
- for(i=0; i<(Y_BOARD-1); i++)
- {
- if( n[i] == TRUE && n[i+1] == TRUE )
- return TRUE;
- }
- return FALSE;
- }
-
- int bestmove()
- {
- int xsquare[Y_BOARD][X_BOARD], n[X_BOARD], i, snake;
-
- gotoxy(1,19);
- textcolor(4);
- if(xWon(COMPUTER, square) != -1)
- {
- cprintf("Computer Previous Depth : +1\n");
- return xWon(COMPUTER, square);
- }
- if(xWon(HUMAN, square) != -1)
- {
- cprintf("Computer Previous Depth : -1\n");
- return xWon(HUMAN, square);
- }
-
- for(i=0; i<X_BOARD; i++)
- {
- if(y_Base(move[i], square) != -1 && col[move[i]] == COMPUTER)
- {
- duplicate(xsquare, square);
- makeMove(COMPUTER, move[i], xsquare);
- if(xWon(HUMAN, xsquare) == -1)
- {
- cprintf("Computer Previous Depth : +2\n");
- return move[i];
- }
- }
- }
-
- if(xDoubleHead(COMPUTER, square) != -1)
- {
- duplicate(xsquare, square);
- makeMove(COMPUTER, xDoubleHead(COMPUTER, xsquare), xsquare);
- if(xWon(HUMAN, xsquare) == -1)
- {
- cprintf("Computer Previous Depth : +3\n");
- return xDoubleHead(COMPUTER, square);
- }
- }
-
- if(xDoubleHead(HUMAN, square) != -1)
- {
- duplicate(xsquare, square);
- makeMove(COMPUTER, xDoubleHead(HUMAN, xsquare), xsquare);
- if(xWon(HUMAN, xsquare) == -1)
- {
- cprintf("Computer Previous Depth : -3\n");
- return xDoubleHead(HUMAN, square);
- }
- }
-
- snake =xTwoSnake(COMPUTER, square);
- if( snake != -1)
- {
- duplicate(xsquare, square);
- makeMove(COMPUTER, snake, xsquare);
- if(xWon(HUMAN, xsquare) == -1)
- {
- cprintf("Computer Previous Depth : +4\n");
- return snake;
- }
- }
- if(xTwoSnake(HUMAN, square) != -1)
- {
- duplicate(xsquare, square);
- makeMove(COMPUTER, xTwoSnake(HUMAN, xsquare), xsquare);
- if(xWon(HUMAN, xsquare) == -1)
- {
- cprintf("Computer Previous Depth : -4\n");
- return xTwoSnake(HUMAN, square);
- }
- }
-
- genNumWin(n);
- sorting(n);
-
- for(i=0; i<X_BOARD; i++)
- {
- if( y_Base (n[i], square) != -1)
- {
- duplicate(xsquare, square);
- makeMove(COMPUTER, n[i], xsquare);
- if(xWon(HUMAN, xsquare) == -1)
- {
- cprintf("Computer Previous Depth : +5\n");
- return n[i];
- }
- }
- }
-
- for(i=0; i<X_BOARD; i++)
- {
- if( y_Base (move[i], square) != -1)
- {
- cprintf("Computer Previous Depth : +0\n");
- return move[i];
- }
- }
- return -1;
- }
-
- int max(int n[X_BOARD])
- {
- int i, big;
- big = 0;
- for(i=0; i<X_BOARD; i++)
- {
- if(n[i]>big)
- big = n[i];
- }
- return big;
- }
-
- int status()
- {
- if (isWon(COMPUTER, square))
- return WIN;
- else
- if (isWon(HUMAN, square))
- return LOSE;
- else
- if (isFull())
- return DRAW;
- else
- return OK;
- }
-
- int xDoubleHead(int who, int xsquare[Y_BOARD][X_BOARD])
- {
- int x;
- int xxsquare[Y_BOARD][X_BOARD];
- for(x=0; x<X_BOARD; x++)
- {
- if(y_Base(x,xsquare) != -1)
- {
- duplicate(xxsquare, xsquare);
- makeMove(who, x, xxsquare);
- if(doubleHead(who, xxsquare))
- return x;
- }
- }
- return -1;
- }
-
- int xTwoSnake(int who, int xsquare[Y_BOARD][X_BOARD])
- {
- int x, dx;
- int xxsquare[Y_BOARD][X_BOARD];
- for(x=0; x<X_BOARD; x++)
- {
- if(y_Base(move[x],xsquare) != -1)
- {
- duplicate(xxsquare, xsquare);
- makeMove(who, move[x], xxsquare);
- for(dx=0; dx<X_BOARD; dx++)
- {
- if( twoSnake(who, move[dx], xxsquare) && col[move[dx]] != who)
- {
- if(who == COMPUTER)
- col[move[dx]] = who;
- return move[x];
- }
- }
- }
- }
- return -1;
- }
-
- int xWon(int who, int xsquare[Y_BOARD][X_BOARD])
- {
- int x;
- int xxsquare[Y_BOARD][X_BOARD];
- for(x=0; x<X_BOARD; x++)
- {
- if(y_Base(x,xsquare) != -1)
- {
- duplicate(xxsquare, xsquare);
- makeMove(who, x, xxsquare);
- if(isWon(who, xxsquare))
- return x;
- }
- }
- return -1;
- }
-
- int y_Base(int x, int xsquare[Y_BOARD][X_BOARD])
- {
- int y;
- for(y=0; y<Y_BOARD; y++)
- {
- if(xsquare[y][x] == BASE)
- return y;
- }
- return -1; /*indicate no base at that x*/
- }
-
- void duplicate(int xSquare[Y_BOARD][X_BOARD], int oSquare[Y_BOARD][X_BOARD])
- {
- int x,y;
- for(x=0; x<X_BOARD; x++)
- {
- for(y=0; y<Y_BOARD; y++)
- {
- xSquare[y][x] = oSquare[y][x];
- }
- }
- }
-
- void drawBoard()
- {
- textcolor(0);
- textbackground(7);
- clrscr();
- gotoxy(1,1);
- printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
- printf("| | | | | | | | |\n");
- printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
- printf("| | | | | | | | |\n");
- printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
- printf("| | | | | | | | |\n");
- printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
- printf("| | | | | | | | |\n");
- printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
- printf("| | | | | | | | |\n");
- printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
- printf("| | | | | | | | |\n");
- printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
- printf("| | | | | | | | |\n");
- printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
- printf("| | | | | | | | |\n");
- printf("+-----+-----+-----+-----+-----+-----+-----+-----+\n");
- printf("ARROW:move\tSPACE:select\tESC:exit\n");
- textcolor(1);
- gotoxy(44,20);
- cprintf("%-1s","4 In Line\n");
- gotoxy(44,21);
- cprintf("%-1s","ver Beta by Cheok Yan Cheng\n");
- gotoxy(44,22);
- cprintf("E-mail : yccheok@yahoo.com\n");
- gotoxy(44,23);
- cprintf("Web Site: www.geocities.com/yccheok\n");
- gotoxy(44,24);
- cprintf("Source code included!\n");
- gotoxy(1,22);
- printf("Human's Piece is O\n");
- gotoxy(1,23);
- printf("Computer's Piece is X\n");
- gotoxy(52,1);
- printf("Computer Move :\n");
- gotoxy(52,4);
- printf("Human Move :\n");
- }
-
- void drawPiece()
- {
- int x,y;
- for(x=0; x<X_BOARD; x++)
- {
- for(y=0; y<Y_BOARD; y++)
- {
- if(square[y][x] == HUMAN)
- {
- gotoxy(x*6+4, y*2+2);
- textcolor(1);
- cprintf("O\n");
- }
- else
- if(square[y][x] == COMPUTER)
- {
- gotoxy(x*6+4, y*2+2);
- textcolor(4);
- cprintf("X\n");
- }
- }
- }
- }
-
- void genNumWin(int n[X_BOARD])
- {
- int i, j, k;
- int xsquare[Y_BOARD][X_BOARD];
- int xxsquare[Y_BOARD][X_BOARD];
-
- for(i=0; i<X_BOARD; i++)
- {
- n[i]=0;
- if(y_Base(i, square) != -1) /*has base exsit?*/
- {
- duplicate(xsquare, square);
- makeMove(COMPUTER, i, xsquare);
-
- for(j=0; j<X_BOARD; j++)
- {
- for(k=0; k<Y_BOARD; k++)
- {
- if(xsquare[k][j] == EMPTY || xsquare[k][j] == BASE)
- {
- duplicate(xxsquare, xsquare);
- xxsquare[k][j] = COMPUTER;
- if(isWon(COMPUTER, xxsquare))
- n[i]++;
- }
- }
- }
- }
- }
- }
-
- void getHumanMove()
- {
- int x=3 ;
- int ch;
- while(TRUE)
- {
- gotoxy(x*6 +4, 2);
- ch = (int)getch();
- switch(ch)
- {
- case 75:/*LEFT*/
- if(x>0)
- x--;
- break;
- case 77:/*RIGHT*/
- if(x<(X_BOARD-1))
- x++;
- break;
- case 27:/*ESC*/
- textcolor(7);
- textbackground(0);
- clrscr();
- printf("Thank You For Playing 4 in line by Cheok Yan Cheng!\n");
- exit(0);
- break;
- case 32:/*SPACE*/
- if(humanMove(x))
- {
- drawPiece();
- return;
- }
- else
- {
- gotoxy(1,20);
- textcolor(4);
- cprintf("OOPs! Wrong Move! \n");
- }
- }
- }
- }
-
- void init()
- {
- int x,y;
- for(x=0; x<X_BOARD; x++)
- {
- for(y=0; y<(Y_BOARD-1); y++)
- {
- square[y][x] = EMPTY;
- }
- square[7][x] = BASE;
- col[x] = -1;
- }
- }
-
- void makeMove(int who, int x, int xsquare[Y_BOARD][X_BOARD])
- {
- int y;
- y = y_Base(x, xsquare);
- xsquare[y][x] = who;
- if(y>0)
- xsquare[y-1][x] = BASE;
- }
-
- void sorting(int n[])
- {
- int i, j, alpha;
- int store[X_BOARD];
-
- for(j=0; j<X_BOARD; j++)
- {
- alpha = max(n);
- for(i=0; i<X_BOARD; i++)
- {
- if(n[move[i]] == alpha)
- {
- store[j] = move[i];
- n[move[i]] = -1;
- break;
- }
- }
- }
- for(i=0; i<X_BOARD; i++)
- n[i] = store[i];
- }
-
- int main(void)
- {
- BOOLEAN myturn;
- myturn = TRUE;
- drawBoard();
- srand(time(NULL));
- rand();
- do
- {
- switch (status())
- {
- case WIN:
- case LOSE:
- case DRAW:
- init();
- drawBoard();
- if (myturn)
- {
- makeMove(COMPUTER,(2+rand()%4),square);
- }
- myturn = !myturn;
- drawPiece();
- }
- textcolor(4);
- gotoxy(1,20);
- cprintf("Your Turn, Please.\n");
- getHumanMove();
- gotoxy(1,20);
- textcolor(4);
- switch (status())
- {
- case WIN:
- cprintf(WIN_MESSAGE);
- getch();
- break;
- case LOSE:
- cprintf(LOSE_MESSAGE);
- getch();
- break;
- case DRAW:
- cprintf(DRAW_MESSAGE);
- getch();
- break;
- default:/*OK*/
- if(computerMove())
- {
- gotoxy(1,20);
- drawPiece();
- gotoxy(1,20);
- switch (status())
- {
- case WIN:
- cprintf(WIN_MESSAGE);
- getch();
- break;
- case LOSE:
- cprintf(LOSE_MESSAGE);
- getch();
- break;
- case DRAW:
- cprintf(DRAW_MESSAGE);
- getch();
- break;
- }
- }
- }
- }
- while(TRUE);
- }
|