Recent

Author Topic: Building a better mouse trap - put your textmode TicTacToe game here.  (Read 392 times)

TBMan

  • Sr. Member
  • ****
  • Posts: 348
 I don't understand how to implement nodes, decision trees, scoring the nodes etc. I'd love to write a checkers game or even a chess game, but probably not in this lifetime, lol. I keep thinking about the good ol TicTacToe game and how to code it with minimal IF statements
{as in  IF (game[0,0,] = Otoken) and (game[0,1] =Otoken) and (game[0,2] = Empty) then game[0,2] := Xtoken}. I think I have managed to do it with the following code. When I ran it as computer vs computer for 100 iterations, generally a win outcome was 10% or less. Basically what I did was use a scoring grid in addition to the grid used for the game play and display.

Code: Pascal  [Select][+][-]
  1. program tictactoe;
  2. uses ptccrt,windows;
  3. const
  4.   computer = 2;
  5.   Human = 1;
  6.  
  7.   GoodInput : set of char = ['1','2','3','4','5','6','7','8','9'];
  8.  
  9. type
  10.    playingBoard = array[0..2,0..2] of byte;
  11.  
  12.    ScreenCoord= record
  13.      row,column:integer;
  14.    end;
  15.  
  16.  
  17. var
  18.   Screen :array[0..2,0..2] of screencoord;
  19.   game,score:playingboard;
  20.   ch:char;
  21.   WonGame,
  22.   gameover:boolean;
  23.   Hwin,Cwin,Tie:integer;
  24.   EndingResponse:char;
  25.   ac:integer;
  26.   goesfirst:boolean;
  27.  
  28.  
  29. Procedure InitScreen;
  30. var
  31.   j:integer;
  32. begin
  33. textcolor(14);
  34.      screen[0,0].row := 4; Screen[0,0].column := 12;
  35.      screen[0,1].row := 4; Screen[0,1].column := 24;
  36.      screen[0,2].row := 4; screen[0,2].column := 36;
  37.  
  38.      screen[1,0].row:= 13; screen[1,0].column := 12;
  39.      screen[1,1].row:=13;  screen[1,1].column := 24;
  40.      screen[1,2].row := 13; screen[1,2].column := 36;
  41.  
  42.      screen[2,0].row := 22;screen[2,0].column := 12;
  43.      screen[2,1].row := 22;screen[2,1].column := 24;
  44.      screen[2,2].row := 22;screen[2,2].column := 36;
  45.  
  46. for j := 1 to 24 do
  47.    begin
  48.      gotoxy(screen[0,1].column-2,screen[0,1].row+j-1); write('|');
  49.      gotoxy(screen[0,2].column-2,screen[0,2].row+j-1);write('|');
  50.    end;
  51. for j := 1 to 32 do
  52.    begin
  53.      gotoxy(screen[1,0].column+j-2,screen[1,0].row-1);write('-');
  54.      gotoxy(screen[2,0].column+j-2,screen[2,0].row-1);write('-');
  55.    end;
  56.  
  57. end;
  58.  
  59. Procedure DrawSpot(Token,R,c:integer);
  60. begin
  61. case token of
  62.   Human:begin
  63.            textcolor(15);
  64.            gotoxy(screen[r,c].column,screen[r,c].row);   write('XXXXXXX');
  65.            gotoxy(screen[r,c].column,screen[r,c].row+1); write('X     X');
  66.            gotoxy(screen[r,c].column,screen[r,c].row+2); write('X     X');
  67.            gotoxy(screen[r,c].column,screen[r,c].row+3); write('X     X');
  68.            gotoxy(screen[r,c].column,screen[r,c].row+4); write('X     X');
  69.            gotoxy(screen[r,c].column,screen[r,c].row+5); write('X     X');
  70.            gotoxy(screen[r,c].column,screen[r,c].row+6); write('XXXXXXX');
  71.         end;
  72.   Computer:begin
  73.            Textcolor(4);
  74.            gotoxy(screen[r,c].column,screen[r,c].row);  write('X     X');
  75.            gotoxy(screen[r,c].column,screen[r,c].row+1); write(' X   X ');
  76.            gotoxy(screen[r,c].column,screen[r,c].row+2); write('  X X  ');
  77.            gotoxy(screen[r,c].column,screen[r,c].row+3); write('   X   ');
  78.            gotoxy(screen[r,c].column,screen[r,c].row+4); write('  X X  ');
  79.            gotoxy(screen[r,c].column,screen[r,c].row+5); write(' X   X ');
  80.            gotoxy(screen[r,c].column,screen[r,c].row+6); write('X     X');
  81.            end;
  82. end;
  83.  delay(180);         {adjust as desired}
  84. end;
  85.  
  86. Procedure ScoreToken(rr,cc,Which:integer);
  87.  var
  88.   HCount:integer;
  89.   r,c:integer;
  90.   HowMuch:integer;
  91. begin
  92.         Howmuch := 1 * Which;
  93.         Hcount := 0;
  94.         for c := 0 to 2 do
  95.           if game[rr,c] = Which then inc(Hcount);
  96.         if hcount = 2 then
  97.           for c := 0 to 2 do
  98.               inc(score[rr,c],howmuch);
  99.  
  100.         hcount := 0;
  101.         for r := 0 to 2 do
  102.           if game[r,cc] = Which then inc(hcount);
  103.  
  104.         if hcount = 2 then
  105.           for r := 0 to 2 do inc(score[r,cc],howmuch);
  106.  
  107.      hcount := 0;
  108.      r := 0;
  109.      c := 0;
  110.      repeat
  111.        if game[r,c] = Which then inc(hcount);
  112.        inc(r);inc(c);
  113.      until  r >2;
  114.  
  115.      if hcount = 2 then
  116.      begin
  117.      r := 0;
  118.      c := 0;
  119.         repeat
  120.          inc(score[r,c],howmuch);
  121.          inc(r);inc(c);
  122.         until  r >2;
  123.      end;
  124.  
  125.      r := 0; c := 2;
  126.      hcount := 0;
  127.      repeat
  128.        if game[r,c] = Which then inc(hcount);
  129.       inc(r);dec(c);
  130.      until r > 2;
  131.  
  132.      for c := 0 to 2 do
  133.        if (game[0,c] <> which) and (game[2,c] <> which)
  134.         and (game[0,c] <> 0) and (game[2,c] <> 0) then
  135.            for r := 0 to 2 do inc(score[r,c],which);
  136.  
  137.      if hcount = 2 then
  138.      begin
  139.      r := 0;
  140.      c := 2;
  141.         repeat
  142.          inc(score[r,c],howmuch);
  143.          inc(r);dec(c);
  144.         until  r >2;
  145.      end;
  146.  
  147.     for r := 0 to 2 do
  148.       for c := 0 to 2 do
  149.           if game[r,c] <> 0 then score[r,c] := 0;
  150.  
  151. end;
  152.  
  153.  
  154. Procedure Checkforwin(Who:integer);
  155. var
  156.  r,c:integer;
  157.  count:integer;
  158.  
  159. begin
  160.     gameover := false;
  161.     wongame := false;
  162.     count := 0;
  163.     for r := 0 to 2 do
  164.      if (game[r,0] = who) and (game[r,1] = who) and (game[r,2] = who) then
  165.       wongame := true;
  166.  
  167.     if not wongame then
  168.     for c := 0 to 2 do
  169.       if (game[0,c] = who) and (game[1,c] = who) and (game[2,c] = who)
  170.        then wongame := true;
  171.  
  172.  if (game[0,0] = who) and (game[1,1] = who) and (game[2,2] = who) then
  173.  wongame := true;
  174.  
  175.  if (game[0,2] = who) and (game[1,1] = who) and (game[2,0] = who) then
  176.  wongame := true;
  177.  
  178. if wongame then
  179.    begin
  180.      gotoxy(47,3);clreol;
  181.      gotoxy(47,3);
  182.      gameover := true;
  183.      textcolor(14);
  184.     Case who of
  185.      Computer:begin
  186.                   Writeln('The X''s won');
  187.                   inc(cwin);
  188.               end;
  189.      Human:begin
  190.               writeln('The O''s won');
  191.               inc(hwin);
  192.            end;
  193.      end;
  194.  
  195.   end;
  196.  
  197. count := 0;
  198. if not wongame then
  199. begin
  200.      for r := 0 to 2 do
  201.        for c := 0 to 2 do
  202.          if game[r,c] <> 0 then inc(count);
  203.       Gameover := count = 9;
  204.       if gameover then
  205.       begin
  206.            textcolor(14);
  207.           inc(tie);
  208.           gotoxy(47,3);clreol;
  209.           gotoxy(47,3);write('Tie game!');
  210.       end;
  211.  end;
  212. end;
  213.  
  214.  
  215. procedure boardfix;
  216. var
  217.   r,c:integer;
  218. begin
  219. {checks to make sure the scoring grid reflects where the players are. It zeros out player positions in the score matrix}
  220. for r := 0 to 2 do
  221.    for c := 0 to 2 do
  222.       if game[r,c] <> 0 then score[r,c] := 0;
  223. end;
  224.  
  225. Procedure HumanMove;
  226. var
  227.   HCount:integer;
  228.   r,c:integer;
  229.   ch:char;
  230.   Goodmove:boolean;
  231.  
  232. begin
  233.  
  234. Goodmove := false;
  235.  
  236. repeat
  237. Textcolor(7);
  238. gotoxy(70,18);write('7 8 9');
  239. gotoxy(70,19);write('4 5 6');
  240. gotoxy(70,20);write('1 2 3');
  241. ch := ' ';
  242.  
  243. repeat
  244.  gotoxy(70,21);write('Move:');
  245.  ch := readkey;
  246.  gotoxy(76,21);
  247.   if not (ch in goodinput) then beep(220,400)
  248.   else write(ch);
  249. until ch in goodinput;
  250.  
  251. case ch of
  252. '7','8','9':r := 0;
  253. '4','5','6':r := 1;
  254. '1','2','3':r := 2;
  255. end;
  256.  
  257. case ch of
  258. '7','4','1':c := 0;
  259. '8','5','2':c := 1;
  260. '9','6','3':c := 2;
  261. end;
  262.  
  263.  
  264. If game[r,c] = 0 then
  265.   begin
  266.         game[r,c] := Human;
  267.         Scoretoken(r,c,Human);
  268.         drawspot(Human,r,c);
  269.         goodmove := true;
  270.   end
  271.    else beep(220,400);
  272. until goodmove;
  273.   boardfix;
  274.   checkforwin(Human);
  275. end;
  276.  
  277.  
  278. Procedure ComputerMove(Which:integer);
  279. var
  280.     count:integer;
  281.     rr,cc,
  282.     r,c:integer;
  283.     mademove:boolean;
  284.     highspot:integer;
  285.     RandomNum:integer;
  286.  
  287.   Procedure makemove(rr,cc:integer);
  288.   begin
  289.       mademove := true;
  290.       game[rr,cc] := Which;
  291.       scoretoken(rr,cc,Which);
  292.       drawspot(which,rr,cc);
  293.   end;
  294.  
  295. begin
  296. boardfix;
  297. count := 0;
  298. mademove := false;
  299.  for r := 0 to 2 do
  300.     for c := 0 to 2 do
  301.        if game[r,c] <> 0 then inc(count);
  302.  
  303.  {grab the middle early in the game}
  304. if count <=3 then
  305. if (game[1,1] = 0) and not mademove then
  306.      begin
  307.        r := 1; c := 1;
  308.        makemove(r,c);
  309.      end;
  310.  
  311. if not mademove then
  312. if count <2 then
  313.  begin
  314.     mademove := false;
  315.     {Random corner grab is second}
  316.     repeat
  317.      randomnum := random(4);
  318.      case randomnum of
  319.      0:    if game[0,0] = 0 then
  320.        begin
  321.           r := 0;
  322.           c := 0;
  323.           makemove(r,c);
  324.        end;
  325.  
  326.     1:if (game[0,2] = 0 ) and not mademove then
  327.       begin
  328.          r := 0; c :=2;
  329.          makemove(r,c);
  330.       end;
  331.  
  332.    2: if (game[2,0] = 0) and not mademove then
  333.      begin
  334.         r := 2; c := 0;
  335.         makemove(r,c);
  336.      end;
  337.  
  338.    3:if (game[0,2] = 0) and not mademove then
  339.       begin
  340.             r := 0; c := 2;
  341.             makemove(r,c);
  342.         end;
  343.  
  344.    end;
  345.  until mademove;
  346.  end
  347. else
  348. begin       {Make a move based on score value - win first then block}
  349.      highspot := 0;
  350.      for r := 0 to 2 do
  351.          for c := 0 to 2 do
  352.              if score[r,c] > highspot then
  353.                   begin
  354.                     highspot := score[r,c];
  355.                     rr := r; cc := c;
  356.                   end;
  357.  
  358.      if highspot > 0 then
  359.      begin
  360.         makemove(rr,cc);
  361.         r := rr; c  := cc;
  362.      end
  363.      else
  364.      begin
  365.        {make a random move}
  366.        mademove := false;
  367.      repeat
  368.            r := random(3);
  369.            c := random(3);
  370.      until game[r,c] = 0;
  371.      makemove(r,c);
  372.      end;
  373.  end;
  374.   boardfix;
  375.   checkforwin(Which);
  376. end;
  377.  
  378.  
  379.  
  380. begin
  381. randomize;
  382. hwin := 0;
  383. Cwin := 0;
  384. Tie := 0;
  385. repeat
  386.   fillchar(game,sizeof(game),0);
  387.   fillchar(score,sizeof(score),0);
  388.   clrscr;
  389.   initscreen;
  390.   gameover := false;
  391.   wongame := false;
  392.   ac := random(2);
  393.   goesfirst := (ac = 0);
  394. repeat
  395. if not gameover then
  396. if goesfirst then
  397. humanmove
  398. //computermove(Human)                {the game can play itself}
  399. else computermove(Computer);
  400.  
  401. boardfix;
  402. if not gameover then
  403. if goesfirst then
  404. computermove(Computer)
  405.    else
  406.     Humanmove;
  407. //computermove(Human);
  408.  
  409. boardfix;
  410.  
  411. if wongame then
  412.   begin
  413.    beep(220,180); beep(440,180); beep(880,180);       {comment out for computer vs computer}
  414.   end;
  415.  
  416. until (gameover or wongame);
  417.  
  418.  Textcolor(14);
  419.  gotoxy(40,1);clreol;
  420. gotoxy(40,1);write('O''s wins:',Hwin,' *** X''s wins:',cwin,' *** Ties:',tie);
  421. gotoxy(40,2);clreol;
  422. gotoxy(40,2);write('Game over. Play again? y/n' );
  423. EndingResponse := lowercase(readkey);
  424. until EndingResponse <> 'y';
  425.  
  426. end.
  427.  
  428.  
  429.  
Barry

Newest game (clone),
Missile Commander:
https://www.youtube.com/watch?v=tgKz0cxog-k

 

TinyPortal © 2005-2018