Easy Question (For You)

Please support our Python advertiser: Programming Forums - DaniWeb Sister Site
Reply

Join Date: Apr 2008
Posts: 3
Reputation: eggowaffles is an unknown quantity at this point 
Solved Threads: 0
eggowaffles eggowaffles is offline Offline
Newbie Poster

Easy Question (For You)

 
0
  #1
Apr 15th, 2008
Hey I am obviously new here, but would love to get better at programming. I currently am using Michael Dawson's "Python Programming, Second Edition (for the absolute beginner)" to try and learn it. Anyway he gives code on how to make a very basic tic-tac-toe game inside the cmd prompt window. As a challenge at the end of the chapter he says try to make an unbeatable computer, the one given just goes with what the typically best move would be, starting with middle then going to corners etc. I have spent 3+ hours trying to figure out how to make the computer do something specific based on a human move and cant figure it out. Now I realize this is kinda useless, but I do want to learn programming and don't want to move on in the book if I can't do something I should be able to. Please help me out, here is my current code for computer move.
  
  1. def computer_move(board, computer, human):
  2. """Make computer move."""
  3. # make a copy to work with since function will be changing list
  4. board = board[:]
  5. # the best positions to have, in order
  6.  
  7. BEST_MOVES = (4, 0, 2, 6, 8, 1, 3, 5, 7) # [COLOR="Red"]Only part determining computer moves[/COLOR]
  8.  
  9. print "I shall take square number"
  10. # if computer can win, take that move
  11. for move in legal_moves(board):
  12. board[move] = computer
  13. if winner(board) == computer:
  14. print move
  15. return move
  16. # done checkin this move, undo it
  17. board[move] = EMPTY
  18. # if human can win, block that move
  19. for move in legal_moves(board):
  20. board[move] = human
  21. if winner(board) == human:
  22. print move
  23. return move
  24. #done checking this move, undo it
  25. board[move] = EMPTY
  26. # since no one can win on next move, pick best open square
  27. for move in BEST_MOVES:
  28. if move in legal_moves(board):
  29. print move
  30. return move
Kk now here is entire code for program
  
  1. # Tic-Tac-Toe
  2. # Play the game of ttt against a computer opponent
  3.  
  4. # global constants
  5. X = "X"
  6. O = "O"
  7. EMPTY = " "
  8. TIE = "TIE"
  9. NUM_SQUARES = 9
  10.  
  11. def display_instructions():
  12. """Display Game Instructions."""
  13. print \
  14. """
  15. Welcome to Tic-Tac-Toe.
  16. You will make a move by entering a number 0-8.
  17. The number will correspond to the one on this board.
  18.  
  19. 0 | 1 | 2
  20. -----------
  21. 3 | 4 | 5
  22. -----------
  23. 6 | 7 | 8
  24. """
  25.  
  26. def ask_yes_no(question):
  27. """Ask a yes or no question."""
  28. response = None
  29. while response not in ("y", "n"):
  30. response = raw_input(question).lower()
  31. return response
  32.  
  33. def ask_number(question, low, high):
  34. """Ask for a number within a range."""
  35. response = None
  36. while response not in range(low, high):
  37. response = int(raw_input(question))
  38. return response
  39.  
  40. def pieces():
  41. """Determine if player or computer goes first."""
  42. go_first = ask_yes_no("Would you like to go first? (y/n): ")
  43. if go_first == "y":
  44. print "\nAlright human goes first."
  45. human = X
  46. computer = O
  47. else:
  48. print "Computer will go first then."
  49. computer = X
  50. human = O
  51. return computer, human
  52.  
  53. def new_board():
  54. """Create new game board."""
  55. board = []
  56. for square in range(NUM_SQUARES):
  57. board.append(EMPTY)
  58. return board
  59.  
  60. def display_board(board):
  61. """Display game board on screen."""
  62. print "\n\t", board[0], "|", board[1], "|", board[2]
  63. print "\t", "---------"
  64. print "\t", board[3], "|", board[4], "|", board[5]
  65. print "\t", "---------"
  66. print "\t", board[6], "|", board[7], "|", board[8], "\n"
  67.  
  68. def legal_moves(board):
  69. """Create list of legal moves."""
  70. moves = []
  71. for square in range(NUM_SQUARES):
  72. if board[square] == EMPTY:
  73. moves.append(square)
  74. return moves
  75.  
  76. def winner(board):
  77. """Determine the game winner."""
  78. WAYS_TO_WIN = ((0, 1, 2),
  79. (3, 4, 5),
  80. (6, 7, 8),
  81. (0, 3, 6),
  82. (1, 4, 7),
  83. (2, 5, 8),
  84. (0, 4, 8),
  85. (2, 4, 6))
  86. for row in WAYS_TO_WIN:
  87. if board[row[0]] == board[row[1]] == board[row[2]] != EMPTY:
  88. winner = board[row[0]]
  89. return winner
  90. if EMPTY not in board:
  91. return TIE
  92. return None
  93.  
  94. def human_move(board, human):
  95. """Get human move."""
  96. humanmoves = []
  97. legal = legal_moves(board)
  98. move = None
  99. while move not in legal:
  100. move = ask_number("Where will you move? (0 - 8): ", 0, NUM_SQUARES)
  101. if move not in legal:
  102. print "\nInvalid Move, That square is already occupied, Choose another. \n"
  103. humanmoves.append(move)
  104. print "Fine..."
  105. return move
  106.  
  107.  
  108. def computer_move(board, computer, human):
  109. """Make computer move."""
  110. # make a copy to work with since function will be changing list
  111. board = board[:]
  112. # the best positions to have, in order
  113.  
  114. BEST_MOVES = (4, 0, 2, 6, 8, 1, 3, 5, 7)
  115.  
  116. print "I shall take square number"
  117. # if computer can win, take that move
  118. for move in legal_moves(board):
  119. board[move] = computer
  120. if winner(board) == computer:
  121. print move
  122. return move
  123. # done checkin this move, undo it
  124. board[move] = EMPTY
  125. # if human can win, block that move
  126. for move in legal_moves(board):
  127. board[move] = human
  128. if winner(board) == human:
  129. print move
  130. return move
  131. #done checking this move, undo it
  132. board[move] = EMPTY
  133. # since no one can win on next move, pick best open square
  134. for move in BEST_MOVES:
  135. if move in legal_moves(board):
  136. print move
  137. return move
  138.  
  139.  
  140.  
  141.  
  142.  
  143. def next_turn(turn):
  144. """Switch turns."""
  145. if turn == X:
  146. return O
  147. else:
  148. return X
  149.  
  150. def congrat_winner(the_winner, computer, human):
  151. """Congratulate the winner."""
  152. if the_winner != TIE:
  153. print the_winner, "won!\n"
  154. else:
  155. print "It's a tie!"
  156. if the_winner == computer:
  157. print "Ha you really think you could beat a computer?"
  158. elif the_winner == human:
  159. print "Bet you couldn't do it again!"
  160. elif the_winner == TIE:
  161. print "You were lucky, somehow you managed to not lose..."
  162.  
  163.  
  164. def main():
  165. display_instructions()
  166. computer, human = pieces()
  167. turn = X
  168. board = new_board()
  169. display_board(board)
  170.  
  171. while not winner(board):
  172. if turn == human:
  173. move = human_move(board, human)
  174. board[move] = human
  175. else:
  176. move = computer_move(board, computer, human)
  177. board[move] = computer
  178. display_board(board)
  179. turn = next_turn(turn)
  180. the_winner = winner(board)
  181. congrat_winner(the_winner, computer, human)
  182.  
  183. # start the program
  184. main()
  185.  
  186.  
  187. raw_input("Press the Enter Key to Exit.")
Thanks in advance for any help
Reply With Quote Quick reply to this message  
Join Date: Apr 2008
Posts: 1
Reputation: ramakrishnakota is an unknown quantity at this point 
Solved Threads: 0
ramakrishnakota ramakrishnakota is offline Offline
Newbie Poster

Re: Easy Question (For You)

 
0
  #2
Apr 15th, 2008
i wnat one program that is if you give your date of birth out put is which day your born(weak)?
Reply With Quote Quick reply to this message  
Join Date: Aug 2005
Posts: 138
Reputation: a1eio is an unknown quantity at this point 
Solved Threads: 21
a1eio's Avatar
a1eio a1eio is offline Offline
Junior Poster

Re: Easy Question (For You)

 
0
  #3
Apr 15th, 2008
don't hijack eggowaffles thread ramakrishnakota, if you need help and it's not related to this guy start a new thread
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,065
Reputation: woooee is a jewel in the rough woooee is a jewel in the rough woooee is a jewel in the rough 
Solved Threads: 300
woooee woooee is online now Online
Veteran Poster

Re: Easy Question (For You)

 
0
  #4
Apr 15th, 2008
I didn't spend a lot of time on the code, but best move should be similiar to legal move. IMHO this should be implemented as a class. That would avoid the gobal variables and make the code cleaner. But you may not have gotten into creating classes yet. Also, the function main() is unnecessary. It is common to use "if __name__ == '__main__':" so that you can both test and reuse functions in the code, but in this case main() serves no purpose.
  1. def legal_moves(board):
  2. """Create list of legal moves."""
  3. moves = []
  4. for square in range(NUM_SQUARES):
  5. if board[square] == EMPTY:
  6. moves.append(square)
  7. return moves
  8. #
  9. #
  10. def best_move(board):
  11. for square in BEST_MOVES: ## BEST_MOVES will have to be global
  12. if board[square] == EMPTY:
  13. return square
  14. return -1
Last edited by woooee; Apr 15th, 2008 at 11:44 am.
Reply With Quote Quick reply to this message  
Join Date: Apr 2008
Posts: 3
Reputation: eggowaffles is an unknown quantity at this point 
Solved Threads: 0
eggowaffles eggowaffles is offline Offline
Newbie Poster

Re: Easy Question (For You)

 
0
  #5
Apr 15th, 2008
Thanks for the reply, I will try doing something like this. However I don't see how I could use this in having the computer make a specific move. Like right now if the human were to go board[0], the computer would take board[4], (which is fine), however if human was to take board[8] now computer would take board[2] because right now it just goes from middle then off to corners, and since board[0] is taken it takes board[2] causing the board to look like this.
  1. x | | 0
  2. ----------
  3. | 0 |
  4. ----------
  5. | | x
Which obviously is not good because now human takes board[6] and wins 2 different ways. I would like to have the computer take like board[3] rather than board[2] so the human would have to take board[5] causing the board to look like this and leading to a tie.
  1. x | |
  2. ----------
  3. 0 | 0 | x
  4. ----------
  5. | | x

So I would like to do something like if human controls board[0], board[8] and computer controls board[4] then computer takes board[3]. I just don't know how to implement this into code. Thanks again in advance for any help.
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,065
Reputation: woooee is a jewel in the rough woooee is a jewel in the rough woooee is a jewel in the rough 
Solved Threads: 300
woooee woooee is online now Online
Veteran Poster

Re: Easy Question (For You)

 
0
  #6
Apr 15th, 2008
I was assuming that no one had two in a row. You first want to check for two in a row and if your opponent has it then block, if you have it, win the game. Taking a closer look at your code, it appears that the function computer_move() does just that, but I didn't test it. So I would say, at this point I don't understand what the problem is. Second, if you want to make the computer unbeatable, then you will have to store all losing games: (who started and the number of each move), and not do the same thing again. While you are at it, you could do the same for winning games and try to repeat. On second thought, you only have to keep track of winning games and try to make the same moves for yourself, and different moves if your opponent is on the same track as one of the winning games, which of course would supercede the best_move() function.
Last edited by woooee; Apr 15th, 2008 at 4:21 pm.
Reply With Quote Quick reply to this message  
Join Date: Apr 2008
Posts: 3
Reputation: eggowaffles is an unknown quantity at this point 
Solved Threads: 0
eggowaffles eggowaffles is offline Offline
Newbie Poster

Re: Easy Question (For You)

 
0
  #7
Apr 16th, 2008
Yeah right now it will do that, the 2 in a row block or take the win thing. But see the problem is that right now a human can guarantee them selves a win by setting them selves up for a 2 way win as demonstrated above. See if they end up with board[0] and board[8] it is not 2 in a row however, they automatically win now by taking a corner because then they are set up to win 2 different ways. However if the computer were to go to board[3] during the time the human would have to take board[6] for the block and there by couldnt set them self up for the 2-way-win.
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,065
Reputation: woooee is a jewel in the rough woooee is a jewel in the rough woooee is a jewel in the rough 
Solved Threads: 300
woooee woooee is online now Online
Veteran Poster

Re: Easy Question (For You)

 
0
  #8
Apr 16th, 2008
I see what you mean. You could of course test for that, but then there would be another set of moves that would always beat the computer. There is probably even a "101 ways to win at tic-tac-toe" book, and you would have to test for all 101 ways. I would guess that this is the point to start keeping track of winning games and losing games so eventually the computer would not make any mistakes. The tic-tac-toe entry on Wikipedia has a slightly different best move strategy. They call your current problem a "fork".
A player can play perfect tic-tac-toe if they choose the move with the highest priority in the following table[4].

1. Win: complete three in a row.
2. Block: block their opponent from completing three in a row
3. Fork: threaten a win with two possible completions in two ways
4. Block Fork:

Option 1: create two in a row to force a block (Note: Sometimes, if one forces a block in this manner, the other player's block will result in a fork and a winning position, so care must be taken when there is more than one way to create two in a row. For example, if X has played the center and a corner, and o is in the opposite corner, o must play a corner and not an edge or else x will win).
Option 2: if there is a configuration where the opponent can fork, block that fork

5. Centre: play the centre
6. Opposite Corner: if the opponent is in the corner, play the opposite corner
7. Empty Corner: play an empty corner
8. Empty Side: play on an empty side

The first player, whom we shall designate "X," has 3 possible positions to mark during the first turn. Superficially, it might seem that there are 9 possible positions, corresponding to the 9 squares in the grid. However, by rotating the board, we will find that in the first turn, every corner mark is strategically equivalent to every other corner mark. The same is true of every edge mark. For strategy purposes, there are therefore only three possible first marks: corner, edge, or center. Player X can win or force a draw from any of these starting marks, however playing the corner gives the opponent the smallest choice of squares which must be played to avoid losing[5].

The second player, whom we shall designate "O," must respond to X's opening mark in such a way as to avoid the forced win. Player O must always respond to a corner opening with a center mark, and to a center opening with a corner mark. An edge opening must be answered either with a center mark, a corner mark next to the X, or an edge mark opposite the X. Any other responses will allow X to force the win. Once the opening is completed, O's task is to follow the above list of priorities in order to force the draw, or else to gain a win if X makes a weak play.
Reply With Quote Quick reply to this message  
Join Date: Aug 2009
Posts: 7
Reputation: patto78 is an unknown quantity at this point 
Solved Threads: 0
patto78 patto78 is offline Offline
Newbie Poster

Re: Easy Question (For You)

 
0
  #9
Aug 29th, 2009
Hi,

It's not quite clear from the above whether you managed to implement the code that would make the computer unbeatable in this game. I am using the same book to learn programming and have just attempted this same challenge. I did the following...

In the line directly underneath BEST_MOVES (line 114 in the games code as displayed above), I created a new tuple that reads as follows: COUNTER_PUNCH = (3, 5).

I then entered the following code, sandwiched between the "if human can win..." block and the "since no-one can win" block:

# blocking winning tactic
if human == board[8] and human == board[0] or human == board[2] and human == board[6]:
for move in COUNTER_PUNCH:
if move in legal_moves(board):
print move
return move

This bit of code is designed to prevent the use of the tactic that you refer to above, that allows the human to win every time. So far I have not been able to win since adding this code, so I think I've completed this challenge, but if anyone can see a loophole (or a sleeker way of doing it) I'd be interested to hear about it.

Thanks,
Paul
Reply With Quote Quick reply to this message  
Join Date: Oct 2007
Posts: 794
Reputation: siddhant3s has much to be proud of siddhant3s has much to be proud of siddhant3s has much to be proud of siddhant3s has much to be proud of siddhant3s has much to be proud of siddhant3s has much to be proud of siddhant3s has much to be proud of siddhant3s has much to be proud of siddhant3s has much to be proud of siddhant3s has much to be proud of 
Solved Threads: 135
siddhant3s's Avatar
siddhant3s siddhant3s is offline Offline
Master Poster

Re: Easy Question (For You)

 
0
  #10
Aug 30th, 2009
I think one should always try to look at the date of the last post before replying to a thread no one is interested to read.
It is more than an year old.
Siddhant Sanyam
(Not posting much)
My Blog: Yatantrika
Migrate to Standard C++ :When to tell your C++ Code is Non-Standard.
Please Read before posting: How To Ask Questions The Smart Way
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:



Other Threads in the Python Forum


Views: 912 | Replies: 11
Thread Tools Search this Thread



Tag cloud for Python
About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC