Author Topic: Tic Tac Toe  (Read 287 times)

Galileo

  • Jr. Member
  • **
  • Posts: 79
    • View Profile
Tic Tac Toe
« on: 06. June 2018, 19:30:47 »
WOPR is comming!

Old style code in Yabasic

Code: [Select]
5 REM Adaptation to Yabasic of the program published in Tim Hartnell's book "Artificial Intelligence: Concepts and Programs", with some minor modifications. 6/2018.
10 REM TICTAC
15 INPUT "English (0), Spanish (other number): " IDIOMA : IF NOT IDIOMA THEN RESTORE 2020 ELSE RESTORE 2010 END IF
20 GOSUB 1180: REM INICIALIZACION
30 REM *** REQUISITOS PREVIOS AL JUEGO ***
40 FOR J = 1 TO 9
50 A(J) = 32
60 NEXT J
70 FOR J = 1 TO 5
80 D(J) = 0
90 NEXT J
100 CCONTADOR = 0
110 R$ = ""
120 GOSUB 1070: REM IMPRESION DEL TABLERO
130 REM ** CICLO PRINCIPAL **
140 GOSUB 540: REM MOVIMIENTO DEL ORDENADOR
150 GOSUB 1070: REM IMPRESION DEL TABLERO
160 GOSUB 870: REM COMPRUEBA LA VICTORIA
170 IF R$ <> ""  GOTO 240
180 GOSUB 980: REM SE ACEPTA EL MOVIMIENTO DE LA PERSONA
190 GOSUB 1070: REM IMPRESION DEL TABLERO
200 GOSUB 870: REM COMPRUEBA LA VICTORIA
210 IF R$ = ""  GOTO 140
220 REM ** FIN DEL CICLO PRINCIPAL **
230 REM *****************************
240 REM FIN DEL JUEGO
250 GOSUB 1070: REM IMPRESION DEL TABLERO
260 PRINT: PRINT
270 IF R$ = "G"  PRINT MENSAJE$(1): BANDERA = -1
280 IF R$ = "P"  PRINT MENSAJE$(2): BANDERA = 1
290 IF R$ = "D"  PRINT MENSAJE$(3): GOTO 430
300 REM ACTUALIZACION DE LA BASE DE DATOS
310 FOR B = 1 TO 5
320 FOR J = 2 TO 9
330 IF M(J) = D(B) GOSUB 370
340 NEXT J
350 NEXT B
360 GOTO 430
370 REM ** REORDENACION DE LOS ELEMENTOS DE LA MATRIZ M **
380 TEMP = M(J + BANDERA)
390 M(J + BANDERA) = M(J)
400 M(J) = TEMP
410 J = 9
420 RETURN
430 PRINT: PRINT
440 PRINT MENSAJE$(4)
450 PRINT: PRINT
460 FOR J = 1 TO 9
470 PRINT M(J), " ";
480 NEXT J
490 PRINT: PRINT
500 PRINT MENSAJE$(5)
510 INPUT A$
520 GOTO 30
530 REM ************************
540 REM MOVIMIENTO DEL ORDENADOR
550 P = ASC("O")
560 X = 0
570 J = 1
580 IF A(W(J)) = A(W(J + 1)) AND A(W(J + 2)) = 32 AND A(W(J)) = P  X = W(J + 2): GOTO 750
590 IF A(W(J)) = A(W(J + 2)) AND A(W(J + 1)) = 32 AND A(W(J)) = P  X = W(J + 1): GOTO 750
600 IF A(W(J + 1)) = A(W(J + 2)) AND A(W(J)) = 32 AND A(W(J + 1)) = P  X = W(J): GOTO 750
610 IF J < 21  J = J + 3: GOTO 580
620 IF P = ASC("O")  P = ASC("X"): GOTO 570
630 REM ** SI NO SE GANA SE BUSCA UN MOVIMIENTO DE BLOQUEO **
640 REM * ENTONCES SE USA LA SIGUIENTE SECCION *
650 J = 1
660 IF A(M(J)) = 32  X = M(J): GOTO 750
670 IF J < 10  J = J + 1: GOTO 660
680 H = 0
690 H = H + 1
700 X = INT(RAN(1) * 9): IF A(X) = 32  GOTO 750
710 IF H < 100  GOTO 690
720 R$ = "D": REM ES SIMPLEMENTE UN DIBUJO
730 RETURN
740 REM *********************
750 REM REALIZA EL MOVIMIENTO
760 A(X) = ASC("O")
770 CCONTADOR = CCONTADOR + 1
780 D(CCONTADOR) = X
790 BANDERA = 0
800 FOR J = 1 TO 9
810 IF A(J) = 32  BANDERA = 1
820 NEXT J
830 IF BANDERA = 0 AND R$ = ""  R$ = "D"
840 REM SI TODAS LAS CASILLAS ESTAN LLENAS Y R$ ESTA VACIO, ENTONCES ES SIMPLEMENTE UN DIBUJO
850 RETURN
860 REM *********************
870 REM COMPRUEBA LA VICTORIA
880 J = 1
890 IF A(W(J)) = 32  J = J + 3
900 IF J > 23  RETURN
910 IF A(W(J)) = A(W(J + 1)) AND A(W(J)) = A(W(J + 2))  GOTO 940
920 IF J < 22  J = J + 3: GOTO 890
930 RETURN
940 IF A(W(J)) = ASC("O")  R$ = "G": REM EL ORDENADOR GANA
950 IF A(W(J)) = ASC("X")  R$ = "P": REM EL ORDENADOR PIERDE
960 RETURN
970 REM ************************
980 REM MOVIMIENTO DE LA PERSONA
990 PRINT: PRINT
1000 PRINT MENSAJE$(6)
1010 PRINT MENSAJE$(7); : INPUT MOVIMIENTO
1020 IF MOVIMIENTO < 1 OR MOVIMIENTO > 9  GOTO 1010
1030 IF A(MOVIMIENTO) <> 32  GOTO 1010
1040 A(MOVIMIENTO) = ASC("X")
1050 RETURN
1060 REM *********************
1070 REM IMPRESION DEL TABLERO
1080 CLEAR SCREEN
1090 PRINT: PRINT: PRINT
1100 PRINT " 1 : 2 : 3        ", CHR$(A(1)), " : ", CHR$(A(2)), " : ", CHR$(A(3))
1110 PRINT "-----------      ------------"
1120 PRINT " 4 : 5 : 6        ", CHR$(A(4)), " : ", CHR$(A(5)), " : ", CHR$(A(6))
1130 PRINT "-----------      ------------"
1140 PRINT " 7 : 8 : 9        ", CHR$(A(7)), " : ", CHR$(A(8)), " : ", CHR$(A(9))
1150 PRINT
1160 RETURN
1170 REM **************
1180 REM INICIALIZACION
1190 CLEAR SCREEN
1200 DIM A(9) : REM TABLERO
1210 DIM M(10) : REM ACCESO A LA BASE DE DATOS
1220 DIM W(24) : REM DATOS DE VICTORIA O BLOQUEO
1230 DIM D(5) : REM ACCESO AL MOVIMIENTO EN EL JUEGO ACTUAL
1235 DIM MENSAJE$(1) : READ M$ : N = TOKEN(M$,MENSAJE$(),",") : RESTORE
1240 REM DATOS DE VICTORIA O BLOQUEO
1250 FOR J = 1 TO 24
1260 READ W(J)
1270 NEXT J
1280 DATA 1, 2, 3, 4, 5, 6, 7, 8, 9
1290 DATA 1, 4, 7, 2, 5, 8, 3, 6, 9
1300 DATA 1, 5, 9, 3, 5, 7
1310 REM BASE INICIAL DE DATOS
1320 FOR J = 1 TO 10
1330 READ M(J)
1340 NEXT J
1350 DATA 2, 6, 8, 4, 7, 3, 1, 9, 5, 2
1360 RETURN
2000 REM MENSAJES EN ESPA—OL
2010 DATA "YO GANO,TU GANAS,ES SIMPLEMENTE UN DIBUJO,ESTA ES MI PRIORIDAD ACTUALIZADA,PULSE LA TECLA <RETURN> PARA CONTINUAR,REALICE SU MOVIMIENTO,MOVIMIENTO: "
2020 DATA "I WIN,YOU WIN,IT'S JUST A DRAWING,THIS IS MY PRIORITY UPDATE,PRESS <RETURN> TO CONTINUE,TO MAKE YOUR MOVE,MOVEMENT: "

B+

  • Hero Member
  • *****
  • Posts: 548
    • View Profile
Re: Tic Tac Toe
« Reply #1 on: 07. June 2018, 01:30:55 »
What is WOPR? How shall we prepare for it's coming?  :o

Here is last thing I did with TTT and AI:
Code: [Select]
_TITLE "Tic Tac Toe with AI"
'QB64 version 2017 1106/82 (the day before they switched to version 1.2)
'bplus 2018-01-23
CONST xmax = 800
CONST ymax = 600
CONST redh& = &HFFFF0000
CONST greenh& = &HFF00FF00
CONST blueh& = &HFF0000FF

SCREEN _NEWIMAGE(xmax, ymax, 32)
_SCREENMOVE 360, 60

DEFINT A-Z
COMMON SHARED player$, AI$
DIM SHARED board$(2, 2) 'store X and O here 3x3

WHILE 1
    COLOR greenh&: CLS
    winner$ = "": count = 0: done = 0: ERASE board$

    'get player's choice
    INPUT "Player, enter symbol to use for your squares: (nothing quits) "; player$
    IF player$ = "" THEN END
    IF player$ = "AI" THEN AI$ = "#1 AI" ELSE AI$ = "AI"
    IF LEN(player$) > 15 THEN player$ = LEFT$(player$, 15)

    'who plays first
    INPUT "And now please enter y for yes, if you want to go first: "; first$
    IF first$ = "y" THEN turn$ = player$ ELSE turn$ = AI$

    'prep, make grid according to size of longest participant string
    IF LEN(player$) > LEN(AI$) THEN s = LEN(player$) ELSE s = LEN(AI$)
    sq = 16 * (s + 2)
    xoff = (xmax - 3 * sq) / 2
    yoff = (ymax - 3 * sq) / 2

    'make # grid once
    CLS
    FOR i = 1 TO 2
        LINE (sq * i + xoff, yoff)-STEP(0, 3 * sq)
        LINE (xoff, sq * i + yoff)-STEP(3 * sq, 0)
    NEXT

    'take turns filling out the board until a winner$ is found or board is out of spaces
    DO
        IF turn$ = AI$ THEN
            rc = AIchoice
            bx = rc MOD 3: by = INT(rc / 3)
            board$(bx, by) = AI$
            _DELAY 1 'let player think AI is thinking
            COLOR blueh&
            _PRINTSTRING (bx * sq + xoff + sq / 2 - _PRINTWIDTH(AI$) / 2, by * sq + yoff + sq / 2 - 8), AI$
            count = count + 1
            IF checkwin THEN winner$ = AI$
            turn$ = player$
        ELSE
            'player's turn from mouse click

            'this might NOT be too intuitive but proper mouse catching demands we wait for mouse button release
            m = _MOUSEINPUT: mb = _MOUSEBUTTON(1): mx = _MOUSEX: my = _MOUSEY
            IF mb THEN 'get last place mouse button was down
                mb = _MOUSEBUTTON(1): mx = _MOUSEX: my = _MOUSEY
                WHILE mb 'left button down, wait for mouse button release before doing anything as a "click"
                    'this updates mx, my while waiting for button release
                    m = _MOUSEINPUT: mb = _MOUSEBUTTON(1): mx = _MOUSEX: my = _MOUSEY
                WEND

                'board x and board y?
                ' board is offset by (xoff, yoff) = top left corner, so subtract these from mouse mx, my
                ' then divide by the size of the square (sq) to get the position in the board array
                ' check that position is inbounds of board array
                bx = INT((mx - xoff) / sq): by = INT((my - yoff) / sq)

                'now we have mouse pixels converted to board position of array
                IF bx >= 0 AND bx <= 2 AND by >= 0 AND by <= 2 THEN 'caught mouse in a box!
                    IF board$(bx, by) <> "" THEN
                        BEEP 'NO good! already clicked!
                    ELSE
                        'OK it all checks out, update the board array and the screen display
                        COLOR redh&
                        _PRINTSTRING (bx * sq + xoff + sq / 2 - _PRINTWIDTH(player$) / 2, by * sq + yoff + sq / 2 - 8), player$
                        board$(bx, by) = player$
                        count = count + 1
                        IF checkwin THEN winner$ = player$
                        turn$ = AI$
                    END IF
                ELSE
                    BEEP 'you are clicking out of bounds of board!
                END IF
            END IF
        END IF 'turn
        IF winner$ <> "" THEN done = 1
        IF done = 0 AND count >= 9 THEN done = -1
    LOOP UNTIL done
    COLOR greenh&
    IF done = -1 THEN s$ = "Out of spaces." ELSE s$ = winner$ + " is the winner!"
    _PRINTSTRING ((xmax - _PRINTWIDTH(s$)) / 2, 2 * _FONTHEIGHT), s$
    s$ = "Wait 5 secs for next game..."
    _PRINTSTRING ((xmax - _PRINTWIDTH(s$)) / 2, 4 * _FONTHEIGHT), s$
    _DELAY 5
WEND

FUNCTION checkwin
    FOR i = 0 TO 2
        IF (board$(0, i) = board$(1, i) AND board$(1, i) = board$(2, i)) AND (board$(2, i) <> "") THEN checkwin = 1: EXIT SUB
    NEXT
    FOR i = 0 TO 2
        IF (board$(i, 0) = board$(i, 1) AND board$(i, 1) = board$(i, 2)) AND board$(i, 2) <> "" THEN checkwin = 1: EXIT SUB
    NEXT
    IF (board$(0, 0) = board$(1, 1) AND board$(1, 1) = board$(2, 2)) AND board$(2, 2) <> "" THEN checkwin = 1: EXIT SUB
    IF (board$(0, 2) = board$(1, 1) AND board$(1, 1) = board$(2, 0)) AND board$(2, 0) <> "" THEN checkwin = 1
END FUNCTION

FUNCTION AIchoice
    'test all moves to win
    FOR r = 0 TO 2
        FOR c = 0 TO 2
            IF board$(c, r) = "" THEN
                board$(c, r) = AI$
                IF checkwin THEN
                    board$(c, r) = ""
                    AIchoice = 3 * r + c
                    EXIT FUNCTION
                ELSE
                    board$(c, r) = ""
                END IF
            END IF
        NEXT
    NEXT

    'still here? then no winning moves for AI, how about for player$
    FOR r = 0 TO 2
        FOR c = 0 TO 2
            IF board$(c, r) = "" THEN
                board$(c, r) = player$
                IF checkwin THEN
                    board$(c, r) = ""
                    AIchoice = 3 * r + c 'spoiler move!
                    EXIT FUNCTION
                ELSE
                    board$(c, r) = ""
                END IF
            END IF
        NEXT
    NEXT

    'still here? no winning moves, no spoilers then is middle sq available
    IF board$(1, 1) = "" THEN AIchoice = 4: EXIT FUNCTION

    'still here still? how about a corner office?
    IF board$(0, 0) = "" THEN AIchoice = 0: EXIT FUNCTION
    IF board$(2, 0) = "" THEN AIchoice = 2: EXIT FUNCTION
    IF board$(0, 2) = "" THEN AIchoice = 6: EXIT FUNCTION
    IF board$(2, 2) = "" THEN AIchoice = 8: EXIT FUNCTION

    'still here??? one of these has to go!
    IF board$(1, 0) = "" THEN AIchoice = 1: EXIT FUNCTION
    IF board$(0, 1) = "" THEN AIchoice = 3: EXIT FUNCTION
    IF board$(2, 1) = "" THEN AIchoice = 5: EXIT FUNCTION
    IF board$(1, 2) = "" THEN AIchoice = 7: EXIT FUNCTION

END FUNCTION


From this I went onto Connect 4 with AI (that took a little longer to get a decent game played by AI).
« Last Edit: 07. June 2018, 01:41:56 by B+ »

ZXDunny

  • Full Member
  • ***
  • Posts: 163
    • View Profile
Re: Tic Tac Toe
« Reply #2 on: 07. June 2018, 01:48:21 »
What is WOPR? How shall we prepare for it's coming?  :o

WOPR == War Operation Plan Response. A supercomputer whose AI core almost caused WW3 when a young kid hacked into it while looking for games to download. The war was averted by teaching it to play noughts and crosses, the futility of which it translated into nuclear war scenarios.

See the film "Wargames" from the 80s :)

B+

  • Hero Member
  • *****
  • Posts: 548
    • View Profile
Re: Tic Tac Toe
« Reply #3 on: 07. June 2018, 02:05:48 »
Yes, I remember that one!

I think the character then took a day off from school in next film. ;D

B+

  • Hero Member
  • *****
  • Posts: 548
    • View Profile
Re: Tic Tac Toe
« Reply #4 on: 07. June 2018, 17:35:11 »
BTW, good thing the AI played TTT because if it learned Connect 4 (1974) the movie might have to end differently.

Cybermonkey

  • Administrator
  • Hero Member
  • *****
  • Posts: 588
    • View Profile
    • Home of EGSL
Re: Tic Tac Toe
« Reply #5 on: 08. June 2018, 18:00:02 »
Yes, I remember that one!

I think the character then took a day off from school in next film. ;D

Life moves pretty fast. If you donít stop and look around once in awhile, you could miss it.
Bueller? Bueller? Bueller?  ;D
Best regards,
Cybermonkey

B+

  • Hero Member
  • *****
  • Posts: 548
    • View Profile
Re: Tic Tac Toe
« Reply #6 on: 08. June 2018, 19:54:25 »

John

  • Sr. Member
  • ****
  • Posts: 404
    • View Profile
Re: Tic Tac Toe
« Reply #7 on: 10. June 2018, 09:20:01 »
Here is my contribution to the TTT challenge.

B+

  • Hero Member
  • *****
  • Posts: 548
    • View Profile
Re: Tic Tac Toe
« Reply #8 on: 10. June 2018, 13:39:34 »

Quote
Here is my contribution to the TTT challenge.
Copy of link: http://allbasic.info/ttt/

Ah so it's from your site. Java script? since it can be played over the browser?

Yep!
Code: [Select]
/* Play Tic Toe, against a friend or the computer.
If u choose to play against the computer, the 'Computer Player' will use the getBestMove function to choose one of the best possible moves.
*/

// -- Constants --
const SYMBOLS = {
  x:'X',
  o:'O'
}
const RESULT = {
  incomplete: 0,
  playerXWon: SYMBOLS.x,
  playerOWon: SYMBOLS.o,
  tie: 3
}
const VIEW = {
  question1: 1,
  question2: 2,
  game: 3,
  result: 4
}

function Board (options){
  // Creates the board Object for the game

  // -- Data Stracture --
  state = {
    view: VIEW.question1,
    players: [
      {
        symbol: null,
        isComputer: false,
        score: 0
      },
      {
        symbol: null,
        isComputer: false,
        score: 0
      }
    ]
  }

  function initGame(){
    state.game= {
      _gameBoard: [
        ["", "", ""],
        ["", "", ""],
        ["", "", ""]
      ],
      turn: Math.round(Math.random()), //we set this var randomly for the first move.
    }
  }

  function moveCount(board){
    //receives a board and returns the number of moves that have been played.
    let moveCount = 0
    for (let i = 0; i<board.length; i++){
      for (let j = 0 ; j<board[i].length ; j++){
        if (board[i][j]!=""){
          moveCount++
        }
      }
    }
    return moveCount
  }

  function getResult(board,symbol){
      // receives a board, and the symbol of the player and returns an object with the result and an array of the winning line
      let result = RESULT.incomplete
      if (moveCount(board)<5){
         return {result}
      }

      function succession (line){
        return (line === symbol.repeat(3))
      }

      let line
      let winningLine=[]

      //first we check row, then column, then diagonal
      for (var i = 0 ; i<3 ; i++){
        line = board[i].join('')
        if(succession(line)){
          result = symbol;
          winningLine = [[i,0], [i,1], [i,2]]
          return {result, winningLine};
        }
      }

      for (var j=0 ; j<3; j++){
        let column = [board[0][j],board[1][j],board[2][j]]
        line = column.join('')
        if(succession(line)){
          result = symbol
          winningLine = [[0,j], [1,j], [2,j]]
          return {result, winningLine};
        }
      }

      let diag1 = [board[0][0],board[1][1],board[2][2]]
      line = diag1.join('')
      if(succession(line)){
        result = symbol
        winningLine = [[0,0], [1,1], [2,2]]
        return {result, winningLine};
      }

      let diag2 = [board[0][2],board[1][1],board[2][0]]
      line = diag2.join('')
      if(succession(line)){
        result = symbol
        winningLine = [[0,2], [1,1], [2,0]]
        return {result, winningLine};
      }

      //Check for tie
      if (moveCount(board)==9){
        result=RESULT.tie
        return {result, winningLine}
      }

      return {result}
    }

  function getBestMove (board, symbol){
    // Receives a board, and the symbol of the player who has the next move. Returns the cordinates of the move and a score for that move (1-for winning, 0 for tie, and -1 for losing)
    function copyBoard(board) {
      let copy = []
       for (let row = 0 ; row<3 ; row++){
        copy.push([])
        for (let column = 0 ; column<3 ; column++){
          copy[row][column] = board[row][column]
        }
      }
      return copy
    }

    function getAvailableMoves (board) {
      // Receives a board, and returns an array of available moves.
      let availableMoves = []
      for (let row = 0 ; row<3 ; row++){
        for (let column = 0 ; column<3 ; column++){
          if (board[row][column]===""){
            availableMoves.push({row, column})
          }
        }
      }
      return availableMoves
    }

    function shuffleArray (array){
        // shuffles the array in place
        for (var i = array.length - 1; i > 0; i--) {
            var rand = Math.floor(Math.random() * (i + 1));
            [array[i], array[rand]]=[array[rand], array[i]]
        }
    }

    let availableMoves = getAvailableMoves(board)
    let availableMovesAndScores = []

    for (var i=0 ; i<availableMoves.length ; i++){
      // Iterates over each available move. If it finds a winning move it returns it immediately. Otherwise it pushes a move and a score to the availableMovesAndScores array.
      let move = availableMoves[i]
      let newBoard = copyBoard(board)
      newBoard = applyMove(newBoard,move, symbol)
      result = getResult(newBoard,symbol).result
      let score
      if (result == RESULT.tie) {score = 0}
      else if (result == symbol) {
        score = 1
      }
      else {
        let otherSymbol = (symbol==SYMBOLS.x)? SYMBOLS.o : SYMBOLS.x
        nextMove = getBestMove(newBoard, otherSymbol)
        score = - (nextMove.score)
      }
      if(score === 1)
        return {move, score}
      availableMovesAndScores.push({move, score})
    }

    shuffleArray(availableMovesAndScores)

    availableMovesAndScores.sort((moveA, moveB )=>{
        return moveB.score - moveA.score
      })
    return availableMovesAndScores[0]
  }

  function render(){
    // Renders the screen according to the state.
    function getPlayerName(playerSymbol){
      if(playerSymbol === state.players[0].symbol)
        return state.players[0].isComputer ? 'Computer' : "Player1"
      return state.players[1].isComputer ? 'Computer' : "Player2"
    }

    function buttonHTML(btnGroup, data, text){
      return `<button type="button" class="btn btn-lg btn-default btnGroup${btnGroup}" data=${data}>${text}</button>`
    }

    function htmlSpaces (times){
      return '&emsp;'.repeat(times)
    }

    function htmlQ1(){
      return `<div id="view1"><h3>Which do you prefer?\n</h3>
      ${buttonHTML(1, "1player", "Man Against computer")}
      ${buttonHTML(1, "2players", "Man Against Man")}
      </div>`
    }

    function htmlQ2(){
      const html2=`<div id="view2"><h3>${!state.players[1].isComputer? "Player 1, <br />" : ""}Which symbols would you like to use?</h3>
      ${buttonHTML(2, "X", "X")}
      ${buttonHTML(2, "O", "O")}`
      return html2
    }

    function htmlGame (){
      const moveNumber = moveCount(state.game._gameBoard) + 1
      const playerName = state.game.turn === 0 ? 'Player1' : state.players[1].isComputer ? 'Computer' : 'Player2'
    //   let playerName = 'Computer'
    //   if(!state.players[state.game.turn].isComputer)
    //     playerName = state.game.turn === 0 ? 'Player1' : 'Player2'

      let htmlBefore = `<h3>move: ${moveNumber} ${htmlSpaces(5)} turn: ${playerName}</h3>`
      let board = state.game._gameBoard.reduce(function(acc,curr,rowIndex){
          return acc + `<div id= "row${rowIndex}" class="row">${curr.map((str,colIndex)=>`<div class="cell col${colIndex}" data-row=${rowIndex} data-column=${colIndex}>${str}</div>`).join('')}</div>`
        }, ``)
        let htmlAfter = `<h4>Score: ${htmlSpaces(1)} Player 1 - ${state.players[0].score} ${htmlSpaces(2)} ${state.players[1].isComputer? "Computer" : "Player 2" } - ${state.players[1].score}</h4>`
      return `<div id='gameView'> ${htmlBefore} <div id="board">${board}</div> ${htmlAfter} </div>`
    }


    function htmlGameEnd (){
      function arraysAreEqual (arr1, arr2){
        if(arr1.length !== arr2.length)
          return false;
        for(var i = arr1.length; i--;) {
            if(arr1[i] !== arr2[i])
                return false;
        }
        return true;
      }

      let {result, winningLine} = getResult(state.game._gameBoard, state.players[state.game.turn].symbol )
      let resultText = "tie"
      if(result !== RESULT.tie)
        resultText = getPlayerName(result) + " Won"

      let htmlBefore = `<h3>${resultText} ${htmlSpaces(2)} Click to restart </h3> `
      let board = state.game._gameBoard.reduce(function(acc,curr,rowIndex){
          return acc + `<div id="row${rowIndex}" class="row">${curr.map(
            (str,colIndex)=>
            `<div class="cell col${colIndex} ${winningLine.some(arr=>(arraysAreEqual(arr,[rowIndex,colIndex]))) ? "winningLine" : ""}"
              data-row=${rowIndex} data-column=${colIndex}>${str}</div>`).join('')}</div>`
        }, ``)
        let htmlAfter = `<h4>Score: ${htmlSpaces(1)} Player 1 - ${state.players[0].score} ${htmlSpaces(2)} ${state.players[1].isComputer? "Computer" : "Player 2" } - ${state.players[1].score}</h4>`
      return `<div id='resultView'> ${htmlBefore} <div id="board">${board}</id> ${htmlAfter} </div>`
    }

    let html = ''
    if (state.view == VIEW.question1) {html = htmlQ1()}
    else if (state.view == VIEW.question2) {html = htmlQ2()}
    else if (state.view == VIEW.result) {html=htmlGameEnd()}
    else {html=htmlGame()}
    // console.log(html)
    options.el.innerHTML = html
  }

  function question1Handler (ev){
    state.players[1].isComputer = !($(ev.currentTarget).attr('data')==="2players")
    state.view = VIEW.question2
    render()
  }

  function question2Handler (ev){
    let player1Symbol = $(ev.currentTarget).attr('data')
    state.players[0].symbol=player1Symbol;
    state.players[1].symbol=(player1Symbol===SYMBOLS.x)? SYMBOLS.o: SYMBOLS.x;

    state.view = VIEW.game
    initGame()
    if(state.players[state.game.turn].isComputer)
      doComputerMove()

    render()
  }

  function doComputerMove (){
    let symbol = state.players[1].symbol
    let move = getBestMove(state.game._gameBoard, symbol).move
    executeTurn(state.game._gameBoard,move, symbol)
  }

  function playerMoveHandler (ev){
    let symbol = state.players[state.game.turn].symbol
    let row = parseInt($(ev.currentTarget).attr('data-row'))
    let column = parseInt($(ev.currentTarget).attr('data-column'))
    executeTurn(state.game._gameBoard, {row, column}, symbol)
  }

  function applyMove(board,move, symbol) {
    board[move.row][move.column]= symbol
    return board
  }

  function executeTurn(board, move, symbol) {
    if (board[move.row][move.column]!==""){
      return board
    }

    applyMove(board,move,symbol)
    let result = getResult(board, symbol).result

    if (result === RESULT.incomplete){
      state.game.turn = (state.game.turn+1)%2
      render()
    } else {
      //Increment score and show result
      if(result !== RESULT.tie) {
        let winningPlayer = state.players.find((player)=>{return player.symbol == result})
        winningPlayer.score++
      }

      state.view = VIEW.result
      render()
    }
    if (result==RESULT.incomplete && state.players[state.game.turn].isComputer){
      doComputerMove()
    }
  }

  function beginGame(){
    initGame()
    state.view = VIEW.game
    render()
    if(state.game.turn === 1 && state.players[1].isComputer)
      doComputerMove();
  }

  $(options.el).on('click', '.btnGroup1', question1Handler)
  $(options.el).on('click', '.btnGroup2', question2Handler)
  $(options.el).on('click', '#gameView .cell', playerMoveHandler)
  $(options.el).on('click', '#resultView', beginGame)

  render ()
}


const board = new Board ({
  el : document.getElementById('root')
})

« Last Edit: 10. June 2018, 13:46:05 by B+ »

John

  • Sr. Member
  • ****
  • Posts: 404
    • View Profile
Re: Tic Tac Toe
« Reply #9 on: 10. June 2018, 21:11:05 »
JavaScript in a browser can do some amazing things.

B+

  • Hero Member
  • *****
  • Posts: 548
    • View Profile
Re: Tic Tac Toe
« Reply #10 on: 10. June 2018, 21:15:28 »
JavaScript in a browser can do some amazing things.

Sure! I can see why people are taking their Basic's and translating code to JS, like writing programs to compile in C or C++.

John

  • Sr. Member
  • ****
  • Posts: 404
    • View Profile
Re: Tic Tac Toe
« Reply #11 on: 10. June 2018, 21:22:30 »
ScriptBASIC has a JavaScript (V7) extension module for Linux. The Windows version is buggy and not worth fixing.
« Last Edit: 11. June 2018, 05:28:42 by John »

John

  • Sr. Member
  • ****
  • Posts: 404
    • View Profile
Re: Tic Tac Toe
« Reply #12 on: 11. June 2018, 01:42:42 »
I think JavaScript in a web browser is a good match. Taking it to the server with Node is a joke.