Search code examples
fortranfortran90do-loops

do loop/if statement logic


I'm working on a tic-tac-toe program. The function CHECK_WINNER is supposed to take in a board in a given state and determine if the game has been won, tied, or if players need to continue the game. CHECK_WINNER takes on different values based on the state of the board.

The block of win(n;1:3) lists the 8 possible winning configurations of a tic-tac-toe board.

I think the trouble is in the do loop. My goal is to cycle through each winning scenario for the board for each player (1 and 2) and check if a winning condition has been met. CHECK_MOVE should be 1 if player 1 wins, 2 if player 2 wins, 3 if the game is a draw, and 0 for any other case. What am I doing wrong?

program checkwinner
implicit none
integer, dimension(9) :: board
integer, external :: CHECK_WINNER
integer :: cw

!board = (/ 1,2,1,2,1,2,2,2,1 /)  ! not working correctly. 1 is winner, board full; cw returns 3
!board = (/ 1,2,1,2,0,2,2,2,1 /) ! working correctly. no winner, open spaces; cw returns 0
!board = (/ 1,1,1,0,0,0,0,0,0 /) ! not working. cw should return 1; instead cw returns 0
board = (/ 2,2,2,0,0,0,0,0,0 /) ! not working

cw = CHECK_WINNER(board)
print *, board(1:3)
print *, board(4:6)
print *, board(7:9)
print *, cw

end program checkwinner
!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!
integer function CHECK_WINNER(fboard)
implicit none
integer :: i
integer, dimension(8,3) :: win
integer, dimension(9), intent(in) :: fboard

win(1,1:3) = (/ 1,2,3 /)
win(2,1:3) = (/ 4,5,6 /)
win(3,1:3) = (/ 7,8,9 /)
win(4,1:3) = (/ 1,4,7 /)
win(5,1:3) = (/ 2,5,8 /)
win(6,1:3) = (/ 3,6,9 /)
win(7,1:3) = (/ 1,5,9 /)
win(8,1:3) = (/ 3,5,7 /)

do i = 1,8
     if (fboard(win(i,1)) == 1 .and. fboard(win(i,2)) == 1 .and. fboard(win(i,3)) == 1) then
        CHECK_WINNER = 1
    else if (fboard(win(i,1)) == 2 .and. fboard(win(i,2)) == 2 .and. fboard(win(i,3)) == 2) then
        CHECK_WINNER = 2
    else if ((fboard(win(i,1)) == 1 .or. fboard(win(i,1)) == 2) .and. (fboard(win(i,2)) == 1 .or. &
        fboard(win(i,2)) == 2) .and. (fboard(win(i,3)) == 1 .or. fboard(win(i,3)) == 2)) then
        CHECK_WINNER = 3
    else
        CHECK_WINNER = 0
    end if
end do

end function CHECK_WINNER

Solution

  • So in the example you gave in your code with board = (/ 2,2,2,0,0,0,0,0,0 /) when i=1 in the do-loop of the function, it correctly sets CHECK_WINNER=2 because

    fboard(win(i,1)) == 2 .and. fboard(win(i,2)) == 2 .and. fboard(win(i,3)) == 2
    

    is true. Unfortunately when the loop gets to i=2, i=3 etc it resets CHECK_WINNER to zero because none of the win conditions match. It's the else block which is causing the problem. Change the do loop to

    CHECK_WINNER = 0
    
    do i = 1,8
      if (fboard(win(i,1)) == 1 .and. fboard(win(i,2)) == 1 .and. fboard(win(i,3)) == 1) then
        CHECK_WINNER = 1
      else if (fboard(win(i,1)) == 2 .and. fboard(win(i,2)) == 2 .and. fboard(win(i,3)) == 2) then
        CHECK_WINNER = 2
      else if ((fboard(win(i,1)) == 1 .or. fboard(win(i,1)) == 2) .and. (fboard(win(i,2)) == 1 .or. &
        fboard(win(i,2)) == 2) .and. (fboard(win(i,3)) == 1 .or. fboard(win(i,3)) == 2)) then
        CHECK_WINNER = 3
       end if
    end do
    

    so if it finds a known combination it sets CHECK_WINNER. You could also exit the loop as soon as the known combination is found using exit within each (else)if clause. (after CHECK_WINNER is set)