I'm trying to make a simple console tic tac toe in Python.
What I want is to let the player to choose the position is going to do the next play by moving the cursor with arrow keys
By investigating a bit I've already been able to replace actual strings in a board's position with str.format() and changing the string that position has with an array by an user input.
The following code shows how I achived that.
It only replaces the first position as just an example .
from os import system
board = ["a",'b','c','c','d','e','f','g','h']
#Draws the board
def drawboard():
print(" {0[0]} | {0[1]} | {0[2]} ".format(board))
print("___|___|___")
print(" {0[3]} | {0[4]} | {0[5]} ".format(board))
print("___|___|___")
print(" {0[6]} | {0[7]} | {0[8]} ".format(board))
print(" | | ")
drawboard()
userInput = input()
board[0] = userInput
system("cls") #clears the screen
drawboard()
Writing Tic Tac Toe in console can be done using curses. Its API is pretty straight forward for working with display coordinates. This script will work as described by you above, allowing to navigate with the arrow keys and putting on a key stroke the respective X or O signs. I works well in my shell
import curses
CH_P1 = 'X'
CH_P2 = 'O'
X_STEP = 4
Y_STEP = 2
X_OFFSET = 1
Y_OFFSET = 4
def print_board(stdscr):
stdscr.addstr(0, 0, 'Tic Tac Toe')
stdscr.hline(1, 0, '-', 50)
stdscr.addstr(2, 0, 'Use arrows to move, [SPACE] Draw, [Q] Quit')
stdscr.addstr(Y_OFFSET , X_OFFSET, ' │ │ ')
stdscr.addstr(Y_OFFSET + 1, X_OFFSET, '──┼───┼──')
stdscr.addstr(Y_OFFSET + 2, X_OFFSET, ' │ │ ')
stdscr.addstr(Y_OFFSET + 3, X_OFFSET, '──┼───┼──')
stdscr.addstr(Y_OFFSET + 4, X_OFFSET, ' │ │ ')
def print_players(stdscr, player_id):
stdscr.addstr(Y_OFFSET + 6, 0, 'Player {}'.format(CH_P1),
curses.A_BOLD if player_id == 0 else 0)
stdscr.addstr(Y_OFFSET + 7, 0, 'Player {}'.format(CH_P2),
curses.A_BOLD if player_id == 1 else 0)
def draw(y, x, stdscr, player_id):
stdscr.addch(y, x, CH_P2 if player_id else CH_P1)
def check_victory(board, y, x):
#check if previous move caused a win on horizontal line
if board[0][x] == board[1][x] == board [2][x]:
return True
#check if previous move caused a win on vertical line
if board[y][0] == board[y][1] == board [y][2]:
return True
#check if previous move was on the main diagonal and caused a win
if x == y and board[0][0] == board[1][1] == board [2][2]:
return True
#check if previous move was on the secondary diagonal and caused a win
if x + y == 2 and board[0][2] == board[1][1] == board [2][0]:
return True
return False
def main(stdscr):
# Clear screen
# stdscr.clear()
print_board(stdscr)
player_id = 0
print_players(stdscr, player_id=player_id)
x_pos = 1
y_pos = 1
board = [list(' ') for _ in range(3)]
# This raises ZeroDivisionError when i == 10.
while True:
stdscr.move(Y_OFFSET + y_pos * Y_STEP, X_OFFSET + x_pos * X_STEP)
c = stdscr.getch()
if c == curses.KEY_UP:
y_pos = max(0, y_pos - 1)
elif c == curses.KEY_DOWN:
y_pos = min(2, y_pos + 1)
elif c == curses.KEY_LEFT:
x_pos = max(0, x_pos - 1)
elif c == curses.KEY_RIGHT:
x_pos = min(2, x_pos + 1)
elif c == ord('q') or c == ord('Q'):
break
elif c == ord(' '):
# Update
y, x = stdscr.getyx()
if stdscr.inch(y, x) != ord(' '):
continue
draw(y, x, stdscr, player_id)
board[y_pos][x_pos] = CH_P2 if player_id else CH_P1
if check_victory(board, y_pos, x_pos):
stdscr.addstr(Y_OFFSET + 9, 0, 'Player {} wins'.format(
CH_P2 if player_id else CH_P1))
break
# Switch player
player_id = (player_id + 1) % 2
print_players(stdscr, player_id)
stdscr.refresh()
stdscr.getkey()
if __name__ == '__main__':
curses.wrapper(main)
Related
When I put the snake to start going to the "►" direction, it goes faster than when I do it for "◄" and the same result for "▲" and "▼".
Actually, it literally teleports. Even if I see that it's doing the right way correctly by going from key to key.
Maybe it's doing the process without showing it, until the end.
Do you see any reasons why does that happen? Because I really don't see why.
import numpy as np
from random import randint
import keyboard
from time import sleep
import os
#Get to work
game_area = {}
#Random snake and apple start positions
apple = randint(0, 540)
snake_pos = randint(0, 540)
#Define positions
for x in np.arange(0,540,1):
game_area[x] = '.'
#Insert Apple
game_area[apple] = 'Ó'
#Limit areas
game_area[0], game_area[59], game_area[60], game_area[119],game_area[120], game_area[179],game_area[180], game_area[239],game_area[240],game_area[299],game_area[300],game_area[359], game_area[360],game_area[419],game_area[420],game_area[479],game_area[480], game_area[539] = '╔','╗','║','║','║','║','║','║','║','║','║','║','║','║','║','║','╚','╝'
for x in range(1,59):
game_area[x] = '═'
for x in range(481,539):
game_area[x] = '═'
#Snake Class
class Snake:
def __init__(self, length, position):
self.length = length
self.position = position
def printar(self):
print(self.length,self.position)
snake = Snake(1,snake_pos)
game_area[snake.position] = '►'
#Functions
def prepare_game():
#Create game area
for number, instance in zip(list(game_area.keys()), list(game_area.values())):
if number not in [60,120,180,240,300,360,420,480]:
print(instance, end='')
else:
print('\n' + instance, end='')
print('')
def start_game():
global game_area
game_over = False
while True:
prepare_game()
if game_over == False:
#Keyboard Detect / Automatic Move
if '◄' in list(game_area.values()):
for x,y in game_area.items():
if y == '◄':
if game_area[x - 1] != '║':
game_area[x - 1] = y
game_area[x] = ' '
else:
game_over = True
break
if '►' in list(game_area.values()):
for x,y in game_area.items():
if y == '►':
if game_area[x + 1] != '║':
game_area[x + 1] = y
game_area[x] = ' '
else:
game_over = True
break
if '▲' in list(game_area.values()):
for x,y in game_area.items():
if y == '▲':
if game_area[x - 60] != '═':
game_area[x - 60] = y
game_area[x] = ' '
else:
game_over = True
break
if '▼' in list(game_area.values()):
for x,y in game_area.items():
if y == '▼':
if game_area[x + 60] != '═':
game_area[x + 60] = y
game_area[x] = ' '
else:
game_over = True
break
if keyboard.is_pressed('up arrow'):
pass
if keyboard.is_pressed('left arrow'):
pass
if keyboard.is_pressed('right arrow'):
pass
if keyboard.is_pressed('down arrow'):
pass
if keyboard.is_pressed('space'):
break
#End
sleep(1)
os.system("cls")
continue
else:
break
start_game()
I am currently trying to make a Tic Tac Toe game with minimax implemented in Python. Another feature that I'm trying to implement is different board sizes. But overall, unfortunately, the algorithm is not working.
As a beginner, this is not a surprise for me, but this case seems hopeless. I tried tweaking quite a lot of things (may seem like a lot just to me) just to end up with the same result - the computer filling up the fields from top left to bottom right.
#Sprawdzenie czy ktos wygral w poziomie lub pionie / straight line check
def winLine(line, letter):
return all(n == letter for n in line)
#Utworzenie nowej listy z elementow przekatnych / diagonal check
def winDiagonal(board, letter):
arr = []
tArr = []
for n in range(boardSize):
arr.append(board[n][n])
tArr.append(board[n][boardSize-n-1])
if winLine(arr, letter):
return True
elif winLine(tArr, letter):
return True
else:
return False
def checkWinner (board):
#Liczenie wolnych pol / checking the available fields
openSpots = 9
for n in range(boardSize):
for m in range(boardSize):
if board[n][m] == '0':
openSpots += 1
#Transpozycja planszy, by mozna bylo latwo zastosowac winLine na kolumach / transposition of the board
for letter in (person, ai):
transPos = list(zip(*board))
#Sprawdzanie w poziomie / horizontal check
if any(winLine(row, letter) for row in board):
#print('winline horizontal')
return letter
#Sprawdzanie w pionie / vertical check
elif any (winLine(col, letter) for col in transPos):
#print('winline vertical')
return letter
#Sprawdzanie po przekatnych / diagonal check
elif winDiagonal(board, letter):
return letter
elif openSpots == 0: return 'tie'
else: return 'none'
#Funkcja sprawdzajaca czy dane pole jest wolne / checks whether the field is available
def available (row, col):
global board
#Sprawdzenie czy pole jest wolne
if board[row][col] == '0':
return True
else:
return False
#Stale dla algorytmu minimax / minimax initial scores to compare against
minTarget = float('inf')
maxTarget = float('-inf')
#Slownik z wartosciami liczbowi dla wynikow, komputer maksymalizuje / a dictionary with scores for particular results
scores = {
'X': 10,
'O': -10,
'tie': 0
}
#Algorytm minimax
def minimax(myBoard, depth, maximizes):
#Sprawdzenie czy zaszla wygrana lub remis / Checking whether there is a win or tie
res = checkWinner(myBoard)
if (res != 'none'):
return scores[res]
#Gracz maksymalizujacy/ Maximizing player
elif maximizes == True:
bestScoreMax = maxTarget
for n in range(boardSize):
for m in range(boardSize):
if board[n][m] == '0':
board[n][m] = person
score = minimax(board, depth + 1, False)
board[n][m] = '0'
bestScoreMax = max([score, bestScoreMax])
return bestScoreMax
#Gracz minimalizujacy / minimizing player
elif maximizes == False:
bestScoreMin = minTarget
for n in range(boardSize):
for m in range(boardSize):
if board[n][m] == '0':
board[n][m] = ai
score = minimax(board, depth + 1, True)
board[n][m] = '0'
bestScoreMin = min([score, bestScoreMin])
return bestScoreMin
def makeMove(row, col):
global board
board[row][col] = ai
def computedMove():
global board
myBoard = board
computedTarget = maxTarget
moveX = 2
moveY = 2
for n in range(boardSize):
for m in range(boardSize):
if myBoard[n][m] == '0':
score = minimax(myBoard, 0, True)
if score > computedTarget:
computedTarget = score
moveX = n
moveY = m
makeMove(moveX, moveY)
#print(str(move.x) + ' ' + str(move.y))
# Funkcja pobierajaca ruch uzytkownika / player input for the move
def getPlayerMove():
global board
res = input('Please type in your move on the form \"x y\", x being the number of the row and y the number of the column of your choosing.\n')
col, row = res.split(" ")
row = int(row)
col = int(col)
if available(row-1, col-1):
board[row-1][col-1] = person
else:
print('You cannot make that move')
getPlayerMove()
def drawBoard():
global board
for n in range(boardSize):
for m in range(boardSize):
if board[n][m] == '0':
print(' - ', end='')
else:
print(' '+board[n][m]+' ', end='')
print('\n')
#Zmienna powiadamiajaca o stanie rozgrywki / variable indicating the state of the game
playing = False
# initializing the variable
boardSize = 0
# initializing the players
person = 'X'
ai = 'O'
#Gracz posiadajacy ruch (a takze rozpoczynajacy) / player who is playing at the moment
currentPlayer = ''
while True:
currentPlayer = person
boardSize = int(input("Please enter the size of the board. (one side)\n"))
global board
board = [['0' for i in range(boardSize)] for i in range(boardSize)]
print("You go first.")
playing = True
while playing:
if currentPlayer == person:
drawBoard()
getPlayerMove()
if checkWinner(board) == person:
drawBoard()
print("Yaay, you won!")
playing = False
else:
if checkWinner(board) == 'tie':
drawBoard()
print('It\'s a tie!')
break
else:
currentPlayer = ai
elif currentPlayer == ai:
computedMove()
if checkWinner(board) == ai:
drawBoard()
print('You lose!')
playing = False
else:
if checkWinner(board) == 'tie':
drawBoard()
print('It\'s a tie!')
break
else:
currentPlayer = person
if not input('Do you want to play again?').lower().startswith('y'):
break
In computedMove, you should first play the ai move then check the scores.
def computedMove():
global board
myBoard = board
computedTarget = maxTarget
moveX = 2
moveY = 2
for n in range(boardSize):
for m in range(boardSize):
if myBoard[n][m] == '0':
myBoard[n][m] = ai #This is added
score = minimax(myBoard, 0, True)
if score > computedTarget:
computedTarget = score
moveX = n
moveY = m
makeMove(moveX, moveY)
Also in minimax function, you should use same variable for myBoard and board.
I'm trying to build a Snake game using python, but I'm struggling with the input system. In the snake game, the snake walks through the same direction until someone change his direction.
The way I did was stopping the snake from moving while waits for the next key, but that's not what I want. The snake must walk to the same direction until receive an input to change direction.
How to do the get the key so the snake changes his direction while moving it through the screen and colliding with objects?
import os
from msvcrt import getch
class SnakeGame(object):
screen = None
def __init__(self, rows_count, column_count):
self.screen = self.initialize_screen(rows_count, column_count)
self.collided = False
def initialize_screen(self, rows_count, column_count):
#creates the 2D list with 0 in all values
screen = [[0 for x in range(column_count)] for y in range(rows_count)]
#get the rows
for row in range(len(screen)):
if row == 0 or row == len(screen) - 1:
screen[row] = self.add_same_value_entire_list(screen[row], 1)
else:
for column in range(len(screen[row])):
if column == 0 or column == len(screen[row]) - 1:
screen[row][column] = 1
return screen
def add_same_value_entire_list(self, list, value):
populatedList = [value for i in range(len(list))]
return populatedList
def print_screen(self):
screen_text = ''
for row in self.screen:
for column in row:
screen_text = screen_text + self.translated_value(column)
screen_text = screen_text + '\n'
return screen_text
def translated_value(self, value):
if value == 1:
return '#'
elif value == 2:
return '*'
elif value == -1: #snake body
return 'O'
elif value == -2: #moving left snake head left <----
return '<'
elif value == -3: #moving right snake head right ---->
return '>'
elif value == -4: #moving down
return 'V'
elif value == -5: #moving up
return '^'
else:
return ' '
def play(self):
player = Player()
key_pressed = 9999
self.add_player_to_screen(player)
while(self.defeated() is not True and key_pressed != 27):
self.clear()
print(self.print_screen())
key_pressed = self.read_key()
player.move(self.translate_key(key_pressed))
self.add_player_to_screen(player)
def read_key(self):
return ord(getch())
def add_player_to_screen(self, player):
print(player.location_x)
print(player.location_y)
if(player.position_cordination == 'E'):
self.screen[player.location_x][player.location_y - 1] = 0
elif (player.position_cordination == 'W'):
self.screen[player.location_x][player.location_y + 1] = 0
elif (player.position_cordination == 'N'):
self.screen[player.location_x + 1][player.location_y] = 0
elif (player.position_cordination == 'S'):
self.screen[player.location_x - 1][player.location_y] = 0
if(self.screen[player.location_x][player.location_y] == 0):
self.screen[player.location_x][player.location_y] = player.body
elif(self.screen[player.location_x][player.location_y] < 0):
self.collided = True
def translate_key(self, key):
print (key)
if (key == 224):
key = ord(getch())
print(key)
if (key == 72):
return 'N'
elif (key == 80):
return 'S'
elif (key == 75):
return 'W'
elif (key == 77):
return 'E'
else:
pass
def defeated(self):
return self.collided
def clear(self):
os.system('cls' if os.name=='nt' else 'clear')
class Player(object):
def __init__(self):
self.nodes_size = 1
self.position_cordination = 'E'
self.last_cordination = 'E'
self.location_x = 4
self.location_y = 4
self.body = -3
def draw(self):
body = ''
for index in range(self.nodes_size):
if(index == 0 and self.position_cordination == 'E'):
body = '>'
elif(index == 0 and self.position_cordination == 'W'):
body = '<'
elif(index == 0 and self.position_cordination == 'N'):
body = '^'
elif(index == 0 and self.position_cordination == 'S'):
body = 'V'
else:
body += '-'
return body
def move(self, cordination):
print("Cordinations x = " + str(self.location_x) + " y = " + str(self.location_y))
if (self.position_cordination != 'S' and cordination == 'N'):
self.location_x -= 1
self.body = -5
elif (self.position_cordination != 'N' and cordination == 'S'):
self.location_x +=1
self.body = -4
elif (self.position_cordination != 'W' and cordination == 'E'):
self.location_y += 1
self.body = -3
elif (self.position_cordination != 'E' and cordination == 'W'):
self.location_y -= 1
self.body = -2
else:
pass
self.position_cordination = cordination
print("Cordinations x = " + str(self.location_x) + " y = " + str(self.location_y))
snake = SnakeGame(32, 32)
snake.play()
Hello ! I have a question guys.
I was writing my first serious python training project because I'm beginner but I encountered a problem that stops me from further development of my program.
I don't have idea how can I write function/module in my class that check if player X or player Y has won. I tried on so many different ways but it seems to not work. I know that the my code is looking awful. Thank you for your time spent.
import sys
class Tic_tac_toe():
def __init__(self):
self.board = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ',
'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ',
'low-L': ' ', 'low-M': ' ', 'low-R': ' '}
self.move_X = None
self.move_0 = None
self.WINNING_MOVE = None
self.loop = None
self.nameX = None
self.nameO = None
self.choice = None
def welcome(self):
try:
print("Welcome ! :)\n\nWho is PLAYER X ? :")
self.nameX = input()
print("\nWho is PLAYER O ? :")
self.nameO = input()
print("\nHello {} and {}, ready to play? (Y/N) :".format(self.nameX.title(), self.nameO.title()))
self.choice = input()
if self.choice.title() == 'N' or '\n':
sys.exit()
print('\n{} is PLAYER X.\n{} is PLAYER Y.'.format(self.nameX.title(),self.nameO.title()))
except ValueError:
print('\nTry again:\n')
def printBoard(self):
print()
print(self.board['top-L'] + '|' + self.board['top-M'] + '|' + self.board['top-R'])
print('-+-+-')
print(self.board['mid-L'] + '|' + self.board['mid-M'] + '|' + self.board['mid-R'])
print('-+-+-')
print(self.board['low-L'] + '|' + self.board['low-M'] + '|' + self.board['low-R'])
print()
def moves_X(self):
try:
self.move_X = int(input("Player X :\nChoose field (1,9) : "))
self.write_on_boardX()
self.printBoard()
except ValueError:
print("\nYOU DIDN'T ENTER NUMBER !\n")
def moves_O(self):
try:
self.move_O = int(input("Player O :\nChoose field (1,9) : "))
self.write_on_boardO()
self.printBoard()
except ValueError:
print("\nYOU DIDN'T ENTER NUMBER!\n")
def mix_XO(self):
self.loop = 0
for x in range(1,10):
if self.loop % 2 == 0:
self.moves_X()
self.loop += 1
elif self.loop % 2 == 1:
self.moves_O()
self.loop += 1
def write_on_boardX(self):
if self.move_X == 1:
self.board['top-L'] = 'X'
elif self.move_X == 2:
self.board['top-M'] = 'X'
elif self.move_X == 3:
self.board['top-R'] = 'X'
elif self.move_X == 4:
self.board['mid-L'] = 'X'
elif self.move_X == 5:
self.board['mid-M'] = 'X'
elif self.move_X == 6:
self.board['mid-R'] = 'X'
elif self.move_X == 7:
self.board['low-L'] = 'X'
elif self.move_X == 8:
self.board['low-M'] = 'X'
elif self.move_X == 9:
self.board['low-R'] = 'X'
def write_on_boardO(self):
if self.move_O == 1:
self.board['top-L'] = 'O'
elif self.move_O == 2:
self.board['top-M'] = 'O'
elif self.move_O == 3:
self.board['top-R'] = 'O'
elif self.move_O == 4:
self.board['mid-L'] = 'O'
elif self.move_O == 5:
self.board['mid-M'] = 'O'
elif self.move_O == 6:
self.board['mid-R'] = 'O'
elif self.move_O == 7:
self.board['low-L'] = 'O'
elif self.move_O == 8:
self.board['low-M'] = 'O'
elif self.move_O == 9:
self.board['low-R'] = '0'
def winning_movesX(self):
pass
def main():
app = Tic_tac_toe()
app.welcome()
app.printBoard()
app.mix_XO()
main()
One way to achieve this is to first create a map of all the possible winning 'lines' and then see if the elements on that line are all the same, by creating a set and checking it contains only 1 item (X or O). For example:
lines = [
['top-L','top-M','top-R'],
['top-L', 'mid-L', 'low-L']
... etc ...
]
for line in lines:
if len(set(self.board[x] for x in line])) == 1:
print("Winner:", self.board[line[0]])
Different Approach might be easier...
A simpler way would be to use a 3x3 matrix, e.g. with:
0 as a default value
-1 for player 1
+1 for player 2
You can then calculate the sum of the rows/columns/diagonals. With -3 as a player 1 win, +3 as a player 2 win. For example by using numpy:
>>> import numpy as np
>>> np.zeros((3, 3), dtype=int)
array([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
=> self.board = np.zeros((3,3), dtype=int)
and a win check would roughly look like:
d1,d2 = 0,0 #used to calculate sum of diagonal
for i in range(3):
#check row
if sum(self.board[i, :]) in (3,-3):
self.win = True
#check column
elif sum(self.board[:, i]) in (3,-3):
self.win = True
#check diagonal
d1 += self.board[i, i] #diagonal from top left corner to bottom right corner
d2 += self.board[i, 2-i] #diagonal from top right corner to bottom left corner
elif d1 in (3,-3) or d2 in (-3,3):
self.win = True
Note: You know which player has won since you know who's turn it was last.
Well, and since you seem to be rather new to python here a quick overview on how to access elements of an array:
>>> board = np.zeros((3,3), dtype=int)
>>> board[0][1] = 3
>>> board
array([[0, 3, 0],
[0, 0, 0],
[0, 0, 0]])
And in case you keep this board:
"""
[1] | [2] | [3]
-----------------
[4] | [5] | [6]
-----------------
[7] | [8] | [9]
"""
you could use the integer division // and the modulo function % instead of all the elif statements to determine what field/position on the board the user meant:
position = int(input("Choose position:"))
row = (position-1)//3
column = (position-1)%3
self.board[row][column] = 1 #or -1
P.S.:
If you want to implement a "player vs. computer" later on, you might change the value -1 to -3 to get unique sum values. (-1 +1 +0 = 0 +0 +0)
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm trying to create a python Connect 4 game for 2 players to play, and there is an error that I can't seem to fix. Please help. The code is supposed to randomly choose which player goes first between 1 and 2 and then get their input through the python shell. With the column number, the code should be able to place a marker different for each player onto a connect four board. Here is the code:
import random
import sys
width = 7
height = 6
player1Marker = 'X'
player2Marker = 'O'
def whoGoesFirst():
# Randomly choose the player who goes first.
if random.randint(0, 2) == 0:
return 'Player 1'
else:
return 'Player 2'
def drawBoard(board):
print()
print(' ', end='')
for x in range(1, width + 1):
print(' %s ' % x, end='')
print()
print('+---+' * (width - 1))
for y in range(height):
print('| |' + (' |' * (width - 1)))
print('|', end='')
for x in range(width):
print(' %s |' % board[x][y], end='')
print()
print('| |' + (' |' * (width - 1)))
print('+---+' + ('---+' * (width - 1)))
def getPlayer1Move(game_board):
while True:
print('Player 1: which column do you want to move on (1-7)? Type quit if you want to quit: ' % (width))
move = input()
if move.lower().startswith('q'):
sys.exit()
if move.int():
continue
move = int(move) - 1
if isValidMove(game_board, move):
return move
def getPlayer2Move(game_board):
while True:
print('Player 2: Which column do you want to move on (1-7)? Type quit if you want to quit: ' % (width))
move = input()
if move.lower().startswith('q'):
sys.exit()
if move.int():
continue
move = int(move) - 1
if isValidMove(game_board, move):
return move
def getNewBoard():
game_board = []
for x in range(width):
game_board.append([' '] * height)
return game_board
def p1makeMove(game_board, player, column):
for y in range(height -1, -1, -1):
if game_board[column][x] == ' ':
game_board[column][x] = player1
return
def p2makeMove(game_board, player, column):
for y in range(height -1, -1, -1):
if game_board[column][y] == ' ':
game_board[column][y] = player2
return
def isValidMove(game_board, move):
if move < 0 or move >= (width):
return False
if game_board[move][0] != ' ':
return False
return True
def isBoardFull(game_board):
for x in range(width):
for y in range(height):
if game_board[x][y] == ' ':
return False
return True
def winnerOfGame(game_board, tile):
# check horizontal spaces
for y in range(height):
for x in range(width - 3):
if game_board[x][y] == tile and game_board[x+1][y] == tile and game_board[x+2][y] == tile and game_board[x+3][y] == tile:
return True
# check vertical spaces
for x in range(width):
for y in range(height - 3):
if game_board[x][y] == tile and game_board[x][y+1] == tile and game_board[x][y+2] == tile and game_board[x][y+3] == tile:
return True
# check / diagonal spaces
for x in range(width - 3):
for y in range(3, height):
if game_board[x][y] == tile and game_board[x+1][y-1] == tile and game_board[x+2][y-2] == tile and game_board[x+3][y-3] == tile:
return True
# check \ diagonal spaces
for x in range(width - 3):
for y in range(height - 3):
if game_board[x][y] == tile and game_board[x+1][y+1] == tile and game_board[x+2][y+2] == tile and game_board[x+3][y+3] == tile:
return True
return False
def playAgain():
# This function returns True if the player wants to play again, otherwise it returns False.
print('Do you want to play again? (yes or no)')
return input().lower().startswith('y')
def main():
print('Four In A Row')
print()
while True:
turn = whoGoesFirst()
print('The %s player will go first.' % (turn))
gameBoard = getNewBoard()
while True:
if turn == 'Player 1':
drawBoard(gameBoard)
move1 = getPlayer1Move(gameBoard)
p1makeMove(gameBoard, player1Marker, move1)
if winnerOfGame(gameBoard, player1Marker):
winner = 'Player 1'
break
turn = 'Player 2'
elif turn == 'Player 2':
drawBoard(gameBoard)
move2 = getPlayer2Move(gameBoard)
p2makeMove(gameBoard, player2Marker, move2)
if winnerOfGame(gameBoard, player2Marker):
winner = 'Player 2'
break
turn = 'Player 1'
elif isBoardFull(game_board):
winner = 'tie'
break
drawBoard(mainBoard)
print('Winner is: %s' % winner)
if not playAgain():
break
main()
This is is the error that is displayed after the game board:
Traceback (most recent call last):
File "/Users/EshaS/Documents/Connect4Final.py", line 166, in <module>
main()
File "/Users/EshaS/Documents/Connect4Final.py", line 151, in main
move2 = getPlayer2Move(gameBoard)
File "/Users/EshaS/Documents/Connect4Final.py", line 53, in getPlayer2Move
print('Player 2: Which column do you want to move on (1-7)? Type quit if you want to quit: ' % (width))
TypeError: not all arguments converted during string formatting
At the end of your print, what are you trying to do with % (width)?
You can use:
print('Player 2: [...] %d [...]' % (width))
%d says that you will include width as an int to a specific location in the string you are printing.
e.g.:
print('Player 2: Which column do you want to move on (1-%d)? Type quit if you want to quit:' % (width))
Which will print (assuming that width = 7): Player 2: Which column do you want to move on (1-7)? Type quit if you want to quit:.
By the way, (code just after that), it is better to parse your input. To use the lower function, you need your input to be a string. And .int() function is unclear, best is to use isinstance( <var>, int ). Which gives:
move = str(input())
if move.lower().startswith('q'):
sys.exit()
if isinstance( move, int ):
continue
(This is True for both functions: getPlayer1Move and getPlayer2Move).