Advertisement
Guest User

Untitled

a guest
Nov 21st, 2019
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.97 KB | None | 0 0
  1. # The primary exercise I want you to try and do is noughts and crosses (tic tac toe).
  2. # In this exercise I want you to draw the board as follows:
  3. # 1 | 2 | 3
  4. # ---+---+----
  5. # 4 | 5 | 6
  6. # ---+---+----
  7. # 7 | 8 | 9
  8.  
  9. # The user will always be crosses. Ask the user to choose a square to play.
  10. # Make sure the square is a valid square, I.E.: not occupied and within the range
  11. # After each valid move by the user have the computer play a move (random).
  12. # You can use the pythons random module for this. Everytime both players have made a move draw the state of the board again. And after # each move check if the user or the computer has won.
  13.  
  14. import random
  15.  
  16. ## coordinates
  17. ## [0,0 0,1 0,2]
  18. ## [1,0 1,1 1,2]
  19. ## [2,0 2,1 2,2]
  20.  
  21. #grid_values = [["1", "2", "3"],
  22. # ["4", "5", "6"],
  23. # ["7", "8", "9"]]
  24.  
  25. # test grid
  26. grid_values = [["X", "2", "3"],
  27. ["4", "5", "6"],
  28. ["7", "8", "9"]]
  29.  
  30. game_over = 0
  31.  
  32.  
  33. def checkGrid(gv, move):
  34.  
  35. #print "checking position:", move
  36. #print "position contains:", gv[move[0]][move[1]]
  37.  
  38. if gv[move[0]][move[1]] == "X" or gv[move[0]][move[1]] == "O":
  39. #print "occupied"
  40. return 1
  41.  
  42. else:
  43. #print "empty"
  44. return 0
  45.  
  46. def drawGrid(gv, win=0, wh=[[" ", " ", " "],
  47. [" ", " ", " "],
  48. [" ", " ", " "]],
  49. wv=[[" ", " ", " "],
  50. [" ", " ", " "],
  51. [" ", " ", " "]],
  52. wd=[" ", " ", " ", " "]):
  53.  
  54. if win == "1":
  55. print "Player has won the game!"
  56.  
  57. if win == "2":
  58. print "Computer has won the game!"
  59.  
  60. print "\n", wd[0], wv[0][0], " ", wv[0][1], " ", wv[0][2], wd[1]
  61. print wh[0][0], gv[0][0], "|", gv[0][1], "|", gv[0][2], wh[0][2]
  62. print " ---+---+---"
  63. print wh[1][0], gv[1][0], "|", gv[1][1], "|", gv[1][2], wh[1][2]
  64. print " ---+---+---"
  65. print wh[2][0], gv[2][0], "|", gv[2][1], "|", gv[2][2], wh[2][2]
  66. print wd[2], wv[2][0], " ", wv[2][1], " ", wv[2][2], wd[3], "\n"
  67.  
  68.  
  69. def checkWin(gv):
  70.  
  71. win_horiz = [[" ", " ", " "],
  72. [" ", " ", " "],
  73. [" ", " ", " "]]
  74.  
  75. win_vert = [[" ", " ", " "],
  76. [" ", " ", " "],
  77. [" ", " ", " "]]
  78.  
  79. win_diag = [" ", " ", " ", " "]
  80.  
  81.  
  82. win = 0
  83. #win_type = 0
  84. #win_pos = 0
  85.  
  86. i = 0 #print gv
  87.  
  88. while i < 3:
  89.  
  90. # check if row has match
  91. if gv[i][0] == gv[i][1] and gv[i][0] == gv[i][2]:
  92.  
  93. win_horiz[i][0] = u"\u2192"
  94. win_horiz[i][2] = u"\u2190"
  95.  
  96. if gv[i][0] == "X":
  97. win = 1
  98.  
  99. else:
  100. win = 2
  101.  
  102. # check if column has match
  103. if gv[0][i] == gv[1][i] and gv[0][i] == gv[2][i]:
  104.  
  105. win_vert[0][i] = u"\u2193"
  106. win_vert[2][i] = u"\u2191"
  107.  
  108. if gv[0][i] == "X":
  109. win = 1
  110.  
  111. else:
  112. win = 2
  113.  
  114. i += 1
  115.  
  116. # check for diagonal match
  117. # diagonal win, left to right
  118. if gv[0][0] == gv[1][1] and gv[0][0] == gv[2][2]:
  119.  
  120. win_diag[0] = u"\u2198"
  121. win_diag[3] = u"\u2196"
  122.  
  123. if gv[0][0] == "X":
  124. win = 1
  125.  
  126. else:
  127. win = 2
  128.  
  129. # diagonal win, right to left
  130. if gv[0][2] == gv[1][1] and gv[0][2] == gv[2][0]:
  131.  
  132. win_diag[1] = u"\u2199"
  133. win_diag[2] = u"\u2197"
  134.  
  135. if gv[0][2] == "X":
  136. win = 1
  137.  
  138. else:
  139. win = 2
  140.  
  141.  
  142. if win == 1:
  143. print "\nPlayer Wins!"
  144.  
  145. if win == 2:
  146. print "Computer Wins!"
  147.  
  148. drawGrid(gv, win, win_horiz, win_vert, win_diag)
  149. return win
  150.  
  151.  
  152.  
  153. def getPlay(gv):
  154.  
  155. # get move position value from 1 to 9, enter it into the play grid
  156.  
  157. while True:
  158.  
  159. next_move = raw_input("\nEnter your next move (grid numbers 1 to 9) or q to quit: ")
  160.  
  161. if next_move.isdigit():
  162. next_move = int(next_move)
  163.  
  164. if 1 <= next_move <= 9:
  165.  
  166. xcoord = (next_move - 1) % 3
  167. ycoord = (next_move - 1) / 3
  168.  
  169. if (gv[ycoord][xcoord] != "X") and (gv[ycoord][xcoord] != "O"):
  170. break
  171.  
  172. else:
  173. print("That slot is already taken. Please chose an empty one.")
  174.  
  175. if next_move == "q" or next_move == "Q":
  176. sys.exit(0)
  177.  
  178.  
  179. print "\nPlayer Move:"
  180.  
  181. gv[ycoord][xcoord] = "X"
  182.  
  183. return gv
  184.  
  185. def cpuPlay(gv):
  186. ## Random number based computer moves ##
  187.  
  188. while True:
  189.  
  190. cpu_move = random.randint(1, 9)
  191. xcoord = (cpu_move - 1) % 3
  192. ycoord = (cpu_move - 1) / 3
  193.  
  194. if (gv[ycoord][xcoord] != "X") and (gv[ycoord][xcoord] != "O"):
  195. break
  196.  
  197. print "\nComputer Move:"
  198.  
  199. gv[ycoord][xcoord] = "O"
  200.  
  201. return gv
  202.  
  203.  
  204.  
  205. def cpuAI(gv):
  206. ## "Logic" based computer moves ##
  207.  
  208. ## NESTED FUNCTION
  209.  
  210. ## check new number is not already in temp list
  211. def tempCycle(move, temp):
  212.  
  213. for tmp in temp:
  214. #print "tmp:", tmp
  215. if tmp == move:
  216. #print "Already Exists!", "tmp:", tmp, "move", move
  217. return 1
  218.  
  219. return 0
  220.  
  221.  
  222. ## check if moves are in a row
  223. def doublesCheck(moves):
  224.  
  225. ## NESTED FUNCTIONS
  226.  
  227. ## find missing number in matched row
  228. def rowMatchCheck(rmatch):
  229.  
  230. new_move = [0, 0]
  231.  
  232. for i in range(0, 3):
  233.  
  234. if i != rmatch[0][1] and i != rmatch[1][1]:
  235.  
  236. new_move[0] = rmatch[0][0]
  237. new_move[1] = i
  238. # print "new move:", new_move
  239.  
  240. return new_move
  241.  
  242. ## find missing number in matched col
  243. def colMatchCheck(cmatch):
  244.  
  245. new_move = [0, 0]
  246.  
  247. for i in range(0, 3):
  248.  
  249. if i != cmatch[0][0] and i != cmatch[1][0]:
  250.  
  251. new_move[1] = cmatch[0][1]
  252. new_move[0] = i
  253.  
  254. return new_move
  255.  
  256. ## NESTED FUNCTION END
  257.  
  258.  
  259. row_match = []
  260. col_match = []
  261. diag1_match = []
  262. diag2_match = []
  263.  
  264. row_move = []
  265. col_move = []
  266.  
  267. temp_r = []
  268. temp_c = []
  269.  
  270. i = 0
  271.  
  272. print "\nmoves", moves
  273.  
  274. # check for 2 in a same row or column ##
  275. for mov in moves:
  276. j = 0
  277.  
  278. # print "row match:", row_match, len(row_match)
  279. for mv in moves:
  280.  
  281. if moves[i][0] == moves[j][0] and mov != mv and tempCycle(mov, temp_r) == 0 and tempCycle(mv, temp_r) == 0:
  282.  
  283. temp_r.append(mov)
  284. temp_r.append(mv)
  285.  
  286. row_match.append(mov)
  287. row_match.append(mv)
  288.  
  289.  
  290. if moves[i][1] == moves[j][1] and mov != mv and tempCycle(mov, temp_c) == 0 and tempCycle(mv, temp_c) == 0:
  291.  
  292. temp_c.append(mov)
  293. temp_c.append(mv)
  294.  
  295. col_match.append(mv)
  296. col_match.append(mov)
  297.  
  298. j += 1
  299. i += 1
  300.  
  301. # print "row_match ", row_match
  302. # print "col_match ", col_match
  303. # print "diag1_match", diag1_match
  304. # print "diag2_match", diag2_match, "\n"
  305.  
  306.  
  307. ## cycle through each row match, call rowMatchCheck() to get move to complete row.
  308.  
  309. i = 0
  310. temp = []
  311.  
  312. for mv in row_match:
  313. j = 0
  314.  
  315. for mov in row_match:
  316. ## If 2 rows have the same value, are duplicates, have different col values and are not trasposed versions of the same thing:
  317. if mov[0] == mv[0] and mov != mv and row_match[i][1] != row_match[j][1] and tempCycle(mov, temp) == 0 and tempCycle(mv, temp) == 0:
  318.  
  319. #print "temp", temp
  320. temp.append(mov)
  321. temp.append(mv)
  322. current_match = []
  323.  
  324. current_match.append(mov)
  325. current_match.append(mv)
  326.  
  327. #print "current match row:", current_match, "\n"
  328.  
  329. row_move.append(rowMatchCheck(current_match))
  330.  
  331. j += 1
  332. i += 1
  333.  
  334.  
  335. ## cycle through each column match, call colMatchCheck() to get move to complete column
  336.  
  337. i = 0
  338. temp = []
  339.  
  340. for mv in col_match:
  341. j = 0
  342.  
  343. for mov in col_match:
  344. ## If 2 columns have the same value, are duplicates, have different row values and are not trasposed versions of the same thing:
  345. if mov[1] == mv[1] and mov != mv and col_match[i][0] != col_match[j][0] and tempCycle(mov, temp) == 0 and tempCycle(mv, temp) == 0:
  346.  
  347. #print "temp", temp
  348. temp.append(mov)
  349. temp.append(mv)
  350. current_match = []
  351.  
  352. current_match.append(mov)
  353. current_match.append(mv)
  354.  
  355. #print "current match col:", current_match, "\n"
  356.  
  357. col_move.append(colMatchCheck(current_match))
  358.  
  359. j += 1
  360. i += 1
  361.  
  362. #col_move.append(colMatchCheck(current_match))
  363.  
  364. # print "matched rows", row_match, "\n"
  365. # print "row move", row_move, "\n"
  366. # print "matched columns", col_match, "\n\n"
  367.  
  368.  
  369. # Check for diagonal
  370.  
  371. diag_move = []
  372.  
  373. for mov in moves:
  374.  
  375. if mov == [0, 0] or mov == [1, 1] or mov == [2, 2]:
  376. diag1_match.append(mov)
  377.  
  378. if mov == [0, 2] or mov == [1, 1] or mov == [2, 0]:
  379. diag2_match.append(mov)
  380.  
  381. if len(diag1_match) > 1:
  382. for i in range(0, 3):
  383. if i != diag1_match[0][0] and i != diag1_match[1][0]:
  384. temp_move = [0, 0]
  385. temp_move[0] = i
  386. temp_move[1] = i
  387. diag_move.append(temp_move)
  388.  
  389. if len(diag2_match) > 1:
  390. for i in range(0, 3):
  391. if i != diag2_match[0][0] and i != diag2_match[1][0]:
  392. temp_move = [0, 0]
  393. temp_move[0] = i
  394. temp_move[1] = abs(i - 2)
  395.  
  396. diag_move.append(temp_move)
  397.  
  398.  
  399.  
  400. print "Row moves: ", row_move
  401. print "Col moves: ", col_move
  402. print "Diag moves:", diag_move, "\n"
  403.  
  404. doubles = row_move + col_move + diag_move
  405.  
  406. return doubles
  407.  
  408. ## NESTED FUNCTION END ##
  409.  
  410.  
  411. player_moves = []
  412. cpu_moves = []
  413.  
  414. next_cpu = []
  415.  
  416. ## store current moves ##
  417. for i in range(0, 3):
  418. for j in range(0, 3):
  419.  
  420. temp_player = ["0", "0"]
  421. temp_cpu = ["0", "0"]
  422.  
  423. if gv[i][j] == "X":
  424. temp_player[0] = i
  425. temp_player[1] = j
  426.  
  427. player_moves.append(temp_player)
  428.  
  429. if gv[i][j] == "O":
  430. temp_cpu[0] = i
  431. temp_cpu[1] = j
  432.  
  433. cpu_moves.append(temp_cpu)
  434.  
  435. ## Check for player doubles and get blocking move
  436. print "PLAYER MOVES: 'X'"
  437. defensive_options = doublesCheck(player_moves)
  438.  
  439. ## Check for computer doubles and get winning move
  440. print "COMPUTER MOVES: 'O'"
  441. attacking_options = doublesCheck(cpu_moves)
  442.  
  443. print "Defensive options", defensive_options
  444. print "Attacking options", attacking_options
  445.  
  446.  
  447. ## prioritise winning move over defending
  448. if attacking_options:
  449. next_cpu = attacking_options[0]
  450.  
  451. ## find best defensive move
  452. if not attacking_options and defensive_options:
  453.  
  454. next_cpu = defensive_options[0]
  455.  
  456. print "next_cpu:", next_cpu
  457.  
  458. i = 0
  459. for def1 in defensive_options:
  460. j = 0
  461. for def2 in defensive_options:
  462. if def1 == def2 and i != j:
  463. next_cpu = def1
  464. j += 1
  465. i += 1
  466.  
  467.  
  468. ## If there are no doubles yet:
  469.  
  470. ## Check for Completely empty rows, columns and diagonals
  471. def CheckEmpty(gv):
  472.  
  473. for i in range(0, 3):
  474. # row i is empty
  475. if isdigit(gv[i][0]) and isdigit(gv[i][1]) and isdigit(gv[i][2]):
  476. print "row", i, "is empty"
  477.  
  478. # column i is empty
  479. if isdigit(gv[0][i]) and isdigit(gv[1][i]) and isdigit(gv[2][i]):
  480. print "column", i, "is empty"
  481.  
  482. # diagonal 1 is empty
  483. if isdigit(gv[0][0]) and isdigit(gv[1][1]) and isdigit(gv[2][2])
  484. print "diagonal 1 is empty"
  485.  
  486. # diagonal 2 is empty
  487. if isdigit(gv[0][2]) and isdigit(gv[1][1]) and isdigit(gv[2][0])
  488. print "diagonal 1 is empty"
  489.  
  490.  
  491.  
  492. # if not attacking_options and not defensive_options:
  493. ## Choose best attacking move
  494.  
  495.  
  496.  
  497.  
  498. print "computer move priority", next_cpu
  499. print "other defense moves", defensive_options
  500. print "other attack moves", attacking_options
  501.  
  502.  
  503.  
  504.  
  505.  
  506. return gv
  507.  
  508. ## GAME LOOP ##
  509.  
  510.  
  511. drawGrid(grid_values)
  512.  
  513. turn = 0
  514.  
  515. #while game_over == 0 and turn <= 5:
  516.  
  517. grid_values = getPlay(grid_values)
  518. game_over = checkWin(grid_values)
  519.  
  520. if turn <= 4:
  521.  
  522. ### ENABLE FOR RANDOM AI
  523. #grid_values = cpuPlay(grid_values)
  524.  
  525. ### ENABLE FOR COMPUTER AI
  526. grid_values = cpuAI(grid_values)
  527. game_over = checkWin(grid_values)
  528.  
  529. turn += 1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement