C# exercises (f) Summary

C# 演習前期のまとめ

C#プログラムは「入れ子構造」をしている

csharp_struct

ボタンクリックでメッセージボックス に表示完成したコード

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 test1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // ボタンクリックでメッセージボックスに表示
        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Hello world");
        }
    }
}
*注意:( ” “) ; は全角(漢字)にしてはいけません。全角(漢字)の文章を入れた場合、かならず半角に戻して入力しましょう。

 

●using

usingキーワードは,プログラムの処理の流れには直接関係ありません。その代わり,プログラム全体にわたってどのライブラリを利用するかを明確にする役割があります。

前回触れたように,C#では基盤にある「 .NET Framework」のライブラリを利用してアプリケーションを作ります。.NET Frameworkでは,ライブラリの各機能を処理内容ごとにツリー状のグループに分類して管理します。ちょうど,パソコンでファイルを管理するときに目的別のフォルダを用意して分類・整理しておくのと似た状態を想像すればいいでしょう。フォルダに相当するグループを .NET Frameworkのライブラリでは「名前空間」と呼びます。

●名前空間(namespace)

usingの次に出てくるnamespaceは,それに続くブロックが所属する名前空間を指定するキーワードです。usingのところで,標準ライブラリがSystem以下の名前空間に属していることを説明しましたが,自分で作るプログラムも必ずどこかの名前空間に所属させます。

●class

classは,C#プログラムを構成する最小単位である「クラス」を定義するキーワードです。必ずnamespaceのブロック内に書かれます。C#プログラムの大部分はこのようなクラス定義の集まりです。

●メソッド(method)

メソッドはクラス内で実行される具体的な処理を一つにまとめて名前を付けたものです。メソッドはクラス定義ブロックの中にいくつでも作れます。メソッドの中でほかのメソッドを呼び出したり,ほかのクラスを利用するといったことも可能です。ただ,Mainという名前のメソッドには特別な役割があります。プログラムを起動したときには自動的にMainメソッドが実行されるのです。

●//(コメント)

この構文だけはほかとは異質で,実はC#プログラムに不可欠な要素ではありません。//と書かれた個所から改行までの部分はプログラムの処理の流れからは一切無視されます。つまり,この//以降を削除してしまってもプログラムは全く同じように動作します。

この一見ムダな行は,プログラム内に動作などをメモしておくプログラマ向けの注釈文です。プログラム内での処理という点では全くムダですが,実際のプログラミングでは読みやすい注釈を記述することがプログラミングの重要なテクニックです。例えば,思った通りにプログラムが動かずにミスを探す場合などは,わかりやすいコメントがついているかどうかでミス発見までの作業の効率が大きく変わってきます。あるいは他人の作ったプログラムや過去に自分が作ったプログラムを見る場合,処理だけが書かれているのと,適切なコメントがあるのとでは理解のしやすさが大きく違います。

期末レポート:

A4 2枚以上、eメールで提出する。

  • 提出先:h.chen@ueno.daiichi-koudai.ac.jp
  • タイトル:C#期末レポート (学籍番号)
  • 提出する期限:2016/7/29
  1. C#プログラミング関連名詞の意味を説明する
    1. イベントドリブン
    2. ツールボックス
    3. コントロール
    4. イベント
    5. メソッド
    6. プロパティ
  2. Webプログラミング関連名詞の意味を説明する
    1. API
    2. REST
    3. JSON
    4. Open Data
  3. 学内Proxyを通して、Webデータ取得する方法を説明する
    1. 画面デザイン
    2. プログラム
  4. オープンデータを利用したWebアプリの作成
    1.  オープンデータの好みのどれかを選択
      1.   – 郵便番号検索
      2.   – 天気予報検索
      3.   – その他  「LinkData.org」から探す
    2. オープンデータをブラウザで確認
      1. ブラウザ画面
    3. C#を使って、オープンデータWebアプリの作成
      1. 画面デザイン
      2. プログラム

参考:

 

 

C# exercises (e) Open Data

オープンデータを利用したWebアプリ作成

オープンデータとは

オープンデータOpen Data)とは、特定のデータが、一切の著作権、特許などの制御メカニズムの制限なしで、全ての人が望むように利用・再掲載できるような形で入手できるべきであるというアイデアである。

オープンデータの利用

LinkData.org」には、誰でも無償で利用でき、商用利用も可能なオープンデータが豊富にまとまっています。
都道府県別で探したり、人気ランキングやキーワードを指定しての検索もできるので、自分が興味のあるデータを探すのも簡単でしょう。

LinkDataのサイト内には、全国の「お城データ」や「道の駅データ」、「避難所データ」、「補助金まとめデータ」、「さくら名所データ」…など、意外とユニークで面白いデータがまとまっているので、うまく利用すれば楽しいWebアプリが作れそうです。

「ダウンロード」の項目下に、「その他の形式のAPIリストを表示」というリンクがあるのでクリックします。

すると、外部APIとしてデータが取得できるURLが一覧表示されます。

そこで「JSON」形式のURLをコピーして、実際にブラウザのアドレスバーに入力してみましょう!

あとは、このデータをC#を使って、自分のWebアプリに組み込めば良い。

グループ課題

オープンデータを利用したWebアプリの作成

  1. オープンデータの選択
    1. 郵便番号検索
    2. 天気予報検索
    3. その他
  2. オープンデータをブラウザで確認
  3. C#を使って、オープンデータWebアプリの作成

C# exercises (d) REST & JSON

Visual Studio community 2015 アカウントについて (学内専用)

  1. WebBrowser (基本)
  2. Form(自動操作)
  3. HttpClient
  4. REST & JSON ←今週

RESTとは

RESTとは、RESTはREpresentational State Transferの略。2000年にRoy Fielding氏が提唱した、分散システムにおいて複数のソフトウェアを連携させるのに適した設計原則の集合。また、狭義には、それをWebに適用したソフトウェアの設計様式のこと。一般には後者の意味で用いられることがほとんどである。RESTの世界では、ネットワーク上のコンテンツ(リソース)を一意なURLで表すのが基本。各リソース(URL)に対してGET,POST,PUT,DELETEでリクエストを送信しレスポンスをXMLやjsonなどで受け取る形式(レスポンスのフォーマット形式は指定されていない)。

REST APIをを作る前に先人はどのような設計をしていたのかを見てみましょう。今ではTwitterやfacebook,Github、Amazonなど大きいところではだいたいAPIを提供しているので、お手本は山ほどあります。URL設計やリクエスト・レスポンス、HTTPヘッダなどに着目して見比べてみましょう。

Twitter REST API
レスポンスの情報量が多いので、どういった情報を返すべきか参考になります。
Github API
一番綺麗にまとまっているAPIだと思います。リクエスト・レスポンスがRESTらしく、とても綺麗。

JSONとは

JSONとは、JavaScriptにおけるオブジェクトの表記法を応用したデータ形式。 JSONで表記されたデータは、JavaScript上ではコードとして実行するだけで読み込みが完了する。JSONでは、データ全体を配列またはJavaScriptにおけるオブジェクト(キーと値のペアを列挙した構造体)として記述する。

JSONというのは「データを表現するための記法(≒文法)」です。シンプルなデータであれば、文法など気にせずにただ書けば問題ありません。少々複雑でも、我々は「表」という記法をしっているため、ある程度の複雑さには対応できます。しかし、表で表すのが困難な程度の複雑な構造を持つデータを表現しなければならないことは多々あります。このように、表形式では表現が困難な構造のデータを、人間に対するある程度の可読性を残しつつ、コンピュータに対しても伝達できるような記法、その1つがJSONです。そしてJSON形式で記述したデータのことを、JSON-textといいます。

chenlabのメンバーをJSON-textで表現

{
“name”   : “chenlab”,
“member3” : [ “14TE485”, “14TE406”, “14TE410”, “14TE449” , “14TE461″”, “14TE465″”, “14TE470”],
“member4” : [ “13TE466”, “13TE477”, “13TE486”, “13TE520” , “12TE412″”, “13TE457″”, “13TE405”],
“count”  : 4
}

 

C#でJSON

Newtonsoft.Jsonのインストール

C#でJSON扱うときは、いくつ方法があり、ここはNewtonsoft.Jsonののライブラリを使う。

NuGetパッケージ管理を開く

nuget

Newtonsoft.Jsonを選択して、インストールしてください。

2016-07-14

 

JSONデータサンプル

http://wp-api.xyz/wp-json/posts

先週のプログラムでサンプルデータを取得するように変更してください。

ダウンロード:web_get2 (2)

JSONをクラスとして貼り付け

JSONのデータ構造をC#のクラス定義に変換する。

取得したサンプルデータをコピーして、メニューの「JSONをクラスとして貼り付け」で、プログラムのnamespaceの最後部に貼り付けください。

jsonpaste

JSONプログラミング

16 行に下記の分を入れえてください

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Linq;

デザイン画面に、「button1」ボタンと、「listBox1」リストボックスを追加してください。

デザインのbutton1をダブルクリックし、DeserializeObject処理を入れてください。

private void button1_Click(object sender, EventArgs e)
{
    var json = HTTP_Results.Text;
    var posts = JsonConvert.DeserializeObject<Class1[]>(json);
    foreach(Class1 post in posts)
    {
        listBox1.Items.Add(post.ID);
    }
    // string saveJson = JsonConvert.SerializeObject(posts, Formatting.Indented);

}

実行画面

これて、Jsonデータ(ブログの投稿)の取得、Deserialize、そして(ブログID)表示ができた。

スクリーンショット 2016-07-15 11.35.51

最終プログラム構造

  • Namespace web_get2
    • Class Form1 : Form
      • Form1
      • Quit_Click
      • Request_Click
      • button1_Click
    • Class Rootobject (JSON データ構造)
    • Class Meta (JSON データ構造)
    • Class Links (JSON データ構造)
    • Class Terms (JSON データ構造)
    • 。。。

最終プログラム

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;
// for httpclient
using System.Net.Http;
using System.Net;
using System.IO;
using System.Runtime.Serialization;
// using System.Runtime.Serialization.Json;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Linq;

namespace web_get2
{


    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Quit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private async void Request_Click(object sender, EventArgs e)
        {
            if (ProxyOn.Checked)
            {
                // デフォルト プロキシ情報を取得して、資格情報を設定する 
                var proxy = WebRequest.DefaultWebProxy;
                proxy.Credentials = new NetworkCredential(ProxyID.Text, ProxyPW.Text);
            }
            var client = new HttpClient();
            string response = await client.GetStringAsync(URL.Text);
            HTTP_Results.Text = response;

        }

        private void button1_Click(object sender, EventArgs e)
        {
            var json = HTTP_Results.Text;
            var posts = JsonConvert.DeserializeObject<Class1[]>(json);
            foreach (Class1 post in posts)
            {
                listBox1.Items.Add(post.ID);
            }
            // string saveJson = JsonConvert.SerializeObject(posts, Formatting.Indented);
        }
    }


    public class Rootobject
    {
        public Class1[] Property1 { get; set; }
    }

    public class Class1
    {
        public int ID { get; set; }
        public string title { get; set; }
        public string status { get; set; }
        public string type { get; set; }
        public object author { get; set; }
        public string content { get; set; }
        public object parent { get; set; }
        public string link { get; set; }
        public DateTime date { get; set; }
        public DateTime modified { get; set; }
        public string format { get; set; }
        public string slug { get; set; }
        public string guid { get; set; }
        public string excerpt { get; set; }
        public int menu_order { get; set; }
        public string comment_status { get; set; }
        public string ping_status { get; set; }
        public bool sticky { get; set; }
        public string date_tz { get; set; }
        public DateTime date_gmt { get; set; }
        public string modified_tz { get; set; }
        public DateTime modified_gmt { get; set; }
        public Meta meta { get; set; }
        public object featured_image { get; set; }
        public Terms terms { get; set; }
    }

    public class Meta
    {
        public Links links { get; set; }
    }

    public class Links
    {
        public string self { get; set; }
        public string author { get; set; }
        public string collection { get; set; }
        public string replies { get; set; }
        public string versionhistory { get; set; }
    }

    public class Terms
    {
        public Category[] category { get; set; }
    }

    public class Category
    {
        public int ID { get; set; }
        public string name { get; set; }
        public string slug { get; set; }
        public string description { get; set; }
        public string taxonomy { get; set; }
        public object parent { get; set; }
        public int count { get; set; }
        public string link { get; set; }
        public Meta1 meta { get; set; }
    }

    public class Meta1
    {
        public Links1 links { get; set; }
    }

    public class Links1
    {
        public string collection { get; set; }
        public string self { get; set; }
    }
}

 

C# exercises (c) Web3 HttpClient

Visual Studio community 2015 アカウントについて (学内専用)

  1. WebBrowser (基本)
  2. Form(自動操作)
  3. HttpClient ←今週
  4. REST & JSON

いままで、WebBrowser コントロールを利用して、 Webサイトを表示と操作プログラムを作りました。

今回は直接 http 通信に HttpClient クラスを使用 するプログラムを作ります。

HTTPとは

httpとは、代表的な通信プロトコルの一つで、インターネット上でWebサーバー(サイトの公開側)と、クライアント(ブラウザ:サイトを閲覧する側)が、相互に通信するために使用される仕組みです。

もっと言うと、Webサーバーとクライアント間で、HTML(Webページを作成するための言語)で記載された情報をやりとりするための仕組みです。

この「http」がないと、インターネット上のサイトを見ることができなくなるので、今や無くてはならない仕組みとなります。

r10zu01-2

HTTPコマンド

主なHTTPコマンドには次のようなものがあります。

GET 指定したページの取得を要求します。
HEAD メッセージヘッダを要求します。
POST フォームに入力したデータを送る
PUT サーバーへデータをアップロードする
DELETE サーバー上のデータを削除する

 

HTTPコマンド応答メッセージ

主な応答メッセージには、次のようなものがあります。

200 OK 正常に取得できた
301 恒久的に移転した
302 一時的に移転した
403 Forbidden アクセス拒否
404 Not Found ファイルが見つからない

 

HttpClient 通信プログラム

デザイン

web_get

 

  • Form
    • Form1
  • TextBox
    • textBox1  —
      • Name : URL
      • Text : http://wp-api.xyz
    • textBox2  —
      • Name :  ProxyID
      • Text : (your_proxy_id)
    • textBox3  —
      • Name :  ProxyPW
      • PasswordChar : *
      • Text : (your_proxy_password)
    • textBox4  —
      • Name : HTTP_Results
      • Multiline : True
  • Button
    • button1 —
      • Name : Quit
    • button2 —
      • Name : Request
  • CheckBox
    • checkBox1 —
      • Name : ProxyOn

 

プログラム

HttpClient クラス

// for httpclient
using System.Net.Http;
using System.Net;
using System.IO;
using System.Runtime.Serialization;
// using System.Runtime.Serialization.Json;

Quit ボタン

        private void Quit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

Requestボタン

private async void Request_Click(object sender, EventArgs e)
{
    if (ProxyOn.Checked)
    {
        // デフォルト プロキシ情報を取得して、資格情報を設定する 
        var proxy = WebRequest.DefaultWebProxy;
        proxy.Credentials = new NetworkCredential(ProxyID.Text, ProxyPW.Text);
    }
    var client = new HttpClient();
    string response = await client.GetStringAsync(URL.Text);
    HTTP_Results.Text = response;

}

最終プログラム:

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;
// for httpclient
using System.Net.Http;
using System.Net;
using System.IO;
using System.Runtime.Serialization;
// using System.Runtime.Serialization.Json;


namespace web_get2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Quit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private async void Request_Click(object sender, EventArgs e)
        {
            if (ProxyOn.Checked)
            {
                // デフォルト プロキシ情報を取得して、資格情報を設定する 
                var proxy = WebRequest.DefaultWebProxy;
                proxy.Credentials = new NetworkCredential(ProxyID.Text, ProxyPW.Text);
            }
            var client = new HttpClient();
            string response = await client.GetStringAsync(URL.Text);
            HTTP_Results.Text = response;

        }
    }
}

実行結果

web_get2

 

C# exercises (b) Web2 Form

Visual Studio community 2015 アカウントについて (学内専用)

  1. WebBrowser (基本)
  2. Form(自動操作)←今週
  3. HttpClient
  4. REST & JSON

WebBrowser コントロールを利用した、ブラウザをコントロールアプリケーションの作成手順を紹介します。

Googleの検索ページを利用し、ページに表示されているテキストボックスに文字列が自動的に入力、フォームのサブミットボタンのクリックができ、ページを解析し、含まれるすべてのリンク文字列とそのURLを表示するなどもできる。

このようにプログラムからWebページを操作する場合、事前にそのHTMLのソースをチェックして、操作対象となるHTML要素を明確にしておく必要がある。Googleの検索ページのソースを見ると、フォームの定義部分で次のような記述を見つけることができる。

<form action="/search" name=f >
<input name=q size=55 value="" …… >
<input name=btnG type=submit value="Google 検索" …… >
……

Googleの検索ページ内のフォーム定義部分(抜粋)

この記述から、フォーム(<form>要素)には「f」という名前(name属性)が付けられており、またテキストボックス(<input>要素)には「q」、[Google検索]ボタン(サブミット・ボタン。「type=submit」という属性が付いている<input>要素)には「btnG」という名前が付けられていることが分かる。

 

コントロールの配置

Visual Studioを起動し、新しいWindows Formプロジェクトを作成します。

フォーム上次のコントロールを配置してください

ボタン:

  • button1
  • button2
  • button3
  • button4

リストビュー:

  • listView1
    • listView1.View = View.Details;
    • columnHeader1=HERF
    • columnHeader2=text

ウェブブラウザ:

  • webBrowser1

 

スクリーンショット 2016-07-01 11.28.26

イベントハンドラ

Form1_Load

private void Form1_Load(object sender, EventArgs e)
{
    webBrowser1.Navigate("http://www.google.co.jp");
}

 

button1_Click

private void button1_Click(object sender, EventArgs e)
{
    HtmlElementCollection all = webBrowser1.Document.All;
    HtmlElementCollection forms = all.GetElementsByName("q");
    forms[0].InnerText = "c#"; // テキストボックスに「C#」を入力
}

 

button2_Click

private void button2_Click(object sender, EventArgs e)
{
    HtmlElementCollection all = webBrowser1.Document.All;
    HtmlElementCollection forms = all.GetElementsByName("f");
    forms[0].InvokeMember("submit"); // フォームのサブミット
}

 

button3_Click

private void button3_Click(object sender, EventArgs e)
{
    HtmlElementCollection all = webBrowser1.Document.All;
    HtmlElementCollection forms = all.GetElementsByName("btnG");
    forms[0].InvokeMember("click"); // ボタンのクリック
}

 

button4_Click

private void button4_Click(object sender, EventArgs e)
{
    HtmlDocument doc = webBrowser1.Document;

    // リンク文字列とそのURLの列挙
    foreach (HtmlElement he in doc.GetElementsByTagName("A"))
    {

        string href = he.GetAttribute("href"); // HREF属性の値
        string text = he.InnerText; // リンク文字列

        if (!string.IsNullOrEmpty(href)
            && !string.IsNullOrEmpty(text))
        {
            text = text.Replace("\r\n", ""); // 改行文字の削除
            string[] row_1 = { href, text };
            listView1.Items.Add(new ListViewItem(row_1));
        }
    }
}

 

実行結果

button1クリックすると、ページに表示されているテキストボックスに「C#」という文字列が自動的に入力される。

スクリーンショット 2016-07-01 12.20.27

 

button2、button3のボタンをクリックすると、検索が実行されて検索結果ページが表示される。

スクリーンショット 2016-07-01 12.20.34

button4のボタンをクリックすると、ページに含まれるすべてのリンク文字列とそのURLを表示する。

スクリーンショット 2016-07-01 12.20.47

機能追加

フォーム上textbox などを追加て、検索は「C#」に固定するではなく、textbox などの内容を利用するように機能追加する。

C# exercises (a) Web1 WebBrowser

Visual Studio community 2015 アカウントについて (学内専用)

今週から、4回分けてWebについて学習する

  1. WebBrowser (基本)
  2. WebBrowser (自動操作)
  3. HttpClient
  4. REST & JSON

WebBrowser コントロール

WebBrowser コントロールを利用した、シンプルなアプリケーションの作成手順を紹介します。

Visual Studioを起動し、新しいWindows Formプロジェクトを作成します。

WebBrowserコントロールの配置

ツールボックスから”WebBrowser”コントロールをクリックして選択します。選択後フォームデザイナにドラッグ&ドロップしフォームにWebBrowserコントロールを配置します。

フォームにWebBrowserコントロールを配置した直後の状態です。フォームいっぱいにコントロールが配置されます.

フォーム全体にコントロールが広がる原因は、”Dock”プロパティがデフォルトで”Fill”に設定されるためです。Dockプロパティを”None”に変更します。

Dockプロパティを”None”に変更するとコントロールのリサイズができるようになります。

コード

下記のコードを記述します。

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 WebBrowserControl
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void FormMain_Load(object sender, EventArgs e)
    {
      webBrowser1.Navigate("http://lmspress.net");
    }
  }
}

 

 

解説

WebBrowerコントロールのNavigateメソッドを呼び出すことでページの取得と表示ができます。

実行結果

プロジェクトを実行します。下図のフォームが表示されます。Webサイトのページが読み込まれ表示されました。
webbrowser

ウィンドウをリサイズ対応

Dockプロパティ、またはAnchorプロパティを変更し、ウィンドウのリサイズに伴いWebBrowserコントロールのサイズが変化する設定に変えます。

実行し、ウィンドウをリサイズします。Webページが正しく表示されています。
webbrowser2

機能拡張

下記の機能を追加してください

  1. アドレスバー:URL入力
  2. 戻るボタン:前のページに戻る
  3. リロードボタン:ページ再読み込む

C# exercises (9) Puzzle Game3

Visual Studio community 2015 アカウントについて (学内専用)

パズルゲームUIの改進

改進点:

ピースを順番でセットするではなく、あらかじめランダムにセットして、マウス移動できるようにする

  1. ピースをあらかじめランダムにセット
    1. initialData の改造
      // 変数関係の初期化処理
      private void initialData()
      {
          flg = new bool[9];
          data = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
          answer = new int[] { -1, -1, -1, -1, -1, -1, -1, -1, -1 };
          Random r = new Random(Environment.TickCount);
          for (int i = 0; i < 100; i++)
          {
              int a = r.Next(9);
              int b = r.Next(9);
              int n = data[a];
              data[a] = data[b];
              data[b] = n;
          }
          current = 0;
          answer = data; // chen : ランダムデータを直接結果に
          playflg = true;
          clearflg = false;
      }

       

    2. PlayBox_Paint の改造
      // PlayBoxの表示
      private void PlayBox_Paint(object sender, PaintEventArgs e)
      {
          if (img == null) { return; }
          Graphics g = e.Graphics;
          for (int i = 0; i < 9; i++)
          {
              // if (flg[i] == false) { continue; }    // chen : flg 無視
              if (answer[i] == 8) { continue; } // chen : 9個目描画しない
              int x1 = i % 3;
              int y1 = i / 3;
              int x2 = answer[i] % 3;
              int y2 = answer[i] / 3;
              Rectangle r1 = new Rectangle(100 * x1, 100 * y1, 100, 100);
              Rectangle r2 = new Rectangle(100 * x2, 100 * y2, 100, 100);
              g.DrawImage(img, r1, r2, GraphicsUnit.Pixel);
          }
          if (playflg == false)
          {
              if (clearflg)
              {
                  g.DrawString("CLEAR!!",
                      new Font("Impact", 48, FontStyle.Bold),
                      new SolidBrush(Color.Red),
                      new Point(40, 100));
              }
              else
              {
                  g.DrawString("GAMEOVER...",
                      new Font("Impact", 36, FontStyle.Bold),
                      new SolidBrush(Color.Blue),
                      new Point(20, 200));
              }
          }
      }
      
  2. マウス移動できる (隣と交換可能なら交換)
    private void swap_answer(int n, int m)
    {
        int t;
        t = answer[m];
        answer[m] = answer[n];
        answer[n] = t;
    }
    
    // PlayBoxをクリックした時の処理
    private void PlayBox_MouseDown(object sender, MouseEventArgs e)
    {
        if (playflg == false) { return; }
        if (img == null) { return; }
        if (current > 8) { return; }
        int x = e.X / 100;
        int y = e.Y / 100;
        if (x < 0) { return; }
        if (y < 0) { return; }
        if (x >= 3) { return; }
        if (y >= 3) { return; }
    
    
        int n = x + y * 3;
        //flg[n] = true;
        //answer[n] = data[current];
        //current++;
        if ((x > 0) && answer[(x - 1) + y * 3] == 8) swap_answer(n, (x - 1) + y * 3);
        if ((x < 2) && answer[(x + 1) + y * 3] == 8) swap_answer(n, (x + 1) + y * 3);
        if ((y > 0) && answer[x + (y - 1) * 3] == 8) swap_answer(n, x + (y - 1) * 3);
        if ((y < 2) && answer[x + (y + 1) * 3] == 8) swap_answer(n, x + (y + 1) * 3);
    
        // this.checkGameEnd();
        this.Refresh();
    
    }
  3. 勝負判定
    private void PlayBox_MouseDown(object sender, MouseEventArgs e)
    {
        if (playflg == false) { return; }
        if (img == null) { return; }
        if (current > 8) { return; }
        int x = e.X / 100;
        int y = e.Y / 100;
        if (x < 0) { return; }
        if (y < 0) { return; }
        if (x >= 3) { return; }
        if (y >= 3) { return; }
    
    
        int n = x + y * 3;
        //flg[n] = true;
        //answer[n] = data[current];
        //current++;
        if ((x > 0) && answer[(x - 1) + y * 3] == 8) swap_answer(n, (x - 1) + y * 3);
        if ((x < 2) && answer[(x + 1) + y * 3] == 8) swap_answer(n, (x + 1) + y * 3);
        if ((y > 0) && answer[x + (y - 1) * 3] == 8) swap_answer(n, x + (y - 1) * 3);
        if ((y < 2) && answer[x + (y + 1) * 3] == 8) swap_answer(n, x + (y + 1) * 3);
    
        // this.checkGameEnd();
        this.checkClear();  // chen : clear check
        playflg = !clearflg; // chen :  clear なら、 not play
        this.Refresh();
    
    }

     

  4. 経過時間の表示

C# exercises (8) Puzzle Game2

先週できたパズルゲームUIの改進

参考

  • http://www18.big.or.jp/~neon2/bunkatu/tips9.shtml

改進点:

ピースを順番でセットするではなく、あらかじめランダムにセットして、マウス移動できるようにする

  1. ピースをあらかじめランダムにセット
    1. initialData の改造
    2. PlayBox_Paint の改造
  2. マウス移動できる
  3. 勝負判定
  4. 経過時間の表示

C# exercises (7) Puzzle Game

今回作るのは、イメージを読み込んで利用するパズルゲームです。イメージファイルを読み込むとそれを 9 分割し、ランダムに混ぜます。

プレビューのイメージをフォーム上クリックして配置、すべて正しい場所に配置できればクリアです。

PuzzleGame3x3

 

フォーム作成

サイズ:500 x 400

背景色:適当

スクリーンショット 2016-06-03 10.47.38

PictureBox配置

  • (Name) : PlayBox
  • Size :        300 x 300
  • BackColor :  white

プレビュー用PictureBox配置

  • (Name) : Preview
  • Size :        100 x 100
  • BackColor :  white

スクリーンショット 2016-06-03 10.56.11

 

 

メニュー作成

MenuStrip をフォームにドロップ、下記のようにメニュー追加

  • File
    • Load Image…

 

スクリーンショット 2016-06-03 10.59.28

 

ダイアログ作成

openFileDialog をフォームにドロップ、フィルターを設定

  • Image Files (*.png, *.jpg) | *.png; *.jpg

スクリーンショット 2016-06-03 11.09.08

 

イベント設定

PlayBox

  • MouseDown : PlayBox_MouseDown
  • Paint : PlayBox_Paint

Preview

  • Paint : Preview_Paint

LoadImage

  • Click : LoadImage_Click

スクリーンショット 2016-06-03 11.15.29

 

ソースコード

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 PuzzleApp
{
    public partial class Form1 : Form
    {
        // ゲームで使う変数(フィールド)
        Image img = null;
        bool[] flg = new bool[9];
        int[] data = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
        int[] answer = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
        int current = 0;
        bool playflg = false;
        bool clearflg = false;


        public Form1()
        {
            InitializeComponent();
        }


        // 変数関係の初期化処理
        private void initialData()
        {
            flg = new bool[9];
            data = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
            answer = new int[] { -1, -1, -1, -1, -1, -1, -1, -1, -1 };
            Random r = new Random(Environment.TickCount);
            for (int i = 0; i < 100; i++)
            {
                int a = r.Next(9);
                int b = r.Next(9);
                int n = data[a];
                data[a] = data[b];
                data[b] = n;
            }
            current = 0;
            playflg = true;
            clearflg = false;
        }


        // クリアしたかどうかをチェック
        private void checkClear()
        {
            bool flg = true;
            for (int i = 0; i < 9; i++)
            {
                if (answer[i] != i) { flg = false; }
            }
            clearflg = flg;
        }


        // ゲームが終わったかどうかチェック
        private void checkGameEnd()
        {
            bool flg = false;
            for (int i = 0; i < 9; i++)
            {
                if (answer[i] == -1) { flg = true; }
            }
            playflg = flg;
            if (playflg == false)
            {
                this.checkClear();
            }
        }


        // オープンダイアログを開いてイメージファイルをロードする
        private void LoadImage_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
            {
                img = Image.FromFile(openFileDialog1.FileName);
                this.initialData();
                this.Refresh();
            }
        }


        // PlayBoxの表示
        private void PlayBox_Paint(object sender, PaintEventArgs e)
        {
            if (img == null) { return; }
            Graphics g = e.Graphics;
            for (int i = 0; i < 9; i++)
            {
                if (flg[i] == false) { continue; }
                if (answer[i] == -1) { continue; }
                int x1 = i % 3;
                int y1 = i / 3;
                int x2 = answer[i] % 3;
                int y2 = answer[i] / 3;
                Rectangle r1 = new Rectangle(100 * x1, 100 * y1, 100, 100);
                Rectangle r2 = new Rectangle(100 * x2, 100 * y2, 100, 100);
                g.DrawImage(img, r1, r2, GraphicsUnit.Pixel);
            }
            if (playflg == false)
            {
                if (clearflg)
                {
                    g.DrawString("CLEAR!!",
                        new Font("Impact", 48, FontStyle.Bold),
                        new SolidBrush(Color.Red),
                        new Point(40, 100));
                }
                else
                {
                    g.DrawString("GAMEOVER...",
                        new Font("Impact", 36, FontStyle.Bold),
                        new SolidBrush(Color.Blue),
                        new Point(20, 200));
                }
            }
        }


        // PlayBoxをクリックした時の処理
        private void PlayBox_MouseDown(object sender, MouseEventArgs e)
        {
            if (playflg == false) { return; }
            if (img == null) { return; }
            if (current > 8) { return; }
            int x = e.X / 100;
            int y = e.Y / 100;
            if (x < 0) { return; }
            if (y < 0) { return; }
            if (x >= 3) { return; }
            if (y >= 3) { return; }


            int n = x + y * 3;
            flg[n] = true;
            answer[n] = data[current];
            current++;
            this.checkGameEnd();
            this.Refresh();
        }


        // previewの表示
        private void Preview_Paint(object sender, PaintEventArgs e)
        {
            if (img == null) { return; }
            if (current > 8) { return; }
            int x = data[current] % 3;
            int y = data[current] / 3;
            Graphics g = e.Graphics;
            Rectangle r1 = new Rectangle(0, 0, 100, 100);
            Rectangle r2 = new Rectangle(x * 100, y * 100, 100, 100);
            g.DrawImage(img, r1, r2, GraphicsUnit.Pixel);
        }
    }
}

 

実行結果

 

スクリーンショット 2016-06-03 11.30.31

 

スクリーンショット 2016-06-03 11.29.42

参考

http://www18.big.or.jp/~neon2/bunkatu/tips9.shtml

C# exercises (6) Graphics and Paint

Graphicsオブジェクト

ウインドウの内部を表示したり描き直したりする必要が生ずると、Formに「Paint」というイベントが発生し、Paintプロパティに設定されているメソッドが呼び出されるようになっています。

このPaintイベント用のメソッドは、これまでのクリック時のイベント用メソッドなどとは微妙に違いがあります。これは以下のように定義されます。

private void メソッド名 (object sender, PaintEventArgs e)
{
    ……ここに描画処理を書く……
}

第1引数に、イベントが発生したオブジェクトが渡されるのは同じですが、第2引数に渡されるのはSystem.Windows.Formsパッケージの「PaintEventArgs」というクラスのインスタンスです。これは、描画のためのイベント情報を管理するもので、描画に必要なオブジェクトなどもこの中にまとめられているのです。
中でも重要なのが「Graphics」というオブジェクトです。これはSystem.Drawingパッケージに用意されているクラスで、これはGDI+(Graphics Device Interfaceというグラフィック描画のための機能の強化版)を利用して画面にさまざまな描画を行うための機能を提供します。

Paintイベント

フォームのプロパティをイベントに切り替えて、Paintイベントを探し、メソッド名Form1Paintを入力

スクリーンショット 2016-05-27 11.31.11

Paintイベントで渡されるPaintEventArgsインスタンスから以下のようにして取り出します。

Graphics 変数 = 《PaintEventArgs》.Graphics;

Penと図形の描画

  • g.DrawLine(p,75,75,50,50);  // 直線
  • g.DrawEllipse(p,75,75,50,50);  // 円
private void Form1Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    Pen p = new Pen(Color.Red); // Penインスタンスの作成
    g.DrawEllipse(p,75,75,50,50);
}

Penと多角形を描く

private void Form1Paint(object sender, PaintEventArgs e)
{
 Graphics g = e.Graphics;
 Pen p = new Pen(Color.Red); // Penインスタンスの作成
 Brush b = new SolidBrush(Color.Blue); // Brushインスタンスの作成

 //直線で接続する点の配列を作成
 Point[] ps = {new Point(100, 0),
     new Point(158, 180),
     new Point(4, 69),
     new

Point(195,

 69),
     new Point(41, 180)};
 //多角形を描画する
 g.DrawPolygon(p, ps);
}

 

Brushと塗りつぶし図形

private void Form1Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    Brush b = new SolidBrush(Color.Blue); // Brushインスタンスの作成
    g.DrawEllipse(p,75,75,50,50);
}

実例

using System;
using System.Drawing;
using System.Windows.Forms;
 
namespace MyFrmApp
{
    public class MyForm : Form
    {
             
        public MyForm()
        {
            this.Width = 300;
            this.Height = 200;
            this.Paint += myframe_paint;
        }
             
        private void Form1Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Pen p = new Pen(Color.Red); // Penインスタンスの作成
            Brush b = new SolidBrush(Color.Blue); // Brushインスタンスの作成
            g.FillRectangle(b,50,50,50,50);
            g.DrawEllipse(p,75,75,50,50);


            //直線で接続する点の配列を作成
            Point[] ps = {new Point(0, 0),
            new Point(150, 50),
            new Point(80, 100),
            new Point(100, 150)};
            //多角形を描画する
            g.DrawPolygon(p, ps);
        }
    }
}

スクリーンショット 2016-05-27 11.29.37

演習

五芒星を描く

220px-Pentagram.svg

star

***

五芒星(ごぼうせい、英: pentagram)または五芒星形・五角形・型・型五角形・正5/2角形は、互いに交差する、長さの等しい5本の線分から構成される図形で型正多角形の一種である。 正五角形に内接し、対称的である。 一筆書きが可能。

 

middle_1310314010

Pentacle_2.svg

 参考

  • http://qiita.com/tomato360/items/a59f2ee4df4fd2f24227