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

683 行
14 KiB

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