if you enter an invalid ip, it doesnt crash lmao
This commit is contained in:
parent
b9d6812bf7
commit
2904e1406d
|
|
@ -7,4 +7,4 @@ I will make and train the AI myself.
|
||||||
I might make a GUI in Pygame, depends if i cbs
|
I might make a GUI in Pygame, depends if i cbs
|
||||||
|
|
||||||
todo list:
|
todo list:
|
||||||
3 gamemodes total. ~~player vs player on the same device~~, player vs player lan, and player vs computer
|
3 gamemodes total. ~~player vs player on the same device~~, ~~player vs player lan~~, and player vs computer
|
||||||
|
|
|
||||||
11
client.py
11
client.py
|
|
@ -1,11 +0,0 @@
|
||||||
import socket
|
|
||||||
|
|
||||||
HOST = "127.0.0.1" # The server's hostname or IP address
|
|
||||||
PORT = 65432 # The port used by the server
|
|
||||||
|
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
||||||
s.connect((HOST, PORT))
|
|
||||||
s.sendall(b"Hello, world")
|
|
||||||
data = s.recv(1024)
|
|
||||||
|
|
||||||
print(f"Received {data!r}")
|
|
||||||
198
main.py
198
main.py
|
|
@ -1,12 +1,25 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import socket
|
||||||
from colours import Colours
|
from colours import Colours
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# | Helper functions |
|
||||||
|
# ===========================
|
||||||
def clear():
|
def clear():
|
||||||
if sys.platform.startswith('win'):
|
os.system('cls' if sys.platform.startswith('win') else 'clear')
|
||||||
os.system('cls')
|
|
||||||
|
def colourTile(tile):
|
||||||
|
if tile == 'R':
|
||||||
|
return f"{Colours.BOLD}{Colours.RED}R{Colours.END}"
|
||||||
|
elif tile == 'Y':
|
||||||
|
return f"{Colours.BOLD}{Colours.YELLOW}Y{Colours.END}"
|
||||||
|
elif tile == 'r':
|
||||||
|
return f"{Colours.BOLD}{Colours.LIGHT_GREEN}R{Colours.END}"
|
||||||
|
elif tile == 'y':
|
||||||
|
return f"{Colours.BOLD}{Colours.LIGHT_GREEN}Y{Colours.END}"
|
||||||
else:
|
else:
|
||||||
os.system('clear')
|
return "O"
|
||||||
|
|
||||||
def printBoard(board):
|
def printBoard(board):
|
||||||
rows = []
|
rows = []
|
||||||
|
|
@ -16,122 +29,161 @@ def printBoard(board):
|
||||||
row += f"{Colours.BOLD}| {Colours.END}" + colourTile(column[i]) + " "
|
row += f"{Colours.BOLD}| {Colours.END}" + colourTile(column[i]) + " "
|
||||||
row += f"{Colours.BOLD}|{Colours.END}"
|
row += f"{Colours.BOLD}|{Colours.END}"
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
|
rows.reverse()
|
||||||
rows = rows[::-1]
|
|
||||||
|
|
||||||
toPrint = ""
|
|
||||||
for row in rows:
|
|
||||||
toPrint += (row + "\n")
|
|
||||||
|
|
||||||
print(f""" {Colours.BOLD}CONNECT FOUR
|
print(f""" {Colours.BOLD}CONNECT FOUR
|
||||||
============================={Colours.END}
|
============================={Colours.END}
|
||||||
{toPrint[:-1]}
|
{'\n'.join(rows)}
|
||||||
{Colours.BOLD}==1===2===3===4===5===6===7=={Colours.END}""")
|
{Colours.BOLD}==1===2===3===4===5===6===7=={Colours.END}""")
|
||||||
|
|
||||||
def getIntInput(prompt):
|
def getIntInput(prompt, board=None):
|
||||||
inp = ""
|
|
||||||
while True:
|
while True:
|
||||||
inp = input(prompt)
|
inp = input(prompt)
|
||||||
try:
|
try:
|
||||||
inp = int(inp)
|
inp = int(inp)
|
||||||
break
|
if not 1 <= inp <= 7:
|
||||||
except:
|
raise ValueError
|
||||||
clear()
|
|
||||||
printBoard(board)
|
|
||||||
print("Only positive integers 1-7 allowed")
|
|
||||||
|
|
||||||
return inp
|
return inp
|
||||||
|
except ValueError:
|
||||||
def colourTile(tile):
|
clear()
|
||||||
if tile == 'R':
|
if board:
|
||||||
return f"{Colours.BOLD}{Colours.RED}R{Colours.END}"
|
printBoard(board)
|
||||||
elif tile == 'Y':
|
print("Only integers 1-7 allowed")
|
||||||
return f"{Colours.BOLD}{Colours.YELLOW}Y{Colours.END}"
|
|
||||||
elif tile == 'r': # winning red
|
|
||||||
return f"{Colours.BOLD}{Colours.LIGHT_GREEN}R{Colours.END}"
|
|
||||||
elif tile == 'y': # winning yellow
|
|
||||||
return f"{Colours.BOLD}{Colours.LIGHT_GREEN}Y{Colours.END}"
|
|
||||||
else:
|
|
||||||
return "O"
|
|
||||||
|
|
||||||
def checkWin(board, player):
|
def checkWin(board, player):
|
||||||
rows, cols = (6, 7)
|
rows, cols = (6, 7)
|
||||||
winCount = 4
|
winCount = 4
|
||||||
|
|
||||||
# hoz check
|
|
||||||
for row in range(rows):
|
for row in range(rows):
|
||||||
for col in range(cols - winCount + 1):
|
for col in range(cols - winCount + 1):
|
||||||
if all(board[col + i][row] == player for i in range(winCount)):
|
if all(board[col + i][row] == player for i in range(winCount)):
|
||||||
return [(col + i, row) for i in range(winCount)]
|
return [(col + i, row) for i in range(winCount)]
|
||||||
|
|
||||||
# vert check
|
|
||||||
for col in range(cols):
|
for col in range(cols):
|
||||||
for row in range(rows - winCount + 1):
|
for row in range(rows - winCount + 1):
|
||||||
if all(board[col][row + i] == player for i in range(winCount)):
|
if all(board[col][row + i] == player for i in range(winCount)):
|
||||||
return [(col, row + i) for i in range(winCount)]
|
return [(col, row + i) for i in range(winCount)]
|
||||||
|
|
||||||
# diag / check
|
|
||||||
for col in range(cols - winCount + 1):
|
for col in range(cols - winCount + 1):
|
||||||
for row in range(rows - winCount + 1):
|
for row in range(rows - winCount + 1):
|
||||||
if all(board[col + i][row + i] == player for i in range(winCount)):
|
if all(board[col + i][row + i] == player for i in range(winCount)):
|
||||||
return [(col + i, row + i) for i in range(winCount)]
|
return [(col + i, row + i) for i in range(winCount)]
|
||||||
|
|
||||||
# diag \ check
|
|
||||||
for col in range(cols - winCount + 1):
|
for col in range(cols - winCount + 1):
|
||||||
for row in range(winCount - 1, rows):
|
for row in range(winCount - 1, rows):
|
||||||
if all(board[col + i][row - i] == player for i in range(winCount)):
|
if all(board[col + i][row - i] == player for i in range(winCount)):
|
||||||
return [(col + i, row - i) for i in range(winCount)]
|
return [(col + i, row - i) for i in range(winCount)]
|
||||||
|
|
||||||
# This is defined as columns, not rows. So tile 0 on column 0 is the bottom left tile of the board
|
# ===========================
|
||||||
# you index like board[column][row]
|
# | Player move providers |
|
||||||
board = [
|
# ===========================
|
||||||
['O', 'O', 'O', 'O', 'O', 'O'],
|
def local_move_provider(player, board):
|
||||||
['O', 'O', 'O', 'O', 'O', 'O'],
|
col = getIntInput(f"{colourTile(player)} where do you want to drop your tile? 1-7.\n>>> ", board) - 1
|
||||||
['O', 'O', 'O', 'O', 'O', 'O'],
|
return col
|
||||||
['O', 'O', 'O', 'O', 'O', 'O'],
|
|
||||||
['O', 'O', 'O', 'O', 'O', 'O'],
|
|
||||||
['O', 'O', 'O', 'O', 'O', 'O'],
|
|
||||||
['O', 'O', 'O', 'O', 'O', 'O'],
|
|
||||||
]
|
|
||||||
|
|
||||||
playing = True
|
def socket_receive_move(sock):
|
||||||
player = 'R'
|
return int(sock.recv(1024).decode())
|
||||||
|
|
||||||
while playing:
|
def socket_send_move(sock, col):
|
||||||
clear()
|
sock.sendall(str(col).encode())
|
||||||
printBoard(board)
|
|
||||||
|
# ===========================
|
||||||
|
# | Main game loop |
|
||||||
|
# ===========================
|
||||||
|
def play_game(player1_get_move, player2_get_move):
|
||||||
|
board = [['O'] * 6 for _ in range(7)]
|
||||||
|
player = 'R'
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
|
||||||
chosenColumn = getIntInput(f"{colourTile(player)} where do you want to drop your tile? 1-7.\n>>> ") - 1
|
|
||||||
if chosenColumn < 0:
|
|
||||||
raise IndexError
|
|
||||||
tile = board[chosenColumn].index("O")
|
|
||||||
break
|
|
||||||
except ValueError:
|
|
||||||
clear()
|
clear()
|
||||||
printBoard(board)
|
printBoard(board)
|
||||||
print(f"{Colours.BOLD}You chose a column that is full. Try again{Colours.END}")
|
|
||||||
tile = ""
|
|
||||||
except IndexError:
|
|
||||||
clear()
|
|
||||||
printBoard(board)
|
|
||||||
print(f"{Colours.BOLD}You chose a column outside of the board. Try again{Colours.END}")
|
|
||||||
tile = ""
|
|
||||||
|
|
||||||
board[chosenColumn][tile] = player
|
# Get column from correct player
|
||||||
|
if player == 'R':
|
||||||
|
col = player1_get_move(player, board)
|
||||||
|
else:
|
||||||
|
col = player2_get_move(player, board)
|
||||||
|
|
||||||
|
try:
|
||||||
|
tile = board[col].index("O")
|
||||||
|
except ValueError:
|
||||||
|
continue # column full, skip turn (could add retry logic)
|
||||||
|
|
||||||
|
board[col][tile] = player
|
||||||
|
|
||||||
winPositions = checkWin(board, player)
|
winPositions = checkWin(board, player)
|
||||||
if winPositions:
|
if winPositions:
|
||||||
for x, y in winPositions:
|
for x, y in winPositions:
|
||||||
board[x][y] = board[x][y].lower()
|
board[x][y] = board[x][y].lower()
|
||||||
|
|
||||||
clear()
|
clear()
|
||||||
printBoard(board)
|
printBoard(board)
|
||||||
print(f"{colourTile(player)} won!")
|
print(f"{colourTile(player)} won!")
|
||||||
|
input("Press ENTER to return to the menu.")
|
||||||
break
|
break
|
||||||
|
|
||||||
if player == 'R':
|
player = 'Y' if player == 'R' else 'R'
|
||||||
player = 'Y'
|
|
||||||
|
# ===========================
|
||||||
|
# | Modes |
|
||||||
|
# ===========================
|
||||||
|
def play_local_pvp():
|
||||||
|
play_game(local_move_provider, local_move_provider)
|
||||||
|
|
||||||
|
def play_lan_server():
|
||||||
|
HOST, PORT = "0.0.0.0", 65432
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
|
s.bind((HOST, PORT))
|
||||||
|
s.listen()
|
||||||
|
print("Waiting for player 2...")
|
||||||
|
conn, addr = s.accept()
|
||||||
|
with conn:
|
||||||
|
print(f"Connected by {addr}")
|
||||||
|
play_game(
|
||||||
|
lambda p, b: send_and_return_local_move(p, b, conn),
|
||||||
|
lambda p, b: socket_receive_move(conn)
|
||||||
|
)
|
||||||
|
|
||||||
|
def play_lan_client():
|
||||||
|
while True:
|
||||||
|
HOST, PORT = input("Enter server IP: "), 65432
|
||||||
|
try:
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
|
s.connect((HOST, PORT))
|
||||||
|
print("Connected to server.")
|
||||||
|
play_game(
|
||||||
|
lambda p, b: socket_receive_move(s),
|
||||||
|
lambda p, b: send_and_return_local_move(p, b, s)
|
||||||
|
)
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
print("No game found on that IP. Try again.")
|
||||||
|
|
||||||
|
def send_and_return_local_move(player, board, sock):
|
||||||
|
col = local_move_provider(player, board)
|
||||||
|
socket_send_move(sock, col)
|
||||||
|
return col
|
||||||
|
|
||||||
|
def play_vs_computer():
|
||||||
|
print("PvC mode coming soon!")
|
||||||
|
input("Press Enter to return to menu...")
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# | Menu |
|
||||||
|
# ===========================
|
||||||
|
while True:
|
||||||
|
clear()
|
||||||
|
print("How do you want to play?")
|
||||||
|
print("1. PvP (same device)")
|
||||||
|
print("2. PvP (LAN)")
|
||||||
|
print("3. PvC (vs computer)")
|
||||||
|
print("4. Quit")
|
||||||
|
choice = input("Choose 1-4: ").strip()
|
||||||
|
if choice == "1":
|
||||||
|
play_local_pvp()
|
||||||
|
elif choice == "2":
|
||||||
|
if input("Are you hosting? (y/n): ").lower() == "y":
|
||||||
|
play_lan_server()
|
||||||
else:
|
else:
|
||||||
player = 'R'
|
play_lan_client()
|
||||||
|
elif choice == "3":
|
||||||
|
play_vs_computer()
|
||||||
|
elif choice == "4":
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
input("Invalid choice. Press Enter to try again...")
|
||||||
|
|
|
||||||
16
server.py
16
server.py
|
|
@ -1,16 +0,0 @@
|
||||||
import socket
|
|
||||||
|
|
||||||
HOST = "0.0.0.0"
|
|
||||||
PORT = 65432
|
|
||||||
|
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
||||||
s.bind((HOST, PORT))
|
|
||||||
s.listen()
|
|
||||||
conn, addr = s.accept()
|
|
||||||
with conn:
|
|
||||||
print(f"Connected by {addr}")
|
|
||||||
while True:
|
|
||||||
data = conn.recv(1024)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
conn.sendall(data)
|
|
||||||
183
test.py
183
test.py
|
|
@ -1,183 +0,0 @@
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import socket
|
|
||||||
from colours import Colours
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# | Helper functions |
|
|
||||||
# ===========================
|
|
||||||
def clear():
|
|
||||||
os.system('cls' if sys.platform.startswith('win') else 'clear')
|
|
||||||
|
|
||||||
def colourTile(tile):
|
|
||||||
if tile == 'R':
|
|
||||||
return f"{Colours.BOLD}{Colours.RED}R{Colours.END}"
|
|
||||||
elif tile == 'Y':
|
|
||||||
return f"{Colours.BOLD}{Colours.YELLOW}Y{Colours.END}"
|
|
||||||
elif tile == 'r':
|
|
||||||
return f"{Colours.BOLD}{Colours.LIGHT_GREEN}R{Colours.END}"
|
|
||||||
elif tile == 'y':
|
|
||||||
return f"{Colours.BOLD}{Colours.LIGHT_GREEN}Y{Colours.END}"
|
|
||||||
else:
|
|
||||||
return "O"
|
|
||||||
|
|
||||||
def printBoard(board):
|
|
||||||
rows = []
|
|
||||||
for i in range(6):
|
|
||||||
row = ""
|
|
||||||
for column in board:
|
|
||||||
row += f"{Colours.BOLD}| {Colours.END}" + colourTile(column[i]) + " "
|
|
||||||
row += f"{Colours.BOLD}|{Colours.END}"
|
|
||||||
rows.append(row)
|
|
||||||
rows.reverse()
|
|
||||||
|
|
||||||
print(f""" {Colours.BOLD}CONNECT FOUR
|
|
||||||
============================={Colours.END}
|
|
||||||
{'\n'.join(rows)}
|
|
||||||
{Colours.BOLD}==1===2===3===4===5===6===7=={Colours.END}""")
|
|
||||||
|
|
||||||
def getIntInput(prompt, board=None):
|
|
||||||
while True:
|
|
||||||
inp = input(prompt)
|
|
||||||
try:
|
|
||||||
inp = int(inp)
|
|
||||||
if not 1 <= inp <= 7:
|
|
||||||
raise ValueError
|
|
||||||
return inp
|
|
||||||
except ValueError:
|
|
||||||
clear()
|
|
||||||
if board:
|
|
||||||
printBoard(board)
|
|
||||||
print("Only integers 1-7 allowed")
|
|
||||||
|
|
||||||
def checkWin(board, player):
|
|
||||||
rows, cols = (6, 7)
|
|
||||||
winCount = 4
|
|
||||||
for row in range(rows):
|
|
||||||
for col in range(cols - winCount + 1):
|
|
||||||
if all(board[col + i][row] == player for i in range(winCount)):
|
|
||||||
return [(col + i, row) for i in range(winCount)]
|
|
||||||
for col in range(cols):
|
|
||||||
for row in range(rows - winCount + 1):
|
|
||||||
if all(board[col][row + i] == player for i in range(winCount)):
|
|
||||||
return [(col, row + i) for i in range(winCount)]
|
|
||||||
for col in range(cols - winCount + 1):
|
|
||||||
for row in range(rows - winCount + 1):
|
|
||||||
if all(board[col + i][row + i] == player for i in range(winCount)):
|
|
||||||
return [(col + i, row + i) for i in range(winCount)]
|
|
||||||
for col in range(cols - winCount + 1):
|
|
||||||
for row in range(winCount - 1, rows):
|
|
||||||
if all(board[col + i][row - i] == player for i in range(winCount)):
|
|
||||||
return [(col + i, row - i) for i in range(winCount)]
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# | Player move providers |
|
|
||||||
# ===========================
|
|
||||||
def local_move_provider(player, board):
|
|
||||||
col = getIntInput(f"{colourTile(player)} where do you want to drop your tile? 1-7.\n>>> ", board) - 1
|
|
||||||
return col
|
|
||||||
|
|
||||||
def socket_receive_move(sock):
|
|
||||||
return int(sock.recv(1024).decode())
|
|
||||||
|
|
||||||
def socket_send_move(sock, col):
|
|
||||||
sock.sendall(str(col).encode())
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# | Main game loop |
|
|
||||||
# ===========================
|
|
||||||
def play_game(player1_get_move, player2_get_move):
|
|
||||||
board = [['O'] * 6 for _ in range(7)]
|
|
||||||
player = 'R'
|
|
||||||
|
|
||||||
while True:
|
|
||||||
clear()
|
|
||||||
printBoard(board)
|
|
||||||
|
|
||||||
# Get column from correct player
|
|
||||||
if player == 'R':
|
|
||||||
col = player1_get_move(player, board)
|
|
||||||
else:
|
|
||||||
col = player2_get_move(player, board)
|
|
||||||
|
|
||||||
try:
|
|
||||||
tile = board[col].index("O")
|
|
||||||
except ValueError:
|
|
||||||
continue # column full, skip turn (could add retry logic)
|
|
||||||
|
|
||||||
board[col][tile] = player
|
|
||||||
|
|
||||||
winPositions = checkWin(board, player)
|
|
||||||
if winPositions:
|
|
||||||
for x, y in winPositions:
|
|
||||||
board[x][y] = board[x][y].lower()
|
|
||||||
clear()
|
|
||||||
printBoard(board)
|
|
||||||
print(f"{colourTile(player)} won!")
|
|
||||||
break
|
|
||||||
|
|
||||||
player = 'Y' if player == 'R' else 'R'
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# | Modes |
|
|
||||||
# ===========================
|
|
||||||
def play_local_pvp():
|
|
||||||
play_game(local_move_provider, local_move_provider)
|
|
||||||
|
|
||||||
def play_lan_server():
|
|
||||||
HOST, PORT = "0.0.0.0", 65432
|
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
||||||
s.bind((HOST, PORT))
|
|
||||||
s.listen()
|
|
||||||
print("Waiting for player 2...")
|
|
||||||
conn, addr = s.accept()
|
|
||||||
with conn:
|
|
||||||
print(f"Connected by {addr}")
|
|
||||||
play_game(
|
|
||||||
lambda p, b: send_and_return_local_move(p, b, conn),
|
|
||||||
lambda p, b: socket_receive_move(conn)
|
|
||||||
)
|
|
||||||
|
|
||||||
def play_lan_client():
|
|
||||||
HOST, PORT = input("Enter server IP: "), 65432
|
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
||||||
s.connect((HOST, PORT))
|
|
||||||
print("Connected to server.")
|
|
||||||
play_game(
|
|
||||||
lambda p, b: socket_receive_move(s),
|
|
||||||
lambda p, b: send_and_return_local_move(p, b, s)
|
|
||||||
)
|
|
||||||
|
|
||||||
def send_and_return_local_move(player, board, sock):
|
|
||||||
col = local_move_provider(player, board)
|
|
||||||
socket_send_move(sock, col)
|
|
||||||
return col
|
|
||||||
|
|
||||||
def play_vs_computer():
|
|
||||||
print("PvC mode coming soon!")
|
|
||||||
input("Press Enter to return to menu...")
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# | Menu |
|
|
||||||
# ===========================
|
|
||||||
while True:
|
|
||||||
clear()
|
|
||||||
print("How do you want to play?")
|
|
||||||
print("1. PvP (same device)")
|
|
||||||
print("2. PvP (LAN)")
|
|
||||||
print("3. PvC (vs computer)")
|
|
||||||
print("4. Quit")
|
|
||||||
choice = input("Choose 1-4: ").strip()
|
|
||||||
if choice == "1":
|
|
||||||
play_local_pvp()
|
|
||||||
elif choice == "2":
|
|
||||||
if input("Are you hosting? (y/n): ").lower() == "y":
|
|
||||||
play_lan_server()
|
|
||||||
else:
|
|
||||||
play_lan_client()
|
|
||||||
elif choice == "3":
|
|
||||||
play_vs_computer()
|
|
||||||
elif choice == "4":
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
input("Invalid choice. Press Enter to try again...")
|
|
||||||
Loading…
Reference in New Issue
Block a user