Csata mód működőképes, az AI le tud rakni hajókat

git-tfs-id: [https://sznp.visualstudio.com/DefaultCollection/]$/Torpedo;C13
This commit is contained in:
Norbi Peti 2016-03-16 19:08:39 +00:00
parent d413d77a63
commit d6fe86e650
11 changed files with 291 additions and 33 deletions

View file

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Torpedo
{
public static class AIPlayer
{
private static Random rand = new Random();
public static void PlaceShips()
{
while (Player.Player2.NextShip != -1)
{
int x = rand.Next(Game.GameSize.Width);
int y = rand.Next(Game.GameSize.Height);
bool vertical = rand.Next(2) == 0;
Ship ship = new Ship(x, y, Player.Player2.NextShip, (vertical ? ShipDirection.Vertical : ShipDirection.Horizontal), Player.Player2);
if (!Ship.CheckHasShip(ship))
{
Player.Player2.Ships.Add(ship);
}
}
}
public static void Attack()
{
//TODO
}
}
}

View file

@ -18,7 +18,7 @@ namespace Torpedo
private static ReadOnlyDictionary<FieldTypeEnemy, Color> FieldTypes = new ReadOnlyDictionary<FieldTypeEnemy, Color>(new Dictionary<FieldTypeEnemy, Color>() private static ReadOnlyDictionary<FieldTypeEnemy, Color> FieldTypes = new ReadOnlyDictionary<FieldTypeEnemy, Color>(new Dictionary<FieldTypeEnemy, Color>()
{ {
{FieldTypeEnemy.Targeted, Color.LightBlue}, {FieldTypeEnemy.Missed, Color.LightBlue},
{FieldTypeEnemy.TargetHit, Color.Red}, {FieldTypeEnemy.TargetHit, Color.Red},
{FieldTypeEnemy.EnemyShipDestroyed, Color.Black} {FieldTypeEnemy.EnemyShipDestroyed, Color.Black}
}); });
@ -31,25 +31,35 @@ namespace Torpedo
public override void RenderShip(Ship ship) public override void RenderShip(Ship ship)
{ {
//TODO: Képek az egyes hajótípusokhoz //TODO: Képek az egyes hajótípusokhoz
bool destroyed = ship.DamagedParts.All(p => p);
for (int i = 0; i < ship.Size; i++) for (int i = 0; i < ship.Size; i++)
{ {
FieldTypeEnemy ft = FieldTypeEnemy.Missed;
if (destroyed)
ft = FieldTypeEnemy.EnemyShipDestroyed;
else if (ship.DamagedParts[i])
ft = FieldTypeEnemy.TargetHit;
if (ft == FieldTypeEnemy.Missed) //A Missed itt nem használható, ezért alapértelmezett értékként van használva
continue; //Nem rajzolja meg a sértetlen hajókat és hajórészeket
if (ship.Direction == ShipDirection.Horizontal) if (ship.Direction == ShipDirection.Horizontal)
UpdateField(ship.X + i, ship.Y, FieldTypeEnemy.Targeted); UpdateField(ship.X + i, ship.Y, ft);
else else
UpdateField(ship.X, ship.Y + i, FieldTypeEnemy.Targeted); UpdateField(ship.X, ship.Y + i, ft);
} }
//TODO: Rárajzolni a képet a mezőkre //TODO: Rárajzolni a képet a mezőkre
} }
public override void RenderGameField() public override void RenderGameField()
{ {
Player.Player2.Ships.ForEach(s => RenderShip(s)); Player.CurrentEnemy.Ships.ForEach(s => RenderShip(s));
Player.CurrentOwn.Shots.ForEach(s => UpdateField(s.X, s.Y, FieldTypeEnemy.Missed));
} }
} }
public enum FieldTypeEnemy public enum FieldTypeEnemy
{ {
Targeted, Missed,
TargetHit, TargetHit,
EnemyShipDestroyed EnemyShipDestroyed
} }

View file

@ -4,6 +4,7 @@ using System.Drawing;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms;
namespace Torpedo namespace Torpedo
{ {
@ -14,10 +15,10 @@ namespace Torpedo
/// </summary> /// </summary>
public static Size GameSize { get; private set; } = new Size(10, 10); public static Size GameSize { get; private set; } = new Size(10, 10);
/// <summary> /*/// <summary>
/// A jelenlegi játékos /// A jelenlegi játékos
/// </summary> /// </summary>
public static Player CurrentPlayer = Player.Player1; public static Player CurrentPlayer = Player.Player1;*/
private static GameType type = GameType.Singleplayer; private static GameType type = GameType.Singleplayer;
/// <summary> /// <summary>
@ -42,10 +43,113 @@ namespace Torpedo
/// </summary> /// </summary>
public static event EventHandler<GameTypeChangeEventArgs> GameTypeChange; public static event EventHandler<GameTypeChangeEventArgs> GameTypeChange;
/// <summary>
/// A játék állapotának változásakor hívódik meg (Prepare, Battle)
/// </summary>
public static event EventHandler<GameStateChangeEventArgs> GameStateChange;
private static GameState state = GameState.Prepare;
/// <summary> /// <summary>
/// A játék állapota /// A játék állapota
/// </summary> /// </summary>
public static GameState State { get; set; } = GameState.Prepare; public static GameState State
{
get
{
return state;
}
set
{
state = value;
if (GameStateChange != null)
GameStateChange(null, new GameStateChangeEventArgs(value));
}
}
public static void NextTurn()
{
if (State == GameState.Prepare)
{
if (Player.CurrentOwn == Player.Player1)
{
if (Type == GameType.Singleplayer)
{
Player.SwapPlayers();
AIPlayer.PlaceShips();
State = GameState.Battle;
Player.SwapPlayers();
}
}
else if (Type == GameType.Multiplayer)
{
Player.SwapPlayers();
State = GameState.Battle;
}
else
throw new InvalidOperationException("Az első játékos csak egyszer rakhat le hajókat.");
if (Type == GameType.Multiplayer)
{
GameForm.Instance.SetPanelsVisible(false);
GameRenderer.Own.RenderLines();
GameRenderer.Enemy.RenderLines();
Timer t = new Timer();
t.Interval = 2000;
t.Tick += delegate
{
t.Stop();
Player.SwapPlayers();
GameRenderer.Own.RenderGameField();
GameRenderer.Enemy.RenderGameField();
GameForm.Instance.SetPanelsVisible(true);
};
t.Start();
}
}
else
{
if (Player.CurrentEnemy.Ships.All(s => s.DamagedParts.All(d => d)))
{
MessageBox.Show("Győzelem!");
GameForm.Instance.Reset();
return;
}
if (Type == GameType.Singleplayer)
{
Player.SwapPlayers();
if (Player.CurrentOwn == Player.Player2)
AIPlayer.PlaceShips();
Player.SwapPlayers();
}
else if (Type == GameType.Multiplayer)
{
Timer t = new Timer();
t.Interval = 2000;
int c = 0;
GameForm.Instance.SetPanelsEnabled(false);
t.Tick += delegate
{
if (c >= 1) //Kétszer fut le
{
t.Stop();
Player.SwapPlayers();
GameRenderer.Own.RenderGameField();
GameRenderer.Enemy.RenderGameField();
GameForm.Instance.SetPanelsVisible(true);
GameForm.Instance.SetPanelsEnabled(true);
}
else
{
GameForm.Instance.SetPanelsVisible(false);
GameRenderer.Own.RenderLines();
GameRenderer.Enemy.RenderLines();
c++;
}
};
t.Start();
}
}
}
static Game() static Game()
{ {
@ -54,8 +158,7 @@ namespace Torpedo
private static void Game_GameTypeChange(object sender, GameTypeChangeEventArgs e) private static void Game_GameTypeChange(object sender, GameTypeChangeEventArgs e)
{ {
State = GameState.Prepare; //TODO State = GameState.Prepare;
CurrentPlayer = Player.Player1;
} }
} }

View file

@ -87,6 +87,7 @@
this.enemyPanel.Name = "enemyPanel"; this.enemyPanel.Name = "enemyPanel";
this.enemyPanel.Size = new System.Drawing.Size(300, 300); this.enemyPanel.Size = new System.Drawing.Size(300, 300);
this.enemyPanel.TabIndex = 1; this.enemyPanel.TabIndex = 1;
this.enemyPanel.Click += new System.EventHandler(this.enemyPanel_Click);
this.enemyPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.enemyPanel_Paint); this.enemyPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.enemyPanel_Paint);
// //
// shipSizeLabel // shipSizeLabel

View file

@ -23,14 +23,40 @@ namespace Torpedo
Instance = this; Instance = this;
Game.GameTypeChange += Game_GameTypeChange; Game.GameTypeChange += Game_GameTypeChange;
Game.Type = GameType.Singleplayer; Game.Type = GameType.Singleplayer;
Game.GameStateChange += Game_GameStateChange;
}
public void SetPanelsEnabled(bool enabled)
{
ownPanel.Enabled = enabled;
enemyPanel.Enabled = enabled;
}
public void SetPanelsVisible(bool visible)
{
ownPanel.Visible = visible;
enemyPanel.Visible = visible;
}
public void Reset()
{
egyjátékosToolStripMenuItem.Enabled = true;
egyjátékosToolStripMenuItem.PerformClick();
GameRenderer.Own.RenderGame();
GameRenderer.Enemy.RenderGame();
} }
private void Game_GameTypeChange(object sender, GameTypeChangeEventArgs e) private void Game_GameTypeChange(object sender, GameTypeChangeEventArgs e)
{ {
egyjátékosToolStripMenuItem.Enabled = false; egyjátékosToolStripMenuItem.Enabled = false;
többjátékosToolStripMenuItem.Enabled = false; többjátékosToolStripMenuItem.Enabled = false;
if (Player.Player1.NextShip != -1) moveUpButton.Enabled = true;
shipSizeLabel.Text = "Következő hajó: " + Player.Player1.NextShip; moveDownButton.Enabled = true;
moveLeftButton.Enabled = true;
moveRightButton.Enabled = true;
rotateButton.Enabled = true;
if (Player.CurrentOwn.NextShip != -1)
shipSizeLabel.Text = "Következő hajó: " + Player.CurrentOwn.NextShip;
else else
shipSizeLabel.Text = ""; shipSizeLabel.Text = "";
switch(e.NewValue) switch(e.NewValue)
@ -67,20 +93,23 @@ namespace Torpedo
{ {
if (Game.State != GameState.Prepare) if (Game.State != GameState.Prepare)
return; return;
if (Player.Player1.NextShip == -1) if (Player.CurrentOwn.NextShip == -1)
return; return;
Point clickedfield = GameRenderer.Own.PixelsToFields(ownPanel.PointToClient(Cursor.Position)); Point clickedfield = GameRenderer.Own.PixelsToFields(ownPanel.PointToClient(Cursor.Position));
Ship ship = new Ship(clickedfield.X, clickedfield.Y, Game.CurrentPlayer.NextShip, ShipDirection.Horizontal, false); Ship ship = new Ship(clickedfield.X, clickedfield.Y, Player.CurrentOwn.NextShip, ShipDirection.Horizontal, Player.CurrentOwn);
if (Ship.CheckHasShip(ship)) if (Ship.CheckHasShip(ship))
return; return;
Game.CurrentPlayer.Ships.Add(ship); Player.CurrentOwn.Ships.Add(ship);
GameRenderer.Own.RenderShip(ship); GameRenderer.Own.RenderShip(ship);
lastship = ship; lastship = ship;
//TODO if (Player.CurrentOwn.NextShip != -1)
if (Player.Player1.NextShip != -1) shipSizeLabel.Text = "Következő hajó: " + Player.CurrentOwn.NextShip;
shipSizeLabel.Text = "Következő hajó: " + Player.Player1.NextShip;
else else
{
shipSizeLabel.Text = ""; shipSizeLabel.Text = "";
lastship = null;
Game.NextTurn();
}
} }
private void MoveShip(object sender, EventArgs e) private void MoveShip(object sender, EventArgs e)
@ -105,5 +134,35 @@ namespace Torpedo
lastship.Rotate(); lastship.Rotate();
} }
} }
private void enemyPanel_Click(object sender, EventArgs e)
{
if (Game.State != GameState.Battle)
return;
Point clickedfield = GameRenderer.Enemy.PixelsToFields(enemyPanel.PointToClient(Cursor.Position));
Ship ship = Ship.GetShipAtField(Player.CurrentEnemy, clickedfield.X, clickedfield.Y);
if (ship == null)
{
Player.CurrentOwn.Shots.Add(clickedfield);
}
else
{
if (ship.Direction == ShipDirection.Horizontal)
ship.DamagedParts[clickedfield.X - ship.X] = true;
else
ship.DamagedParts[clickedfield.Y - ship.Y] = true;
}
GameRenderer.Enemy.RenderGameField();
Game.NextTurn();
}
private void Game_GameStateChange(object sender, GameStateChangeEventArgs e)
{
moveUpButton.Enabled = false;
moveDownButton.Enabled = false;
moveLeftButton.Enabled = false;
moveRightButton.Enabled = false;
rotateButton.Enabled = false;
}
} }
} }

View file

@ -31,7 +31,7 @@ namespace Torpedo
RenderLines(); RenderLines();
RenderGameField(); RenderGameField();
} }
private void RenderLines() public void RenderLines()
{ {
using (Graphics gr = Parent.CreateGraphics()) using (Graphics gr = Parent.CreateGraphics())
{ {

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Torpedo
{
public class GameStateChangeEventArgs : EventArgs
{
public GameState NewState;
public GameStateChangeEventArgs(GameState newstate)
{
NewState = newstate;
}
}
}

View file

@ -42,7 +42,7 @@ namespace Torpedo
public override void RenderGameField() public override void RenderGameField()
{ {
Player.Player1.Ships.ForEach(s => RenderShip(s)); //TODO Player.CurrentOwn.Ships.ForEach(s => RenderShip(s));
} }
} }

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -11,9 +12,9 @@ namespace Torpedo
/// <summary> /// <summary>
/// <para>Az első játékos</para> /// <para>Az első játékos</para>
/// </summary> /// </summary>
public static Player Player1 { get; set; } public static Player Player1 { get; set; } = new Player();
private static Player p2; private static Player p2 = new Player();
/// <summary> /// <summary>
/// <para>A második játékos</para> /// <para>A második játékos</para>
/// </summary> /// </summary>
@ -29,6 +30,34 @@ namespace Torpedo
} }
} }
private static bool swapped = false;
/// <summary>
/// Az aktuális játékos
/// </summary>
public static Player CurrentOwn
{
get
{
return (swapped ? Player2 : Player1);
}
}
/// <summary>
/// Az aktuális ellenfél
/// </summary>
public static Player CurrentEnemy
{
get
{
return (swapped ? Player1 : Player2);
}
}
public static void SwapPlayers()
{
swapped = !swapped;
}
static Player() static Player()
{ {
Game.GameTypeChange += Game_GameTypeChange_Global; Game.GameTypeChange += Game_GameTypeChange_Global;
@ -38,6 +67,7 @@ namespace Torpedo
{ {
Player1 = new Player(); Player1 = new Player();
Player2 = new Player(); Player2 = new Player();
swapped = false;
} }
/// <summary> /// <summary>
@ -73,5 +103,7 @@ namespace Torpedo
return -1; return -1;
} }
} }
public List<Point> Shots = new List<Point>();
} }
} }

View file

@ -25,15 +25,22 @@ namespace Torpedo
} }
public ShipDirection Direction { get; set; } public ShipDirection Direction { get; set; }
public bool[] DamagedParts; public bool[] DamagedParts;
public bool Enemy; public Player Owner;
public bool Enemy
{
get
{
return Owner == Player.CurrentEnemy;
}
}
public Ship(int x, int y, int size, ShipDirection direction, bool enemy) public Ship(int x, int y, int size, ShipDirection direction, Player owner)
{ {
X = x; X = x;
Y = y; Y = y;
Size = size; //A DamagedParts-ot is inicializálja Size = size; //A DamagedParts-ot is inicializálja
Direction = direction; Direction = direction;
Enemy = enemy; Owner = owner;
} }
/// <summary> /// <summary>
@ -97,7 +104,7 @@ namespace Torpedo
{ {
if (dircheck) if (dircheck)
{ {
Ship ship2 = GetShipAtField(ship.Enemy, ship.X + dx + i, ship.Y + dy); Ship ship2 = GetShipAtField(ship.Owner, ship.X + dx + i, ship.Y + dy);
if (ship2 != null && ship2 != ship) if (ship2 != null && ship2 != ship)
{ {
hasship = true; hasship = true;
@ -106,7 +113,7 @@ namespace Torpedo
} }
else else
{ {
Ship ship2 = GetShipAtField(ship.Enemy, ship.X + dx, ship.Y + dy + i); Ship ship2 = GetShipAtField(ship.Owner, ship.X + dx, ship.Y + dy + i);
if (ship2 != null && ship2 != ship) if (ship2 != null && ship2 != ship)
{ {
hasship = true; hasship = true;
@ -117,13 +124,8 @@ namespace Torpedo
return hasship; return hasship;
} }
public static Ship GetShipAtField(bool enemy, int x, int y) public static Ship GetShipAtField(Player player, int x, int y)
{ {
Player player = null;
if (enemy)
player = Player.Player2;
else
player = Player.Player1;
return player.Ships.SingleOrDefault(s => return player.Ships.SingleOrDefault(s =>
{ {
if (s.Direction != ShipDirection.Horizontal) if (s.Direction != ShipDirection.Horizontal)

View file

@ -50,6 +50,7 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AIPlayer.cs" />
<Compile Include="EnemyGameRenderer.cs" /> <Compile Include="EnemyGameRenderer.cs" />
<Compile Include="GameForm.cs"> <Compile Include="GameForm.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
@ -59,6 +60,7 @@
</Compile> </Compile>
<Compile Include="Game.cs" /> <Compile Include="Game.cs" />
<Compile Include="GameRenderer.cs" /> <Compile Include="GameRenderer.cs" />
<Compile Include="GameStateChangeEventArgs.cs" />
<Compile Include="GameTypeChangeEventArgs.cs" /> <Compile Include="GameTypeChangeEventArgs.cs" />
<Compile Include="OwnGameRenderer.cs" /> <Compile Include="OwnGameRenderer.cs" />
<Compile Include="Player.cs" /> <Compile Include="Player.cs" />