My solutions to Harvard's online course CS50AI, An Introduction to Machine Learning
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
4.6 KiB

4 years ago
  1. import pygame
  2. import sys
  3. import time
  4. import tictactoe as ttt
  5. pygame.init()
  6. size = width, height = 600, 400
  7. # Colors
  8. black = (0, 0, 0)
  9. white = (255, 255, 255)
  10. screen = pygame.display.set_mode(size)
  11. mediumFont = pygame.font.Font("OpenSans-Regular.ttf", 28)
  12. largeFont = pygame.font.Font("OpenSans-Regular.ttf", 40)
  13. moveFont = pygame.font.Font("OpenSans-Regular.ttf", 60)
  14. user = None
  15. board = ttt.initial_state()
  16. ai_turn = False
  17. while True:
  18. for event in pygame.event.get():
  19. if event.type == pygame.QUIT:
  20. sys.exit()
  21. screen.fill(black)
  22. # Let user choose a player.
  23. if user is None:
  24. # Draw title
  25. title = largeFont.render("Play Tic-Tac-Toe", True, white)
  26. titleRect = title.get_rect()
  27. titleRect.center = ((width / 2), 50)
  28. screen.blit(title, titleRect)
  29. # Draw buttons
  30. playXButton = pygame.Rect((width / 8), (height / 2), width / 4, 50)
  31. playX = mediumFont.render("Play as X", True, black)
  32. playXRect = playX.get_rect()
  33. playXRect.center = playXButton.center
  34. pygame.draw.rect(screen, white, playXButton)
  35. screen.blit(playX, playXRect)
  36. playOButton = pygame.Rect(5 * (width / 8), (height / 2), width / 4, 50)
  37. playO = mediumFont.render("Play as O", True, black)
  38. playORect = playO.get_rect()
  39. playORect.center = playOButton.center
  40. pygame.draw.rect(screen, white, playOButton)
  41. screen.blit(playO, playORect)
  42. # Check if button is clicked
  43. click, _, _ = pygame.mouse.get_pressed()
  44. if click == 1:
  45. mouse = pygame.mouse.get_pos()
  46. if playXButton.collidepoint(mouse):
  47. time.sleep(0.2)
  48. user = ttt.X
  49. elif playOButton.collidepoint(mouse):
  50. time.sleep(0.2)
  51. user = ttt.O
  52. else:
  53. # Draw game board
  54. tile_size = 80
  55. tile_origin = (width / 2 - (1.5 * tile_size),
  56. height / 2 - (1.5 * tile_size))
  57. tiles = []
  58. for i in range(3):
  59. row = []
  60. for j in range(3):
  61. rect = pygame.Rect(
  62. tile_origin[0] + j * tile_size,
  63. tile_origin[1] + i * tile_size,
  64. tile_size, tile_size
  65. )
  66. pygame.draw.rect(screen, white, rect, 3)
  67. if board[i][j] != ttt.EMPTY:
  68. move = moveFont.render(board[i][j], True, white)
  69. moveRect = move.get_rect()
  70. moveRect.center = rect.center
  71. screen.blit(move, moveRect)
  72. row.append(rect)
  73. tiles.append(row)
  74. game_over = ttt.terminal(board)
  75. player = ttt.player(board)
  76. # Show title
  77. if game_over:
  78. winner = ttt.winner(board)
  79. if winner is None:
  80. title = f"Game Over: Tie."
  81. else:
  82. title = f"Game Over: {winner} wins."
  83. elif user == player:
  84. title = f"Play as {user}"
  85. else:
  86. title = f"Computer thinking..."
  87. title = largeFont.render(title, True, white)
  88. titleRect = title.get_rect()
  89. titleRect.center = ((width / 2), 30)
  90. screen.blit(title, titleRect)
  91. # Check for AI move
  92. if user != player and not game_over:
  93. if ai_turn:
  94. time.sleep(0.5)
  95. move = ttt.minimax(board)
  96. board = ttt.result(board, move)
  97. ai_turn = False
  98. else:
  99. ai_turn = True
  100. # Check for a user move
  101. click, _, _ = pygame.mouse.get_pressed()
  102. if click == 1 and user == player and not game_over:
  103. mouse = pygame.mouse.get_pos()
  104. for i in range(3):
  105. for j in range(3):
  106. if (board[i][j] == ttt.EMPTY and tiles[i][j].collidepoint(mouse)):
  107. board = ttt.result(board, (i, j))
  108. if game_over:
  109. againButton = pygame.Rect(width / 3, height - 65, width / 3, 50)
  110. again = mediumFont.render("Play Again", True, black)
  111. againRect = again.get_rect()
  112. againRect.center = againButton.center
  113. pygame.draw.rect(screen, white, againButton)
  114. screen.blit(again, againRect)
  115. click, _, _ = pygame.mouse.get_pressed()
  116. if click == 1:
  117. mouse = pygame.mouse.get_pos()
  118. if againButton.collidepoint(mouse):
  119. time.sleep(0.2)
  120. user = None
  121. board = ttt.initial_state()
  122. ai_turn = False
  123. pygame.display.flip()