11 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
20241144010020 26645d8d0b Adicionar modo de ganhar e melhorar barcos 2024-11-21 13:57:29 -03:00
20241144010020 3062b0e853 Consertar um monte de coisa 2024-11-21 13:52:20 -03:00
6 changed files with 310 additions and 50 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
# 20241144010013 # Sobre
Repositorio que contem uma versão **MELHORADA** de batalha naval.
# Repository for random Projects that run through my mind
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()
+81 -47
View File
@@ -1,15 +1,29 @@
#setup #setup
import turtle as tl import turtle as tl
import random import random, sys
posx = [-200, -100, 0, 100, 200] args = sys.argv
posy = [-200, -100, 0, 100, 200] # 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]
postiro = [] postiro = []
for i in range(5): for i in range(len(posx)):
for j in range(5): for j in range(len(posy)):
postiro.append(f"{(i-2) * 100} {(j-2) * 100}") postiro.append(f"{i-2} {j-2}")
print((i-2) * 100, (j-2) * 100)
#postiro = ['-200 -200', '-200 -100', '-200 0', '-200 100', '-200 200', '-100 -200', '-100 -100', '-100 0', '-100 100', '-100 200', '0 -200', '0 -100', '0 0', '0 100', '0 200', '100 -200', '100 -100', '100 0', '100 100', '100 200', '200 -200', '200 -100', '200 0', '200 100', '200 200']
tl.setup(650,650,None,None) tl.setup(650,650,None,None)
tl.title("Naval Battle 1943 Loading...") tl.title("Naval Battle 1943 Loading...")
@@ -17,15 +31,17 @@ tl.speed(0)
#funções #funções
def linhax(x,y): def linhax(x: int, y: int) -> None:
tl.up(); tl.goto(x,y) tl.up()
tl.down(); tl.goto(x+600,y) tl.goto(x,y)
pass tl.down()
tl.goto(x+600,y)
def linhay(x,y): def linhay(x: int, y: int) -> None:
tl.up(); tl.goto(x,y) tl.up()
tl.down(); tl.goto(x,y+600) tl.goto(x,y)
pass tl.down()
tl.goto(x,y+600)
#radar screen #radar screen
@@ -39,58 +55,76 @@ linhax(-300,300)
#linhas X #linhas X
for i in range(5): for i in range(5):
linhax(-300, (i-2)*100) linhax(-300, (i-2)*100)
tl.write(str((i-2) * 100), False, align="right") tl.write(num2char(i), False, align="right")
#linhas Y #linhas Y
for i in range(5): for i in range(5):
linhay((i-2)*100, -300) linhay((i-2)*100, -300)
tl.write(str((i-2) * 100), False, align="right") tl.write(str(i), False, align="right")
#Tabuleiro pronto #Tabuleiro pronto
tl.title("Naval Battle 1943") tl.title("Naval Battle 1943")
tl.hideturtle() tl.hideturtle()
boat = tl.Turtle() boat = tl.Turtle()
boat.up(); boat.goto(0,0); boat.left(90) boat.shapesize(3, 3)
boat.up()
boat.goto(0,0)
boat.left(90)
#Enemies #Enemies
e1 = tl.Turtle() AMOUNT_OF_ENEMIES = 3
e1.up() enemies = []
e1.color("red")
e1.goto(-100,-100)
for i in range(AMOUNT_OF_ENEMIES):
enemy = tl.Turtle()
enemy.color("red")
enemy.up()
e2 = tl.Turtle() if not has_argument(args, "D"):
e2.up() enemy.hideturtle()
e2.color("red") else:
e2.goto(random.choice(posx), random.choice(posy)) enemy.shapesize(3, 3)
if e1.pos() == e2.pos():
e2.goto(random.choice(posx), random.choice(posy)) pos = [random.choice(posy), random.choice(posy)]
enemy.goto((pos[0] - 2) * 100, (pos[1] - 2) * 100)
e3 = tl.Turtle() enemies.append([enemy, pos])
e3.up()
e3.color("red")
e3.goto(random.choice(posx), random.choice(posy))
if e1.pos() == e3.pos():
e3.goto(random.choice(posx), random.choice(posy))
if e2.pos() == e3.pos():
e3.goto(random.choice(posx), random.choice(posy))
#partidas #partidas
win = False win = False
while win == False: while win == False:
tirox = tl.numinput("linha X do disparo","Em qual quadrante X devemos disparar a artilharia") 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")
if (tirox,tiroy) == e1.pos(): tiroy = char2num(tiroy.upper())
boat.goto(tirox,tiroy)
if tirox == None or tiroy == None:
tl.exitonclick()
boat.goto((tirox - 2) * 100, (tiroy - 2) * 100)
acerto = False
for enemy in enemies:
if [tirox,tiroy] == enemy[1]:
hit_enemy: list[tl.Turtle, list[int, int]] = enemy
acerto = True
break
if acerto:
print("Acerto!") print("Acerto!")
boat.write("U-boat Afundado\n Capitão!",False,align="center") boat.write("U-boat Afundado\n Capitão!",False,align="center")
break
hit_enemy[0].hideturtle()
enemies.remove(hit_enemy)
else: else:
boat.goto(tirox,tiroy)
print("errou!") print("errou!")
boat.write("Erramos o alvo\n Capitão!",False,align="center") boat.write("Erramos o alvo\n Capitão!",False,align="center")
continue acerto = False
if len(enemies) <= 0: # tamanho negativo???
win = True
print("Você ganhou!!")
#Execução
tl.mainloop()
tl.exitonclick() 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()