Морской бой с# Winforms
Делаю морской бой с двумя ботами на WinForms,которые играют друг с другом.Но результаты все естественно выводятся сразу,т.к. задержки между выстрелами нет.Надо бы сделать задержку,чтобы видно было каждый ход.Thread.sleep() вызывает зависания,если его применить. Скорее всего тут много потоков нужно,но я плохо разбираюсь в этом, поэтому прошу помощи.
SeaFight.cs:
namespace SeaFight
{
class Map
{
public static int mapSize = 10;
public static int cellSize = 30;
public static Label game_over;
public static int[,] myMap = new int[mapSize, mapSize];
public static int[,] enemyMap = new int[mapSize, mapSize];
public static Button[,] myButtons = new Button[mapSize, mapSize];
public static Button[,] enemyButtons = new Button[mapSize, mapSize];
public static void initShips(Ship[] ships)
{
Random rnd = new Random();
for (int i = 0; i < 10; i++)
{
if (i == 0)
{
ships[i] = new Ship(4, rnd.Next(2) > 0);
}
else if (i > 0 && i <= 2)
{
ships[i] = new Ship(3, rnd.Next(2) > 0);
}
else if (i > 2 && i <= 5)
{
ships[i] = new Ship(2, rnd.Next(2) > 0);
}
else if (i > 5 && i < 10)
{
ships[i] = new Ship(1, rnd.Next(2) > 0);
}
}
}
public static void positionShips(Ship[] ships, int[,] map)
{
Random rnd = new Random();
for (int i = 0; i < 10;)
{
if (ships[i].setPosition(rnd.Next(1, 11), rnd.Next(1, 11), map)) i++;
}
}
}
public partial class SeaFight : Form
{
public string alphabet = "АБВГДЕЖЗИК";
public bool isPlaying = false;
public Bot bot;
public SeaFight()
{
InitializeComponent();
this.Text = "Морской бой";
Init();
}
public void Init()
{
isPlaying = false;
CreateMaps();
bot = new Bot();
ConfigureShips();
Map.enemyMap = bot.ConfigureShips();
}
public void CreateMaps()
{
this.Width = Map.mapSize * 2 * Map.cellSize + 50;
this.Height = (Map.mapSize + 3) * Map.cellSize + 50;
for (int i = 0; i < Map.mapSize; i++)
{
for (int j = 0; j < Map.mapSize; j++)
{
Map.myMap[i, j] = 0;
Button button = new Button();
button.Location = new Point(j * Map.cellSize, i * Map.cellSize);
button.Size = new Size(Map.cellSize, Map.cellSize);
button.BackColor = Color.White;
if (j == 0 || i == 0)
{
button.BackColor = Color.Gray;
if (i == 0 && j > 0)
button.Text = alphabet[j - 1].ToString();
if (j == 0 && i > 0)
button.Text = i.ToString();
}
Map.myButtons[i, j] = button;
this.Controls.Add(button);
}
}
for (int i = 0; i < Map.mapSize; i++)
{
for (int j = 0; j < Map.mapSize; j++)
{
Map.myMap[i, j] = 0;
Map.enemyMap[i, j] = 0;
Button button = new Button();
button.Location = new Point(320 + j * Map.cellSize, i * Map.cellSize);
button.Size = new Size(Map.cellSize, Map.cellSize);
button.BackColor = Color.White;
if (j == 0 || i == 0)
{
button.BackColor = Color.Gray;
if (i == 0 && j > 0)
button.Text = alphabet[j - 1].ToString();
if (j == 0 && i > 0)
button.Text = i.ToString();
}
Map.enemyButtons[i, j] = button;
this.Controls.Add(button);
}
}
Label map1 = new Label();
map1.Text = "Player's map";
map1.Location = new Point((Map.mapSize * Map.cellSize / 2) - 40, Map.mapSize * Map.cellSize + 10);
this.Controls.Add(map1);
Label map2 = new Label();
map2.Text = "Enemy's map";
map2.Location = new Point(280 + Map.mapSize * Map.cellSize / 2, Map.mapSize * Map.cellSize + 10);
this.Controls.Add(map2);
Map.game_over = new Label();
Map.game_over.Location = new Point(120 + Map.mapSize * Map.cellSize / 2, Map.mapSize * Map.cellSize + 60);
this.Controls.Add(Map.game_over);
Button clear = new Button();
clear.Height = 30;
clear.Text = "New game";
clear.Location = new Point(280 + Map.mapSize * Map.cellSize / 2, Map.mapSize * Map.cellSize + 40);
clear.Click += Clear_Click;
this.Controls.Add(clear);
Button startButton = new Button();
startButton.Height = 30;
startButton.Text = "Начать";
startButton.Click += Start;
startButton.Location = new Point((Map.mapSize * Map.cellSize / 2) - 40, Map.mapSize * Map.cellSize + 40);
this.Controls.Add(startButton);
}
private void Clear_Click(object? sender, EventArgs e)
{
this.Controls.Clear();
Init();
}
public void Start(object sender, EventArgs e)
{
isPlaying = true;
PlayerShoot();
}
public bool CheckIfMapIsNotEmpty()//is map empty
{
bool isEmpty1 = true;
bool isEmpty2 = true;
for (int i = 1; i < Map.mapSize; i++)
{
for (int j = 1; j < Map.mapSize; j++)
{
if (Map.myMap[i, j] != 0)
isEmpty1 = false;
if (Map.enemyMap[i, j] != 0)
isEmpty2 = false;
}
}
if (isEmpty1 || isEmpty2)
return false;
else return true;
}
public int[,] ConfigureShips()
{
Ship[] ships = new Ship[10];
Map.initShips(ships);
Map.positionShips(ships, Map.myMap);
return Map.myMap;
}
public void PlayerShoot()
{
if (isPlaying)
{
while (Map.game_over.Text == "")
{
Random r = new Random();
int posX = r.Next(1, Map.mapSize);
int posY = r.Next(1, Map.mapSize);
while (Map.enemyButtons[posX, posY].BackColor == Color.Blue || Map.enemyButtons[posX, posY].BackColor == Color.Black)
{
posX = r.Next(1, Map.mapSize);
posY = r.Next(1, Map.mapSize);
}
Button pressedButton = Map.enemyButtons[posX, posY];
bool playerTurn = Shoot(pressedButton);
bool you_win = true;
bool enemy_win = true;
for (int i = 0; i < Map.mapSize - 1; i++)
{
for (int j = 0; j < Map.mapSize - 1; j++)
{
if (Map.myMap[i, j] == 1 && Map.myButtons[i, j].Text != "X")//если найден неподбитый корабль
{
you_win = false;
break;
}
}
}
for (int i = 0; i < Map.mapSize - 1; i++)
{
for (int j = 0; j < Map.mapSize - 1; j++)
{
if (Map.enemyMap[i, j] == 1 && Map.enemyButtons[i, j].Text != "X")//если найден неподбитый корабль
{
enemy_win = false;
break;
}
}
}
if (you_win || enemy_win)
{
if (you_win)
{
Map.game_over.Text = "Bot №1 win";
Map.game_over.BackColor = Color.Green;
break;
}
if (enemy_win)
{
Map.game_over.Text = "Bot №2 win";
Map.game_over.BackColor = Color.Green;
break;
}
}
}
}
}
public bool Shoot(Button pressedButton)
{
bool hit = false;
if (isPlaying)
{
int delta = 0;
if (pressedButton.Location.X > 320)
delta = 320;
if (Map.enemyMap[pressedButton.Location.Y / Map.cellSize, (pressedButton.Location.X - delta) / Map.cellSize] != 0)
{
hit = true;
Map.enemyMap[pressedButton.Location.Y / Map.cellSize, (pressedButton.Location.X - delta) / Map.cellSize] = 0;
pressedButton.BackColor = Color.Red;
pressedButton.Text = "X";
}
else
{
hit = false;
if (pressedButton.BackColor != Color.Black&& pressedButton.BackColor != Color.Red) bot.Shoot();
if (pressedButton.BackColor!=Color.Red) pressedButton.BackColor = Color.Black;
}
}
return hit;
}
}
}
Bot.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SeaFight
{
public class Bot
{
public int[,] myMap = new int[Map.mapSize, Map.mapSize];//bot`s map
public int[,] enemyMap = new int[Map.mapSize, Map.mapSize];//player`s map
public Button[,] myButtons = new Button[Map.mapSize, Map.mapSize];//bot's cells
public Button[,] enemyButtons = new Button[Map.mapSize, Map.mapSize];//player's cells
public Bot()
{
this.myMap = Map.enemyMap;
this.enemyMap = Map.myMap;
this.enemyButtons = Map.myButtons;
this.myButtons = Map.enemyButtons;
}
public bool IsInsideMap(int i, int j)//check valid cell
{
if (i < 0 || j < 0 || i >= Map.mapSize || j >= Map.mapSize)
{
return false;
}
return true;
}
public bool IsEmpty(int i, int j, int length)//check empty cell
{
bool isEmpty = true;
for (int k = j; k < j + length; k++)
{
if (myMap[i, k] != 0)
{
isEmpty = false;
break;
}
}
return isEmpty;
}
public int[,] ConfigureShips()
{
Ship[] ships = new Ship[10];
Map.initShips(ships);
Map.positionShips(ships, myMap);
return myMap;
}
public bool Shoot()
{
bool hit = false;
Random r = new Random();
int posX = r.Next(1, Map.mapSize);
int posY = r.Next(1, Map.mapSize);
while (enemyButtons[posX, posY].BackColor == Color.Blue || enemyButtons[posX, posY].BackColor == Color.Black)
{
posX = r.Next(1, Map.mapSize);
posY = r.Next(1, Map.mapSize);
}
if (enemyMap[posX, posY] != 0)
{
hit = true;
enemyMap[posX, posY] = 0;
enemyButtons[posX, posY].BackColor = Color.Blue;
enemyButtons[posX, posY].Text = "X";
}
else
{
hit = false;
enemyButtons[posX, posY].BackColor = Color.Black;
}
if (hit) {
Shoot();
}
return hit;
}
}
}
Ship.cs:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SeaFight
{
class Ship
{
private int[,] configMap;
private int size;
private bool horizont;
public bool Horizont
{
get { return horizont; }
set { horizont = value; }
}
public Ship(int size, bool horizont) {
this.size = size;
configMap = new int[10, 10];
this.horizont = horizont;
clearShip();
}
public bool setPosition(int x, int y, int[,] map) // set x,y from 1 to 10
{
if (map[y-1, x-1] != 1 && size != 1)
{
if (horizont)
{
if ((x + size) < 10 - 1)
{
for (int i = 0; i < size; i++)
{
if (scanAround(x + i, y, map) == false)
{
return false;
}
}
for (int i = 0; i < size; i++)
{
configMap[y, x + i] = 1;
}
setMap(map);
return true;
}
else
{
return false;
}
}
else
{
if ((y + size) < 10 - 1)
{
for (int i = 0; i < size; i++)
{
if (scanAround(x, y + i, map) == false)
{
return false;
}
}
for (int i = 0; i < size; i++)
{
configMap[y + i, x] = 1;
}
setMap(map);
return true;
}
else
{
return false;
}
}
}
else if (map[y-1, x-1] != 1 && size == 1)
{
if (scanAround(x, y, map))
{
configMap[y, x] = 1;
setMap(map);
return true;
}
else {
return false;
}
}
else
return false;
}
public int[,] getConfigMap() {
return configMap;
}
private bool scanAround(int x, int y, int[,] map) {
try
{
if (
map[y, x + 1] != 1 && map[y + 1, x + 1] != 1 &&
map[y + 1, x] != 1 && map[y + 1, x - 1] != 1 &&
map[y, x - 1] != 1 && map[y - 1, x - 1] != 1 &&
map[y - 1, x] != 1 && map[y - 1, x + 1] != 1)
{
return true;
}
else
{
return false;
}
}
catch (Exception ) { }
return false;
}
public void setMap(int[,] map)
{
for (int i = 1; i < 10 - 1; i++)
{
for (int j = 1; j < 10 - 1; j++)
{
if (getConfigMap()[i, j] == 1)
map[i, j] = 1;
}
}
}
public void clearShip() {
for (int i = 0; i < 10; i++)
{
for (int j = 0; j <10; j++)
{
configMap[j, i] = 0;
}
}
}
}
}
Ответы (1 шт):
Автор решения: ACTAVexe
→ Ссылка
Сделай в конструкторе своей формы timer и сделай ему тик как тебе надо(по умолчанию там 100 мили секунд или 0,1 секунды) поставь Enable true и сделай событие tick там где и делай что либо со своей игрой. Это всё без потоков если что.