diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d5ab227 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vs/* +*/bin/* +*/obj/* diff --git a/BlokusGUI.sln b/BlokusGUI.sln new file mode 100644 index 0000000..a6a3e22 --- /dev/null +++ b/BlokusGUI.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33122.133 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlokusGUI", "BlokusGUI\BlokusGUI.csproj", "{31B75923-390C-48B3-B558-2A932DFD3B91}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {31B75923-390C-48B3-B558-2A932DFD3B91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {31B75923-390C-48B3-B558-2A932DFD3B91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {31B75923-390C-48B3-B558-2A932DFD3B91}.Debug|x64.ActiveCfg = Debug|x64 + {31B75923-390C-48B3-B558-2A932DFD3B91}.Debug|x64.Build.0 = Debug|x64 + {31B75923-390C-48B3-B558-2A932DFD3B91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {31B75923-390C-48B3-B558-2A932DFD3B91}.Release|Any CPU.Build.0 = Release|Any CPU + {31B75923-390C-48B3-B558-2A932DFD3B91}.Release|x64.ActiveCfg = Release|x64 + {31B75923-390C-48B3-B558-2A932DFD3B91}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FA758EFC-CF7A-42AB-A796-D628010214BF} + EndGlobalSection +EndGlobal diff --git a/BlokusGUI/App.config b/BlokusGUI/App.config new file mode 100644 index 0000000..56efbc7 --- /dev/null +++ b/BlokusGUI/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/BlokusGUI/BlokusGUI.csproj b/BlokusGUI/BlokusGUI.csproj new file mode 100644 index 0000000..20ba6dc --- /dev/null +++ b/BlokusGUI/BlokusGUI.csproj @@ -0,0 +1,142 @@ + + + + + Debug + AnyCPU + {31B75923-390C-48B3-B558-2A932DFD3B91} + WinExe + BlokusGUI + BlokusGUI + v4.7.2 + 512 + true + true + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + 7.3 + prompt + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + 7.3 + prompt + true + + + + + + + + + + + + + + + + + + Form + + + MainForm.cs + + + + + + + Form + + + FormGameSetup.cs + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + FormGameSetup.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + False + Microsoft .NET Framework 4.7.2 %28x86 および x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + \ No newline at end of file diff --git a/BlokusGUI/Board.cs b/BlokusGUI/Board.cs new file mode 100644 index 0000000..94c1e77 --- /dev/null +++ b/BlokusGUI/Board.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Drawing; + +namespace BlokusGUI { + /// + /// ボード(盤)クラス + /// シングルトンパターンを適用 + /// + class Board { + const int BOARD_IMG_SIZE = 600; // ボード画像サイズ + public Brush[] PieceColors = { + Brushes.DodgerBlue, Brushes.OrangeRed, Brushes.ForestGreen, Brushes.DarkViolet, + Brushes.Peru, Brushes.Gold, Brushes.Turquoise, Brushes.HotPink}; // プレイヤーの色 + + private static Board _instace = new Board(); // 唯一のインスタンス + + public int BoardSize { get; private set; } = 0; // ボードのマス数 + public int[,] Cell { get; private set; } // [y,x]位置のマスの状態 -1:無 0-7:プレイヤーマス + + private float _cellSize = 0; // 描画マスサイズ + private float _margin = 0; // ボード周囲の幅 + + /// + /// コンストラクタ + /// + private Board() { + } + + /// + /// 唯一のインスタンス取得 + /// + /// インスタンス + public static Board GetInstance() { + return _instace; + } + + /// + /// 初期化 + /// + /// ボードのマス数 + public void Initialize(int boardSize) { + BoardSize = boardSize; + Cell = new int[BoardSize, BoardSize]; + for (var y=0; y< BoardSize; y++) { + for (var x = 0; x < BoardSize; x++) { + Cell[y, x] = -1; + } + } + _cellSize = (float)BOARD_IMG_SIZE / (BoardSize + 1); + _margin = _cellSize / 2; + } + + /// + /// ボードを描画する + /// + /// 選択中のピース番号(非選択:<0) + /// マウスの位置(0~1) + /// + public Bitmap DrawBoard(int hold, PointF pos) { + var bmp = new Bitmap(BOARD_IMG_SIZE, BOARD_IMG_SIZE); + var g = Graphics.FromImage(bmp); + // 背景と枠の描画 + g.FillRectangle(Brushes.AntiqueWhite, 0, 0, bmp.Width, bmp.Height); + var gridPen = new Pen(Color.DarkBlue, 2); + var padding = 3; + for (var i = 0; i < BoardSize+1; i++) { + g.DrawLine(gridPen, _margin + i * _cellSize, _margin, _margin + i * _cellSize, BOARD_IMG_SIZE - _margin); + g.DrawLine(gridPen, _margin, _margin + i * _cellSize, BOARD_IMG_SIZE - _margin, _margin + i * _cellSize); + } + // マスの描画 + for (var y = 0; y < BoardSize; y++) { + for (var x = 0; x < BoardSize; x++) { + if (Cell[y, x] >= 0) { + g.FillRectangle(PieceColors[Cell[y, x]], + _margin + padding + x * _cellSize, _margin + padding + y * _cellSize, + _cellSize - padding * 2, _cellSize - padding * 2); + } + } + } + // 操作ピースの描画 + var pieces = Pieces.GetInstance(); + if (hold >= 0 && hold < pieces.NumPieces()) { + var x = (int)((pos.X * BOARD_IMG_SIZE - _margin) / _cellSize); + var y = (int)((pos.Y * BOARD_IMG_SIZE - _margin) / _cellSize); + var shape = pieces.GetShape(hold); + shape.ForEach(p => { + var px = x + p.X; + var py = y + p.Y; + if (px >= 0 && py >= 0 && px < BoardSize && py < BoardSize) { + g.FillRectangle(Brushes.Gray, + _margin + padding + px * _cellSize, _margin + padding + py * _cellSize, + _cellSize - padding * 2, _cellSize - padding * 2); + } + }); + } + + return bmp; + } + + /// + /// ピースを置く + /// + /// プレイヤー番号(0-7) + /// 選択ピース番号 + /// マウス位置 + /// true: 置いた false: 置けなかった + public bool SetPiece(int player, int hold, PointF pos) { + var pieces = Pieces.GetInstance(); + if (hold < 0 || hold >= pieces.NumPieces()) return false; + var x = (int)((pos.X * BOARD_IMG_SIZE - _margin) / _cellSize); + var y = (int)((pos.Y * BOARD_IMG_SIZE - _margin) / _cellSize); + var shape = pieces.GetShape(hold); + // ピースが盤外でないかチェック + if (shape.Any(p => p.X + x < 0 || p.Y + y < 0 || p.X + x >= BoardSize || p.Y + y >= BoardSize)) return false; + // ピースの重なりがないかチェック + if (shape.Any(p => Cell[p.Y + y, p.X + x] >= 0)) return false; + + // ピースを置く + shape.ForEach(p => { Cell[p.Y + y, p.X + x] = player; }); + + return true; + } + } +} diff --git a/BlokusGUI/FormGameSetup.Designer.cs b/BlokusGUI/FormGameSetup.Designer.cs new file mode 100644 index 0000000..c4709bd --- /dev/null +++ b/BlokusGUI/FormGameSetup.Designer.cs @@ -0,0 +1,155 @@ + +namespace BlokusGUI { + partial class FormGameSetup { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() { + this.UpdownPlayers = new System.Windows.Forms.NumericUpDown(); + this.label1 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + this.label2 = new System.Windows.Forms.Label(); + this.UpdownBoardSize = new System.Windows.Forms.NumericUpDown(); + ((System.ComponentModel.ISupportInitialize)(this.UpdownPlayers)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.UpdownBoardSize)).BeginInit(); + this.SuspendLayout(); + // + // UpdownPlayers + // + this.UpdownPlayers.Font = new System.Drawing.Font("MS UI Gothic", 36F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(128))); + this.UpdownPlayers.Location = new System.Drawing.Point(43, 47); + this.UpdownPlayers.Maximum = new decimal(new int[] { + 8, + 0, + 0, + 0}); + this.UpdownPlayers.Minimum = new decimal(new int[] { + 2, + 0, + 0, + 0}); + this.UpdownPlayers.Name = "UpdownPlayers"; + this.UpdownPlayers.ReadOnly = true; + this.UpdownPlayers.Size = new System.Drawing.Size(81, 55); + this.UpdownPlayers.TabIndex = 0; + this.UpdownPlayers.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.UpdownPlayers.Value = new decimal(new int[] { + 2, + 0, + 0, + 0}); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("MS UI Gothic", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(128))); + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(152, 21); + this.label1.TabIndex = 1; + this.label1.Text = "参加人数を選択"; + // + // button1 + // + this.button1.Font = new System.Drawing.Font("MS UI Gothic", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(128))); + this.button1.Location = new System.Drawing.Point(104, 133); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(145, 45); + this.button1.TabIndex = 2; + this.button1.Text = "開始"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Font = new System.Drawing.Font("MS UI Gothic", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(128))); + this.label2.Location = new System.Drawing.Point(211, 9); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(138, 21); + this.label2.TabIndex = 3; + this.label2.Text = "盤サイズを選択"; + // + // UpdownBoardSize + // + this.UpdownBoardSize.Font = new System.Drawing.Font("MS UI Gothic", 36F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(128))); + this.UpdownBoardSize.Increment = new decimal(new int[] { + 2, + 0, + 0, + 0}); + this.UpdownBoardSize.Location = new System.Drawing.Point(224, 47); + this.UpdownBoardSize.Maximum = new decimal(new int[] { + 35, + 0, + 0, + 0}); + this.UpdownBoardSize.Minimum = new decimal(new int[] { + 5, + 0, + 0, + 0}); + this.UpdownBoardSize.Name = "UpdownBoardSize"; + this.UpdownBoardSize.ReadOnly = true; + this.UpdownBoardSize.Size = new System.Drawing.Size(107, 55); + this.UpdownBoardSize.TabIndex = 4; + this.UpdownBoardSize.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.UpdownBoardSize.Value = new decimal(new int[] { + 11, + 0, + 0, + 0}); + // + // FormGameSetup + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(368, 190); + this.ControlBox = false; + this.Controls.Add(this.UpdownBoardSize); + this.Controls.Add(this.label2); + this.Controls.Add(this.button1); + this.Controls.Add(this.label1); + this.Controls.Add(this.UpdownPlayers); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "FormGameSetup"; + this.ShowInTaskbar = false; + this.Text = "BlokusGUI ゲーム条件の設定"; + this.TopMost = true; + ((System.ComponentModel.ISupportInitialize)(this.UpdownPlayers)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.UpdownBoardSize)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.NumericUpDown UpdownPlayers; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.NumericUpDown UpdownBoardSize; + } +} \ No newline at end of file diff --git a/BlokusGUI/FormGameSetup.cs b/BlokusGUI/FormGameSetup.cs new file mode 100644 index 0000000..d22f694 --- /dev/null +++ b/BlokusGUI/FormGameSetup.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace BlokusGUI { + public partial class FormGameSetup : Form { + + public int NumPlayers { get; private set; } + public int BoardSize { get; private set; } + + public FormGameSetup() { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) { + NumPlayers = decimal.ToInt32(UpdownPlayers.Value); + BoardSize = decimal.ToInt32(UpdownBoardSize.Value); + this.Close(); + } + } +} diff --git a/BlokusGUI/FormGameSetup.resx b/BlokusGUI/FormGameSetup.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/BlokusGUI/FormGameSetup.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/BlokusGUI/Game.cs b/BlokusGUI/Game.cs new file mode 100644 index 0000000..fd33c1a --- /dev/null +++ b/BlokusGUI/Game.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Diagnostics; + +namespace BlokusGUI { + + /// + /// プレイヤークラス + /// + class Player { + public bool Alive { get; set; } = true; // true: プレイ中 false: 降参 + public List PiecesUsed { get; set; } // true: 使用済みピース false: 未使用 + + /// + /// コンストラクタ + /// + public Player() { + PiecesUsed = new List(new bool[Pieces.GetInstance().NumPieces()]); + } + } + + /// + /// ゲームクラス + /// シングルトンパターンを適用 + /// + class Game { + private static Game _instace = new Game(); // 唯一のインスタンス + + public int NumPlayers { get; private set; } // プレイヤー数 + public List Players { get; private set; } // プレイヤー情報 + public int TurnPlayer { get; private set; } // 現在のプレイヤー + public int AlivePlayers { get; private set; } // プレイ中の人数 + + /// + /// コンストラクタ + /// + private Game() { + } + + /// + /// 唯一のインスタンス取得 + /// + /// インスタンス + public static Game GetInstance() { + return _instace; + } + + /// + /// ゲーム初期化 + /// + /// プレイヤー数 + public void Initialize(int numPlayers) { + NumPlayers = numPlayers; + Players = new List(); + for (var i = 0; i < NumPlayers; i++) { + Players.Add(new Player()); + } + TurnPlayer = 0; + AlivePlayers = NumPlayers; + } + + /// + /// ピースを置く + /// + /// ピース番号 + public void SetPiece(int piece) { + Players[TurnPlayer].PiecesUsed[piece] = true; + this.SwitchPlayer(); + } + + /// + /// 降参 + /// + public void GiveUp() { + Players[TurnPlayer].Alive = false; + if (--AlivePlayers > 0) { + this.SwitchPlayer(); + } else { + this.GameOver(); + } + } + + /// + /// ゲーム終了 + /// + private void GameOver() { + + } + + /// + /// 次のプレイヤーへ + /// + private void SwitchPlayer() { + do { + TurnPlayer = (TurnPlayer + 1) % NumPlayers; + } while (Players[TurnPlayer].Alive == false); + } + } +} diff --git a/BlokusGUI/MainForm.Designer.cs b/BlokusGUI/MainForm.Designer.cs new file mode 100644 index 0000000..fc4410e --- /dev/null +++ b/BlokusGUI/MainForm.Designer.cs @@ -0,0 +1,73 @@ + +namespace BlokusGUI { + partial class MainForm { + /// + /// 必要なデザイナー変数です。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 使用中のリソースをすべてクリーンアップします。 + /// + /// マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。 + protected override void Dispose(bool disposing) { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows フォーム デザイナーで生成されたコード + + /// + /// デザイナー サポートに必要なメソッドです。このメソッドの内容を + /// コード エディターで変更しないでください。 + /// + private void InitializeComponent() { + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.PicPlayerLabel = new System.Windows.Forms.PictureBox(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PicPlayerLabel)).BeginInit(); + this.SuspendLayout(); + // + // pictureBox1 + // + this.pictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; + this.pictureBox1.Location = new System.Drawing.Point(187, 10); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(360, 360); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.pictureBox1.TabIndex = 1; + this.pictureBox1.TabStop = false; + this.pictureBox1.Click += new System.EventHandler(this.pictureBox1_Click); + this.pictureBox1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseMove); + // + // PicPlayerLabel + // + this.PicPlayerLabel.Location = new System.Drawing.Point(12, 10); + this.PicPlayerLabel.Name = "PicPlayerLabel"; + this.PicPlayerLabel.Size = new System.Drawing.Size(161, 28); + this.PicPlayerLabel.TabIndex = 2; + this.PicPlayerLabel.TabStop = false; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(563, 382); + this.Controls.Add(this.PicPlayerLabel); + this.Controls.Add(this.pictureBox1); + this.Name = "Form1"; + this.Text = "BlokusGUI"; + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PicPlayerLabel)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.PictureBox PicPlayerLabel; + } +} + diff --git a/BlokusGUI/MainForm.cs b/BlokusGUI/MainForm.cs new file mode 100644 index 0000000..213b446 --- /dev/null +++ b/BlokusGUI/MainForm.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Diagnostics; + +namespace BlokusGUI { + public partial class MainForm : Form { + private Game _game = Game.GetInstance(); // ゲームのインスタンス + private Board _board = Board.GetInstance(); // ボードのインスタンス + private Pieces _pieces = Pieces.GetInstance(); // ピースのインスタンス + private Button[] _pieceButtons; // ボタン配列 + private int _hold = -1; // ピースの選択状態 + private PointF _mousePos = new PointF(-1, -1); // マウス位置(pictureBox内相対位置) + + /// + /// コンストラクタ + /// + public MainForm() { + InitializeComponent(); + + // ゲーム条件設定 + var frmSelectPlayers = new FormGameSetup(); + frmSelectPlayers.ShowDialog(); + + // 初期化 + _game.Initialize(frmSelectPlayers.NumPlayers); + _board.Initialize(frmSelectPlayers.BoardSize); + this.Draw(); + + // ピースボタン生成 + var btnSize = new Size(77, 53); + _pieceButtons = new Button[_pieces.NumPieces()]; + for (var i=0; i< _pieces.NumPieces(); i++) { + _pieceButtons[i] = new Button(); + var col = i % 2; + var row = i / 2; + _pieceButtons[i].Location = new Point(12 + 84 * col, 45 + 60 * row); + _pieceButtons[i].Size = btnSize; + _pieceButtons[i].Text = _pieces.GetShapeString(i); + _pieceButtons[i].Tag = i; + _pieceButtons[i].Click += new EventHandler(this.PieceButton_Click); + } + this.Controls.AddRange(_pieceButtons); + this.UpdateController(); + } + + /// + /// グラフィクス描画 + /// + private void Draw() { + pictureBox1.Image = _board.DrawBoard(_hold, _mousePos); + pictureBox1.Refresh(); + } + + /// + /// ピースボタンクリック + /// + /// + /// + private void PieceButton_Click(object sender, EventArgs e) { + _hold = (int)((Button)sender).Tag; + } + + /// + /// 盤上でマウス移動 + /// + /// + /// + private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { + _mousePos.X = (float)e.X / pictureBox1.Width; + _mousePos.Y = (float)e.Y / pictureBox1.Height; + if (_hold >= 0) Draw(); + } + + /// + /// 盤上でマウスクリック + /// + /// + /// + private void pictureBox1_Click(object sender, EventArgs e) { + if (_hold < 0 || _hold >= _pieces.NumPieces()) return; + + if (((MouseEventArgs)e).Button == MouseButtons.Left) { + if (_board.SetPiece(_game.TurnPlayer, _hold, _mousePos)) { + _game.SetPiece(_hold); + _hold = -1; + this.Draw(); + Console.Beep(1600, 200); + this.UpdateController(); + } else { + Console.Beep(800, 200); + } + } + if (((MouseEventArgs)e).Button == MouseButtons.Right) { + _hold = -1; + this.Draw(); + } + } + + /// + /// 操作部の状態更新 + /// + private void UpdateController() { + var bmp = new Bitmap(PicPlayerLabel.Width, PicPlayerLabel.Height); + var g = Graphics.FromImage(bmp); + g.FillRectangle(_board.PieceColors[_game.TurnPlayer], 0, 0, bmp.Width, bmp.Height); + g.DrawString($"プレイヤー {_game.TurnPlayer + 1} の番", new Font("MS UI Gothic", 14), Brushes.White, 3, 3); + PicPlayerLabel.Image = bmp; + PicPlayerLabel.Refresh(); + + for (var i = 0; i < _pieces.NumPieces(); i++) { + _pieceButtons[i].Enabled = !_game.Players[_game.TurnPlayer].PiecesUsed[i]; + } + } + } +} diff --git a/BlokusGUI/MainForm.resx b/BlokusGUI/MainForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/BlokusGUI/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/BlokusGUI/Pieces.cs b/BlokusGUI/Pieces.cs new file mode 100644 index 0000000..b7c8de9 --- /dev/null +++ b/BlokusGUI/Pieces.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlokusGUI { + + /// + /// 位置情報 + /// + struct Pos { + public int X { get; set; } + public int Y { get; set; } + public Pos(int x, int y) { + X = x; + Y = y; + } + } + + /// + /// ピースクラス + /// シングルトンパターンを適用 + /// + class Pieces { + private static Pieces _instace = new Pieces(); // 唯一のインスタンス + + private List> _pieces = new List>(); + + /// + /// コンストラクタ + /// + private Pieces() { + // ピースの形を定義 + _pieces.Add(new List() { new Pos(0, 0) }); + _pieces.Add(new List() { new Pos(0, 0), new Pos(0, 1) }); + _pieces.Add(new List() { new Pos(-1, 0), new Pos(0, 0), new Pos(1, 0) }); + } + + /// + /// 唯一のインスタンス取得 + /// + /// インスタンス + public static Pieces GetInstance() { + return _instace; + } + + /// + /// ピースの個数 + /// + /// + public int NumPieces() { + return _pieces.Count(); + } + + /// + /// ピース形状取得(位置リスト) + /// + /// ピース番号 + /// + public List GetShape(int piece) { + return _pieces[piece]; + } + + /// + /// ピース形状取得(文字列) + /// + /// ピース番号 + /// + public string GetShapeString(int piece) { + var grid = new bool[3, 5]; + var minX = _pieces[piece].Min(c => c.X); + var minY = _pieces[piece].Min(c => c.Y); + var maxX = 0; + var maxY = 0; + _pieces[piece].ForEach(p => { + grid[p.Y - minY, p.X - minX] = true; + if (p.X - minX > maxX) maxX = p.X - minX; + if (p.Y - minY > maxY) maxY = p.Y - minY; + }); + var shape = ""; + for (int y=0; y<= maxY; y++) { + for(int x=0; x<= maxX; x++) { + shape += grid[y, x] ? "■" : " "; + } + shape += "\n"; + } + return shape; + } + } +} diff --git a/BlokusGUI/Program.cs b/BlokusGUI/Program.cs new file mode 100644 index 0000000..b96bbd7 --- /dev/null +++ b/BlokusGUI/Program.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace BlokusGUI { + static class Program { + /// + /// アプリケーションのメイン エントリ ポイントです。 + /// + [STAThread] + static void Main() { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + } +} diff --git a/BlokusGUI/Properties/AssemblyInfo.cs b/BlokusGUI/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7a77468 --- /dev/null +++ b/BlokusGUI/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 +// 制御されます。アセンブリに関連付けられている情報を変更するには、 +// これらの属性値を変更します。 +[assembly: AssemblyTitle("BlokusGUI")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("BlokusGUI")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible を false に設定すると、このアセンブリ内の型は COM コンポーネントから +// 参照できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 +// その型の ComVisible 属性を true に設定してください。 +[assembly: ComVisible(false)] + +// このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります +[assembly: Guid("31b75923-390c-48b3-b558-2a932dfd3b91")] + +// アセンブリのバージョン情報は、以下の 4 つの値で構成されています: +// +// メジャー バージョン +// マイナー バージョン +// ビルド番号 +// リビジョン +// +// すべての値を指定するか、次を使用してビルド番号とリビジョン番号を既定に設定できます +// 既定値にすることができます: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/BlokusGUI/Properties/Resources.Designer.cs b/BlokusGUI/Properties/Resources.Designer.cs new file mode 100644 index 0000000..b2e4804 --- /dev/null +++ b/BlokusGUI/Properties/Resources.Designer.cs @@ -0,0 +1,61 @@ +//------------------------------------------------------------------------------ +// +// このコードはツールによって生成されました。 +// ランタイム バージョン:4.0.30319.42000 +// +// このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 +// コードが再生成されるときに損失したりします +// +//------------------------------------------------------------------------------ + + +namespace BlokusGUI.Properties { + /// + /// ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。 + /// + // このクラスは StronglyTypedResourceBuilder クラスが ResGen + // または Visual Studio のようなツールを使用して自動生成されました。 + // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に + // ResGen を実行し直すか、または VS プロジェクトをリビルドします。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// このクラスで使用されるキャッシュされた ResourceManager インスタンスを返します。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if ((resourceMan == null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BlokusGUI.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// すべてについて、現在のスレッドの CurrentUICulture プロパティをオーバーライドします + /// 現在のスレッドの CurrentUICulture プロパティをオーバーライドします。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/BlokusGUI/Properties/Resources.resx b/BlokusGUI/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/BlokusGUI/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/BlokusGUI/Properties/Settings.Designer.cs b/BlokusGUI/Properties/Settings.Designer.cs new file mode 100644 index 0000000..c3eb92d --- /dev/null +++ b/BlokusGUI/Properties/Settings.Designer.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + + +namespace BlokusGUI.Properties { + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/BlokusGUI/Properties/Settings.settings b/BlokusGUI/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/BlokusGUI/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..61174a9 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +ss2209 Blokus Online +--------------------------------- +スキルゼミ2022年度第9回課題 Blokus Online + +# BlokusGUI プロジェクト +- BlokusのGUI実装例 +- Visual C# 2022 + +# 未実装 +- 不足ピース +- ピースの回転 +- 各プレイヤーの開始点設定と表示 +- 配置ルールの検証 +- 勝敗判定と表示 +- 対戦終了後に最初のメニューに戻る + +# 改良ポイント +- ピースのボタンなどグラフィカルに +- 効果音 +- 勝敗表示の工夫 +- 全プレイヤーのピースを表示 +- Windowサイズ変更に対応 +- その他自由に