9 Commits

Author SHA1 Message Date
20241144010020 05a26bd99d Move drawing functions into static class 2024-12-05 17:39:58 -03:00
20241144010020 0ee1082c6d Start abstracting game into a class 2024-12-03 11:37:01 -03:00
20241144010020 393c1b23b4 Change ugly code 2024-12-03 10:14:25 -03:00
20241144010020 6dd9557681 Add function type hints 2024-12-03 10:07:18 -03:00
20241144010020 649b5b27f7 Use byte length as data_size 2024-11-30 10:09:17 -03:00
20241144010020 055e4fa224 Add simple networking module and test 2024-11-29 11:39:53 -03:00
20241144010020 276b090cfd Atualizar readme 2024-11-21 14:21:07 -03:00
20241144010020 6003ed385e Mudar colunas para letras 2024-11-21 14:13:21 -03:00
20241144010020 e2fb482e4e Adicionar modo debug 2024-11-21 14:05:36 -03:00
6 changed files with 273 additions and 17 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
# 20241144010013
# Repository for random Projects that run through my mind
# Sobre
Repositorio que contem uma versão **MELHORADA** de batalha naval.
Fork do [repositório de Kaio Henrique](https://gitea.mange.ifrn.edu.br/20241144010013/20241144010013)
+79
View File
@@ -0,0 +1,79 @@
def make_board(size: int, filler = 0) -> list:
return [[filler for _ in range(size)] for _ in range(size)]
class DrawerHelper:
@staticmethod
def draw_columnsnrows(board) -> None:
max_num_len = len(str(len(board) - 1))
# Currently inserts the columns and rows into the board
for i in range(len(board)):
for j in range(len(board[i])):
if i == 0 and j == 0:
board[i][j] = " " * max_num_len
elif i == 0:
board[i][j] = chr(j + 64)
elif j == 0:
board[i][j] = str(i).rjust(max_num_len)
else:
board[i][j] = " "
def draw_ships(board, ships) -> None:
for i in range(len(ships)):
for j in range(len(ships[i])):
if ships[i][j] == 1:
board[i + 1][j + 1] = "B"
def draw_shots(board, hit_ships) -> None:
for i in range(len(hit_ships)):
for j in range(len(hit_ships[i])):
if hit_ships[i][j] == 1:
board[i + 1][j + 1] = "X"
if hit_ships[i][j] == -1:
board[i + 1][j + 1] = "O"
def draw_board(board) -> None:
for i in range(len(board)):
for j in range(len(board[i])):
print(board[i][j], end=" ")
print()
class Game:
def __init__(self, board_size: int, enemy_amount: int = 5) -> None:
self.my_ships = make_board(board_size)
# Two different boards, one to show your ships and one to show the places you have shot
self.hit_ships = make_board(board_size) # -1 = shot but not hit, 0 = not hit, 1 = hit
self.total_enemy_amount = enemy_amount
self.my_drawn_board = make_board(board_size + 1, " ")
self.enemy_drawn_board = make_board(board_size + 1, " ")
@property
def enemy_amount(self) -> int:
# Get the enemy amount based on the amount of ships that are not hit in the hit ships var
return self.total_enemy_amount - sum([row.count(1) for row in self.hit_ships])
def draw(self) -> None:
DrawerHelper.draw_ships(self.my_drawn_board, self.my_ships)
DrawerHelper.draw_shots(self.my_drawn_board, self.hit_ships)
DrawerHelper.draw_board(self.my_drawn_board)
def hit(self, x: int, y: int, state: int) -> None:
self.hit_ships[x][y] = state
def shoot(self, x: int, y: int) -> int:
"""Shot at own board and return hit or not hit"""
if self.my_ships[x][y] == 1:
return 1
return -1
na = Game(5)
DrawerHelper.draw_columnsnrows(na.my_drawn_board)
na.my_ships[2][2] = 1
na.hit(1, 2, na.shoot(1, 2))
na.draw()
+44 -14
View File
@@ -1,6 +1,21 @@
#setup
import turtle as tl
import random
import random, sys
args = sys.argv
# name, -arguments
def has_argument(args: list[str], arg: str) -> bool:
if len(args) > 1:
if args[1].startswith("-"):
for chr in args[1]:
if chr == arg:
return True
return False
def num2char(num: int) -> chr:
return chr(num + 65)
def char2num(char: str) -> int:
return ord(char) - 65
posx = [0, 1, 2, 3, 4]
posy = [0, 1, 2, 3, 4]
@@ -16,15 +31,17 @@ tl.speed(0)
#funções
def linhax(x,y):
tl.up(); tl.goto(x,y)
tl.down(); tl.goto(x+600,y)
pass
def linhax(x: int, y: int) -> None:
tl.up()
tl.goto(x,y)
tl.down()
tl.goto(x+600,y)
def linhay(x,y):
tl.up(); tl.goto(x,y)
tl.down(); tl.goto(x,y+600)
pass
def linhay(x: int, y: int) -> None:
tl.up()
tl.goto(x,y)
tl.down()
tl.goto(x,y+600)
#radar screen
@@ -38,7 +55,7 @@ linhax(-300,300)
#linhas X
for i in range(5):
linhax(-300, (i-2)*100)
tl.write(str(i), False, align="right")
tl.write(num2char(i), False, align="right")
#linhas Y
for i in range(5):
@@ -47,10 +64,14 @@ for i in range(5):
#Tabuleiro pronto
tl.title("Naval Battle 1943")
tl.hideturtle()
boat = tl.Turtle()
boat.shapesize(3, 3)
boat.up(); boat.goto(0,0); boat.left(90)
boat.up()
boat.goto(0,0)
boat.left(90)
#Enemies
AMOUNT_OF_ENEMIES = 3
@@ -58,9 +79,14 @@ enemies = []
for i in range(AMOUNT_OF_ENEMIES):
enemy = tl.Turtle()
enemy.up()
enemy.hideturtle()
enemy.color("red")
enemy.up()
if not has_argument(args, "D"):
enemy.hideturtle()
else:
enemy.shapesize(3, 3)
pos = [random.choice(posy), random.choice(posy)]
enemy.goto((pos[0] - 2) * 100, (pos[1] - 2) * 100)
@@ -70,7 +96,8 @@ for i in range(AMOUNT_OF_ENEMIES):
win = False
while win == False:
tirox = tl.numinput("linha X do disparo","Em qual quadrante X devemos disparar a artilharia")
tiroy = tl.numinput("linha Y do disparo","Em qual quadrante Y devemos disparar a artilharia")
tiroy = tl.textinput("linha Y do disparo","Em qual quadrante Y devemos disparar a artilharia")
tiroy = char2num(tiroy.upper())
if tirox == None or tiroy == None:
tl.exitonclick()
@@ -83,9 +110,11 @@ while win == False:
hit_enemy: list[tl.Turtle, list[int, int]] = enemy
acerto = True
break
if acerto:
print("Acerto!")
boat.write("U-boat Afundado\n Capitão!",False,align="center")
hit_enemy[0].hideturtle()
enemies.remove(hit_enemy)
else:
@@ -97,4 +126,5 @@ while win == False:
win = True
print("Você ganhou!!")
tl.exitonclick()
View File
+123
View File
@@ -0,0 +1,123 @@
import socket, threading
class Networking:
"""
A class that contains common networking functions for both server and client.
"""
@staticmethod
def recv_any_size(sock):
"""
Receives data from the socket without knowing the size of the data.
The sender must send the size of the data before sending the data.
"""
data_size = sock.recv(1024).decode()
sock.send("OK".encode())
data = sock.recv(int(data_size)).decode()
return data
@staticmethod
def send_any_size(sock, data):
"""
Sends data to the socket without knowing the size of the data.
Sends the size of the data before sending the data.
"""
data_len = str(len(bytes(data, "utf-8"))).encode()
sock.send(data_len)
response = sock.recv(1024).decode()
sock.send(data.encode())
class Server:
"""
A basic server class that can be inherited to create a custom server.
Contains some basic networking functions.
"""
def __init__(self, host = "127.0.0.1", port = 8080):
"""
Hosts a basic server on the specified host and port
"""
self.host = host
self.port = port
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.host, self.port))
def start(self, max_connections = 5):
"""
Starts the server and listens for *max_connections* connections, defaulted to 5
"""
self.server.listen(max_connections)
while True:
client, addr = self.server.accept()
print(f"Connection from {addr}")
# Start a new thread for the client
threading.Thread(target=self.handle_client, args=(client,)).start()
def handle_client(self, client):
"""
Checks if the client sent "exit" and closes the connection if it did, else send the data back.
Overwrite with your own implementation.
"""
while True:
data = self.recv(client)
if data == "exit":
break
self.send(client, data)
pass
def send(self, client, data):
"""
Sends data to the client
"""
Networking.send_any_size(client, data)
def recv(self, client):
"""
Receives data from the client
"""
return Networking.recv_any_size(client)
def stop(self):
"""
Stops the server
"""
self.server.close()
class Client:
"""
A basic client class that can be inherited to create a custom client.
Contains some basic networking functions.
"""
def __init__(self, host = "127.0.0.1", port = 8080):
"""
Connects to a server on the specified host and port
"""
self.host = host
self.port = port
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((self.host, self.port))
def send(self, data):
"""
Sends data to the server
"""
Networking.send_any_size(self.sock, data)
def recv(self):
"""
Receives data from the server
"""
return Networking.recv_any_size(self.sock)
def close(self):
"""
Closes the connection
"""
Networking.send_any_size(self.sock, "exit")
self.sock.close()
+24
View File
@@ -0,0 +1,24 @@
from networking import net_module
import socket, threading
class Test_server(net_module.Server):
def handle_client(self, client: socket.socket):
print(self.recv(client))
self.send(client, "Hello World")
print(self.recv(client))
client.close()
class Test_client(net_module.Client):
def main(self):
self.send("Hello World")
print(self.recv())
self.close()
server = Test_server()
threading.Thread(target=server.start, args=(1,)).start()
client = Test_client()
client.main()