Can’t place a ship part next to another part

I started working on a project in C# using Windows Forms, making a sea battle game.

How my game works:

When the program starts, a dialog is displayed where we have two options:
-Player vs player
-Player vs computer

After that dialog, another dialog appears where we choose the following:

4×4
8×8
10×10
(what dimensions do we want the fields to be when we place the ships)

Then, after that selection, a dialog appears with the display of those fields and it looks like this:

For example I chose 4×4:

4×4 field

I will give an example and what is the output:

I choose a 4×4 field for placing ships (one size 1 ship and two size 2 ships are placed on a 4×4 field)

First I was offered a size 1 ship.

I set it at the following coordinates i=0, j=0 (i is a column, j is a row) Size 1 ship placed

Then after that it’s the turn of the size 2 ship, and now I need to place that ship.

I place the first part of the ship at i = 2, j =0, and place it successfully. First part of size 2 ship placed

Then I try to place another part of that ship (size 2) at i = 2, j =1, unsuccessfully it says “you cannot place a part of the ship at this position try again” unsuccessful

I also try to set that other part of the ship to i = 3, j = 0, but it still fails. unsuccessful

I’ve been trying to solve the problem for an hour now, but I don’t know where the error/bug is and why it’s not working.

Here is the code of that class:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace oop_template
{
    public partial class ShipPlacementForm : Form
    {
        private int tableSize;
        private List<Ship> ships;
        private List<Ship> placedShips;
        private Button[,] tableButtons;
        private int currentShipIndex;
        private Ship currentShip;
        private bool horizontalPlacement;

        public List<Ship> PlacedShips
        {
            get { return placedShips; }
        }

        public ShipPlacementForm(int tableSize, List<Ship> ships)
        {
            this.tableSize = tableSize;
            this.ships = ships;
            this.placedShips = new List<Ship>();
            CustomInitializeComponent();

            // Initialize placement of the first ship
            this.currentShipIndex = 0;
            SetCurrentShip();
            deleteButton.Enabled = false; // Disable delete until at least one ship is placed
        }

        private void CustomInitializeComponent()
        {
            this.SuspendLayout();

            // Dynamically create buttons for the table fields
            tableButtons = new Button[tableSize, tableSize];
            for (int i = 0; i < tableSize; i++)
            {
                for (int j = 0; j < tableSize; j++)
                {
                    tableButtons[i, j] = new Button();
                    tableButtons[i, j].Size = new Size(30, 30);
                    tableButtons[i, j].Location = new Point(30 * i, 30 * j);
                    tableButtons[i, j].Click += new EventHandler(TableButton_Click);
                    this.Controls.Add(tableButtons[i, j]);
                }
            }

            // Label for displaying the current ship
            this.currentShipLabel = new Label();
            this.currentShipLabel.Location = new Point(30 * tableSize, 30);
            this.currentShipLabel.AutoSize = true;
            this.Controls.Add(this.currentShipLabel);

            // Button for confirmation
            this.confirmButton = new Button();
            this.confirmButton.Text = "Confirm";
            this.confirmButton.Location = new Point(30 * tableSize, 60);
            this.confirmButton.Click += new EventHandler(ConfirmButton_Click);
            this.confirmButton.Enabled = false; // Disabled until all ships are placed
            this.Controls.Add(this.confirmButton);

            // Button for deleting a ship
            this.deleteButton = new Button();
            this.deleteButton.Text = "Delete Ship";
            this.deleteButton.Location = new Point(30 * tableSize, 90);
            this.deleteButton.Click += new EventHandler(DeleteButton_Click);
            this.deleteButton.Enabled = false; // Disabled until at least one ship is placed
            this.Controls.Add(this.deleteButton);

            // Set form size
            this.ClientSize = new System.Drawing.Size(30 * (tableSize + 2), 30 * tableSize);
            this.Name = "ShipPlacementForm";
            this.Text = "Ship Placement";
            this.ResumeLayout(false);
            this.PerformLayout();
        }

        private void TableButton_Click(object sender, EventArgs e)
        {
            Button clickedButton = sender as Button;
            if (clickedButton == null)
                return;

            int x = clickedButton.Location.X / 30;
            int y = clickedButton.Location.Y / 30;

            if (CanPlaceShipPart(x, y))
            {
                PlaceShipPart(x, y);
                currentShip.Positions.Add(new Point(x, y));

                if (currentShip.Positions.Count == 1)
                {
                    // First part of the ship is placed, wait for the second part to determine orientation
                    deleteButton.Enabled = false; // Disable deletion until the entire ship is placed
                }
                else if (currentShip.Positions.Count == 2)
                {
                    // Determine the orientation of the ship based on the first two positions
                    horizontalPlacement = currentShip.Positions[0].Y == currentShip.Positions[1].Y;
                }

                // Check if the ship is complete
                if (currentShip.Positions.Count == currentShip.Size)
                {
                    placedShips.Add(currentShip);
                    currentShipIndex++;

                    if (currentShipIndex < ships.Count)
                    {
                        SetCurrentShip();
                    }
                    else
                    {
                        currentShipLabel.Text = "All ships are placed.";
                        confirmButton.Enabled = true;
                        deleteButton.Enabled = true;
                    }
                }
            }
            else
            {
                MessageBox.Show("You cannot place a ship part on this position. Please try again.");
            }
        }

        private void DeleteButton_Click(object sender, EventArgs e)
        {
            currentShipLabel.Text = "Click on any part of the ship you want to delete.";
            foreach (var ship in placedShips)
            {
                foreach (var position in ship.Positions)
                {
                    tableButtons[position.X, position.Y].Click += DeleteShipClick;
                }
            }
        }

        private void DeleteShipClick(object sender, EventArgs e)
        {
            Button clickedButton = sender as Button;
            if (clickedButton == null)
                return;

            int x = clickedButton.Location.X / 30;
            int y = clickedButton.Location.Y / 30;

            Ship shipToDelete = null;

            foreach (var ship in placedShips)
            {
                if (ship.Positions.Contains(new Point(x, y)))
                {
                    shipToDelete = ship;
                    break;
                }
            }

            if (shipToDelete != null)
            {
                DeleteShip(shipToDelete);
                currentShipLabel.Text = $"Place a ship of size {shipToDelete.Size}";
                currentShip = shipToDelete;
                currentShipIndex = ships.IndexOf(shipToDelete);

                foreach (var position in shipToDelete.Positions)
                {
                    tableButtons[position.X, position.Y].Click -= DeleteShipClick;
                }
            }

            deleteButton.Enabled = placedShips.Count > 0;
        }

        private void DeleteShip(Ship ship)
        {
            foreach (var position in ship.Positions)
            {
                tableButtons[position.X, position.Y].BackColor = default(Color);
                tableButtons[position.X, position.Y].Enabled = true;
            }
            placedShips.Remove(ship);
            ships.Insert(currentShipIndex, ship); // Return the ship to the list for re-placement
        }

        private void ConfirmButton_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;
            this.Close();
        }

        private void SetCurrentShip()
        {
            currentShip = ships[currentShipIndex];
            currentShip.Positions.Clear();
            currentShipLabel.Text = $"Place a ship of size {currentShip.Size}";
            deleteButton.Enabled = placedShips.Count > 0;
        }

        private bool CanPlaceShipPart(int x, int y)
        {
            if (tableButtons[x, y].BackColor == Color.Gray)
                return false; // The field is already taken

            // Check continuity of ship placement
            if (currentShip.Positions.Count > 0)
            {
                var lastPos = currentShip.Positions[currentShip.Positions.Count - 1];

                // Check if the second part of the ship can be placed next to the first one
                bool validHorizontalPos = (x == lastPos.X && Math.Abs(y - lastPos.Y) == 1);
                bool validVerticalPos = (y == lastPos.Y && Math.Abs(x - lastPos.X) == 1);

                if (validHorizontalPos || validVerticalPos)
                {
                    // Check if the adjacent field is taken
                    foreach (var (dx, dy) in new[] { (-1, 0), (1, 0), (0, -1), (0, 1) })
                    {
                        int nx = x + dx;
                        int ny = y + dy;

                        if (nx >= 0 && nx < tableSize && ny >= 0 && ny < tableSize)
                        {
                            if (tableButtons[nx, ny].BackColor == Color.Gray)
                                return false; // The adjacent field is taken
                        }
                    }

                    return true;
                }
                else
                {
                    return false;
                }
            }

            return true;
        }

        private void PlaceShipPart(int x, int y)
        {
            tableButtons[x, y].BackColor = Color.Gray; // Color the field gray
            tableButtons[x, y].Enabled = false; // Disable clicking on the same field again
        }

        private Label currentShipLabel;
        private Button confirmButton;
        private Button deleteButton;
    }
}

Thank you for your time.

PS: sorry if I am grammatically incorrect somewhere, English is not my native language

New contributor

Огњен Стојановић is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật