Author Topic: Re: midnight tic tac toe - exercise game  (Read 791 times)

0 Members and 1 Guest are viewing this topic.

This topic contains a post which is marked as Best Answer. Press here if you would like to see it.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: midnight tic tac toe - exercise game
« on: June 15, 2019, 01:35:08 am »
Well if you get too lonely there is AI guy to play against, it's hard (impossible) to beat.

 
TTT with ron77.PNG
« Last Edit: June 15, 2019, 01:36:29 am by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: midnight tic tac toe - exercise game
« Reply #1 on: June 15, 2019, 02:24:41 pm »
It's more fun to play against something! :)

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: midnight tic tac toe - exercise game
« Reply #2 on: June 15, 2019, 02:59:04 pm »
Hi ron77,

You might like this in your game or toolbox, wait for a key from certain set of key presses:
Code: QB64: [Select]
  1. _TITLE "GetKey$ test" 'B+ 2019-06-15
  2.  
  3.     PRINT "Press #'s 0 to 9 or escape..."
  4.     ky$ = GetKey$(CHR$(27) + "1234567890")
  5.     IF INSTR("1234567890", ky$) THEN PRINT "You pressed "; ky$ ELSE PRINT "Goodbye!"
  6.     PRINT
  7. LOOP UNTIL ASC(ky$) = 27
  8.  
  9. FUNCTION GetKey$ (keysToCatch$)
  10.     DIM k$
  11.     DO
  12.         k$ = INKEY$
  13.         WHILE LEN(k$) = 0
  14.             k$ = INKEY$
  15.             _LIMIT 60
  16.         WEND
  17.     LOOP UNTIL INSTR(keysToCatch$, k$)
  18.     GetKey$ = k$
  19.  

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: midnight tic tac toe - exercise game
« Reply #3 on: June 18, 2019, 06:21:45 pm »
Hi ron77,

I still see a couple of places where GetKey$ could be used to eliminate all Enter key presses needed for INPUT's. In my opinion it is best to be consistent, all enter's or all just one key press.

You know, I think I play a game longer when it let's me win once in awhile, this latest version for instance. I remember being turned off early on by a version on NIM, it always won and was a bit snotty about it. So this might be more enjoyable than INVICTUS you have planned or the AI I showed here for that matter.
« Last Edit: June 18, 2019, 09:37:40 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: midnight tic tac toe - exercise game
« Reply #4 on: June 19, 2019, 09:30:46 am »
Hi ron77,

Ah! so much smoother without enter any where. The choice of 1 player or 2 might be made only once at the beginning for 1 less question each round...

Oh but you say final version...? so much more can be done eg, Center Print text lines on screen:
replace:
Code: QB64: [Select]
  1.  
  2. opening
  3.  
  4.     ky2$ = GetKey$(CHR$(27) + CHR$(13))
  5.     IF ky2$ = CHR$(27) THEN END
  6. LOOP UNTIL ky2$ = CHR$(13)
  7.  
  8. PRINT "PLAY IN FULL SCREEN MODE? - y/n:"
  9.     ky3$ = GetKey$("yn")
  10.     IF INSTR("y", ky3$) THEN _FULLSCREEN: EXIT DO
  11. LOOP UNTIL ky3$ = "n"
  12.  
  13. '... and this
  14. SUB opening
  15.     PRINT "     " + DATE$ + " " + TIME$
  16.     PRINT
  17.     PRINT "   WELCOME FRIEND TO:"
  18.     PRINT
  19.     PRINT "       MIDNIGHT TIC TAC TOE GAME!"
  20.     PRINT
  21.     PRINT "  WINS = 10 POINTS: TIES = 5 POINTS EACH"
  22.     PRINT
  23.     PRINT " A SMALL GAME TO PLAY BEFORE BED-TIME"
  24.     PRINT
  25.     PRINT "    BY RON77 AND ITAY"
  26.     PRINT
  27.     PRINT "PRESS ENTER TO CONTINUE OR ESC TO QUIT"
  28.     PRINT
  29.  
  30.  


with this:
Code: QB64: [Select]
  1. opening
  2.  
  3. '... and this
  4. SUB opening
  5.     DIM k$
  6.     cp 3, DATE$ + " Time:" + TIME$
  7.     cp 5, "WELCOME FRIEND TO:"
  8.     cp 7, "MIDNIGHT TIC TAC TOE GAME!"
  9.     cp 9, "WINS = 10 POINTS: TIES = 5 POINTS EACH"
  10.     cp 11, "A SMALL GAME TO PLAY BEFORE BED-TIME"
  11.     cp 13, "BY RON77 AND ITAY"
  12.     cp 18, "PRESS ENTER TO CONTINUE OR ESC TO QUIT"
  13.     k$ = GetKey$(CHR$(27) + CHR$(13))
  14.     IF k$ = CHR$(27) THEN END
  15.     cp 20, "PLAY IN FULL SCREEN MODE? - y/n:"
  16.     k$ = GetKey$("yn")
  17.     IF k$ = "y" THEN _FULLSCREEN
  18.  
  19. SUB cp (row, s$) 'print text centered on screen row
  20.     LOCATE row, (80 - LEN(s$)) / 2: PRINT s$
revised opening.PNG


I am certain that the number of lines of code could be easily reduced below 200, wouldn't change the play of game but good coding challenge... to get inventive.

With solid study of game from reducing lines, might be ready to learn mouse skills.



« Last Edit: June 19, 2019, 09:56:44 am by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: midnight tic tac toe - exercise game
« Reply #5 on: June 19, 2019, 04:03:54 pm »
Hi ron77,

Of course you can set ending code like opening to save some lines. In fact everywhere you print something you could probably use cp instead, even the board.

If gameArray() is shared don't need to use it in procedure calls.

Also there is hardly any difference between CheckWinner and CheckWinnerComp. I think if the function returned the mark of the winner if it finds one you wouldn't need the redundant procedure.
eg, if a(0) = a(1) = a(2) then function = a(0)
If function finds no winner after 8 checks then function = 0
 
Yes, for AI, if you go through open spots in the game array and substitute in the marker then check if winner then remove marker from game array you can save yourself all that crazy array copying!!!

Play again?
Code: QB64: [Select]
  1.     PRINT "play again y/n?:"
  2.     again$ = UCASE$(GetKey$("yn"))
  3. LOOP UNTIL again$ = "N"
  4.  

Over and over I see you are not using GetKey$ correctly:
Code: QB64: [Select]
  1.     ky4$ = GetKey$("12")
  2.     IF INSTR("12", ky4$) THEN numPlayer = VAL(ky4$)  '
  3.  
GetKey$ will be either 1 or 2, no checking with INSTR necessary

Just say:
Code: QB64: [Select]
  1. numPlayer = VAL(GetKey$("12")
« Last Edit: June 19, 2019, 04:40:19 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: midnight tic tac toe - exercise game
« Reply #6 on: June 19, 2019, 05:28:47 pm »
Code: QB64: [Select]
  1. SUB board (gameArray() AS STRING)
  2.     cp 2, "Welcome to MIDNIGHT TIC TAC TOE GAME!"
  3.     cp 4, greetings
  4.     cp 6, "ֲֲִִִִִִִִִ¿"
  5.     cp 7, "³   ³   ³   ³"
  6.     cp 8, "³ " + gameArray(0) + " ³ " + gameArray(1) + " ³ " + gameArray(2) + " ³"
  7.     cp 9, "³(0)³(1)³(2)³"
  8.     cp 10, "ֳִִִִִִִִִֵֵ´"
  9.     cp 11, "³   ³   ³   ³"
  10.     cp 12, "³ " + gameArray(3) + " ³ " + gameArray(4) + " ³ " + gameArray(5) + " ³"
  11.     cp 13, "³(3)³(4)³(5)³"
  12.     cp 14, "ֳִִִִִִִִִֵֵ´"
  13.     cp 15, "³   ³   ³   ³"
  14.     cp 16, "³ " + gameArray(6) + " ³ " + gameArray(7) + " ³ " + gameArray(8) + " ³"
  15.     cp 17, "³(6)³(7)³(8)³"
  16.     cp 18, "ְֱֱִִִִִִִִִ"
  17.  
  18.  

gameArray is Shared the board SUB does not need that argument passed to it
Code: QB64: [Select]
  1. SUB board
  2.  
is all that is needed.

Here is revised Winner$ function that replaces the two that are almost redundant.
Code: QB64: [Select]
  1. FUNCTION Winner$
  2.     IF game(0) = game(1) AND game(1) = game(2) AND game(0) <> " " THEN
  3.         Winner$ = game(0)
  4.     ELSEIF game(3) = game(4) AND game(4) = game(5) AND game(3) <> " " THEN
  5.         Winner$ = game(3)
  6.     ELSEIF game(6) = game(7) AND game(7) = game(8) AND game(6) <> " " THEN
  7.         Winner$ = game(6)
  8.     ELSEIF game(0) = game(3) AND game(3) = game(6) AND game(0) <> " " THEN
  9.         Winner$ = game(0)
  10.     ELSEIF game(1) = game(4) AND game(4) = game(7) AND game(1) <> " " THEN
  11.         Winner$ = game(1)
  12.     ELSEIF game(2) = game(5) AND game(5) = game(8) AND game(2) <> " " THEN
  13.         Winner$ = game(2)
  14.     ELSEIF game(0) = game(4) AND game(4) = game(8) AND game(0) <> " " THEN
  15.         Winner$ = game(0)
  16.     ELSEIF game(6) = game(4) AND game(4) = game(2) AND game(6) <> " " THEN
  17.         Winner$ = game(6)
  18.     ELSE
  19.         Winner$ = ""
  20.     END IF
  21.  

I am in process of checking the computer moves (now called AI function) with the new Winner$ function now.
EDIT: oops! I thought I saved last change...

BTW I renamed gameArray game() since I changed game$ to again$ and dumped all the array copying that you guys were doing.

Again I say, where ever you use GetKey$, you don't have to check it again with INSTR() that's the beauty of GetKey$, you get what you require in CatchKeys$. see line 50 and 71 and 96
« Last Edit: June 19, 2019, 05:40:13 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: midnight tic tac toe - exercise game
« Reply #7 on: June 19, 2019, 09:02:29 pm »
Hi ron77,

I'm sorry about your teacher. Once I got rolling with makeover, I couldn't stop until made my goal of less than 200 lines.

Quote
as for the dim shared not needed to passed as parameters to subs\functions i didn't know that yet that's how i am used to writing code (a legacy from VB.NET)
I was trying to say that if you DIM SHARE an array, then you don't have to include it in the parameters list of the sub definition:
Code: QB64: [Select]
  1. SUB Board(myArray as string)

IF myArray was already in main code:
Code: QB64: [Select]
  1. DIM SHARE myArray(1 to n) AS STRING

you can just do this:
Code: QB64: [Select]
  1. SUB Board
because myArray is already available to any procedure.


Quote
well i checked your solution to the Winner$ function and it only works for 2 players but not for the AI function and as for your say that doing a copy of the Game Array is unnecessary i think it's a must cause the AI needs a copy of the game array so it can mess around with it without the original game array is changed...
I didn't have to copy the game() because when I switched an empty space with a sign$ and it didn't do anything for the AI, I switched it back to the empty space and tried another spot. So the array remains intact unless the AI finds a winner move, then it is already made in the array and does not have to be switched back to a space.

It all works and in less than 200 lines:
Code: QB64: [Select]
  1. 'started by me ron77 on 6-15-2019 saturday night...
  2. 'one boring lonley weekend night i started to feel sad with no one to talk to...
  3. 'so i started this on my own so i won't feel lonely and sad all night
  4. 'by morning i got it right as a begining of a it was a white-night coding thing
  5. '5-6-7 cups of coffee and a few cigarettes and relaxing music was all that it took
  6. 'by sun rise i felt better
  7. '7 AM - add possiblemoves function
  8. '10:30 AM - added a counter named turns to count turns and stop after 9 moves in case there is a tie and nobody wins
  9. '9 PM - had a lesson with my teacher and we added a human vs. computer play with basic AI :) we also made some design modification
  10. '6-17-2019 - more design modification to the board and to the code - added Bplus GetKey$ function and now no need for INPUT command to get user input added another loop to keep playing after first finished
  11. 'me and my teacher are working on a second harder AI alogarithem to beat in HUMAN VS. COMPUTER called INVICTUS MODE which will hopefully be very hard to beat next lesson on WED this week...
  12. '6-18-2019 - in the meanwhile i am posting this short version 1 of tic tac toe in QB64 FORUM without level 2 INVICTUS MODE AI alogarithem: ENJOY! :)
  13. '6-19-2019 - final version! thanks to all how helped!
  14. '6-19-2019 - Bplus makeover reduce to less than 200 lines
  15.  
  16. _TITLE "MIDNIGHT TIC TAC TOE"
  17. DIM SHARED game(8) AS STRING, numPlayer AS INTEGER, greetings AS STRING, code$, turns AS INTEGER
  18. DIM SHARED scoreX AS INTEGER, scoreO AS INTEGER, scoreComp AS INTEGER
  19. DIM i AS INTEGER, again$
  20.  
  21. opening
  22.     FOR i = 0 TO 8: game(i) = " ": NEXT 'clear last board
  23.     turns = 0 'reset count
  24.     IF numPlayer = 2 THEN
  25.         greetings = "TWO PLAYERS X AND O"
  26.         DO
  27.             player "X"
  28.             IF code$ = "win" THEN scoreX = scoreX + 10: EXIT DO
  29.             IF code$ = "tie" THEN scoreX = scoreX + 5: scoreO = scoreO + 5: EXIT DO
  30.             player "O"
  31.             IF code$ = "win" THEN scoreO = scoreO + 10: EXIT DO
  32.             IF code$ = "tie" THEN scoreX = scoreX + 5: scoreO = scoreO + 5: EXIT DO
  33.         LOOP
  34.     ELSE
  35.         greetings = "HUMAN PLAYER AS X VS. COMPUTER AS O"
  36.         DO
  37.             player "X"
  38.             IF code$ = "win" THEN scoreX = scoreX + 10: EXIT DO
  39.             IF code$ = "tie" THEN scoreX = scoreX + 5: scoreComp = scoreComp + 5: EXIT DO
  40.             IF AI = -1 THEN
  41.                 board
  42.                 cp 19, "O is winner."
  43.                 scoreComp = scoreComp + 10
  44.                 EXIT DO
  45.             ELSE
  46.                 turns = turns + 1
  47.             END IF
  48.         LOOP
  49.     END IF
  50.     cp 21, "play again y/n?"
  51.     again$ = UCASE$(GetKey$("yn"))
  52. LOOP UNTIL again$ = "N"
  53. ending
  54.  
  55. SUB player (sign$) 'replace 3 repeated code blocks with this
  56.     DIM k$, inpt AS INTEGER
  57.     code$ = ""
  58.     board
  59.     cp 19, "Where to mark " + sign$ + "? press 0-8 or ESC to stop:"
  60.     k$ = GetKey$(CHR$(27) + "012345678")
  61.     IF ASC(k$) = 27 THEN ending ELSE inpt = VAL(k$)
  62.     IF game(inpt) = " " THEN
  63.         game(inpt) = sign$
  64.         board
  65.         IF Winner$ = sign$ THEN
  66.             code$ = "win": cp 19, sign$ + " wins!"
  67.         ELSE
  68.             turns = turns + 1
  69.             IF turns = 9 THEN
  70.                 code$ = "tie": cp 19, "Tie nobody wins!"
  71.             END IF
  72.         END IF
  73.     ELSE
  74.         board
  75.         cp 19, "The square is occupied choose another."
  76.         _DELAY 1.5
  77.         player sign$ ' recursive do this again!
  78.     END IF
  79.  
  80. SUB ending
  81.     CLS
  82.     cp 7, "G O O D  -  N I G H T !"
  83.     cp 9, "       AND SWEET DREAMS!"
  84.     cp 11, "HUMAN PLAYER X HAS" + STR$(scoreX) + " points"
  85.     cp 13, "HUMAN PLAYER O HAS" + STR$(scoreO) + " points"
  86.     cp 15, "COMPUTER PLAYER O HAS" + STR$(scoreComp) + " points"
  87.     SLEEP
  88.     END
  89.  
  90. SUB board
  91.     CLS
  92.     cp 1, "Welcome to MIDNIGHT TIC TAC TOE GAME!"
  93.     cp 3, greetings
  94.     cp 5, "ÚÄÄÄÂÄÄÄÂÄÄÄ¿"
  95.     cp 6, "³   ³   ³   ³"
  96.     cp 7, "³ " + game(0) + " ³ " + game(1) + " ³ " + game(2) + " ³"
  97.     cp 8, "³(0)³(1)³(2)³"
  98.     cp 9, "ÃÄÄÄÅÄÄÄÅÄÄÄ´"
  99.     cp 10, "³   ³   ³   ³"
  100.     cp 11, "³ " + game(3) + " ³ " + game(4) + " ³ " + game(5) + " ³"
  101.     cp 12, "³(3)³(4)³(5)³"
  102.     cp 13, "ÃÄÄÄÅÄÄÄÅÄÄÄ´"
  103.     cp 14, "³   ³   ³   ³"
  104.     cp 15, "³ " + game(6) + " ³ " + game(7) + " ³ " + game(8) + " ³"
  105.     cp 16, "³(6)³(7)³(8)³"
  106.     cp 17, "ÀÄÄÄÁÄÄÄÁÄÄÄÙ"
  107.  
  108. SUB opening
  109.     DIM k$
  110.     cp 3, DATE$ + " " + TIME$
  111.     cp 5, "WELCOME FRIEND TO:"
  112.     cp 7, "MIDNIGHT TIC TAC TOE GAME!"
  113.     cp 9, "WINS = 10 POINTS: TIES = 5 POINTS EACH"
  114.     cp 11, "A SMALL GAME TO PLAY BEFORE BED-TIME"
  115.     cp 13, "BY RON77, ITAY and BPLUS"
  116.     cp 18, "PRESS ENTER TO CONTINUE OR ESC TO QUIT"
  117.     k$ = GetKey$(CHR$(27) + CHR$(13))
  118.     IF k$ = CHR$(27) THEN END
  119.     cp 20, "Press 1 for One Player or 2 for Two Players?"
  120.     numPlayer = VAL(GetKey$("12"))
  121.     cp 22, "PLAY IN FULL SCREEN MODE? - y/n"
  122.     k$ = GetKey$("yn")
  123.     IF k$ = "y" THEN _FULLSCREEN
  124.  
  125. SUB cp (row, s$) 'print text centered on screen row
  126.     LOCATE row, (80 - LEN(s$)) / 2: PRINT s$;
  127.  
  128. FUNCTION GetKey$ (keysToCatch$)
  129.     DIM k$
  130.     DO
  131.         k$ = INKEY$
  132.         WHILE LEN(k$) = 0
  133.             k$ = INKEY$
  134.             _LIMIT 60
  135.         WEND
  136.     LOOP UNTIL INSTR(keysToCatch$, k$)
  137.     GetKey$ = k$
  138.  
  139.     DIM i AS INTEGER, rndNumber AS INTEGER
  140.     FOR i = 0 TO 8 'computer seeks win
  141.         IF game(i) = " " THEN
  142.             game(i) = "O"
  143.             IF Winner$ = "O" THEN
  144.                 AI = -1: EXIT FUNCTION 'signal win
  145.             ELSE
  146.                 game(i) = " "
  147.             END IF
  148.         END IF
  149.     NEXT
  150.     FOR i = 0 TO 8 'computer seeks spoiler
  151.         IF game(i) = " " THEN
  152.             game(i) = "X"
  153.             IF Winner$ = "X" THEN
  154.                 game(i) = "O": EXIT FUNCTION
  155.             ELSE
  156.                 game(i) = " "
  157.             END IF
  158.         END IF
  159.     NEXT
  160.     rndNumber = INT(RND * 9) 'computers picks random open space
  161.     WHILE game(rndNumber) <> " "
  162.         rndNumber = INT(RND * 9)
  163.     WEND
  164.     game(rndNumber) = "O"
  165.  
  166. FUNCTION Winner$
  167.     IF game(0) = game(1) AND game(1) = game(2) AND game(0) <> " " THEN
  168.         Winner$ = game(0)
  169.     ELSEIF game(3) = game(4) AND game(4) = game(5) AND game(3) <> " " THEN
  170.         Winner$ = game(3)
  171.     ELSEIF game(6) = game(7) AND game(7) = game(8) AND game(6) <> " " THEN
  172.         Winner$ = game(6)
  173.     ELSEIF game(0) = game(3) AND game(3) = game(6) AND game(0) <> " " THEN
  174.         Winner$ = game(0)
  175.     ELSEIF game(1) = game(4) AND game(4) = game(7) AND game(1) <> " " THEN
  176.         Winner$ = game(1)
  177.     ELSEIF game(2) = game(5) AND game(5) = game(8) AND game(2) <> " " THEN
  178.         Winner$ = game(2)
  179.     ELSEIF game(0) = game(4) AND game(4) = game(8) AND game(0) <> " " THEN
  180.         Winner$ = game(0)
  181.     ELSEIF game(6) = game(4) AND game(4) = game(2) AND game(6) <> " " THEN
  182.         Winner$ = game(6)
  183.     ELSE
  184.         Winner$ = ""
  185.     END IF
  186.  

The BIG screen is nice for late night Tic Tac Toe!

Oh yeah, I sort of figured out why you were using INSTR in some places after GetKey$ call. With CHR$(27) added to the CatchKey$ string, you did have to figure out first if ESCAPE was pressed and K$ was coming back with that! before processing the other key presses.
« Last Edit: June 19, 2019, 09:11:00 pm by bplus »

Marked as best answer by on June 27, 2021, 08:12:33 pm

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: midnight tic tac toe - exercise game
« Reply #8 on: June 19, 2019, 09:27:18 pm »
Oh hey ron77,

There is a wide open door to winning against the AI, (not 100% guarantee but still pretty good) see if you can figure it out ;-))