您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

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