Python Connect-FourConnect Four game in JavaPygame version of my 3D Tic Tac Toe/Connect 4Connect Four in...
Is there some relative to Dutch word "kijken" in German?
My cat mixes up the floors in my building. How can I help him?
Do authors have to be politically correct in article-writing?
Eww, those bytes are gross
We are very unlucky in my court
"Free" Hopf algebra
Isn't using the Extrusion Multiplier like cheating?
A starship is travelling at 0.9c and collides with a small rock. Will it leave a clean hole through, or will more happen?
Would a National Army of mercenaries be a feasible idea?
Using only 1s, make 29 with the minimum number of digits
Book where aliens are selecting humans for food consumption
Slow moving projectiles from a hand-held weapon - how do they reach the target?
What to do when being responsible for data protection in your lab, yet advice is ignored?
Why do members of Congress in committee hearings ask witnesses the same question multiple times?
Does Windows 10's telemetry include sending *.doc files if Word crashed?
Are there neural networks with very few nodes that decently solve non-trivial problems?
Lick explanation
It took me a lot of time to make this, pls like. (YouTube Comments #1)
Why avoid shared user accounts?
If I sold a PS4 game I owned the disc for, can I reinstall it digitally?
Does static make a difference for a const local variable?
What is the lore-based reason that the Spectator has the Create Food and Water trait, instead of simply not requiring food and water?
Quenching swords in dragon blood; why?
Can an insurance company drop you after receiving a bill and refusing to pay?
Python Connect-Four
Connect Four game in JavaPygame version of my 3D Tic Tac Toe/Connect 4Connect Four in PythonJava Connect Four “Four in a row” detection algorithmsConnect Four appletPython Search file for string and read into listConnect Four in JavaConnect Four class projectSimple Game Connect Four in Python 3Basic Connect Four game
$begingroup$
I am currently using Python 3.5.2 to create a connect four basic game. My game should work for two players and tell you when you have won, be it horizontal vertical or diagonal. However I do not know how to make my code smaller or more efficient, is there a way to cut down, or is my method just not very efficient in itself?
I have tried looking up various other ways of doing this code, alas I found them difficult to understand. My code does not have any errors I have picked up on, and though I have completed the task I set myself, I do not feel this is the best way to do it.
If anybody had any suggestions, that would be much appreciated. If I knew how to make it shorter without losing functionality I would do so.
I hope my code will help anybody else attempting the same task as mine is rather basic.
import time
grid1 = [0,0,0,0] # bottom row
grid2 = [0,0,0,0]
grid3 = [0,0,0,0]
grid4 = [0,0,0,0]
grids = [grid1,grid2,grid3,grid4]
check = []
user = 1
class fullSlot_error (Exception):
pass
def hasWon_def():
print ("player "+str(user)+" has won")
time.sleep (1)
def grid_def():
print ("",grid4,"n",grid3,"n",grid2,"n",grid1)
def user_def():
global user
if user < 2:
user = 2
else:
user = 1
return user
def slotFull_def():
while True:
try:
if grid4[userInput -1] != 0:
raise fullSlot_error
else:
break
except fullSlot_error:
print ("slot is full try again")
confirm_def()
def confirm_def():
looop= True
while looop== True:
try:
global userInput
userInput = int(input("ninput a slot player "+str(user)+"(1,4)n"))
if userInput < 5 and 0 < userInput:
looop = False
else:
print ("invalid int")
except ValueError:
print ("invalid input")
def placement_def():
counter = 0
for i in range (0,4):
slotFull_def()
if (grids[i][userInput -1] == 0):
grids [i][userInput - 1] = int(user)
grid_def()
break
def check_def():
global loop
global check
for i in range(0,4):
for a in range(0,4):
check.append(grids[i][a])
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
else:
check = []
for i in range(0,4):
for a in range(0,4):
check.append(grids[a][i])
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
else:
check = []
def checkEmpty_def():
global check
for i in range (0,4):
for a in range (0,4):
check.append(grids[i][a])
if 0 not in check:
print ("full")
def checks_def():
check_def()
checkEmpty_def()
diagcheck_def()
def diagcheck_def():
global loop
global check
check = []
diag = 0
for i in range (0,4):
check.append (grids[diag][diag])
diag = diag +1
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
check = []
diag = 3
diag2 = 0
for i in range (0,4):
check.append (grids[diag][diag2])
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
loop = True
while loop == True:
check_def()
confirm_def()
placement_def()
checks_def()
if loop == False:
break
user_def()
python beginner game connect-four
$endgroup$
add a comment |
$begingroup$
I am currently using Python 3.5.2 to create a connect four basic game. My game should work for two players and tell you when you have won, be it horizontal vertical or diagonal. However I do not know how to make my code smaller or more efficient, is there a way to cut down, or is my method just not very efficient in itself?
I have tried looking up various other ways of doing this code, alas I found them difficult to understand. My code does not have any errors I have picked up on, and though I have completed the task I set myself, I do not feel this is the best way to do it.
If anybody had any suggestions, that would be much appreciated. If I knew how to make it shorter without losing functionality I would do so.
I hope my code will help anybody else attempting the same task as mine is rather basic.
import time
grid1 = [0,0,0,0] # bottom row
grid2 = [0,0,0,0]
grid3 = [0,0,0,0]
grid4 = [0,0,0,0]
grids = [grid1,grid2,grid3,grid4]
check = []
user = 1
class fullSlot_error (Exception):
pass
def hasWon_def():
print ("player "+str(user)+" has won")
time.sleep (1)
def grid_def():
print ("",grid4,"n",grid3,"n",grid2,"n",grid1)
def user_def():
global user
if user < 2:
user = 2
else:
user = 1
return user
def slotFull_def():
while True:
try:
if grid4[userInput -1] != 0:
raise fullSlot_error
else:
break
except fullSlot_error:
print ("slot is full try again")
confirm_def()
def confirm_def():
looop= True
while looop== True:
try:
global userInput
userInput = int(input("ninput a slot player "+str(user)+"(1,4)n"))
if userInput < 5 and 0 < userInput:
looop = False
else:
print ("invalid int")
except ValueError:
print ("invalid input")
def placement_def():
counter = 0
for i in range (0,4):
slotFull_def()
if (grids[i][userInput -1] == 0):
grids [i][userInput - 1] = int(user)
grid_def()
break
def check_def():
global loop
global check
for i in range(0,4):
for a in range(0,4):
check.append(grids[i][a])
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
else:
check = []
for i in range(0,4):
for a in range(0,4):
check.append(grids[a][i])
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
else:
check = []
def checkEmpty_def():
global check
for i in range (0,4):
for a in range (0,4):
check.append(grids[i][a])
if 0 not in check:
print ("full")
def checks_def():
check_def()
checkEmpty_def()
diagcheck_def()
def diagcheck_def():
global loop
global check
check = []
diag = 0
for i in range (0,4):
check.append (grids[diag][diag])
diag = diag +1
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
check = []
diag = 3
diag2 = 0
for i in range (0,4):
check.append (grids[diag][diag2])
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
loop = True
while loop == True:
check_def()
confirm_def()
placement_def()
checks_def()
if loop == False:
break
user_def()
python beginner game connect-four
$endgroup$
add a comment |
$begingroup$
I am currently using Python 3.5.2 to create a connect four basic game. My game should work for two players and tell you when you have won, be it horizontal vertical or diagonal. However I do not know how to make my code smaller or more efficient, is there a way to cut down, or is my method just not very efficient in itself?
I have tried looking up various other ways of doing this code, alas I found them difficult to understand. My code does not have any errors I have picked up on, and though I have completed the task I set myself, I do not feel this is the best way to do it.
If anybody had any suggestions, that would be much appreciated. If I knew how to make it shorter without losing functionality I would do so.
I hope my code will help anybody else attempting the same task as mine is rather basic.
import time
grid1 = [0,0,0,0] # bottom row
grid2 = [0,0,0,0]
grid3 = [0,0,0,0]
grid4 = [0,0,0,0]
grids = [grid1,grid2,grid3,grid4]
check = []
user = 1
class fullSlot_error (Exception):
pass
def hasWon_def():
print ("player "+str(user)+" has won")
time.sleep (1)
def grid_def():
print ("",grid4,"n",grid3,"n",grid2,"n",grid1)
def user_def():
global user
if user < 2:
user = 2
else:
user = 1
return user
def slotFull_def():
while True:
try:
if grid4[userInput -1] != 0:
raise fullSlot_error
else:
break
except fullSlot_error:
print ("slot is full try again")
confirm_def()
def confirm_def():
looop= True
while looop== True:
try:
global userInput
userInput = int(input("ninput a slot player "+str(user)+"(1,4)n"))
if userInput < 5 and 0 < userInput:
looop = False
else:
print ("invalid int")
except ValueError:
print ("invalid input")
def placement_def():
counter = 0
for i in range (0,4):
slotFull_def()
if (grids[i][userInput -1] == 0):
grids [i][userInput - 1] = int(user)
grid_def()
break
def check_def():
global loop
global check
for i in range(0,4):
for a in range(0,4):
check.append(grids[i][a])
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
else:
check = []
for i in range(0,4):
for a in range(0,4):
check.append(grids[a][i])
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
else:
check = []
def checkEmpty_def():
global check
for i in range (0,4):
for a in range (0,4):
check.append(grids[i][a])
if 0 not in check:
print ("full")
def checks_def():
check_def()
checkEmpty_def()
diagcheck_def()
def diagcheck_def():
global loop
global check
check = []
diag = 0
for i in range (0,4):
check.append (grids[diag][diag])
diag = diag +1
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
check = []
diag = 3
diag2 = 0
for i in range (0,4):
check.append (grids[diag][diag2])
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
loop = True
while loop == True:
check_def()
confirm_def()
placement_def()
checks_def()
if loop == False:
break
user_def()
python beginner game connect-four
$endgroup$
I am currently using Python 3.5.2 to create a connect four basic game. My game should work for two players and tell you when you have won, be it horizontal vertical or diagonal. However I do not know how to make my code smaller or more efficient, is there a way to cut down, or is my method just not very efficient in itself?
I have tried looking up various other ways of doing this code, alas I found them difficult to understand. My code does not have any errors I have picked up on, and though I have completed the task I set myself, I do not feel this is the best way to do it.
If anybody had any suggestions, that would be much appreciated. If I knew how to make it shorter without losing functionality I would do so.
I hope my code will help anybody else attempting the same task as mine is rather basic.
import time
grid1 = [0,0,0,0] # bottom row
grid2 = [0,0,0,0]
grid3 = [0,0,0,0]
grid4 = [0,0,0,0]
grids = [grid1,grid2,grid3,grid4]
check = []
user = 1
class fullSlot_error (Exception):
pass
def hasWon_def():
print ("player "+str(user)+" has won")
time.sleep (1)
def grid_def():
print ("",grid4,"n",grid3,"n",grid2,"n",grid1)
def user_def():
global user
if user < 2:
user = 2
else:
user = 1
return user
def slotFull_def():
while True:
try:
if grid4[userInput -1] != 0:
raise fullSlot_error
else:
break
except fullSlot_error:
print ("slot is full try again")
confirm_def()
def confirm_def():
looop= True
while looop== True:
try:
global userInput
userInput = int(input("ninput a slot player "+str(user)+"(1,4)n"))
if userInput < 5 and 0 < userInput:
looop = False
else:
print ("invalid int")
except ValueError:
print ("invalid input")
def placement_def():
counter = 0
for i in range (0,4):
slotFull_def()
if (grids[i][userInput -1] == 0):
grids [i][userInput - 1] = int(user)
grid_def()
break
def check_def():
global loop
global check
for i in range(0,4):
for a in range(0,4):
check.append(grids[i][a])
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
else:
check = []
for i in range(0,4):
for a in range(0,4):
check.append(grids[a][i])
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
else:
check = []
def checkEmpty_def():
global check
for i in range (0,4):
for a in range (0,4):
check.append(grids[i][a])
if 0 not in check:
print ("full")
def checks_def():
check_def()
checkEmpty_def()
diagcheck_def()
def diagcheck_def():
global loop
global check
check = []
diag = 0
for i in range (0,4):
check.append (grids[diag][diag])
diag = diag +1
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
check = []
diag = 3
diag2 = 0
for i in range (0,4):
check.append (grids[diag][diag2])
if (check == [1,1,1,1] or check == [2,2,2,2]):
hasWon_def()
loop = False
return loop
break
loop = True
while loop == True:
check_def()
confirm_def()
placement_def()
checks_def()
if loop == False:
break
user_def()
python beginner game connect-four
python beginner game connect-four
edited Jul 12 '16 at 14:21
syb0rg
16.6k797181
16.6k797181
asked Jul 12 '16 at 14:16
bubblez go popbubblez go pop
116228
116228
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
$begingroup$
Some suggestions:
- It is generally recommended to follow the pep8 style for Python code. For example no space between function names and paranthesis,
lower_case_function_names, spaces after commas, etc. - You can define your grid in a single operation rather than 5.
- For
print, you can use*to unpack your nested list, then usesep='n'to put each row on a different line. - It would be better to have at least one top-level function, rather than doing everything in the root of the script.
- You don't need global variables, it is better to pass the variables as arguments and return the result.
- For print, if you give multiple values as arguments, spaces are automatically inserted between the arguments.
- You don't get any benefit from using a custom exception here, just use a
breakin youriftest. - you can use one-line
iftests (called "ternary expressions") to simplify some of your code. - There isn't much benefit from a simple one-line function that is only used in one place. It makes things harder to read and slows the code down a tiny bit. Just inline the code.
- There isn't much point using a sentinel variable (like
looop) when you just assignFalseto it at a certain point. Just usebreak, andcontinueif need be to skip later parts of the loop. - It is better to put the absolute minimal amount of code possible in your
tryblock to avoid accidentally catching the wrong exception. - you can combine multiple comparisons, such as
0 < userInput < 5. - You can use
returninstead ofbreakto exit out of awhileloop if you just want to return the result at that point with no further processing. - You can use
into test if a value is in a list or other sequence of values rather then usingand. - You never use
counterinplacement_def. - The
0is implied inrange(0, x), so you can leave it out. - Rather than using
rangeand indexing a list, it is easier to iterate over the list directly. - You always subtract
1fromuserInput. It would be easier to subtract one at the beginning. - Rather than appending a list several times to another list, use
extendto append the all the elements at once.
checkdoesn't need to be global, its state is never shared between functions.- You can use
allto simplify checking rows or columns, andzipto transpose lists. - You can use
anyandallto simplify your checks for whether a player has won and for whether the grid is full. - You could simplify the code somewhat by having the check functions return a boolean, then printing in
checks_def. - I don't think
placement_defis correct. You get a user input every time through the loop, rather than just once, and you overwrite the value if it is the current use or empty, when you want to overwrite only if empty. Further, you loop from top to bottom, when you want to loop from bottom to top. - You hard-code the grid size, but it would be easy to allow the user to specify a square grid size.
So here is my code:
def play(n=None):
if n is None:
while True:
try:
n = int(input('Input the grid size: '))
except ValueError:
print('Invalid input')
continue
if n <= 0:
print('Invalid input')
continue
break
grids = [[0]*n for _ in range(n)]
user = 1
print('Current board:')
print(*grids, sep='n')
while True:
user_input = get_input(user, grids, n)
place_piece(user_input, user, grids)
print('Current board:')
print(*grids, sep='n')
if (check_won(grids, user, n) or
check_won(zip(*grids), user, n) or
diagcheck_won(grids, user, n) or
diagcheck_won(grids[::-1], user, n)):
print('Player', user, 'has won')
return
if not any(0 in grid for grid in grids):
return
user = 2 if user == 1 else 1
def get_input(user, grids, n):
instr = 'Input a slot player {0} from 1 to {1}: '.format(user, n)
while True:
try:
user_input = int(input(instr))
except ValueError:
print('invalid input:', user_input)
continue
if 0 > user_input or user_input > n+1:
print('invalid input:', user_input)
elif grids[0][user_input-1] != 0:
print('slot', user_input, 'is full try again')
else:
return user_input-1
def place_piece(user_input, user, grids):
for grid in grids[::-1]:
if not grid[user_input]:
grid[user_input] = user
return
def check_won(grids, user, n):
return any(all(cell == user for cell in grid) for grid in grids)
def diagcheck_won(grids, user, n):
return all(grids[x][x] == user for x in range(n))
if __name__ == '__main__':
play()
Note that this could be simplified even further using numpy arrays, but that is more advanced.
$endgroup$
$begingroup$
Could you please explain what grids [::-1] is and what its purpose is? I assume it is some sort of callback to an existing variable however being new to python, I do not know how it would do this.
$endgroup$
– bubblez go pop
Jul 13 '16 at 14:16
$begingroup$
@bubblezgopop slice syntax isl[start:stop:step]. A step of -1 means going backwards through the list (start is assumed to be beginning of the list and end the end of the list if not specified, like here).
$endgroup$
– Graipher
Jul 13 '16 at 14:24
$begingroup$
@bubblezgopop: As Graipher said, it is going backwards. The idea is to start at the bottom of the board, and then move upwards row-by-row until it finds one where the chosen column is empty. That way the board fills bottom-to-top (as in a real connect 4 board) rather than top-to-bottom as you had.
$endgroup$
– TheBlackCat
Jul 13 '16 at 16:22
$begingroup$
what if grid is of 6 x 7 ?
$endgroup$
– YaSh Chaudhary
Oct 12 '17 at 5:11
$begingroup$
@YaShChaudhary: You ask for two numbers,, saymandn. You can either get them a singleinputwithsplitto separate them or twoinputs. Then you use the two numbers where you previously used one, something likegrids = [[0]*m for _ in range(n)].
$endgroup$
– TheBlackCat
Nov 1 '17 at 19:33
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f134636%2fpython-connect-four%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Some suggestions:
- It is generally recommended to follow the pep8 style for Python code. For example no space between function names and paranthesis,
lower_case_function_names, spaces after commas, etc. - You can define your grid in a single operation rather than 5.
- For
print, you can use*to unpack your nested list, then usesep='n'to put each row on a different line. - It would be better to have at least one top-level function, rather than doing everything in the root of the script.
- You don't need global variables, it is better to pass the variables as arguments and return the result.
- For print, if you give multiple values as arguments, spaces are automatically inserted between the arguments.
- You don't get any benefit from using a custom exception here, just use a
breakin youriftest. - you can use one-line
iftests (called "ternary expressions") to simplify some of your code. - There isn't much benefit from a simple one-line function that is only used in one place. It makes things harder to read and slows the code down a tiny bit. Just inline the code.
- There isn't much point using a sentinel variable (like
looop) when you just assignFalseto it at a certain point. Just usebreak, andcontinueif need be to skip later parts of the loop. - It is better to put the absolute minimal amount of code possible in your
tryblock to avoid accidentally catching the wrong exception. - you can combine multiple comparisons, such as
0 < userInput < 5. - You can use
returninstead ofbreakto exit out of awhileloop if you just want to return the result at that point with no further processing. - You can use
into test if a value is in a list or other sequence of values rather then usingand. - You never use
counterinplacement_def. - The
0is implied inrange(0, x), so you can leave it out. - Rather than using
rangeand indexing a list, it is easier to iterate over the list directly. - You always subtract
1fromuserInput. It would be easier to subtract one at the beginning. - Rather than appending a list several times to another list, use
extendto append the all the elements at once.
checkdoesn't need to be global, its state is never shared between functions.- You can use
allto simplify checking rows or columns, andzipto transpose lists. - You can use
anyandallto simplify your checks for whether a player has won and for whether the grid is full. - You could simplify the code somewhat by having the check functions return a boolean, then printing in
checks_def. - I don't think
placement_defis correct. You get a user input every time through the loop, rather than just once, and you overwrite the value if it is the current use or empty, when you want to overwrite only if empty. Further, you loop from top to bottom, when you want to loop from bottom to top. - You hard-code the grid size, but it would be easy to allow the user to specify a square grid size.
So here is my code:
def play(n=None):
if n is None:
while True:
try:
n = int(input('Input the grid size: '))
except ValueError:
print('Invalid input')
continue
if n <= 0:
print('Invalid input')
continue
break
grids = [[0]*n for _ in range(n)]
user = 1
print('Current board:')
print(*grids, sep='n')
while True:
user_input = get_input(user, grids, n)
place_piece(user_input, user, grids)
print('Current board:')
print(*grids, sep='n')
if (check_won(grids, user, n) or
check_won(zip(*grids), user, n) or
diagcheck_won(grids, user, n) or
diagcheck_won(grids[::-1], user, n)):
print('Player', user, 'has won')
return
if not any(0 in grid for grid in grids):
return
user = 2 if user == 1 else 1
def get_input(user, grids, n):
instr = 'Input a slot player {0} from 1 to {1}: '.format(user, n)
while True:
try:
user_input = int(input(instr))
except ValueError:
print('invalid input:', user_input)
continue
if 0 > user_input or user_input > n+1:
print('invalid input:', user_input)
elif grids[0][user_input-1] != 0:
print('slot', user_input, 'is full try again')
else:
return user_input-1
def place_piece(user_input, user, grids):
for grid in grids[::-1]:
if not grid[user_input]:
grid[user_input] = user
return
def check_won(grids, user, n):
return any(all(cell == user for cell in grid) for grid in grids)
def diagcheck_won(grids, user, n):
return all(grids[x][x] == user for x in range(n))
if __name__ == '__main__':
play()
Note that this could be simplified even further using numpy arrays, but that is more advanced.
$endgroup$
$begingroup$
Could you please explain what grids [::-1] is and what its purpose is? I assume it is some sort of callback to an existing variable however being new to python, I do not know how it would do this.
$endgroup$
– bubblez go pop
Jul 13 '16 at 14:16
$begingroup$
@bubblezgopop slice syntax isl[start:stop:step]. A step of -1 means going backwards through the list (start is assumed to be beginning of the list and end the end of the list if not specified, like here).
$endgroup$
– Graipher
Jul 13 '16 at 14:24
$begingroup$
@bubblezgopop: As Graipher said, it is going backwards. The idea is to start at the bottom of the board, and then move upwards row-by-row until it finds one where the chosen column is empty. That way the board fills bottom-to-top (as in a real connect 4 board) rather than top-to-bottom as you had.
$endgroup$
– TheBlackCat
Jul 13 '16 at 16:22
$begingroup$
what if grid is of 6 x 7 ?
$endgroup$
– YaSh Chaudhary
Oct 12 '17 at 5:11
$begingroup$
@YaShChaudhary: You ask for two numbers,, saymandn. You can either get them a singleinputwithsplitto separate them or twoinputs. Then you use the two numbers where you previously used one, something likegrids = [[0]*m for _ in range(n)].
$endgroup$
– TheBlackCat
Nov 1 '17 at 19:33
add a comment |
$begingroup$
Some suggestions:
- It is generally recommended to follow the pep8 style for Python code. For example no space between function names and paranthesis,
lower_case_function_names, spaces after commas, etc. - You can define your grid in a single operation rather than 5.
- For
print, you can use*to unpack your nested list, then usesep='n'to put each row on a different line. - It would be better to have at least one top-level function, rather than doing everything in the root of the script.
- You don't need global variables, it is better to pass the variables as arguments and return the result.
- For print, if you give multiple values as arguments, spaces are automatically inserted between the arguments.
- You don't get any benefit from using a custom exception here, just use a
breakin youriftest. - you can use one-line
iftests (called "ternary expressions") to simplify some of your code. - There isn't much benefit from a simple one-line function that is only used in one place. It makes things harder to read and slows the code down a tiny bit. Just inline the code.
- There isn't much point using a sentinel variable (like
looop) when you just assignFalseto it at a certain point. Just usebreak, andcontinueif need be to skip later parts of the loop. - It is better to put the absolute minimal amount of code possible in your
tryblock to avoid accidentally catching the wrong exception. - you can combine multiple comparisons, such as
0 < userInput < 5. - You can use
returninstead ofbreakto exit out of awhileloop if you just want to return the result at that point with no further processing. - You can use
into test if a value is in a list or other sequence of values rather then usingand. - You never use
counterinplacement_def. - The
0is implied inrange(0, x), so you can leave it out. - Rather than using
rangeand indexing a list, it is easier to iterate over the list directly. - You always subtract
1fromuserInput. It would be easier to subtract one at the beginning. - Rather than appending a list several times to another list, use
extendto append the all the elements at once.
checkdoesn't need to be global, its state is never shared between functions.- You can use
allto simplify checking rows or columns, andzipto transpose lists. - You can use
anyandallto simplify your checks for whether a player has won and for whether the grid is full. - You could simplify the code somewhat by having the check functions return a boolean, then printing in
checks_def. - I don't think
placement_defis correct. You get a user input every time through the loop, rather than just once, and you overwrite the value if it is the current use or empty, when you want to overwrite only if empty. Further, you loop from top to bottom, when you want to loop from bottom to top. - You hard-code the grid size, but it would be easy to allow the user to specify a square grid size.
So here is my code:
def play(n=None):
if n is None:
while True:
try:
n = int(input('Input the grid size: '))
except ValueError:
print('Invalid input')
continue
if n <= 0:
print('Invalid input')
continue
break
grids = [[0]*n for _ in range(n)]
user = 1
print('Current board:')
print(*grids, sep='n')
while True:
user_input = get_input(user, grids, n)
place_piece(user_input, user, grids)
print('Current board:')
print(*grids, sep='n')
if (check_won(grids, user, n) or
check_won(zip(*grids), user, n) or
diagcheck_won(grids, user, n) or
diagcheck_won(grids[::-1], user, n)):
print('Player', user, 'has won')
return
if not any(0 in grid for grid in grids):
return
user = 2 if user == 1 else 1
def get_input(user, grids, n):
instr = 'Input a slot player {0} from 1 to {1}: '.format(user, n)
while True:
try:
user_input = int(input(instr))
except ValueError:
print('invalid input:', user_input)
continue
if 0 > user_input or user_input > n+1:
print('invalid input:', user_input)
elif grids[0][user_input-1] != 0:
print('slot', user_input, 'is full try again')
else:
return user_input-1
def place_piece(user_input, user, grids):
for grid in grids[::-1]:
if not grid[user_input]:
grid[user_input] = user
return
def check_won(grids, user, n):
return any(all(cell == user for cell in grid) for grid in grids)
def diagcheck_won(grids, user, n):
return all(grids[x][x] == user for x in range(n))
if __name__ == '__main__':
play()
Note that this could be simplified even further using numpy arrays, but that is more advanced.
$endgroup$
$begingroup$
Could you please explain what grids [::-1] is and what its purpose is? I assume it is some sort of callback to an existing variable however being new to python, I do not know how it would do this.
$endgroup$
– bubblez go pop
Jul 13 '16 at 14:16
$begingroup$
@bubblezgopop slice syntax isl[start:stop:step]. A step of -1 means going backwards through the list (start is assumed to be beginning of the list and end the end of the list if not specified, like here).
$endgroup$
– Graipher
Jul 13 '16 at 14:24
$begingroup$
@bubblezgopop: As Graipher said, it is going backwards. The idea is to start at the bottom of the board, and then move upwards row-by-row until it finds one where the chosen column is empty. That way the board fills bottom-to-top (as in a real connect 4 board) rather than top-to-bottom as you had.
$endgroup$
– TheBlackCat
Jul 13 '16 at 16:22
$begingroup$
what if grid is of 6 x 7 ?
$endgroup$
– YaSh Chaudhary
Oct 12 '17 at 5:11
$begingroup$
@YaShChaudhary: You ask for two numbers,, saymandn. You can either get them a singleinputwithsplitto separate them or twoinputs. Then you use the two numbers where you previously used one, something likegrids = [[0]*m for _ in range(n)].
$endgroup$
– TheBlackCat
Nov 1 '17 at 19:33
add a comment |
$begingroup$
Some suggestions:
- It is generally recommended to follow the pep8 style for Python code. For example no space between function names and paranthesis,
lower_case_function_names, spaces after commas, etc. - You can define your grid in a single operation rather than 5.
- For
print, you can use*to unpack your nested list, then usesep='n'to put each row on a different line. - It would be better to have at least one top-level function, rather than doing everything in the root of the script.
- You don't need global variables, it is better to pass the variables as arguments and return the result.
- For print, if you give multiple values as arguments, spaces are automatically inserted between the arguments.
- You don't get any benefit from using a custom exception here, just use a
breakin youriftest. - you can use one-line
iftests (called "ternary expressions") to simplify some of your code. - There isn't much benefit from a simple one-line function that is only used in one place. It makes things harder to read and slows the code down a tiny bit. Just inline the code.
- There isn't much point using a sentinel variable (like
looop) when you just assignFalseto it at a certain point. Just usebreak, andcontinueif need be to skip later parts of the loop. - It is better to put the absolute minimal amount of code possible in your
tryblock to avoid accidentally catching the wrong exception. - you can combine multiple comparisons, such as
0 < userInput < 5. - You can use
returninstead ofbreakto exit out of awhileloop if you just want to return the result at that point with no further processing. - You can use
into test if a value is in a list or other sequence of values rather then usingand. - You never use
counterinplacement_def. - The
0is implied inrange(0, x), so you can leave it out. - Rather than using
rangeand indexing a list, it is easier to iterate over the list directly. - You always subtract
1fromuserInput. It would be easier to subtract one at the beginning. - Rather than appending a list several times to another list, use
extendto append the all the elements at once.
checkdoesn't need to be global, its state is never shared between functions.- You can use
allto simplify checking rows or columns, andzipto transpose lists. - You can use
anyandallto simplify your checks for whether a player has won and for whether the grid is full. - You could simplify the code somewhat by having the check functions return a boolean, then printing in
checks_def. - I don't think
placement_defis correct. You get a user input every time through the loop, rather than just once, and you overwrite the value if it is the current use or empty, when you want to overwrite only if empty. Further, you loop from top to bottom, when you want to loop from bottom to top. - You hard-code the grid size, but it would be easy to allow the user to specify a square grid size.
So here is my code:
def play(n=None):
if n is None:
while True:
try:
n = int(input('Input the grid size: '))
except ValueError:
print('Invalid input')
continue
if n <= 0:
print('Invalid input')
continue
break
grids = [[0]*n for _ in range(n)]
user = 1
print('Current board:')
print(*grids, sep='n')
while True:
user_input = get_input(user, grids, n)
place_piece(user_input, user, grids)
print('Current board:')
print(*grids, sep='n')
if (check_won(grids, user, n) or
check_won(zip(*grids), user, n) or
diagcheck_won(grids, user, n) or
diagcheck_won(grids[::-1], user, n)):
print('Player', user, 'has won')
return
if not any(0 in grid for grid in grids):
return
user = 2 if user == 1 else 1
def get_input(user, grids, n):
instr = 'Input a slot player {0} from 1 to {1}: '.format(user, n)
while True:
try:
user_input = int(input(instr))
except ValueError:
print('invalid input:', user_input)
continue
if 0 > user_input or user_input > n+1:
print('invalid input:', user_input)
elif grids[0][user_input-1] != 0:
print('slot', user_input, 'is full try again')
else:
return user_input-1
def place_piece(user_input, user, grids):
for grid in grids[::-1]:
if not grid[user_input]:
grid[user_input] = user
return
def check_won(grids, user, n):
return any(all(cell == user for cell in grid) for grid in grids)
def diagcheck_won(grids, user, n):
return all(grids[x][x] == user for x in range(n))
if __name__ == '__main__':
play()
Note that this could be simplified even further using numpy arrays, but that is more advanced.
$endgroup$
Some suggestions:
- It is generally recommended to follow the pep8 style for Python code. For example no space between function names and paranthesis,
lower_case_function_names, spaces after commas, etc. - You can define your grid in a single operation rather than 5.
- For
print, you can use*to unpack your nested list, then usesep='n'to put each row on a different line. - It would be better to have at least one top-level function, rather than doing everything in the root of the script.
- You don't need global variables, it is better to pass the variables as arguments and return the result.
- For print, if you give multiple values as arguments, spaces are automatically inserted between the arguments.
- You don't get any benefit from using a custom exception here, just use a
breakin youriftest. - you can use one-line
iftests (called "ternary expressions") to simplify some of your code. - There isn't much benefit from a simple one-line function that is only used in one place. It makes things harder to read and slows the code down a tiny bit. Just inline the code.
- There isn't much point using a sentinel variable (like
looop) when you just assignFalseto it at a certain point. Just usebreak, andcontinueif need be to skip later parts of the loop. - It is better to put the absolute minimal amount of code possible in your
tryblock to avoid accidentally catching the wrong exception. - you can combine multiple comparisons, such as
0 < userInput < 5. - You can use
returninstead ofbreakto exit out of awhileloop if you just want to return the result at that point with no further processing. - You can use
into test if a value is in a list or other sequence of values rather then usingand. - You never use
counterinplacement_def. - The
0is implied inrange(0, x), so you can leave it out. - Rather than using
rangeand indexing a list, it is easier to iterate over the list directly. - You always subtract
1fromuserInput. It would be easier to subtract one at the beginning. - Rather than appending a list several times to another list, use
extendto append the all the elements at once.
checkdoesn't need to be global, its state is never shared between functions.- You can use
allto simplify checking rows or columns, andzipto transpose lists. - You can use
anyandallto simplify your checks for whether a player has won and for whether the grid is full. - You could simplify the code somewhat by having the check functions return a boolean, then printing in
checks_def. - I don't think
placement_defis correct. You get a user input every time through the loop, rather than just once, and you overwrite the value if it is the current use or empty, when you want to overwrite only if empty. Further, you loop from top to bottom, when you want to loop from bottom to top. - You hard-code the grid size, but it would be easy to allow the user to specify a square grid size.
So here is my code:
def play(n=None):
if n is None:
while True:
try:
n = int(input('Input the grid size: '))
except ValueError:
print('Invalid input')
continue
if n <= 0:
print('Invalid input')
continue
break
grids = [[0]*n for _ in range(n)]
user = 1
print('Current board:')
print(*grids, sep='n')
while True:
user_input = get_input(user, grids, n)
place_piece(user_input, user, grids)
print('Current board:')
print(*grids, sep='n')
if (check_won(grids, user, n) or
check_won(zip(*grids), user, n) or
diagcheck_won(grids, user, n) or
diagcheck_won(grids[::-1], user, n)):
print('Player', user, 'has won')
return
if not any(0 in grid for grid in grids):
return
user = 2 if user == 1 else 1
def get_input(user, grids, n):
instr = 'Input a slot player {0} from 1 to {1}: '.format(user, n)
while True:
try:
user_input = int(input(instr))
except ValueError:
print('invalid input:', user_input)
continue
if 0 > user_input or user_input > n+1:
print('invalid input:', user_input)
elif grids[0][user_input-1] != 0:
print('slot', user_input, 'is full try again')
else:
return user_input-1
def place_piece(user_input, user, grids):
for grid in grids[::-1]:
if not grid[user_input]:
grid[user_input] = user
return
def check_won(grids, user, n):
return any(all(cell == user for cell in grid) for grid in grids)
def diagcheck_won(grids, user, n):
return all(grids[x][x] == user for x in range(n))
if __name__ == '__main__':
play()
Note that this could be simplified even further using numpy arrays, but that is more advanced.
edited Jul 13 '16 at 14:35
Graipher
25.2k53687
25.2k53687
answered Jul 12 '16 at 16:36
TheBlackCatTheBlackCat
2,22449
2,22449
$begingroup$
Could you please explain what grids [::-1] is and what its purpose is? I assume it is some sort of callback to an existing variable however being new to python, I do not know how it would do this.
$endgroup$
– bubblez go pop
Jul 13 '16 at 14:16
$begingroup$
@bubblezgopop slice syntax isl[start:stop:step]. A step of -1 means going backwards through the list (start is assumed to be beginning of the list and end the end of the list if not specified, like here).
$endgroup$
– Graipher
Jul 13 '16 at 14:24
$begingroup$
@bubblezgopop: As Graipher said, it is going backwards. The idea is to start at the bottom of the board, and then move upwards row-by-row until it finds one where the chosen column is empty. That way the board fills bottom-to-top (as in a real connect 4 board) rather than top-to-bottom as you had.
$endgroup$
– TheBlackCat
Jul 13 '16 at 16:22
$begingroup$
what if grid is of 6 x 7 ?
$endgroup$
– YaSh Chaudhary
Oct 12 '17 at 5:11
$begingroup$
@YaShChaudhary: You ask for two numbers,, saymandn. You can either get them a singleinputwithsplitto separate them or twoinputs. Then you use the two numbers where you previously used one, something likegrids = [[0]*m for _ in range(n)].
$endgroup$
– TheBlackCat
Nov 1 '17 at 19:33
add a comment |
$begingroup$
Could you please explain what grids [::-1] is and what its purpose is? I assume it is some sort of callback to an existing variable however being new to python, I do not know how it would do this.
$endgroup$
– bubblez go pop
Jul 13 '16 at 14:16
$begingroup$
@bubblezgopop slice syntax isl[start:stop:step]. A step of -1 means going backwards through the list (start is assumed to be beginning of the list and end the end of the list if not specified, like here).
$endgroup$
– Graipher
Jul 13 '16 at 14:24
$begingroup$
@bubblezgopop: As Graipher said, it is going backwards. The idea is to start at the bottom of the board, and then move upwards row-by-row until it finds one where the chosen column is empty. That way the board fills bottom-to-top (as in a real connect 4 board) rather than top-to-bottom as you had.
$endgroup$
– TheBlackCat
Jul 13 '16 at 16:22
$begingroup$
what if grid is of 6 x 7 ?
$endgroup$
– YaSh Chaudhary
Oct 12 '17 at 5:11
$begingroup$
@YaShChaudhary: You ask for two numbers,, saymandn. You can either get them a singleinputwithsplitto separate them or twoinputs. Then you use the two numbers where you previously used one, something likegrids = [[0]*m for _ in range(n)].
$endgroup$
– TheBlackCat
Nov 1 '17 at 19:33
$begingroup$
Could you please explain what grids [::-1] is and what its purpose is? I assume it is some sort of callback to an existing variable however being new to python, I do not know how it would do this.
$endgroup$
– bubblez go pop
Jul 13 '16 at 14:16
$begingroup$
Could you please explain what grids [::-1] is and what its purpose is? I assume it is some sort of callback to an existing variable however being new to python, I do not know how it would do this.
$endgroup$
– bubblez go pop
Jul 13 '16 at 14:16
$begingroup$
@bubblezgopop slice syntax is
l[start:stop:step]. A step of -1 means going backwards through the list (start is assumed to be beginning of the list and end the end of the list if not specified, like here).$endgroup$
– Graipher
Jul 13 '16 at 14:24
$begingroup$
@bubblezgopop slice syntax is
l[start:stop:step]. A step of -1 means going backwards through the list (start is assumed to be beginning of the list and end the end of the list if not specified, like here).$endgroup$
– Graipher
Jul 13 '16 at 14:24
$begingroup$
@bubblezgopop: As Graipher said, it is going backwards. The idea is to start at the bottom of the board, and then move upwards row-by-row until it finds one where the chosen column is empty. That way the board fills bottom-to-top (as in a real connect 4 board) rather than top-to-bottom as you had.
$endgroup$
– TheBlackCat
Jul 13 '16 at 16:22
$begingroup$
@bubblezgopop: As Graipher said, it is going backwards. The idea is to start at the bottom of the board, and then move upwards row-by-row until it finds one where the chosen column is empty. That way the board fills bottom-to-top (as in a real connect 4 board) rather than top-to-bottom as you had.
$endgroup$
– TheBlackCat
Jul 13 '16 at 16:22
$begingroup$
what if grid is of 6 x 7 ?
$endgroup$
– YaSh Chaudhary
Oct 12 '17 at 5:11
$begingroup$
what if grid is of 6 x 7 ?
$endgroup$
– YaSh Chaudhary
Oct 12 '17 at 5:11
$begingroup$
@YaShChaudhary: You ask for two numbers,, say
m and n. You can either get them a single input with split to separate them or two inputs. Then you use the two numbers where you previously used one, something like grids = [[0]*m for _ in range(n)].$endgroup$
– TheBlackCat
Nov 1 '17 at 19:33
$begingroup$
@YaShChaudhary: You ask for two numbers,, say
m and n. You can either get them a single input with split to separate them or two inputs. Then you use the two numbers where you previously used one, something like grids = [[0]*m for _ in range(n)].$endgroup$
– TheBlackCat
Nov 1 '17 at 19:33
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f134636%2fpython-connect-four%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown